Get random numbers without async (for Rust getrandom)?

getrandom by default isn’t supported on ICP. The solution is to provide a custom backend to get rust to compile:


#[unsafe(no_mangle)]
unsafe extern "Rust" fn __getrandom_v03_custom(
    dest: *mut u8,
    len: usize,
) -> Result<(), getrandom_03::Error> {
    // ...
}

the problem arises when there is a need to use getrandom because some other dependency needs it.

ic_cdk::management_canister::raw_rand() is not an option as it is async and the extern fn cannot call. What is a way to get random numbers without async here (if any)?

We recommend this as the approach for using randomness on the IC, Security best practices: Miscellaneous | Internet Computer

In short, you seed a PRNG with randomness from raw_rand on a timer, so that access to the PRNG will be synchronous.

In your case, the custom getrandom fn will access this PRNG to fill random bytes.

Nice, always glad to hear I’m not doing it wrong :grinning_face_with_smiling_eyes:

If useful as OP is using getrandom v3 and not v2 as in the documentation, here’s one my usage of both.

Note: my code uses latest ic_cdk so in comparison to documentation, the spawn usage is also be spared.

PS: If someone has a better idea than Error::new_custom(0) for returning an error when init fails, I’m not against it!

LOL :rofl:

I’m using both because some crates use getrandom v2 and some use v3 and I have to include both and enable custom backend for them because otherwise builds fail :woman_facepalming:

I ended up returning Error::UNEXPECTED, which is probably more accurate than just a 0.

My solution is a combination of what everyone has posted, thanks y’all. I apparently can’t post links here so I made a gist of it at ranile/2a7d4d3d2c3a8689e5196a537bbcbfae

Nice, agree and therefore, done as well.