Issue about generate random string Panicked at 'could not initialize thread_rng: getrandom: this target is not supported'

Reject text: Canister ryjl3-tyaaa-aaaaa-abbba-cai trapped explicitly: Panicked at ‘could not initialize thread_rng: getrandom: this target is not supported’, /Users/xxxx/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.7.3/src/rngs/thread.rs:65:17

dependencies:
rand = “0.7.3”
getrandom = { version = “0.2.6”, features = [“js”]}

“dfx”: “0.9.3”,

I refered to previous solution, it doesn’t work. Does anyone know how to solve it?

features = [“js”] works in a JS environment; it does not work in a freestanding WASM environment. What you instead do is use the register_custom_getrandom! macro to register a CSPRNG you seeded through ic0.raw_rand. (I am curious what previous solution you refer to, that wasn’t that.)

I tried higher rand version

I briefly looked into this at some point and assumed it wouldn’t work because the docs for register_custom_getrandom said:

The function to register must have the same signature as getrandom::getrandom

and that function isn’t async so I don’t understand how raw_rand can be called.

@AdamS if you have advice on how to make this work it would be really helpful.

Right, like I said you’d seed an RNG of your choice with raw_rand. Once created and stored in a static, this RNG can be used synchronously.

Does anyone have an example of this working?

use getrandom::register_custom_getrandom;
fn custom_getrandom(buf: &mut [u8]) -> Result<(), getrandom::Error> {
    // What goes here?
    return Ok(());
}

register_custom_getrandom!(custom_getrandom);

I did this:

use getrandom::register_custom_getrandom;
fn custom_getrandom(buf: &mut [u8]) -> Result<(), getrandom::Error> {
    let mut rng = StdRng::seed_from_u64(123);
    rng.fill_bytes(buf);
    return Ok(());
}

This will return the same numbers every time. What you can do instead is seed an RNG of your choice with raw_rand. Once created and stored in a static, this RNG can be used synchronously. For example:

thread_local! {
    static RNG: RefCell<Option<StdRng>> = RefCell::new(None);
}
#[init]
fn init() {
    ic_cdk::timer::set_timer(Duration::ZERO, || ic_cdk::spawn(async {
        let (seed,): ([u8; 32],) = ic_cdk::call(Principal::management_canister(), "raw_rand", ()).await.unwrap();
        RNG.with(|rng| *rng.borrow_mut() = Some(StdRng::from_seed(seed)));
    }));
}
fn custom_getrandom(buf: &mut [u8]) -> Result<(), getrandom::Error> {
    RNG.with(|rng| rng.borrow_mut().as_mut().unwrap().fill_bytes(buf));
    Ok(())
}
4 Likes

Thank you, this is what I was looking for! :pray: