How does the upgrading of canister works

I’m using ic-stable-memory libary by @senior.joinu.
here is my upgrading code:

#[pre_upgrade]
pub fn pre_upgrade() {
    let init_state: InitState = INIT_STATE.with(|state| state.borrow().clone());
    let init_state = SBox::new(init_state).expect("failed to clone");
    let system_state = SYSTEM_STATE
        .with(|state| state.borrow().clone())
        .expect("failed to clone");
    let system_state = SBox::new(system_state).expect("failed to box");
    let user_state = USER_STATE.with(|state| state.borrow().clone().expect("failed to clone"));
    let user_state = SBox::new(user_state).expect("failed to box");
    let offer_state = OFFER_STATE.with(|state| state.borrow().clone().expect("failed to clonex"));
    let offer_state = SBox::new(offer_state).expect("failed to box");
    store_custom_data(0, init_state);
    store_custom_data(1, system_state);
    store_custom_data(2, user_state);
    store_custom_data(3, offer_state);
    stable_memory_pre_upgrade().expect("out of memory");
}

#[post_upgrade]
pub fn post_upgrade() {
    stable_memory_post_upgrade();
    let init_state: SBox<InitState> = retrieve_custom_data(0).unwrap();
    let system_state: SBox<System> = retrieve_custom_data(1).unwrap();
    let user_state: SBox<UserState> = retrieve_custom_data(2).unwrap();
    let offer_state: SBox<OfferState> = retrieve_custom_data(3).unwrap();
    INIT_STATE.with(|state| {
        *state.borrow_mut() = init_state.into_inner();
    });
    SYSTEM_STATE.with(|state| {
        *state.borrow_mut() = system_state.into_inner();
    });
    USER_STATE.with(|state| {
        *state.borrow_mut() = user_state.into_inner();
    });
    OFFER_STATE.with(|state| {
        *state.borrow_mut() = offer_state.into_inner();
    });
}

when I try to upgrade the canister it fails with this error:

Error: Failed while trying to deploy canisters.
Caused by: Failed while trying to deploy canisters.
  Failed while trying to install all canisters.
    Failed to install wasm module to canister 'contract'.
      Failed during wasm installation call: The Replica returned an error: code 5, message: "Canister bw4dl-smaaa-aaaaa-qaacq-cai trapped: heap out of bounds"

Can you please also provide us with your init method and how you declare the state (thread_locals)?

Does this error happen on upgrade or on initial deployment?

UPD:
also, how much heap memory does your state occupy before upgrading?

thread_local! {
    pub static INIT_STATE: RefCell<InitState> = RefCell::default();
    pub static OFFER_STATE: RefCell<OfferState> = RefCell::default();
    pub static USER_STATE: RefCell<UserState> = RefCell::default();
    pub static SYSTEM_STATE: RefCell<System> = RefCell::default();
}

How do I check how much storage is being used, I don’t know!

1 Like

There is a memory field in the canister status response. Is that useful for you?

2 Likes

is there heap limit for upgrading the codes?

Yes, the Wasm runtime is only 32 bit for now, so you can only have up to 4GB in the heap

damn, what if my canister holds more data than that of 4gb?
what’s the say to make it work at the moment?

Then you have to store data in stable storage. Stable storage goes up to 48 GB (or is it 64 already?)

hmm, how do I do that?
can you show some code?
I’m using ic-stable-memory so I’m guessing my data is already on stable-memory.
is that how it’s done? or I’m wrong?

also in the above code/project. I just have inserted few bytes of data. why did it failed?

I’m no good with ic-stable-memory, but I can recommend you have a look at the readme to see some examples. Otherwise, please ping @senior.joinu, he’s the author

I would suggest you to provide us with a MRE. This way I could try it locally and see what happens.
From the error message itself I don’t see if this is a bug with ic-stable-memory, but it may be.

what’s MRE?
here is my init method:

pub fn init() {
    ic_stable_memory::stable_memory_init();
    let caller = ic_cdk::caller();
    INIT_STATE.with(|state| {
        let mut state = state.borrow_mut();
        state.authority = caller;
    })
}

A minimal reproducible example.

can you explain what do i have to share?

Yes, sure.
So you have this code that doesn’t work. If it is not a secret, just share it without modifying and provide an instruction on how to achieve the same error you’re having.
If it is a secret, then find a way to achieve the same error with similar code, that does not reveal any secrets, and share this code instead.

hello @Severin, does the memory size returned from the method is heap storage or it is also the combination of stable memory too?

It the sum of Wasm and stable memory sizes.

4 Likes

It’s been 64 GiB for a bit now.