Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/references/_attachments/ic.did
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,17 @@ type canister_install_mode = variant {
};
};

type install_code_preconditions = record {
stopped : opt bool;
total_num_changes : opt nat64;
};

type install_code_args = record {
mode : canister_install_mode;
canister_id : canister_id;
wasm_module : wasm_module;
arg : blob;
preconditions : opt install_code_preconditions;
sender_canister_version : opt nat64;
};

Expand All @@ -225,6 +231,7 @@ type install_chunked_code_args = record {
chunk_hashes_list : vec chunk_hash;
wasm_module_hash : blob;
arg : blob;
preconditions : opt install_code_preconditions;
sender_canister_version : opt nat64;
};

Expand Down
46 changes: 35 additions & 11 deletions docs/references/ic-interface-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -2342,6 +2342,18 @@ The `wasm_module` field specifies the canister module to be installed. The syste

- If the `wasm_module` starts with byte sequence `[0x1f, 0x8b, 0x08]`, the system parses `wasm_module` as a gzip-compressed WebAssembly binary.

The optional `preconditions` parameter can contain preconditions for this call to succeed: all provided preconditions must be satisfied,
otherwise the call fails without any changes to the canister. The supported preconditions are:

- `stopped` (`opt bool`)

If set to `opt true`, then the canister status must be stopped.

- `total_num_changes` (`opt nat64`)

If provided, then the total number of canister changes that have been ever recorded in the history (as returned by the [IC Method `canister_info`](#ic-canister_info))
must match the provided value.

The optional `sender_canister_version` parameter can contain the caller's canister version. If provided, its value must be equal to `ic0.canister_version`.

This method traps if the canister's cycle balance decreases below the canister's freezing limit after executing the method.
Expand All @@ -2354,12 +2366,12 @@ This method installs code that had previously been uploaded in chunks.

Only controllers of the target canister can call this method.

The `mode`, `arg`, and `sender_canister_version` parameters are as for `install_code`.
The `mode`, `arg`, `preconditions`, and `sender_canister_version` parameters are as for `install_code`.
The `target_canister` specifies the canister where the code should be installed.
The optional `store_canister` specifies the canister in whose chunk storage the chunks are stored (this parameter defaults to `target_canister` if not specified).
For the call to succeed, the caller must be a controller of the `store_canister` or the caller must be the `store_canister`. The `store_canister` must be on the same subnet as the target canister.

The `chunk_hashes_list` specifies a list of hash values `[h1,...,hk]` with `k <= MAX_CHUNKS_IN_LARGE_WASM`. The system looks up in the chunk store of `store_canister` (or that of the target canister if `store_canister` is not specified) blobs corresponding to `h1,...,hk` and concatenates them to obtain a blob of bytes referred to as `wasm_module` in `install_code`. It then checks that the SHA-256 hash of `wasm_module` is equal to the `wasm_module_hash` parameter and calls `install_code` with parameters `(record {mode; target_canister; wasm_module; arg; sender_canister_version})`.
The `chunk_hashes_list` specifies a list of hash values `[h1,...,hk]` with `k <= MAX_CHUNKS_IN_LARGE_WASM`. The system looks up in the chunk store of `store_canister` (or that of the target canister if `store_canister` is not specified) blobs corresponding to `h1,...,hk` and concatenates them to obtain a blob of bytes referred to as `wasm_module` in `install_code`. It then checks that the SHA-256 hash of `wasm_module` is equal to the `wasm_module_hash` parameter and calls `install_code` with parameters `(record {mode; target_canister; wasm_module; arg; preconditions; sender_canister_version})`.

### IC method `uninstall_code` {#ic-uninstall_code}

Expand Down Expand Up @@ -5160,6 +5172,16 @@ Private_custom_sections = parse_private_custom_sections(A.wasm_module);
(A.mode = install and S.canisters[A.canister_id] = EmptyCanister) or A.mode = reinstall
M.caller ∈ S.controllers[A.canister_id]

S.canister_history[A.canister_id] = {
total_num_changes = N;
recent_changes = H;
}

if A.preconditions.stopped = opt true:
S.canister_status[A.canister_id] = Stopped
if A.preconditions.total_num_changes is not null:
A.preconditions.total_num_changes = N

dom(Mod.update_methods) ∩ dom(Mod.query_methods) = ∅
dom(Mod.update_methods) ∩ dom(Mod.composite_query_methods) = ∅
dom(Mod.query_methods) ∩ dom(Mod.composite_query_methods) = ∅
Expand Down Expand Up @@ -5205,10 +5227,6 @@ if S.memory_allocation[A.canister_id] > 0:

(S.wasm_memory_limit[A.canister_id] = 0) or |New_state.store.mem| <= S.wasm_memory_limit[A.canister_id]

S.canister_history[A.canister_id] = {
total_num_changes = N;
recent_changes = H;
}
New_canister_history = {
total_num_changes = N + 1;
recent_changes = H · {
Expand Down Expand Up @@ -5282,6 +5300,16 @@ Private_custom_sections = parse_private_custom_sections(A.wasm_module)
M.caller ∈ S.controllers[A.canister_id]
S.canisters[A.canister_id] = { wasm_state = Old_state; module = Old_module, …}

S.canister_history[A.canister_id] = {
total_num_changes = N;
recent_changes = H;
}

if A.preconditions.stopped = opt true:
S.canister_status[A.canister_id] = Stopped
if A.preconditions.total_num_changes is not null:
A.preconditions.total_num_changes = N

dom(Mod.update_methods) ∩ dom(Mod.query_methods) = ∅
dom(Mod.update_methods) ∩ dom(Mod.composite_query_methods) = ∅
dom(Mod.query_methods) ∩ dom(Mod.composite_query_methods) = ∅
Expand Down Expand Up @@ -5370,10 +5398,6 @@ if S.memory_allocation[A.canister_id] > 0:

(S.wasm_memory_limit[A.canister_id] = 0) or |New_state.store.mem| <= S.wasm_memory_limit[A.canister_id]

S.canister_history[A.canister_id] = {
total_num_changes = N;
recent_changes = H;
}
New_canister_history = {
total_num_changes = N + 1;
recent_changes = H · {
Expand Down Expand Up @@ -5448,7 +5472,7 @@ wasm_module = S.chunk_store[store_canister][h1] || ... || S.chunk_store[store_ca
A.wasm_module_hash = SHA-256(wasm_module)
M' = M with
method_name = 'install_code'
arg = candid(record {A.mode; A.target_canister; wasm_module; A.arg; A.sender_canister_version})
arg = candid(record {A.mode; A.target_canister; wasm_module; A.arg; A.preconditions; A.sender_canister_version})

```

Expand Down