From d265c2c6f2dd0ffa4767d25fec002d9d28525291 Mon Sep 17 00:00:00 2001
From: mraszyk <31483726+mraszyk@users.noreply.github.com>
Date: Fri, 28 Jul 2023 13:16:14 +0200
Subject: [PATCH 01/12] rephrase description of create_canister method (#207)
---
spec/index.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/spec/index.md b/spec/index.md
index 652c1f632..ebc4f3e49 100644
--- a/spec/index.md
+++ b/spec/index.md
@@ -1776,7 +1776,9 @@ The optional `settings` parameter can be used to set the following settings:
- `controllers` (`vec principal`)
- A list of principals. Must be between 0 and 10 in size. This value is assigned to the *controllers* attribute of the canister.
+ A list of at most 10 principals. The principals in this list become the *controllers* of the canister.
+ Note that the caller of the `create_canister` call is not a controller of the canister
+ unless it is a member of the `controllers` list.
Default value: A list containing only the caller of the `create_canister` call.
From 5a8c93f8cd316ddc9890ff04153b5412f863b267 Mon Sep 17 00:00:00 2001
From: mraszyk <31483726+mraszyk@users.noreply.github.com>
Date: Fri, 28 Jul 2023 13:18:58 +0200
Subject: [PATCH 02/12] update ecdsa_public_key specs (#208)
---
spec/index.md | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/spec/index.md b/spec/index.md
index ebc4f3e49..23af818c8 100644
--- a/spec/index.md
+++ b/spec/index.md
@@ -1934,14 +1934,12 @@ This method takes no input and returns 32 pseudo-random bytes to the caller. The
### IC method `ecdsa_public_key` {#ic-ecdsa_public_key}
-This method returns a [SEC1](https://www.secg.org/sec1-v2.pdf) encoded ECDSA public key for the given canister using the given derivation path. If the `canister_id` is unspecified, it will default to the canister id of the caller. The `derivation_path` is a vector of variable length byte strings. Each byte string may be of arbitrary length, including empty. The total number of strings in `derivation_path` can be at most 255. The `key_id` is a struct specifying both a curve and a name. The availability of a particular `key_id` depends on implementation.
+This method returns a [SEC1](https://www.secg.org/sec1-v2.pdf) encoded ECDSA public key for the given canister using the given derivation path. If the `canister_id` is unspecified, it will default to the canister id of the caller. The `derivation_path` is a vector of variable length byte strings. Each byte string may be of arbitrary length, including empty. The total number of byte strings in the `derivation_path` must be at most 255. The `key_id` is a struct specifying both a curve and a name. The availability of a particular `key_id` depends on implementation.
-For curve `secp256k1`, the public key is derived using a generalization of BIP32 (see [ia.cr/2021/1330, Appendix D](https://ia.cr/2021/1330)). To derive (non-hardened) [BIP-0032](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)-compatible public keys, each byte string (`blob`) in the `derivation_path` must be a 4-byte big-endian encoding of an unsigned integer less than 231.
+For curve `secp256k1`, the public key is derived using a generalization of BIP32 (see [ia.cr/2021/1330, Appendix D](https://ia.cr/2021/1330)). To derive (non-hardened) [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)-compatible public keys, each byte string (`blob`) in the `derivation_path` must be a 4-byte big-endian encoding of an unsigned integer less than 231. If the `derivation_path` contains a byte string that is not a 4-byte big-endian encoding of an unsigned integer less than 231, then a derived public key will be returned, but that key derivation process will not be compatible with the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) standard.
The return result is an extended public key consisting of an ECDSA `public_key`, encoded in [SEC1](https://www.secg.org/sec1-v2.pdf) compressed form, and a `chain_code`, which can be used to deterministically derive child keys of the `public_key`.
-This call requires that the ECDSA feature is enabled, and the `canister_id` meets the requirement of a canister id. Otherwise it will be rejected.
-
### IC method `sign_with_ecdsa` {#ic-sign_with_ecdsa}
This method returns a new [ECDSA](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf) signature of the given `message_hash` that can be separately verified against a derived ECDSA public key. This public key can be obtained by calling `ecdsa_public_key` with the caller's `canister_id`, and the same `derivation_path` and `key_id` used here.
From 3f62116689942167744270a883542b468111f6da Mon Sep 17 00:00:00 2001
From: mraszyk <31483726+mraszyk@users.noreply.github.com>
Date: Fri, 28 Jul 2023 13:25:06 +0200
Subject: [PATCH 03/12] drop formal model in Isabelle/HOL (#206)
---
.github/workflows/isabelle.yml | 23 -
README.md | 20 -
theories/IC.thy | 3098 --------------------------------
theories/ROOT | 8 -
4 files changed, 3149 deletions(-)
delete mode 100644 .github/workflows/isabelle.yml
delete mode 100644 theories/IC.thy
delete mode 100644 theories/ROOT
diff --git a/.github/workflows/isabelle.yml b/.github/workflows/isabelle.yml
deleted file mode 100644
index 2b2a018d6..000000000
--- a/.github/workflows/isabelle.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Build on Ubuntu
-on:
- push:
- paths:
- - 'theories/**'
-
-jobs:
- isabelle:
- runs-on: ubuntu-latest
- steps:
- - name: Check out the repo
- uses: actions/checkout@v2
- - name: Run Isabelle with Docker
- uses: addnab/docker-run-action@v3
- with:
- image: martin2718/isabelle
- options: -v ${{ github.workspace }}:/interface-spec
- run: Isabelle/bin/isabelle build -e -v -D /interface-spec/theories/
- - name: Haskell Code
- uses: actions/upload-artifact@v2
- with:
- name: haskell-code
- path: ${{ github.workspace }}/theories/code
diff --git a/README.md b/README.md
index e8eeef12b..fdb11a137 100644
--- a/README.md
+++ b/README.md
@@ -31,26 +31,6 @@ The `master` branch contains finished designs, but is not directly scheduled
for implementation. It lists version version number `∞`. The reference
implementation on this branch typically does _not_ fully implement the spec. This branch should always be “ahead” of all the release branches.
-## Formal Model
-
-We are developing a formal model of Interface Spec in the interactive theorem prover [Isabelle/HOL](https://isabelle.in.tum.de/).
-The formal development is included in the directory `theories/`.
-
-To setup the environment, follow the standard [instructions](https://isabelle.in.tum.de/installation.html) for Isabelle/HOL.
-Additionally, you may want to setup `isabelle` as an alias for the path `bin/isabelle` in your local Isabelle directory.
-
-To browse the formal model, open Isabelle/jEdit:
-```
-isabelle jedit theories/IC.thy
-```
-from the root directory of this repository.
-
-To build the formal model and export Haskell code from the formal model, run
-```
-isabelle build -e -v -D theories/
-```
-in the root directory of this repository. The exported Haskell code can then be found under `theories/code/`.
-
## Contributing
This repository accepts external contributions, conditioned on acceptance of the [Contributor Lincense Agreement](https://github.com/dfinity/cla/).
diff --git a/theories/IC.thy b/theories/IC.thy
deleted file mode 100644
index f760e71e8..000000000
--- a/theories/IC.thy
+++ /dev/null
@@ -1,3098 +0,0 @@
-theory IC
- imports "HOL-Library.AList"
-begin
-
-(* General helper lemmas *)
-
-lemma in_set_updD: "x \ set (xs[n := z]) \ x \ set xs \ x = z"
- by (meson insert_iff set_update_subset_insert subsetD)
-
-(* Partial maps *)
-
-typedef ('a, 'b) list_map = "{f :: ('a \ 'b) list. distinct (map fst f)}"
- by (auto intro: exI[of _ "[]"])
-
-setup_lifting type_definition_list_map
-
-lift_bnf (dead 'k, set: 'v) list_map [wits: "[] :: ('k \ 'v) list"] for map: map rel: rel
- by auto
-
-hide_const (open) map set rel
-
-lift_definition list_map_dom :: "('a, 'b) list_map \ 'a set" is
- "set \ map fst" .
-
-lift_definition list_map_vals :: "('a, 'b) list_map \ 'b list" is
- "map snd" .
-
-lift_definition list_map_range :: "('a, 'b) list_map \ 'b set" is
- "set \ map snd" .
-
-lemma in_set_map_filter_vals: "z \ set (List.map_filter g (list_map_vals f)) \ \w \ list_map_range f. g w = Some z"
- by transfer (force simp: List.map_filter_def)
-
-lift_definition list_map_sum_vals :: "('b \ nat) \ ('a, 'b) list_map \ nat" is
- "\g. sum_list \ (map (g \ snd))" .
-
-lift_definition list_map_get :: "('a, 'b) list_map \ 'a \ 'b option" is
- "map_of" .
-
-lemma list_map_get_dom[dest]: "x \ list_map_dom f \ list_map_get f x = None \ False"
- by transfer auto
-
-lemma list_map_get_range: "list_map_get f x = Some y \ y \ list_map_range f"
- by transfer force
-
-lift_definition list_map_set :: "('a, 'b) list_map \ 'a \ 'b \ ('a, 'b) list_map" is
- "\f x y. AList.update x y f"
- by (rule distinct_update)
-
-lemma list_map_get_set: "list_map_get (list_map_set f x y) z = (if x = z then Some y else list_map_get f z)"
- by transfer (auto simp add: update_Some_unfold update_conv)
-
-lemma list_map_dom_set[simp]: "list_map_dom (list_map_set f x y) = list_map_dom f \ {x}"
- by transfer (auto simp add: dom_update)
-
-lemma list_map_range_setD: "z \ list_map_range (list_map_set f x y) \ z \ list_map_range f \ z = y"
- apply transfer
- apply auto
- apply (metis distinct_update image_iff map_of_eq_Some_iff snd_eqD update_Some_unfold)
- done
-
-lift_definition list_map_del :: "('a, 'b) list_map \ 'a \ ('a, 'b) list_map" is
- "\f x. AList.delete x f"
- by (rule distinct_delete)
-
-lemma list_map_get_del: "list_map_get (list_map_del f x) z = (if x = z then None else list_map_get f z)"
- by transfer (auto simp add: delete_conv')
-
-lemma list_map_dom_del[simp]: "list_map_dom (list_map_del f x) = list_map_dom f - {x}"
- by transfer (simp add: delete_keys)
-
-lemma list_map_range_del: "z \ list_map_range (list_map_del f x) \ z \ list_map_range f"
- apply transfer
- apply auto
- apply (metis Some_eq_map_of_iff delete_notin_dom distinct_delete fst_eqD imageI map_of_delete snd_eqD)
- done
-
-lift_definition list_map_empty :: "('a, 'b) list_map" is "[]"
- by auto
-
-lemma list_map_get_empty[simp]: "list_map_get list_map_empty x = None"
- by transfer auto
-
-lemma list_map_empty_dom[simp]: "list_map_dom list_map_empty = {}"
- by transfer auto
-
-lemma list_map_empty_range[simp]: "list_map_range list_map_empty = {}"
- by transfer auto
-
-lift_definition list_map_init :: "('a \ 'b) list \ ('a, 'b) list_map" is
- "\xys. AList.updates (map fst xys) (map snd xys) []"
- using distinct_updates
- by force
-
-lift_definition list_map_map :: "('b \ 'c) \ ('a, 'b) list_map \ ('a, 'c) list_map" is
- "\f xs. map (\(k, v). (k, f v)) xs"
- by (auto simp: comp_def case_prod_beta)
-
-lemma list_map_dom_map_map[simp]: "list_map_dom (list_map_map g f) = list_map_dom f"
- by transfer force
-
-lemma list_map_range_map_map[simp]: "list_map_range (list_map_map g f) = g ` list_map_range f"
- by transfer force
-
-lemma list_map_sum_vals_split: "(\ctxt. ctxt \ list_map_range xs \ f (g ctxt) \ f ctxt) \ list_map_sum_vals f xs =
- list_map_sum_vals id
- (list_map_map (\ctxt. if P ctxt then f ctxt - f (g ctxt) else 0) xs) +
- list_map_sum_vals f
- (list_map_map (\ctxt. if P ctxt then g ctxt else ctxt) xs)"
- apply (transfer fixing: f g P)
- subgoal for xs
- by (induction xs) auto
- done
-
-lemma list_map_sum_vals_filter:
- assumes "\b. b \ list_map_range xs \ P b = None \ f b = 0" "\b y. b \ list_map_range xs \ P b = Some y \ f b = g y"
- shows "list_map_sum_vals id (list_map_map f xs) = sum_list (map g (List.map_filter P (list_map_vals xs)))"
- using assms
- apply (transfer fixing: f g P)
- subgoal for xs
- by (induction xs) (auto simp: List.map_filter_def)
- done
-
-lemma list_map_sum_in_ge_aux:
- fixes g :: "'a \ nat"
- shows "distinct (map fst f) \ map_of f x = Some y \ g y \ sum_list (map g (map snd f))"
- by (induction f) (auto split: if_splits)
-
-lemma list_map_sum_in_ge: "list_map_get f x = Some y \ list_map_sum_vals g f \ g y"
- apply transfer
- using list_map_sum_in_ge_aux[OF _ map_of_is_SomeI]
- by fastforce
-
-lemma list_map_sum_in_aux: fixes g :: "'a \ nat"
- shows "distinct (map fst f) \ map_of f x = Some y \
- sum_list (map (g \ snd) (AList.update x y' f)) = sum_list (map (g \ snd) f) + g y' - g y"
- apply (induction f)
- apply auto[1]
- subgoal for a f
- using list_map_sum_in_ge_aux[OF _ map_of_is_SomeI, of f x y g]
- by auto
- done
-
-lemma list_map_sum_in: "list_map_get f x = Some y \ list_map_sum_vals g (list_map_set f x y') = list_map_sum_vals g f + g y' - g y"
- apply transfer
- using list_map_sum_in_aux
- by fastforce
-
-lemma list_map_sum_out_aux:
- "x \ set (map fst f) \ sum_list (map (g \ snd) (AList.update x y f)) = sum_list (map (g \ snd) f) + g y"
- by (induction f) (auto simp: add.assoc)
-
-lemma list_map_sum_out: "x \ list_map_dom f \ list_map_sum_vals g (list_map_set f x y) = list_map_sum_vals g f + g y"
- apply transfer
- using list_map_sum_out_aux
- by fastforce
-
-lemma list_map_del_sum_aux:
- fixes g :: "'a \ nat"
- shows "distinct (map fst f) \ map_of f x = Some y \ sum_list (map (g \ snd) f) = sum_list (map (g \ snd) (AList.delete x f)) + g y"
- by (induction f) auto
-
-lemma list_map_del_sum: "list_map_get f x = Some y \ list_map_sum_vals g f = list_map_sum_vals g (list_map_del f x) + g y"
- apply transfer
- using list_map_del_sum_aux
- by fastforce
-
-(* Abstract behaviour *)
-
-(* Abstract canisters *)
-
-type_synonym 's method_name = 's
-
-type_synonym 'b arg = 'b
-type_synonym 'p caller_id = 'p
-
-type_synonym timestamp = nat
-type_synonym canister_version = nat
-datatype status = Running | Stopping | Stopped
-record ('b) env =
- time :: timestamp
- global_timer :: nat
- balance :: nat
- freezing_limit :: nat
- certificate :: "'b option"
- status :: status
- canister_version :: canister_version
-
-type_synonym reject_code = nat
-datatype ('b, 's) response =
- Reply "'b"
-| Reject reject_code 's
-record ('p, 'canid, 's, 'b, 'c) method_call =
- callee :: 'canid
- method_name :: "'s method_name"
- arg :: 'b
- transferred_cycles :: nat
- callback :: 'c
-
-record 'x cycles_return =
- return :: 'x
- cycles_used :: nat
-record ('w, 'b) init_return =
- new_state :: 'w
- new_certified_data :: "'b option"
- new_global_timer :: "nat option"
- cycles_used :: nat
-record ('sm, 'b) pre_upgrade_return =
- stable_memory :: 'sm
- new_certified_data :: "'b option"
- cycles_used :: nat
-type_synonym trap_return = "unit cycles_return"
-record ('w, 'p, 'canid, 's, 'b, 'c) update_return =
- new_state :: 'w
- new_calls :: "('p, 'canid, 's, 'b, 'c) method_call list"
- new_certified_data :: "'b option"
- new_global_timer :: "nat option"
- response :: "('b, 's) response option"
- cycles_accepted :: nat
- cycles_used :: nat
-record ('b, 's) query_return =
- response :: "('b, 's) response"
- cycles_used :: nat
-record ('w, 'p, 'canid, 's, 'b, 'c) system_task_return =
- new_state :: 'w
- new_calls :: "('p, 'canid, 's, 'b, 'c) method_call list"
- new_certified_data :: "'b option"
- new_global_timer :: "nat option"
- cycles_used :: nat
-type_synonym ('w, 'p, 'canid, 's, 'b, 'c) update_func = "'w \ trap_return + ('w, 'p, 'canid, 's, 'b, 'c) update_return"
-type_synonym ('w, 'b, 's) query_func = "'w \ trap_return + ('b, 's) query_return"
-type_synonym ('w, 'p, 'canid, 's, 'b, 'c) system_task_func = "'w \ trap_return + ('w, 'p, 'canid, 's, 'b, 'c) system_task_return"
-
-type_synonym available_cycles = nat
-type_synonym refunded_cycles = nat
-
-datatype inspect_method_result = Accept | Reject
-record ('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module_rec =
- init :: "'canid \ 'b arg \ 'p caller_id \ 'b env \ trap_return + ('w, 'b) init_return"
- pre_upgrade :: "'w \ 'p \ 'b env \ trap_return + ('sm, 'b) pre_upgrade_return"
- post_upgrade :: "'canid \ 'sm \ 'b arg \ 'p caller_id \ 'b env \ trap_return + ('w, 'b) init_return"
- update_methods :: "('s method_name, ('b arg \ 'p caller_id \ 'b env \ available_cycles) \ ('w, 'p, 'canid, 's, 'b, 'c) update_func) list_map"
- query_methods :: "('s method_name, ('b arg \ 'p caller_id \ 'b env) \ ('w, 'b, 's) query_func) list_map"
- heartbeat :: "'b env \ ('w, 'p, 'canid, 's, 'b, 'c) system_task_func"
- global_timer :: "'b env \ ('w, 'p, 'canid, 's, 'b, 'c) system_task_func"
- callbacks :: "('c \ ('b, 's) response \ refunded_cycles \ 'b env \ available_cycles) \ ('w, 'p, 'canid, 's, 'b, 'c) update_func"
- inspect_message :: "('s method_name \ 'w \ 'b arg \ 'p caller_id \ 'b env) \ trap_return + inspect_method_result cycles_return"
-typedef ('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module =
- "{m :: ('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module_rec. list_map_dom (update_methods m) \ list_map_dom (query_methods m) = {}}"
- by (auto intro: exI[of _ "\init = undefined, pre_upgrade = undefined, post_upgrade = undefined,
- update_methods = list_map_empty, query_methods = list_map_empty, heartbeat = undefined, global_timer = undefined, callbacks = undefined,
- inspect_message = undefined\"])
-
-setup_lifting type_definition_canister_module
-
-lift_definition canister_module_init :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ 'canid \ 'b arg \ 'p \ 'b env \ trap_return + ('w, 'b) init_return" is "init" .
-lift_definition canister_module_pre_upgrade :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ 'w \ 'p \ 'b env \ trap_return + ('sm, 'b) pre_upgrade_return" is pre_upgrade .
-lift_definition canister_module_post_upgrade :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ 'canid \ 'sm \ 'b arg \ 'p \ 'b env \ trap_return + ('w, 'b) init_return" is post_upgrade .
-lift_definition canister_module_update_methods :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ ('s, ('b arg \ 'p \ 'b env \ available_cycles) \ ('w, 'p, 'canid, 's, 'b, 'c) update_func) list_map" is update_methods .
-lift_definition canister_module_query_methods :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ ('s, ('b arg \ 'p \ 'b env) \ ('w, 'b, 's) query_func) list_map" is query_methods .
-lift_definition canister_module_heartbeat :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ 'b env \ ('w, 'p, 'canid, 's, 'b, 'c) system_task_func" is heartbeat .
-lift_definition canister_module_global_timer :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ 'b env \ ('w, 'p, 'canid, 's, 'b, 'c) system_task_func" is global_timer .
-lift_definition canister_module_callbacks :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ ('c \ ('b, 's) response \ refunded_cycles \ 'b env \ available_cycles) \ ('w, 'p, 'canid, 's, 'b, 'c) update_func" is callbacks .
-lift_definition canister_module_inspect_message :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \ ('s \ 'w \ 'b arg \ 'p \ 'b env) \ trap_return + inspect_method_result cycles_return" is inspect_message .
-
-lift_definition dispatch_method :: "'s \ ('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module \
- ((('b arg \ 'p \ 'b env \ available_cycles) \ ('w, 'p, 'canid, 's, 'b, 'c) update_func) + (('b arg \ 'p \ 'b env) \ ('w, 'b, 's) query_func)) option" is
- "\f m. case list_map_get (update_methods m) f of Some f' \ Some (Inl f') | None \ (case list_map_get (query_methods m) f of Some f' \ Some (Inr f') | None \ None)" .
-
-(* Call contexts *)
-
-record ('b, 'p, 'uid, 'canid, 's) request =
- nonce :: 'b
- ingress_expiry :: nat
- sender :: 'uid
- canister_id :: 'canid
- method_name :: 's
- arg :: 'b
-datatype ('b, 'p, 'uid, 'canid, 's, 'c, 'cid) call_origin =
- From_user "('b, 'p, 'uid, 'canid, 's) request"
-| From_canister "'cid" "'c"
-| From_system
-record ('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt_rep =
- canister :: 'canid
- origin :: "('b, 'p, 'uid, 'canid, 's, 'c, 'cid) call_origin"
- needs_to_respond :: bool
- deleted :: bool
- available_cycles :: nat
-
-typedef ('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt = "{ctxt :: ('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt_rep.
- (deleted ctxt \ \needs_to_respond ctxt) \ (\needs_to_respond ctxt \ available_cycles ctxt = 0)}"
- by (auto intro: exI[of _ "\canister = undefined, origin = undefined, needs_to_respond = True, deleted = False, available_cycles = 0\"])
-
-setup_lifting type_definition_call_ctxt
-
-lift_definition call_ctxt_canister :: "('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt \ 'canid" is "canister" .
-lift_definition call_ctxt_origin :: "('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt \ ('b, 'p, 'uid, 'canid, 's, 'c, 'cid) call_origin" is "origin" .
-lift_definition call_ctxt_needs_to_respond :: "('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt \ bool" is needs_to_respond .
-lift_definition call_ctxt_deleted :: "('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt \ bool" is deleted .
-lift_definition call_ctxt_available_cycles :: "('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt \ nat" is available_cycles .
-
-lemma call_ctxt_not_needs_to_respond_available_cycles: "\call_ctxt_needs_to_respond x2 \ call_ctxt_available_cycles x2 = 0"
- by transfer auto
-
-lift_definition call_ctxt_respond :: "('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt \ ('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt" is
- "\ctxt. ctxt\needs_to_respond := False, available_cycles := 0\"
- by auto
-
-lemma call_ctxt_respond_canister[simp]: "call_ctxt_canister (call_ctxt_respond ctxt) = call_ctxt_canister ctxt"
- by transfer auto
-
-lemma call_ctxt_respond_origin[simp]: "call_ctxt_origin (call_ctxt_respond ctxt) = call_ctxt_origin ctxt"
- by transfer auto
-
-lemma call_ctxt_respond_needs_to_respond[dest]: "call_ctxt_needs_to_respond (call_ctxt_respond ctxt) \ False"
- by transfer auto
-
-lemma call_ctxt_respond_available_cycles[simp]: "call_ctxt_available_cycles (call_ctxt_respond ctxt) = 0"
- by transfer auto
-
-lift_definition call_ctxt_deduct_cycles :: "nat \ ('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt \ ('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt" is
- "\n ctxt. ctxt\available_cycles := available_cycles ctxt - n\"
- by auto
-
-lemma call_ctxt_deduct_cycles_canister[simp]: "call_ctxt_canister (call_ctxt_deduct_cycles n ctxt) = call_ctxt_canister ctxt"
- by transfer auto
-
-lemma call_ctxt_deduct_cycles_origin[simp]: "call_ctxt_origin (call_ctxt_deduct_cycles n ctxt) = call_ctxt_origin ctxt"
- by transfer auto
-
-lemma call_ctxt_deduct_cycles_needs_to_respond[simp]: "call_ctxt_needs_to_respond (call_ctxt_deduct_cycles n ctxt) = call_ctxt_needs_to_respond ctxt"
- by transfer auto
-
-lemma call_ctxt_deduct_cycles_available_cycles[simp]: "call_ctxt_available_cycles (call_ctxt_deduct_cycles n ctxt) = call_ctxt_available_cycles ctxt - n"
- by transfer auto
-
-lift_definition call_ctxt_delete :: "('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt \ ('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt" is
- "\ctxt. ctxt\deleted := True, needs_to_respond := False, available_cycles := 0\"
- by auto
-
-lemma call_ctxt_delete_canister[simp]: "call_ctxt_canister (call_ctxt_delete ctxt) = call_ctxt_canister ctxt"
- by transfer auto
-
-lemma call_ctxt_delete_needs_to_respond[simp]: "call_ctxt_needs_to_respond (call_ctxt_delete ctxt) = False"
- by transfer auto
-
-(* Calls and Messages *)
-
-datatype 'canid queue_origin = System | Canister 'canid
-datatype 'canid queue = Unordered | Queue "'canid queue_origin" 'canid
-datatype ('s, 'p, 'b, 'c) entry_point =
- Public_method "'s method_name" "'p" "'b"
-| Callback "'c" "('b, 's) response" "refunded_cycles"
-| Heartbeat
-| Global_timer
-
-datatype ('b, 'p, 'uid, 'canid, 's, 'c, 'cid) message =
- Call_message "('b, 'p, 'uid, 'canid, 's, 'c, 'cid) call_origin" 'p 'canid 's 'b nat "'canid queue"
-| Func_message 'cid 'canid "('s, 'p, 'b, 'c) entry_point" "'canid queue"
-| Response_message "('b, 'p, 'uid, 'canid, 's, 'c, 'cid) call_origin" "('b, 's) response" nat
-
-(* API requests *)
-
-type_synonym 'b path = "'b list"
-record ('b, 'uid) StateRead =
- nonce :: 'b
- ingress_expiry :: nat
- sender :: 'uid
- paths :: "'b path list"
-record ('b, 'uid, 'canid, 's) CanisterQuery =
- nonce :: 'b
- ingress_expiry :: nat
- sender :: 'uid
- canister_id :: 'canid
- method_name :: 's
- arg :: 'b
-type_synonym ('b, 'uid, 'canid, 's) APIReadRequest = "('b, 'uid) StateRead + ('b, 'uid, 'canid, 's) CanisterQuery"
-
-record ('p, 'canid, 'pk, 'sig) delegation =
- pubkey :: 'pk
- targets :: "'canid list option"
- senders :: "'p list option"
- expiration :: timestamp
-record ('p, 'canid, 'pk, 'sig) signed_delegation =
- delegation :: "('p, 'canid, 'pk, 'sig) delegation"
- signature :: "'sig"
-
-record ('b, 'p, 'uid, 'canid, 's, 'pk, 'sig) envelope =
- content :: "('b, 'p, 'uid, 'canid, 's) request + ('b, 'uid, 'canid, 's) APIReadRequest"
- sender_pubkey :: "'pk option"
- sender_sig :: "'sig option"
- sender_delegation :: "('p, 'canid, 'pk, 'sig) delegation list"
-
-datatype ('b, 's) request_status = Received | Processing | Rejected reject_code 's | Replied 'b | Done
-
-(* The system state *)
-
-record ('p, 'canid, 'b, 'w, 'sm, 'c, 's) can_state_rec =
- wasm_state :: 'w
- module :: "('p, 'canid, 'b, 'w, 'sm, 'c, 's) canister_module"
- raw_module :: 'b
- public_custom_sections :: "('s, 'b) list_map"
- private_custom_sections :: "('s, 'b) list_map"
-type_synonym ('p, 'canid, 'b, 'w, 'sm, 'c, 's) can_state = "('p, 'canid, 'b, 'w, 'sm, 'c, 's) can_state_rec option"
-datatype ('b, 'p, 'uid, 'canid, 's, 'c, 'cid) can_status = Running | Stopping "(('b, 'p, 'uid, 'canid, 's, 'c, 'cid) call_origin \ nat) list" | Stopped
-record ('p, 'uid, 'canid, 'b, 'w, 'sm, 'c, 's, 'cid, 'pk) ic =
- requests :: "(('b, 'p, 'uid, 'canid, 's) request, ('b, 's) request_status) list_map"
- canisters :: "('canid, ('p, 'canid, 'b, 'w, 'sm, 'c, 's) can_state) list_map"
- controllers :: "('canid, 'p set) list_map"
- freezing_threshold :: "('canid, nat) list_map"
- canister_status :: "('canid, ('b, 'p, 'uid, 'canid, 's, 'c, 'cid) can_status) list_map"
- canister_version :: "('canid, canister_version) list_map"
- time :: "('canid, timestamp) list_map"
- global_timer :: "('canid, nat) list_map"
- balances :: "('canid, nat) list_map"
- certified_data :: "('canid, 'b) list_map"
- system_time :: timestamp
- call_contexts :: "('cid, ('p, 'uid, 'canid, 'b, 's, 'c, 'cid) call_ctxt) list_map"
- messages :: "('b, 'p, 'uid, 'canid, 's, 'c, 'cid) message list"
- root_key :: 'pk
-
-fun simple_status :: "('b, 'p, 'uid, 'canid, 's, 'c, 'cid) can_status \ status" where
- "simple_status can_status.Running = status.Running"
-| "simple_status (can_status.Stopping _) = status.Stopping"
-| "simple_status can_status.Stopped = status.Stopped"
-
-(* Initial state *)
-
-definition initial_ic :: "nat \ 'pk \ ('p, 'uid, 'canid, 'b, 'w, 'sm, 'c, 's, 'cid, 'pk) ic" where
- "initial_ic t pk = \requests = list_map_empty,
- canisters = list_map_empty,
- controllers = list_map_empty,
- freezing_threshold = list_map_empty,
- canister_status = list_map_empty,
- canister_version = list_map_empty,
- time = list_map_empty,
- global_timer = list_map_empty,
- balances = list_map_empty,
- certified_data = list_map_empty,
- system_time = t,
- call_contexts = list_map_empty,
- messages = [],
- root_key = pk\"
-
-(* Invariants *)
-
-definition ic_can_status_inv :: "('b, 'p, 'uid, 'canid, 's, 'c, 'cid) can_status set \ 'cid set \ bool" where
- "ic_can_status_inv st c = (\can_status \ st.
- case can_status of Stopping os \ \(orig, cycles) \ set os. (case orig of
- From_canister ctxt_id _ \ ctxt_id \ c
- | _ \ True)
- | _ \ True)"
-
-lemma ic_can_status_inv_mono1: "ic_can_status_inv x y \
- z \ x \ {can_status.Running, can_status.Stopped} \
- ic_can_status_inv z y"
- by (fastforce simp: ic_can_status_inv_def split: can_status.splits call_origin.splits)
-
-lemma ic_can_status_inv_mono2: "ic_can_status_inv x y \
- y \ z \
- ic_can_status_inv x z"
- by (force simp: ic_can_status_inv_def split: can_status.splits call_origin.splits)
-
-lemma ic_can_status_inv_stopping: "ic_can_status_inv x y \
- (\ctxt_id c. os = From_canister ctxt_id c \ ctxt_id \ y) \
- z \ x \ {can_status.Stopping [(os, cyc)]} \
- ic_can_status_inv z y"
- by (fastforce simp: ic_can_status_inv_def split: can_status.splits call_origin.splits)
-
-lemma ic_can_status_inv_stopping_app: "ic_can_status_inv x y \
- can_status.Stopping w \ x \
- (\ctxt_id c. os = From_canister ctxt_id c \ ctxt_id \ y) \
- z \ x \ {can_status.Stopping (w @ [(os, cyc)])} \
- ic_can_status_inv z y"
- by (force simp: ic_can_status_inv_def split: can_status.splits call_origin.splits dest!: subsetD[where ?A=z])
-
-lemma ic_can_status_inv_del: "ic_can_status_inv x z \
- (\os other_ctxt_id c cyc. Stopping os \ x \