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.

3 Likes

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!

1 Like

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

1 Like

Nice, agree and therefore, done as well.