Skip to content

Commit 7dfb9cd

Browse files
feat: Certification versions V27 and V28
Update to the specifications related to the new `last_install_timestamp` and `canister_creation_timestamp` leaves in the state tree.
1 parent 9d98a55 commit 7dfb9cd

4 files changed

Lines changed: 33 additions & 1 deletion

File tree

docs/references/ic-interface-spec/abstract-behavior.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,8 @@ S = {
515515
environment_variables: CanisterId ↦ (Text ↦ Text)
516516
on_low_wasm_memory_hook_status: CanisterId ↦ OnLowWasmMemoryHookStatus;
517517
certified_data: CanisterId ↦ Blob;
518+
canister_creation_timestamp: CanisterId ↦ Timestamp;
519+
last_install_timestamp: CanisterId ↦ Timestamp;
518520
canister_history: CanisterId ↦ CanisterHistory;
519521
canister_log_visibility: CanisterId ↦ CanisterLogVisibility;
520522
canister_snapshot_visibility: CanisterId ↦ CanisterSnapshotVisibility;
@@ -625,6 +627,8 @@ The initial state of the IC is
625627
environment_variables = ();
626628
on_low_wasm_memory_hook_status = ();
627629
certified_data = ();
630+
canister_creation_timestamp = ();
631+
last_install_timestamp = ();
628632
canister_history = ();
629633
canister_log_visibility = ();
630634
canister_snapshot_visibility = ();
@@ -1755,6 +1759,7 @@ S' = S with
17551759
canisters[Canister_id] = EmptyCanister
17561760
snapshots[A.canister_id] = null
17571761
time[Canister_id] = CurrentTime
1762+
canister_creation_timestamp[Canister_id] = CurrentTime
17581763
global_timer[Canister_id] = 0
17591764
controllers[Canister_id] = New_controllers
17601765
chunk_store[Canister_id] = ()
@@ -2395,6 +2400,7 @@ S' = S with
23952400
else:
23962401
global_timer[A.canister_id] = 0
23972402
canister_version[A.canister_id] = S.canister_version[A.canister_id] + 1
2403+
last_install_timestamp[A.canister_id] = S.time[A.canister_id]
23982404
balances[A.canister_id] = New_balance
23992405
reserved_balances[A.canister_id] = New_reserved_balance
24002406
canister_history[A.canister_id] = New_canister_history
@@ -2561,6 +2567,7 @@ S' = S with
25612567
else:
25622568
global_timer[A.canister_id] = 0
25632569
canister_version[A.canister_id] = S.canister_version[A.canister_id] + 1
2570+
last_install_timestamp[A.canister_id] = S.time[A.canister_id]
25642571
balances[A.canister_id] = New_balance;
25652572
reserved_balances[A.canister_id] = New_reserved_balance;
25662573
canister_history[A.canister_id] = New_canister_history
@@ -3192,6 +3199,7 @@ S' = S with
31923199
canisters[Canister_id] = EmptyCanister
31933200
snapshots[Canister_id] = null
31943201
time[Canister_id] = CurrentTime
3202+
canister_creation_timestamp[Canister_id] = CurrentTime
31953203
global_timer[Canister_id] = 0
31963204
controllers[Canister_id] = New_controllers
31973205
compute_allocation[Canister_id] = New_compute_allocation
@@ -3527,6 +3535,7 @@ S' = S with
35273535
reserved_balances[A.canister_id] = New_reserved_balance
35283536
canister_history[A.canister_id] = New_canister_history
35293537
canister_version[A.canister_id] = S.canister_version[A.canister_id] + 1
3538+
last_install_timestamp[A.canister_id] = S.time[A.canister_id]
35303539
messages = Older_messages · Younger_messages ·
35313540
ResponseMessage {
35323541
origin = M.origin;
@@ -4732,6 +4741,8 @@ may_read_path_for_canister(S, _, ["request_status", Rid, "error_code"]) =
47324741
∀ (R ↦ (_, ECID')) ∈ dom(S.requests). hash_of_map(R) = Rid => RS.sender == R.sender ∧ ECID == ECID'
47334742
may_read_path_for_canister(S, _, ["canister", cid, "module_hash"]) = cid == ECID
47344743
may_read_path_for_canister(S, _, ["canister", cid, "controllers"]) = cid == ECID
4744+
may_read_path_for_canister(S, _, ["canister", cid, "canister_creation_timestamp"]) = cid == ECID
4745+
may_read_path_for_canister(S, _, ["canister", cid, "last_install_timestamp"]) = cid == ECID
47354746
may_read_path_for_canister(S, _, ["canister", cid, "metadata", name]) = cid == ECID ∧ UTF8(name) ∧
47364747
(cid ∉ dom(S.canisters[cid]) ∨
47374748
S.canisters[cid] = EmptyCanister ∨
@@ -4809,6 +4820,8 @@ state_tree(S) = {
48094820
{ canister_id :
48104821
{ "module_hash" : SHA256(C.raw_module) | if C ≠ EmptyCanister } ∪
48114822
{ "controllers" : CBOR(S.controllers[canister_id]) } ∪
4823+
{ "canister_creation_timestamp" : S.canister_creation_timestamp[canister_id] } ∪
4824+
{ "last_install_timestamp" : S.last_install_timestamp[canister_id] | if C ≠ EmptyCanister } ∪
48124825
{ "metadata": { name: blob | (name, blob) ∈ S.canisters[canister_id].public_custom_sections ∪ S.canisters[canister_id].private_custom_sections } }
48134826
| (canister_id, C) ∈ S.canisters };
48144827
}

docs/references/ic-interface-spec/changelog.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ sidebar:
88

99
## Changelog {#changelog}
1010

11+
### 0.65.0 (2026-07-24) {$0_65_0}
12+
* Two new paths in the certified state tree, `/canister/<canister_id>/canister_creation_timestamp`
13+
(the time at which the canister was created) and `/canister/<canister_id>/last_install_timestamp`
14+
(the time at which the canister's code was most recently deployed or a snapshot was loaded onto it),
15+
both expressed in nanoseconds since 1970-01-01. Both can be requested via `read_state` if
16+
`<canister_id>` matches the effective canister id of the request.
17+
1118
### 0.64.0 (2026-07-06) {$0_64_0}
1219
* New optional `permissions` field in request delegations restricting the kinds of requests
1320
the delegation applies for: the value `"queries"` restricts the delegation to query calls

docs/references/ic-interface-spec/https-interface.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ All requested paths must have the following form:
314314

315315
- `/canister/<canister_id>/controllers`. Can be requested if `<canister_id>` matches `<effective_canister_id>`. The order of controllers in the value at this path may vary depending on the implementation.
316316

317+
- `/canister/<canister_id>/canister_creation_timestamp`. Can be requested if `<canister_id>` matches `<effective_canister_id>`.
318+
319+
- `/canister/<canister_id>/last_install_timestamp`. Can be requested if `<canister_id>` matches `<effective_canister_id>`.
320+
317321
- `/canister/<canister_id>/metadata/<name>`. Can be requested if `<canister_id>` matches `<effective_canister_id>`, `<name>` is encoded in UTF-8, and
318322

319323
- canister with canister id `<canister_id>` does not exist or

docs/references/ic-interface-spec/index.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ Request statuses will not actually be kept around indefinitely, and eventually t
615615
616616
### Canister information {#state-tree-canister-information}
617617
618-
Users have the ability to learn about the hash of the canister's module, its current controllers, and metadata in a certified way.
618+
Users have the ability to learn about the hash of the canister's module, its current controllers, metadata, creation time, and last install time in a certified way.
619619
620620
- `/canister/<canister_id>/module_hash` (blob):
621621
@@ -625,6 +625,14 @@ Users have the ability to learn about the hash of the canister's module, its cur
625625
626626
The current controllers of the canister. The value consists of a CBOR (see [CBOR](#cbor)) data item with major type 6 ("Semantic tag") and tag value `55799`, followed by an array of principals in their binary form (CDDL `#6.55799([* bytes .size (0..29)])`, see [CDDL](#cddl)).
627627
628+
- `/canister/<canister_id>/canister_creation_timestamp` (natural):
629+
630+
The time at which the canister was created, expressed in nanoseconds since 1970-01-01. If the canister was created before this information was recorded, this path does not exist.
631+
632+
- `/canister/<canister_id>/last_install_timestamp` (natural):
633+
634+
The time at which the canister's code was most recently deployed ([code install, reinstall, or upgrade](./management-canister.md#ic-install_code)) or a [snapshot was loaded](./management-canister.md#ic-load_canister_snapshot) onto it, expressed in nanoseconds since 1970-01-01. If the canister is empty, or its code was deployed before this information was recorded, this path does not exist.
635+
628636
- `/canister/<canister_id>/metadata/<name>` (blob):
629637
630638
If the canister has a [custom section](https://webassembly.github.io/spec/core/binary/modules.html#custom-section) called `icp:public <name>` or `icp:private <name>`, this path contains the content of the custom section. Otherwise, this path does not exist.

0 commit comments

Comments
 (0)