I have an init function in my Rust canister, and I am trying to get access to randomness from the random beacon within that init function. I get the following error "ic0_call_new" cannot be executed in init mode.
I am trying to do this from the init function:
let call_result: Result<(Vec<u8>,), _> = ic_cdk::api::call::call(ic_cdk::export::Principal::management_canister(), "raw_rand", ()).await;
Yes, I can confirm that is a limitiation, documented in the Interface Spec.
Motoko will actually statically reject actors that try to send messages from their initialisation code, but I guess the Rust library cannot or is not designed to enforce this.
My understanding is that the canister_init method is used to set up the initial invariants of the canister.
If you allowed messaging during canister_init, then another canister, or the canister itself, could call into the canister under construction, before its invariants have been established.
This is a well-known flaw with constructors in some OO languages, IIRC.
(NB: I didn’t design the System API and am just speculating on the rationale.)
It looks like there is a workaround for this limitation. Just discovered it.
You can use ic-cron library to schedule a task inside init() function and then immediately process that task in the first ever heartbeat of your canister.