├── .gitignore
├── .gitmodules
├── Dockerfile
├── Jenkinsfile
├── LICENSE.md
├── README.md
├── casper
├── coq
│ ├── .gitignore
│ ├── Makefile
│ ├── README.md
│ ├── _CoqProject
│ └── theories
│ │ ├── AccountableSafety.v
│ │ ├── HashTree.v
│ │ ├── Justification.v
│ │ ├── NatExt.v
│ │ ├── PlausibleLiveness.v
│ │ ├── Quorums.v
│ │ ├── SetTheoryProps.v
│ │ ├── SlashableBound.v
│ │ ├── Slashing.v
│ │ ├── State.v
│ │ ├── StrongInductionLtn.v
│ │ ├── Validator.v
│ │ └── Weight.v
└── report
│ ├── .gitignore
│ ├── ACM-Reference-Format.bst
│ ├── acmart.cls
│ ├── bib.bib
│ ├── comment.cut
│ ├── lstcoq.sty
│ ├── report.pdf
│ └── report.tex
├── dynamic
├── Makefile
├── dynamic-abstract-beacon-chain-syntax.md
├── dynamic-abstract-beacon-chain.md
├── process-attestation-spec.k
├── process-block-spec.k
├── process-deposit-spec.k
├── process-epoch-spec.k
├── process-justification-finalization-spec.md
├── process-rewards-penalties-spec.k
├── process-slashing-spec.k
├── process-slots-spec.k
├── process-validator-activation-eligibility-spec.k
├── process-validator-activation-spec.k
├── process-validator-ejection-spec.k
├── process-validator-exit-spec.k
├── process-validator-updates-spec.k
├── tests
│ ├── concrete
│ │ ├── test1.abc
│ │ ├── test1.abc.expected
│ │ ├── test2.abc
│ │ ├── test2.abc.expected
│ │ ├── test3.abc
│ │ └── test3.abc.expected
│ ├── note.txt
│ ├── success.out
│ └── symbolic
│ │ ├── a-spec.k
│ │ ├── b-spec.k
│ │ ├── c-spec.k
│ │ ├── d-spec.k
│ │ ├── e-spec.k
│ │ ├── f-spec.k
│ │ ├── f2-spec.k
│ │ ├── finalization-cases.txt
│ │ ├── g-spec.k
│ │ ├── g2-spec.k
│ │ ├── h-spec.k
│ │ ├── i-spec.k
│ │ ├── j-spec.k
│ │ ├── k0-spec.k
│ │ ├── k1a-spec.k
│ │ ├── k1b-spec.k
│ │ ├── k2a-spec.k
│ │ ├── k2b-spec.k
│ │ ├── kn1-spec.k
│ │ ├── kn2-spec.k
│ │ ├── l.smt2
│ │ ├── l1-spec.k
│ │ ├── l2-spec.k
│ │ ├── l3-spec.k
│ │ ├── l4-spec.k
│ │ ├── l5-spec.k
│ │ ├── l6-spec.k
│ │ ├── m-spec.k
│ │ ├── m2-spec.k
│ │ ├── m3-spec.k
│ │ ├── n.smt2
│ │ ├── n1-spec.k
│ │ ├── n2-spec.k
│ │ ├── n3-spec.k
│ │ ├── n4-spec.k
│ │ ├── n5-spec.k
│ │ ├── n6-spec.k
│ │ ├── n7-spec.k
│ │ ├── n8-spec.k
│ │ ├── n9-spec.k
│ │ ├── o1-spec.k
│ │ ├── o2-spec.k
│ │ ├── p1-spec.k
│ │ ├── p2-spec.k
│ │ ├── process-finalization-spec.k
│ │ ├── process-justification-spec.k
│ │ ├── process-rewards-penalties-and-validator-updates-spec.k
│ │ ├── process-rewards-penalties-spec.k
│ │ ├── process-slots-base0-spec.k
│ │ ├── process-slots-base1-spec.k
│ │ ├── process-slots-inductive-spec.k
│ │ ├── q1-spec.k
│ │ ├── q2-spec.k
│ │ ├── q3-spec.k
│ │ ├── q4-spec.k
│ │ └── simple-spec.k
└── verification.k
├── fork-choice-rule
└── preliminary-analysis-fork-choice-rule.pdf
├── resources
├── Notes-on-justification-diagram.png
└── pdf-icon.png
└── weak-subjectivity
├── Makefile
├── after-n-epoch-balance-top-ups.pdf
├── after-n-epoch.pdf
├── balance-top-ups.pdf
├── discussion.tex
├── header.tex
├── intro.tex
├── llncs.cls
├── paper.tex
├── ref.bib
├── splncs04.bst
├── weak-subjectivity-analysis.pdf
└── ws-period.tex
/.gitignore:
--------------------------------------------------------------------------------
1 | /*/.build
2 | /dynamic/process-justification-finalization-lemma.k
3 | /dynamic/process-justification-finalization-spec.k
4 | /dynamic/tests/concrete/*.out
5 | /dynamic/*-spec.k.out
6 | .kompile*
7 | .kprove*
8 | .krun*
9 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "deps/pandoc-tangle"]
2 | path = deps/pandoc-tangle
3 | url = https://github.com/ehildenb/pandoc-tangle
4 | ignore = untracked
5 | [submodule "deps/k"]
6 | path = deps/k
7 | url = https://github.com/kframework/k.git
8 | ignore = untracked
9 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG K_COMMIT
2 | FROM runtimeverificationinc/kframework-k:ubuntu-bionic-${K_COMMIT}
3 |
4 | RUN apt-get update \
5 | && apt-get upgrade --yes \
6 | && apt-get install --yes \
7 | cmake \
8 | coq \
9 | pandoc \
10 | python3
11 |
12 | ARG USER_ID=1000
13 | ARG GROUP_ID=1000
14 | RUN groupadd -g $GROUP_ID user && useradd -m -u $USER_ID -s /bin/sh -g user user
15 |
16 | USER user:user
17 | WORKDIR /home/user
18 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | pipeline {
2 | options { ansiColor('xterm') }
3 | agent {
4 | dockerfile {
5 | label 'docker'
6 | additionalBuildArgs '--build-arg K_COMMIT=$(cd deps/k && git rev-parse --short=7 HEAD) --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)'
7 | }
8 | }
9 | stages {
10 | stage('Init title') {
11 | when { changeRequest() }
12 | steps { script { currentBuild.displayName = "PR ${env.CHANGE_ID}: ${env.CHANGE_TITLE}" } }
13 | }
14 | stage('Build and Test') {
15 | parallel {
16 | stage('Dynamic - K') {
17 | stages {
18 | stage('Build') { steps { sh 'cd dynamic && make build -j2' } }
19 | stage('Test') { steps { sh 'cd dynamic && make test -j4' } }
20 | }
21 | }
22 | //stage('Static - Coq') {
23 | // steps {
24 | // sh '''
25 | // cd casper/coq
26 | // make
27 | // '''
28 | // }
29 | //}
30 | }
31 | }
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Beacon Chain Verification Team. All Rights Reserved.
2 |
3 | Developed by:
4 |
5 | Runtime Verification, Inc.
6 |
7 | University of Illinois/NCSA
8 | Open Source License
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy of
11 | this software and associated documentation files (the "Software"), to deal with
12 | the Software without restriction, including without limitation the rights to
13 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14 | of the Software, and to permit persons to whom the Software is furnished to do
15 | so, subject to the following conditions:
16 |
17 | * Redistributions of source code must retain the above copyright notice,
18 | this list of conditions and the following disclaimers.
19 |
20 | * Redistributions in binary form must reproduce the above copyright notice,
21 | this list of conditions and the following disclaimers in the
22 | documentation and/or other materials provided with the distribution.
23 |
24 | * Neither the names of the Beacon Chain Verification Team,
25 | Runtime Verification, Inc., nor the names of
26 | its contributors may be used to endorse or promote products derived from
27 | this Software without specific prior written permission.
28 |
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
35 | SOFTWARE.
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Formal Verification of Beacon Chain Specification
2 |
3 | This repository consists of the following developments:
4 |
5 | 1. Mechanized proofs of key properties of finality in [the "Gasper" protocol](https://arxiv.org/abs/2003.03052):
6 | - Model and proofs (in Coq): [`casper/coq/`](casper/coq)
7 | - A technical report describing the model and the proofs: [`casper/report/`](casper/report)
8 |
9 | 2. _(ongoing)_ Mechanized proofs of the refinement soundness of [the state transition (Phase 0)](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md) w.r.t. the Gasper protocol:
10 | - Model (in K): [`dynamic/dynamic-abstract-beacon-chain.md`](dynamic/dynamic-abstract-beacon-chain.md)
11 | - Proofs (in K): `*-spec.k` files in [`dynamic/`](dynamic)
12 |
13 | 3. Analysis on the weak subjectivity period for Ethereum 2.0:
14 | - Report: [[PDF](weak-subjectivity/weak-subjectivity-analysis.pdf)] [[Source](weak-subjectivity)]
15 |
16 | 4. Preliminary analysis on the fork choice rule for the Beacon chain:
17 | - Report: [[PDF](fork-choice-rule/preliminary-analysis-fork-choice-rule.pdf)] [[Source](https://docs.google.com/document/d/1xiSWfuqssGatVSzYobPhPR-BxgW9Q_5rydyfQvWJW-U/)]
18 |
--------------------------------------------------------------------------------
/casper/coq/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | .*.aux
3 | *.a
4 | *.cma
5 | *.cmi
6 | *.cmo
7 | *.cmx
8 | *.cmxa
9 | *.cmxs
10 | *.glob
11 | *.d
12 | *.native
13 | *.o
14 | *.vio
15 | *.vo
16 | *.vos
17 | *.vok
18 | build/
19 | .coq-native/
20 | .csdp.cache
21 | .lia.cache
22 | .nia.cache
23 | .nlia.cache
24 | .nra.cache
25 | csdp.cache
26 | lia.cache
27 | nia.cache
28 | nlia.cache
29 | nra.cache
30 | Makefile.coq
31 | Makefile.coq.conf
32 | **\#*
--------------------------------------------------------------------------------
/casper/coq/Makefile:
--------------------------------------------------------------------------------
1 | all: default
2 |
3 | default: Makefile.coq
4 | $(MAKE) -f Makefile.coq
5 |
6 | quick: Makefile.coq
7 | $(MAKE) -f Makefile.coq quick
8 |
9 | clean: Makefile.coq
10 | $(MAKE) -f Makefile.coq cleanall
11 | rm -f Makefile.coq Makefile.coq.conf
12 |
13 | Makefile.coq: _CoqProject
14 | coq_makefile -f _CoqProject -o Makefile.coq
15 |
16 | .PHONY: all default quick clean
--------------------------------------------------------------------------------
/casper/coq/README.md:
--------------------------------------------------------------------------------
1 | # Modeling and Verifying Gasper in Coq
2 |
3 | This part of the repository gives a formalization in Coq of finality in Gasper, an abstraction of the Beacon Chain specification described [here](https://arxiv.org/abs/2003.03052). Gasper's finality generalizes [Casper FFG](https://arxiv.org/abs/1710.09437). With this formalization, we mechanize proofs of three main results of Gasper:
4 |
5 | - **Accountable safety:** No two conflicting blocks are finalized without having at least 1/3 of validator deposits slashed.
6 |
7 | - **Plausible liveness:** Assuming that at least 2/3 of validators (by deposit) follow the protocol, it is always possible to continue to finalize new blocks irrespective of what has happened before.
8 |
9 | - **Slashable bound:** Even when the set of active validators is dynamic, a lower bound (given in terms of validator activation and exit policies) on what stake worth of validators is provably slashable can be guaranteed.
10 |
11 | This development is based on previously developed models and proofs of Casper in Coq [here](https://github.com/runtimeverification/casper-proofs). It extends that work in four significant ways:
12 |
13 | - Unifying the two distinct models built sepearately for safey and liveness, and proving both properties in the same unified model.
14 |
15 | - Generalizing the definition of finalization to k-finalization (as defined in the [Gasper protocol](https://arxiv.org/abs/2003.03052)), along with the accountable safety proof.
16 |
17 | - Generalizing the model and proofs to dynamic validator sets, and
18 |
19 | - Modeling validator set weights and proving the slashable bound theorem.
20 |
21 | A more detailed explanation of the models and proofs can be found in the technical report:
22 |
23 |
*[Verifying Gasper with Dynamic Validator Sets in Coq](../report/report.pdf)*
24 |
25 | ## Model Layout
26 |
27 | ### Utility files
28 |
29 | - [NatExt.v](theories/NatExt.v): some additional properties of natural numbers
30 | - [SetTheoryProps.v](theories/SetTheoryProps.v): some additional set-theoretic properties
31 | - [StrongInductionLtn.v](theories/StrongInductionLtn.v): some strong induction principles on natural numbers, adapted from work by Tej Chajed
32 |
33 | ### Casper abstract model
34 |
35 | These files define an abstract view of Casper's validators, blocks and votes, and specify its justification and finalization mechanisms.
36 |
37 | - [Validator.v](theories/Validator.v): validators and their stake
38 | - [Weight.v](theories/Weight.v): weights of validator sets and their properties
39 | - [HashTree.v](theories/HashTree.v): the checkpoint block trees and their properties
40 | - [State.v](theories/State.v): the state as a set of votes cast
41 | - [Slashing.v](theories/Slashing.v): the slashing conditions
42 | - [Quorums.v](theories/Quorums.v): Quorum predicates and properties
43 | - [Justification.v](theories/Justification.v): justification and finalization definitions and their properties
44 |
45 |
46 | ### Casper properties
47 |
48 | These files contain the major theorems about Casper.
49 |
50 | - [AccountableSafety.v](theories/AccountableSafety.v): Proof of the Accountable Safety theorem
51 | - [PlausibleLiveness.v](theories/PlausibleLiveness.v): Proof of the Plausible Liveness theorem
52 | - [SlashableBound.v](theories/SlashableBound.v): Proof of the Slashable Bound theorem
53 |
54 | ## Requirements
55 |
56 | * [Coq 8.9 or 8.10](https://coq.inria.fr)
57 | * [Mathematical Components 1.8 or 1.9](http://math-comp.github.io/math-comp/) (`ssreflect`)
58 | * [CoqHammer 1.0.9](https://github.com/lukaszcz/coqhammer)
59 | * [finmap](https://github.com/math-comp/finmap)
60 |
61 | ## Building
62 |
63 | We recommend installing dependencies via [OPAM](http://opam.ocaml.org/doc/Install.html):
64 |
65 | ```
66 | opam repo add coq-released https://coq.inria.fr/opam/released
67 | opam install coq coq-mathcomp-ssreflect coq-hammer coq-mathcomp-finmap
68 | ```
69 |
70 | Then, run `make` in the directory of this README to check all definitions and proofs.
71 |
72 | ## Getting Help
73 |
74 | Feel free to report GitHub issues here or to contact us at: [contact@runtimeverification.com](contact@runtimeverification.com).
75 |
--------------------------------------------------------------------------------
/casper/coq/_CoqProject:
--------------------------------------------------------------------------------
1 | -Q theories Casper
2 |
3 | theories/NatExt.v
4 | theories/StrongInductionLtn.v
5 | theories/SetTheoryProps.v
6 | theories/Validator.v
7 | theories/Weight.v
8 | theories/HashTree.v
9 | theories/State.v
10 | theories/Slashing.v
11 | theories/Quorums.v
12 | theories/Justification.v
13 | theories/AccountableSafety.v
14 | theories/PlausibleLiveness.v
15 | theories/SlashableBound.v
16 |
--------------------------------------------------------------------------------
/casper/coq/theories/HashTree.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp.ssreflect
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | Set Implicit Arguments.
7 | Unset Strict Implicit.
8 | Unset Printing Implicit Defensive.
9 |
10 | (******************************************************************************)
11 | (* A representation of block (hash) trees and related properties *)
12 | (* Note: We consider the checkpoint tree of blocks, and so a "block" refers *)
13 | (* to a "checkpoint block" throughout the specs below. *)
14 | (******************************************************************************)
15 |
16 | (* We assume finite hash values (block identifiers) *)
17 | Parameter Hash : finType.
18 |
19 | (* This relation links blocks (b,b'), written b <~ b', if b is the parent *)
20 | (* of b' in the block tree *)
21 | Parameter hash_parent : rel Hash.
22 |
23 | Notation "h1 <~ h2" := (hash_parent h1 h2) (at level 50).
24 |
25 | (* A block cannot be a parent of itself *)
26 | Axiom hash_parent_irreflexive:
27 | forall h1 h2, h1 <~ h2 -> h1 <> h2.
28 |
29 | (* A block cannot have two distinct parent blocks *)
30 | Axiom hash_at_most_one_parent :
31 | forall h1 h2 h3, h2 <~ h1 -> h3 <~ h1 -> h2 = h3.
32 |
33 | (* The ancestor reltion `<~*`: the reflexive-transitive closure of `<~` *)
34 | Definition hash_ancestor h1 h2 := connect hash_parent h1 h2.
35 |
36 | Notation "h1 <~* h2" := (hash_ancestor h1 h2) (at level 50).
37 |
38 | Notation "h1 ~* h2" := (~ hash_ancestor h1 h2) (at level 50).
39 |
40 | (* The genesis block *)
41 | Parameter genesis : Hash.
42 |
43 | (* We will need to use several properties of ancestry inherited from the *)
44 | (* reflexive-transitive closure operation "connect". We define these *)
45 | (* lemmas rather than unfolding the hash_ancestor definition inside *)
46 | (* other proofs. *)
47 |
48 | (* A block is an ancestor of itself *)
49 | Lemma hash_self_ancestor :
50 | forall h, h <~* h.
51 | Proof.
52 | by apply/connect0.
53 | Qed.
54 |
55 | (* A parent block is a proper ancestor block *)
56 | Lemma hash_parent_ancestor :
57 | forall h1 h2,
58 | h1 <~ h2 -> h1 <~* h2 /\ h1 <> h2.
59 | Proof.
60 | split.
61 | by apply/connect1.
62 | by apply/hash_parent_irreflexive.
63 | Qed.
64 |
65 | (* A parent of an ancestor is an ancestor *)
66 | Lemma hash_ancestor_stepL :
67 | forall h1 h2 h3,
68 | h1 <~ h2 -> h2 <~* h3 -> h1 <~* h3.
69 | Proof.
70 | move => h1 h2 h3.
71 | move/connect1.
72 | by apply/connect_trans.
73 | Qed.
74 |
75 | (* An ancestor of a parent is an ancestor *)
76 | Lemma hash_ancestor_stepR :
77 | forall h1 h2 h3,
78 | h1 <~* h2 -> h2 <~ h3 -> h1 <~* h3.
79 | Proof.
80 | move => h1 h2 h3 H1 H2.
81 | apply: connect_trans; eauto.
82 | by apply/connect1.
83 | Qed.
84 |
85 | (* An ancestor of an ancestor is an ancestor *)
86 | Lemma hash_ancestor_concat :
87 | forall h1 h2 h3,
88 | h1 <~* h2 -> h2 <~* h3 -> h1 <~* h3.
89 | Proof.
90 | move => h1 h2 h3 H2 H1.
91 | by apply: connect_trans; eauto.
92 | Qed.
93 |
94 | (* A block can never conflict with itself *)
95 | Lemma hash_nonancestor_nonequal:
96 | forall h1 h2,
97 | h1 ~* h2 -> h1 <> h2.
98 | Proof.
99 | intros h1 h2 Hna.
100 | contradict Hna.
101 | replace h1 with h2.
102 | apply hash_self_ancestor.
103 | Qed.
104 |
105 | (* A conflicting block cannot belong to the ancestry of that block *)
106 | Lemma hash_ancestor_conflict:
107 | forall h1 h2 p,
108 | h1 <~* h2 -> p ~* h2 -> p ~* h1.
109 | Proof.
110 | move => h1 h2 p H1 H2 Hp.
111 | destruct H2.
112 | move: Hp H1.
113 | by apply/connect_trans.
114 | Qed.
115 |
116 | (* This definition of ancestry makes the exact number of steps explicit *)
117 | Inductive nth_ancestor : nat -> Hash -> Hash -> Prop :=
118 | | nth_ancestor_0 : forall h1, nth_ancestor 0 h1 h1
119 | | nth_ancestor_nth : forall n h1 h2 h3,
120 | nth_ancestor n h1 h2 -> h2 <~ h3 ->
121 | nth_ancestor n.+1 h1 h3.
122 |
123 | (* The nth_ancestor is an ancestor *)
124 | Lemma nth_ancestor_ancestor :
125 | forall n s t,
126 | nth_ancestor n s t -> (s <~* t).
127 | Proof.
128 | induction 1.
129 | apply connect0.
130 | apply connect_trans with h2;[|apply connect1];assumption.
131 | Qed.
132 |
133 | (* nth_ancestor_0 must be with oneself *)
134 | Lemma nth_ancestor_0_refl :
135 | forall h1 h2,
136 | nth_ancestor 0 h1 h2 ->
137 | h1 = h2.
138 | Proof.
139 | intros h1 h2 H_an.
140 | inversion H_an; subst. reflexivity.
141 | Qed.
142 |
143 | (* a parent is a first-level ancestor *)
144 | Example parent_ancestor : forall h1 h2,
145 | h1 <~ h2 <-> nth_ancestor 1 h1 h2.
146 | Proof.
147 | move => h1 h2; split; move => Hp.
148 | apply: nth_ancestor_nth; eauto.
149 | exact: nth_ancestor_0.
150 | inversion Hp; subst.
151 | apply nth_ancestor_0_refl in H0.
152 | subst. assumption.
153 | Qed.
154 |
--------------------------------------------------------------------------------
/casper/coq/theories/NatExt.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp.ssreflect
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | From mathcomp.finmap
7 | Require Import finmap.
8 |
9 | Set Implicit Arguments.
10 | Unset Strict Implicit.
11 | Unset Printing Implicit Defensive.
12 |
13 | (******************************************************************************)
14 | (* Some basic extentions/properties of nats needed in the rest of the specs. *)
15 | (******************************************************************************)
16 |
17 | (* The `highest' value in a finite set of nats *)
18 | Definition highest (A : {fset nat}) : nat :=
19 | \max_(i : A) (val i).
20 |
21 | (* The `highest' is the maximum value *)
22 | Lemma highest_ub:
23 | forall (A : {fset nat}) (x:nat), x \in A -> x <= highest A.
24 | Proof.
25 | move => A x Hx.
26 | case (insubP [subType of A] x) => /=; last by move: Hx =>->.
27 | move => k Hk =><-.
28 | exact: leq_bigmax_cond.
29 | Qed.
30 |
31 | (* The successor cannot be smaller *)
32 | Lemma ltSnn n: (n.+1 < n) = false.
33 | Proof.
34 | by apply/negP/negP; rewrite leqNgt; apply/negP; case/negP.
35 | Qed.
36 |
37 | (* Basic fact about nats *)
38 | Lemma leq_one_means_zero_or_one : forall n,
39 | n <= 1 -> n = 0 \/ n = 1.
40 | Proof.
41 | intros n H_leq.
42 | induction n. left; reflexivity.
43 | intuition. destruct IHn. by apply ltnW.
44 | subst. right. easy. subst. inversion H_leq.
45 | Qed.
46 |
47 | (* Basic subtraction fact *)
48 | Lemma sub_eq n : n - n = 0.
49 | Proof. by elim: n => [|n IHn]. Qed.
50 |
51 | (* Conditional associativity of add-sub *)
52 | Lemma addnDAr n m p :
53 | m >= p -> (n + m) - p = n + (m - p).
54 | Proof.
55 | elim: n m => [|n IHn] [|m IHm];trivial.
56 | rewrite leqn0.
57 | by move/eqP => Hp;subst.
58 | apply IHn in IHm as IH.
59 | rewrite [in RHS]addSnnS -[in RHS]addn1 [in RHS]addnA.
60 | rewrite -IH.
61 | rewrite addSn. rewrite [in LHS]subSn. by rewrite [in RHS]addn1.
62 | apply (leq_trans IHm). clear.
63 | elim: m => [|m IHm]. rewrite addn1. apply ltn0Sn.
64 | by rewrite -addn1 addnA leq_add2r.
65 | Qed.
66 |
67 | (* Two uninterpreted functions are introduced to represent quantities that will be *)
68 | (* used in the statement of the slashsable bound theorem. These are not strictly *)
69 | (* necessary, but they enable using statements and proof arguments that are closer *)
70 | (* to the paper. *)
71 | Parameter one_third : nat -> nat.
72 | Parameter two_third : nat -> nat.
73 |
74 | (* Basic axioms assumed to hold for these function symbols *)
75 | Axiom thirds_def : forall n, n - two_third n = one_third n.
76 | Axiom leq_two_thirds : forall n, two_third n <= n.
77 |
78 | (* This property follows from leq_two_thirds above *)
79 | Lemma wt_two_thirds_sum : forall n m,
80 | two_third n + two_third m <= n + m.
81 | Proof.
82 | by move => n m; apply: (leq_add (leq_two_thirds n) (leq_two_thirds m)).
83 | Qed.
84 |
85 |
--------------------------------------------------------------------------------
/casper/coq/theories/Quorums.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp.ssreflect
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | From mathcomp.finmap
7 | Require Import finmap.
8 |
9 | From Casper
10 | Require Import NatExt.
11 |
12 | From Casper
13 | Require Import Validator Weight HashTree State Slashing.
14 |
15 | Set Implicit Arguments.
16 | Unset Strict Implicit.
17 | Unset Printing Implicit Defensive.
18 |
19 | Open Scope fmap_scope.
20 | Open Scope big_scope.
21 |
22 | (******************************************************************************)
23 | (* Validator sets, quorums and quorum properties *)
24 | (******************************************************************************)
25 |
26 |
27 | (* A finite map vset defining the set of validators for a given block *)
28 | Parameter vset : {fmap Hash -> {set Validator}}.
29 |
30 | (* We assume the map vset is total *)
31 | Axiom vs_fun : forall h : Hash, h \in vset.
32 |
33 | (** Quorum Predicates **)
34 | (* A predicate for an "at least 1/3 weight" set of validators *)
35 | Definition quorum_1 (vs : {set Validator}) (b : Hash) : bool :=
36 | (vs \subset vset.[vs_fun b]) &&
37 | (wt vs >= one_third (wt vset.[vs_fun b])).
38 |
39 | (* A predicate for an "at least 2/3 weight" set of validators *)
40 | Definition quorum_2 (vs : {set Validator}) (b : Hash) : bool :=
41 | (vs \subset vset.[vs_fun b]) &&
42 | (wt vs >= two_third (wt vset.[vs_fun b])).
43 |
44 | (* Meaning of a validator set being slashed in the general context of *)
45 | (* dynamic validator sets *)
46 | Definition q_intersection_slashed st :=
47 | exists (bL bR: Hash) (vL vR: {set Validator}),
48 | vL \subset vset.[vs_fun bL] /\
49 | vR \subset vset.[vs_fun bR] /\
50 | quorum_2 vL bL /\
51 | quorum_2 vR bR /\
52 | forall v, v \in vL -> v \in vR -> slashed st v.
53 |
54 | (* The assumption on quorums that a supermajority quorum with respect to a *)
55 | (* block is nonempty (Needed for liveness) *)
56 | Axiom quorum_2_nonempty:
57 | forall (b:Hash) (q :{set Validator}),
58 | quorum_2 q b -> exists v, v \in q.
59 |
60 | (* The property that, with respect to a block b, adding more b-validators *)
61 | (* to a supermajority leaves a supermajority (Needed for liveness) *)
62 | Lemma quorum_2_upclosed:
63 | forall (b:Hash) (q q':{set Validator}),
64 | q \subset q' -> q' \subset vset.[vs_fun b] -> quorum_2 q b ->
65 | quorum_2 q' b.
66 | Proof.
67 | move=> b q q' Hqsubq' Hq'.
68 | rewrite /quorum_2.
69 | move/andP=> [Hq Hqwt].
70 | apply/andP;split. exact Hq'.
71 | apply wt_inc_leq in Hqsubq'.
72 | by apply (leq_trans Hqwt Hqsubq').
73 | Qed.
74 |
75 |
76 |
--------------------------------------------------------------------------------
/casper/coq/theories/SetTheoryProps.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp.ssreflect
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | Set Implicit Arguments.
7 | Unset Strict Implicit.
8 | Unset Printing Implicit Defensive.
9 |
10 | (******************************************************************************)
11 | (* Various set-theoretic properties that are used in the rest of the specs. *)
12 | (******************************************************************************)
13 |
14 |
15 | Lemma setID_disjoint {T : finType} (A B:{set T}):
16 | [disjoint (A :&: B) & (A :\: B)].
17 | Proof.
18 | rewrite -setI_eq0 eqEsubset.
19 | apply/andP;split;apply/subsetP => x;last by rewrite in_set0.
20 | move/setIP=> [H1 H2].
21 | move/setIP: H1 => [_ H1].
22 | move/setDP: H2 => [_ H2].
23 | move/negP: H2 => H2.
24 | by contradiction.
25 | Qed.
26 |
27 | Lemma setDD_disjoint {T : finType} (A B:{set T}):
28 | [disjoint (A :\: B) & (B :\: A)].
29 | Proof.
30 | rewrite -setI_eq0 eqEsubset.
31 | apply/andP;split;apply/subsetP => x;last by rewrite in_set0.
32 | move/setIP=> [H1 H2].
33 | move/setDP: H1 => [H1a H1b].
34 | move/setDP: H2 => [H2a H2b].
35 | move/negP: H2b => H2b.
36 | by contradiction.
37 | Qed.
38 |
39 | Lemma setDDI_disjoint {T : finType} (A B:{set T}):
40 | [disjoint A :\: B :|: B :\: A & A :&: B].
41 | Proof.
42 | rewrite -setI_eq0 eqEsubset.
43 | apply/andP;split;apply/subsetP => x;last by rewrite in_set0.
44 | move/setIP=> [H1 H2].
45 | move/setIP: H2 => [Hin1 Hin2].
46 | case/setUP: H1 => H;move/setDP: H => [_ Hnotin2];
47 | move/negP: Hnotin2 => Hnotin2;contradiction.
48 | Qed.
49 |
50 | Lemma setU_par {T : finType} (A B:{set T}):
51 | A :|: B = (A :\: B) :|: (B :\: A) :|: (A :&: B).
52 | Proof.
53 | apply/eqP.
54 | rewrite eqEsubset.
55 | apply/andP;split;apply/subsetP => x.
56 | case/setUP=> H.
57 | - rewrite -setUA setUC -setUA.
58 | apply/setUP;right.
59 | by rewrite setUC -setDDr setDv setD0.
60 | - rewrite -setUA.
61 | apply/setUP;right.
62 | by rewrite setIC -setDDr setDv setD0.
63 | case/setUP=> H.
64 | - case/setUP: H => H.
65 | * move/setDP: H => [H _].
66 | by apply/setUP;left.
67 | * move/setDP: H => [H _].
68 | by apply/setUP;right.
69 | - move/setIP: H => [H _].
70 | by apply/setUP;left.
71 | Qed.
72 |
73 | Lemma setIs_disjoint {T : finType} (A B C: {set T}):
74 | [disjoint A & B] -> [disjoint A & B :&: C].
75 | Proof.
76 | move/setDidPl=> <-.
77 | rewrite -setI_eq0 eqEsubset.
78 | apply/andP;split;apply/subsetP => x;last by rewrite in_set0.
79 | move/setIP=> [H1 H2].
80 | move/setDP: H1 => [_ H1].
81 | move/setIP: H2 => [H2 _].
82 | by move/negP: H1 => H1.
83 | Qed.
84 |
85 | Lemma setIID_disjoint {T : finType} (A B C: {set T}):
86 | [disjoint (A :&: B) & (A :&: C :\: B)].
87 | Proof.
88 | rewrite setDIl.
89 | apply: setIs_disjoint.
90 | apply: setID_disjoint.
91 | Qed.
92 |
93 | Lemma setIIDD_disjoint {T : finType} (A B C D: {set T}):
94 | [disjoint A :&: B :|: A :&: C :\: B & B :&: D :\: A].
95 | Proof.
96 | rewrite -setI_eq0 eqEsubset.
97 | apply/andP;split;apply/subsetP => x;last by rewrite in_set0.
98 | move/setIP=> [H1 H2].
99 | move/setUP: H1 => H1.
100 | move/setDP: H2 => [H2a H2b].
101 | case: H1.
102 | - move/setIP=> [H _]. by move/negP: H2b.
103 | - move/setDP=> [H _]. move/setIP: H => [H _]. by move/negP: H2b.
104 | Qed.
105 |
106 | Lemma setIIDD_subset {T : finType} (A B C D: {set T}):
107 | A \subset C ->
108 | B \subset D ->
109 | A :&: B :|: A :&: D :\: B :|: B :&: C :\: A \subset C :&: D.
110 | Proof.
111 | move=> Ha Hb.
112 | move/subsetP:Ha => Ha.
113 | move/subsetP:Hb => Hb.
114 | apply/subsetP => x.
115 | case/setUP=> H.
116 | apply/setIP.
117 | - case/setUP: H => H.
118 | * move/setIP: H => [Hxa Hxb].
119 | by (apply Ha in Hxa;apply Hb in Hxb).
120 | * move/setDP: H => [Hxad _]. move/setIP: Hxad => [Hxa Hxd].
121 | by (apply Ha in Hxa).
122 | - move/setDP: H => [Hxbc _]. move/setIP: Hxbc => [Hxb Hxc].
123 | apply Hb in Hxb. by apply/setIP.
124 | Qed.
125 |
126 | Lemma setID2_disjoint {T : finType} (A B C:{set T}):
127 | [disjoint (A :&: C) & (B :\: C)].
128 | Proof.
129 | rewrite -setI_eq0 eqEsubset.
130 | apply/andP;split;apply/subsetP => x;last by rewrite in_set0.
131 | move/setIP=> [H1 H2].
132 | move/setIP: H1 => [_ H1].
133 | move/setDP: H2 => [_ H2].
134 | by move/negP: H2 => H2.
135 | Qed.
136 |
137 | Lemma setID2_subset {T : finType} (A B C:{set T}):
138 | A \subset B ->
139 | A \subset (A :&: C) :|: (B :\: C).
140 | Proof.
141 | move/subsetP => H.
142 | apply/subsetP => x.
143 | move=> Hs0.
144 | apply/setUP.
145 | have : (x \in C) || ~~(x \in C) by apply orbN.
146 | case/orP=> H'.
147 | - left. by apply/setIP.
148 | - right. apply H in Hs0. by apply/setDP.
149 | Qed.
150 |
151 | Lemma set3D_disjoint {T : finType} (A B C:{set T}):
152 | [disjoint C :\: B & A :\: C].
153 | Proof.
154 | rewrite -setI_eq0 eqEsubset.
155 | apply/andP;split;apply/subsetP => x;last by rewrite in_set0.
156 | move/setIP=> [H1 H2].
157 | move/setDP: H1 => [H1a H1b].
158 | move/setDP: H2 => [H2a H2b].
159 | move/negP: H2b => H2b.
160 | by contradiction.
161 | Qed.
162 |
163 | Lemma set3D_subset {T : finType} (A B C:{set T}):
164 | A :\: B \subset C :\: B :|: A :\: C.
165 | Proof.
166 | apply/subsetP => x.
167 | move/setDP=> [H1 H2].
168 | apply/setUP.
169 | have : (x \in C) || ~~(x \in C) by apply orbN.
170 | case/orP=> H.
171 | - left. by apply/setDP;split.
172 | - right. by apply/setDP;split.
173 | Qed.
174 |
175 |
--------------------------------------------------------------------------------
/casper/coq/theories/Slashing.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp.ssreflect
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | From mathcomp.finmap
7 | Require Import finmap.
8 |
9 | From Casper
10 | Require Import Validator HashTree State.
11 |
12 | Set Implicit Arguments.
13 | Unset Strict Implicit.
14 | Unset Printing Implicit Defensive.
15 |
16 | (******************************************************************************)
17 | (* Definitions of the slashing conditions *)
18 | (******************************************************************************)
19 |
20 | (* A validator may not make two votes with different target hashes at the *)
21 | (* same target height (whatever the source blocks) *)
22 | Definition slashed_double_vote st v :=
23 | exists t1 t2, t1 <> t2 /\ exists s1 s1_h s2 s2_h t_h,
24 | vote_msg st v s1 t1 s1_h t_h /\ vote_msg st v s2 t2 s2_h t_h.
25 |
26 | (* A validator may not make two votes with the source and target of one *)
27 | (* vote both strictly between the source and target of the other *)
28 | Definition slashed_surround_vote st v :=
29 | exists s1 t1 s1_h t1_h,
30 | exists s2 t2 s2_h t2_h,
31 | vote_msg st v s1 t1 s1_h t1_h /\
32 | vote_msg st v s2 t2 s2_h t2_h /\
33 | s2_h > s1_h /\ t2_h < t1_h.
34 |
35 | (* A slashed validator is one that has double-voted or surround-voted *)
36 | Definition slashed st v : Prop :=
37 | slashed_double_vote st v \/ slashed_surround_vote st v.
38 |
--------------------------------------------------------------------------------
/casper/coq/theories/State.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp.ssreflect
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | From mathcomp.finmap
7 | Require Import finmap.
8 |
9 | From Casper
10 | Require Import Validator HashTree.
11 |
12 | Set Implicit Arguments.
13 | Unset Strict Implicit.
14 | Unset Printing Implicit Defensive.
15 |
16 | (******************************************************************************)
17 | (* A representation of state as a set of votes cast. *)
18 | (* *)
19 | (* Each vote names source and target nodes by giving hash and height, and is *)
20 | (* signed by a particular validator. This is taken directly from the way *)
21 | (* votes are expressed in the original Casper paper. *)
22 | (******************************************************************************)
23 |
24 | (* A vote is a tuple: *)
25 | (* (attestor, source, target, source height, target height) *)
26 | (* *)
27 | Definition Vote := (Validator * Hash * Hash * nat * nat)%type.
28 |
29 | (* A State is described by the finite set of votes cast. *)
30 | Definition State := {fset Vote}.
31 |
32 | (* A boolean vote_msg predicate that tells us whether a vote belongs to *)
33 | (* the state *)
34 | Definition vote_msg (st:State) v s t (s_h t_h:nat) : bool :=
35 | (v,s,t,s_h,t_h) \in st .
36 |
37 | (* Vote projection operations *)
38 | Definition vote_val (v:Vote) : Validator :=
39 | match v with
40 | (x,_,_,_,_) => x
41 | end.
42 |
43 | Definition vote_source (v:Vote) : Hash :=
44 | match v with
45 | (_,s,_,_,_) => s
46 | end.
47 |
48 | Definition vote_target (v:Vote) : Hash :=
49 | match v with
50 | (_,_,t,_,_) => t
51 | end.
52 |
53 | Definition vote_source_height (v:Vote) : nat :=
54 | match v with
55 | (_,_,_,s_h,_) => s_h
56 | end.
57 |
58 | Definition vote_target_height (v:Vote) : nat :=
59 | match v with
60 | (_,_,_,_,t_h) => t_h
61 | end.
62 |
63 | (* Reconstructing a vote using its projections *)
64 | Lemma vote_unfold (vote:Vote):
65 | vote = ((vote_val vote),
66 | (vote_source vote),
67 | (vote_target vote),
68 | (vote_source_height vote),
69 | (vote_target_height vote)).
70 | Proof.
71 | by move:vote=>[[[[v s] t] s_h] t_h].
72 | Qed.
--------------------------------------------------------------------------------
/casper/coq/theories/StrongInductionLtn.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | (******************************************************************************)
7 | (* This utility module proves a few induction principles used in other *)
8 | (* proofs. *)
9 | (******************************************************************************)
10 |
11 | (* Two strong induction principles over natural numbers,
12 | as represented in the MathComp library.
13 | Adapted from work by Tej Chajed. *)
14 |
15 | Section StrongInductionLtn.
16 |
17 | Variable P:nat -> Prop.
18 |
19 | (** The stronger inductive hypothesis given in strong induction. The standard
20 | [nat ] induction principle provides only n = pred m, with [P 0] required
21 | separately. *)
22 | Hypothesis IH : forall m, (forall n, n < m -> P n) -> P m.
23 |
24 | Lemma P0 : P 0.
25 | Proof.
26 | apply IH; intros.
27 | exfalso; inversion H.
28 | Qed.
29 |
30 | Hint Resolve P0 : core.
31 |
32 | Lemma pred_increasing : forall (n m : nat),
33 | n <= m ->
34 | n.-1 <= m.-1.
35 | Proof. by elim => //= n IH'; case. Qed.
36 |
37 | Local Lemma strong_induction_all : forall n,
38 | (forall m, m <= n -> P m).
39 | Proof.
40 | elim => //=; first by case.
41 | move => n IH' m Hm.
42 | apply: IH.
43 | move => n' Hn'.
44 | apply: IH'.
45 | have Hnn: n < n.+1 by apply ltnSn.
46 | move: Hm.
47 | rewrite leq_eqVlt.
48 | move/orP.
49 | case.
50 | - move/eqP => Hm.
51 | by move: Hm Hn' =>->.
52 | - move => Hm.
53 | have Hmn: m <= n by [].
54 | suff Hsuff: n' < n.
55 | rewrite leq_eqVlt.
56 | apply/orP.
57 | by right.
58 | by apply: leq_trans; eauto.
59 | Qed.
60 |
61 | Theorem strong_induction_ltn : forall n, P n.
62 | Proof.
63 | eauto using strong_induction_all.
64 | Qed.
65 |
66 | End StrongInductionLtn.
67 |
68 | Section StrongInductionSub.
69 |
70 | Variable k : nat.
71 |
72 | Variable T : Type.
73 |
74 | Variable P : nat -> T -> Prop.
75 |
76 | Hypothesis IH : forall (v1 : nat) (h1 : T), (forall (v1a : nat) (h1a : T), k < v1a -> v1a - k < v1 - k -> P v1a h1a) -> P v1 h1.
77 |
78 | Theorem strong_induction_sub : forall n t, P n t.
79 | Proof.
80 | elim/strong_induction_ltn.
81 | move => m IH' t.
82 | apply IH.
83 | move => v1a h1a Hlt Hlt'.
84 | apply: IH'.
85 | rewrite ltn_subRL in Hlt'.
86 | rewrite subnKC in Hlt' => //.
87 | rewrite leq_eqVlt.
88 | by apply/orP; right.
89 | Qed.
90 |
91 | End StrongInductionSub.
--------------------------------------------------------------------------------
/casper/coq/theories/Validator.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp.ssreflect
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | From mathcomp.finmap
7 | Require Import finmap.
8 |
9 | Set Implicit Arguments.
10 | Unset Strict Implicit.
11 | Unset Printing Implicit Defensive.
12 |
13 | Open Scope fmap_scope.
14 |
15 | (******************************************************************************)
16 | (* Validators and validator stake *)
17 | (******************************************************************************)
18 |
19 | (* We assume finite sets of validators *)
20 | Parameter Validator : finType.
21 |
22 | (* A finite map defining the stake (weight) of a validator *)
23 | (* Note: weight is a nat *)
24 | Parameter stake : {fmap Validator -> nat}.
25 |
26 | (* We assume the map stake is total *)
27 | Axiom st_fun : forall v : Validator, v \in stake.
28 |
29 |
--------------------------------------------------------------------------------
/casper/coq/theories/Weight.v:
--------------------------------------------------------------------------------
1 | Set Warnings "-parsing".
2 | From mathcomp.ssreflect
3 | Require Import all_ssreflect.
4 | Set Warnings "parsing".
5 |
6 | From mathcomp.finmap
7 | Require Import finmap.
8 |
9 | From Casper
10 | Require Import NatExt SetTheoryProps.
11 |
12 | From Casper
13 | Require Import Validator.
14 |
15 | Set Implicit Arguments.
16 | Unset Strict Implicit.
17 | Unset Printing Implicit Defensive.
18 |
19 | Open Scope fmap_scope.
20 |
21 | (******************************************************************************)
22 | (* Definitions and properties of the function `wt' mapping validator sets to *)
23 | (* values corresponding to their weights. Many of these results follow from *)
24 | (* properties of \sum and set-theoretic properties of set operations. *)
25 | (******************************************************************************)
26 |
27 | (* A finite map defining the weight of a given set of validators as the sum of
28 | * stake values of its validators
29 | *)
30 | Definition wt (s:{set Validator}) : nat :=
31 | (\sum_(v in s) stake.[st_fun v]).
32 |
33 | (* wt is always non-negative *)
34 | Lemma wt_nonneg s: wt s >= 0.
35 | Proof. by []. Qed.
36 |
37 | (* wt of the empty set is always 0 *)
38 | Lemma wt_set0 : wt set0 = 0.
39 | Proof.
40 | by rewrite /wt big_set0.
41 | Qed.
42 |
43 | (* set inclusion induces an order on weights *)
44 | Lemma wt_inc_leq (s1 s2:{set Validator}):
45 | s1 \subset s2 -> wt s1 <= wt s2.
46 | Proof.
47 | rewrite /wt.
48 | rewrite [\sum_(v in s2) _](big_setID s1) //=.
49 | move/setIidPr => ->.
50 | apply: leq_addr.
51 | Qed.
52 |
53 | (* equal sets have the same weight *)
54 | Lemma wt_eq (s1 s2:{set Validator}):
55 | s1 = s2 -> wt s1 = wt s2.
56 | Proof.
57 | move=> Heq.
58 | by rewrite /wt Heq.
59 | Qed.
60 |
61 | (* sets commute under wt *)
62 | Lemma wt_meetC (s1 s2:{set Validator}):
63 | wt (s1 :&: s2) = wt (s2 :&: s1).
64 | Proof.
65 | by [rewrite /wt setIC].
66 | Qed.
67 |
68 | (* the weight of the union of two disjoint sets is exactly the sum of
69 | * their weights
70 | *)
71 | Lemma wt_join_disjoint (s1 s2:{set Validator}):
72 | [disjoint s1 & s2] -> wt (s1 :|: s2) = wt s1 + wt s2.
73 | Proof.
74 | move=> Hdis.
75 | rewrite /wt.
76 | rewrite (eq_bigl [predU s1 & s2]); last by move=> i; rewrite !inE.
77 | rewrite bigU //=.
78 | Qed.
79 |
80 | (* The weight of the difference of two sets *)
81 | Lemma wt_diff (s1 s2:{set Validator}):
82 | wt (s1 :\: s2) = wt s1 - wt (s1 :&: s2).
83 | Proof.
84 | rewrite -{2}(setID s1 s2).
85 | rewrite (wt_join_disjoint).
86 | rewrite addnC -addnBA; last by [].
87 | by rewrite sub_eq addn0.
88 | by apply: setID_disjoint.
89 | Qed.
90 |
91 | (* The weight of the union of two sets as the sum of weights of its partitions *)
92 | Lemma wt_join_partition (s1 s2:{set Validator}):
93 | wt (s1 :|: s2) = wt (s1 :\: s2) + wt (s2 :\: s1) + wt (s1 :&: s2).
94 | Proof.
95 | rewrite -!wt_join_disjoint.
96 | apply: wt_eq. apply: setU_par.
97 | apply: setDDI_disjoint.
98 | apply: setDD_disjoint.
99 | Qed.
100 |
101 | (* The weight of the union of two sets in terms of the weights of the sets *)
102 | Lemma wt_join (s1 s2:{set Validator}):
103 | wt (s1 :|: s2) = wt s1 + wt s2 - wt (s1 :&: s2).
104 | Proof.
105 | rewrite -{2}(setID s1 s2).
106 | rewrite -{4}(setID s2 s1).
107 | rewrite [wt (s1 :&: s2 :|: _)]wt_join_disjoint; last by apply setID_disjoint.
108 | rewrite [wt (s2 :&: s1 :|: _)]wt_join_disjoint; last by apply setID_disjoint.
109 | rewrite [s2 :&: s1]setIC.
110 | rewrite -addnA [_ + wt (s2 :\: s1)]addnC.
111 | rewrite [wt (s1 :\: s2) + (_+_)]addnA.
112 | rewrite -wt_join_partition.
113 | rewrite -addnBAC; last by [].
114 | by rewrite sub_eq add0n.
115 | Qed.
116 |
117 | (* Properties of the weight of the intersection of two sets *)
118 | Lemma wt_meet_leq1 (s1 s2:{set Validator}):
119 | wt (s1 :&: s2) <= wt s1.
120 | Proof.
121 | apply: wt_inc_leq; apply: subsetIl.
122 | Qed.
123 |
124 | Lemma wt_meet_leq2 (s1 s2:{set Validator}):
125 | wt (s1 :&: s2) <= wt s2.
126 | Proof.
127 | apply: wt_inc_leq; apply: subsetIr.
128 | Qed.
129 |
130 | Lemma wt_meet_leq (s1 s2:{set Validator}):
131 | wt (s1 :&: s2) <= wt s1 + wt s2.
132 | Proof.
133 | have H1:= (wt_meet_leq1 s1 s2).
134 | have H2:= (leq_addr (wt s2) (wt s1)).
135 | apply: (leq_trans H1 H2).
136 | Qed.
137 |
138 |
--------------------------------------------------------------------------------
/casper/report/.gitignore:
--------------------------------------------------------------------------------
1 | *.aux
2 | *.bbl
3 | *.blg
4 | *.log
5 | *.out
6 | *.synctex.gz
7 |
--------------------------------------------------------------------------------
/casper/report/comment.cut:
--------------------------------------------------------------------------------
1 |
2 | We thank Danny Ryan, Carl Beekhuizen, Martin Lundfall, Yan Zhang and Aditya Asgaonkar from the Ethereum Foundation for their valuable feedback and comments. This work was funded by the Ethereum Foundation.
3 |
4 | % %% contents suppressed with 'anonymous'
5 | % %% Commands \grantsponsor{}{}{} and
6 | % %% \grantnum[]{}{} should be used to
7 | % %% acknowledge financial support and will be used by metadata
8 | % %% extraction tools.
9 | % This material is based upon work supported by the
10 | % \grantsponsor{GS100000001}{National Science
11 | % Foundation}{http://dx.doi.org/10.13039/100000001} under Grant
12 | % No.~\grantnum{GS100000001}{nnnnnnn} and Grant
13 | % No.~\grantnum{GS100000001}{mmmmmmm}. Any opinions, findings, and
14 | % conclusions or recommendations expressed in this material are those
15 | % of the author and do not necessarily reflect the views of the
16 | % National Science Foundation.
17 |
--------------------------------------------------------------------------------
/casper/report/lstcoq.sty:
--------------------------------------------------------------------------------
1 | % colors
2 | \definecolor{shadecolor}{gray}{1.00}
3 | \definecolor{darkgray}{gray}{0.30}
4 | \definecolor{violet}{rgb}{0.56, 0.0, 1.0}
5 | \definecolor{forestgreen}{rgb}{0.13, 0.55, 0.13}
6 |
7 | % Col language definition
8 | \lstdefinelanguage{Coq} {
9 | mathescape=true,
10 | texcl=false,
11 | morekeywords=[1]{
12 | Add,
13 | All,
14 | Arguments,
15 | Axiom,
16 | Bind,
17 | Canonical,
18 | Check,
19 | Close,
20 | CoFixpoint,
21 | CoInductive,
22 | Coercion,
23 | Contextual,
24 | Corollary,
25 | Defined,
26 | Definition,
27 | Delimit,
28 | End,
29 | Example,
30 | Export,
31 | Fact,
32 | Fixpoint,
33 | Goal,
34 | Graph,
35 | Hint,
36 | Hypotheses,
37 | Hypothesis,
38 | Implicit,
39 | Implicits,
40 | Import,
41 | Inductive,
42 | Lemma,
43 | Let,
44 | Local,
45 | Locate,
46 | Ltac,
47 | Maximal
48 | Module,
49 | Morphism,
50 | Next,
51 | Notation,
52 | Obligation,
53 | Open,
54 | Parameter,
55 | Parameters,
56 | Prenex,
57 | Print,
58 | Printing,
59 | Program,
60 | Projections,
61 | Proof,
62 | Proposition,
63 | Qed,
64 | Record,
65 | Relation,
66 | Remark,
67 | Require,
68 | Reserved,
69 | Resolve,
70 | Rewrite,
71 | Save,
72 | Scope,
73 | Search,
74 | Section,
75 | Show,
76 | Strict,
77 | Structure,
78 | Tactic,
79 | Theorem,
80 | Unset,
81 | Variable,
82 | Variables,
83 | View,
84 | inside,
85 | outside
86 | },
87 | morekeywords=[2]{
88 | as,
89 | cofix,
90 | else,
91 | end,
92 | exists,
93 | exists2,
94 | fix,
95 | for,
96 | forall,
97 | fun,
98 | if,
99 | % in,
100 | is,
101 | let,
102 | match,
103 | nosimpl,
104 | of,
105 | return,
106 | struct,
107 | then,
108 | vfun,
109 | with
110 | },
111 | morekeywords=[3]{Type, Prop, Set, True, False},
112 | morekeywords=[4]{
113 | after,
114 | apply,
115 | assert,
116 | auto,
117 | bool_congr,
118 | case,
119 | change,
120 | clear,
121 | compute,
122 | congr,
123 | cut,
124 | cutrewrite,
125 | destruct,
126 | elim,
127 | field,
128 | fold,
129 | generalize,
130 | have,
131 | heval,
132 | hnf,
133 | induction,
134 | injection,
135 | intro,
136 | intros,
137 | intuition,
138 | inversion,
139 | left,
140 | loss,
141 | move,
142 | nat_congr,
143 | nat_norm,
144 | pattern,
145 | pose,
146 | refine,
147 | rename,
148 | replace,
149 | revert,
150 | rewrite,
151 | right,
152 | ring,
153 | % set,
154 | simpl,
155 | split,
156 | suff,
157 | suffices,
158 | symmetry,
159 | transitivity,
160 | trivial,
161 | unfold,
162 | unlock,
163 | using,
164 | without,
165 | wlog,
166 | autorewrite
167 | },
168 | morekeywords=[5]{
169 | assumption,
170 | by,
171 | contradiction,
172 | done,
173 | exact,
174 | lia,
175 | gappa,
176 | omega,
177 | reflexivity,
178 | romega,
179 | solve,
180 | tauto,
181 | discriminate,
182 | unsat
183 | },
184 | morecomment=[s]{(*}{*)},
185 | morekeywords=[6]{do, first, try, idtac, repeat},
186 | showstringspaces=false,
187 | morestring=[b]",
188 | % Size of tabulations
189 | tabsize=3,
190 | % Enables ASCII chars 128 to 255
191 | extendedchars=true,
192 | % Case sensitivity
193 | sensitive=true,
194 | % Automatic breaking of long lines
195 | breaklines=false,
196 | % Default style fors listings
197 | %basicstyle=\scriptsize\ttfamily,
198 | basicstyle=\footnotesize\ttfamily,
199 | % Position of captions is bottom
200 | captionpos=b,
201 | % Full flexible columns
202 | columns=[l]fullflexible,
203 | % Style for (listings') identifiers
204 | identifierstyle={\color{black}},
205 | % Style for declaration keywords
206 | keywordstyle=[1]{\color{violet}},
207 | % Style for gallina keywords
208 | keywordstyle=[2]{\color{forestgreen}},
209 | % Style for sorts keywords
210 | keywordstyle=[3]{\color{forestgreen}},
211 | % Style for tactics keywords
212 | keywordstyle=[4]{\color{blue}},
213 | % Style for terminators keywords
214 | keywordstyle=[5]{\color{red}},
215 | %Style for iterators
216 | keywordstyle=[6]{\color{violet}},
217 | % Style for strings
218 | stringstyle=,
219 | % Style for comments
220 | commentstyle=\it\ttfamily\color{brown},
221 | % Style for lines numbering
222 | numberstyle=\tiny,
223 | literate={\\/}{{$\lor~$}}1
224 | {/\\}{{$\land~$}}1
225 | {<>}{{$\neq~$}}1
226 | {<->}{{$\leftrightarrow~$}}1
227 | {:->}{{$\mapsto~$\!}}1
228 | {\\->}{{$\mapsto~$\!}}1
229 | {<--}{{$\asgn~$}}1
230 | {\\in}{{$\in~$}}1
231 | {\\notin}{{$\notin~$}}1
232 | {++}{{$+\!+\!~$}}1
233 | {->}{{$\to~$}}1
234 | {forall}{{$\forall~$}}1
235 | {exists}{{$\exists~$}}1
236 | {=>}{{$\Rightarrow~$}}1
237 | {\\~}{{$\lnot\;$}}1
238 | % {\\+}{{$\!\join\!~$}}1
239 | }
240 |
241 | \lstdefinestyle{Coq}{language=Coq}
242 | \lstset{language=Coq}
243 |
--------------------------------------------------------------------------------
/casper/report/report.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/runtimeverification/beacon-chain-verification/7563b9b338eef019a11edadb8d8e520775a165bf/casper/report/report.pdf
--------------------------------------------------------------------------------
/dynamic/Makefile:
--------------------------------------------------------------------------------
1 | # Settings
2 | # --------
3 |
4 | BUILD_DIR := .build
5 | DEFN_DIR := $(BUILD_DIR)/defn
6 |
7 | DEPS_DIR := ../deps
8 | PANDOC_TANGLE_SUBMODULE := $(DEPS_DIR)/pandoc-tangle
9 |
10 | K_SUBMODULE := $(abspath $(DEPS_DIR)/k)
11 |
12 | ifneq (,$(wildcard $(K_SUBMODULE)/k-distribution/target/release/k/bin/*))
13 | K_RELEASE ?= $(abspath $(K_SUBMODULE)/k-distribution/target/release/k)
14 | else
15 | K_RELEASE ?= $(dir $(shell which kompile))..
16 | endif
17 | K_BIN := $(K_RELEASE)/bin
18 | K_LIB := $(K_RELEASE)/lib/kframework
19 | export K_RELEASE
20 |
21 | PATH := $(K_BIN):$(PATH)
22 | export PATH
23 |
24 | PYTHONPATH := $(K_LIB)
25 | export PYTHONPATH
26 |
27 | TANGLER := $(PANDOC_TANGLE_SUBMODULE)/tangle.lua
28 | LUA_PATH := $(PANDOC_TANGLE_SUBMODULE)/?.lua;;
29 | export TANGLER
30 | export LUA_PATH
31 |
32 | .SECONDARY:
33 |
34 | .PHONY: all clean clean-submodules
35 |
36 | all: build
37 |
38 | clean:
39 | rm -rf $(BUILD_DIR)
40 | rm -f process-justification-finalization-spec.k process-justification-finalization-lemma.k
41 |
42 | # Dependencies
43 | # ------------
44 |
45 | K_JAR := $(K_SUBMODULE)/k-distribution/target/release/k/lib/java/kernel-1.0-SNAPSHOT.jar
46 |
47 | .PHONY: deps deps-k
48 |
49 | deps: deps-k
50 | deps-k: $(K_JAR)
51 |
52 | ifneq ($(RELEASE),)
53 | K_BUILD_TYPE := FastBuild
54 | else
55 | K_BUILD_TYPE := Debug
56 | endif
57 |
58 | $(K_JAR):
59 | cd $(K_SUBMODULE) && mvn package -DskipTests -Dproject.build.type=$(K_BUILD_TYPE)
60 |
61 | # Building
62 | # --------
63 |
64 | MAIN_MODULE := DYNAMIC-ABSTRACT-BEACON-CHAIN
65 | SYNTAX_MODULE := $(MAIN_MODULE)-SYNTAX
66 | MAIN_DEFN_FILE := dynamic-abstract-beacon-chain
67 |
68 | SOURCE_MD_FILES := dynamic-abstract-beacon-chain \
69 | dynamic-abstract-beacon-chain-syntax
70 | SOURCE_K_FILES := verification
71 | EXTRA_SOURCE_FILES :=
72 |
73 | ALL_FILES := $(patsubst %, %.md, $(SOURCE_MD_FILES)) $(patsubst %, %.k, $(SOURCE_K_FILES)) $(EXTRA_SOURCE_FILES)
74 |
75 | tangle_concrete := k & (concrete | ! symbolic)
76 | tangle_symbolic := k & (symbolic | ! concrete)
77 |
78 | .PHONY: build build-concrete build-symbolic
79 |
80 | build: build-concrete build-symbolic
81 |
82 | KOMPILE_OPTS += --emit-json
83 |
84 | ifneq (,$(RELEASE))
85 | KOMPILE_OPTS += -O3
86 | endif
87 |
88 | KOMPILE_CONCRETE_OPTS :=
89 |
90 | KOMPILE_CONCRETE := kompile --debug --backend java --md-selector "$(tangle_concrete)" \
91 | $(KOMPILE_OPTS) $(KOMPILE_CONCRETE_OPTS)
92 |
93 | KOMPILE_SYMBOLIC_OPTS :=
94 |
95 | KOMPILE_SYMBOLIC := kompile --debug --backend java --md-selector "$(tangle_symbolic)" \
96 | $(KOMPILE_OPTS) $(KOMPILE_SYMBOLIC_OPTS)
97 |
98 | ### Concrete Backend
99 |
100 | concrete_dir := $(DEFN_DIR)/concrete
101 | concrete_files := $(ALL_FILES)
102 | concrete_main_module := VERIFICATION
103 | concrete_syntax_module := DYNAMIC-ABSTRACT-BEACON-CHAIN-SYNTAX
104 | concrete_main_file := verification.k
105 | concrete_kompiled := $(concrete_dir)/verification-kompiled/timestamp
106 |
107 | build-concrete: $(concrete_kompiled)
108 |
109 | $(concrete_kompiled): $(concrete_files)
110 | $(KOMPILE_CONCRETE) $(concrete_main_file) \
111 | --main-module $(concrete_main_module) \
112 | --syntax-module $(concrete_syntax_module) \
113 | --directory $(concrete_dir) \
114 | -I $(CURDIR)
115 |
116 | ### Symbolic Backend
117 |
118 |
119 | symbolic_dir := $(DEFN_DIR)/symbolic
120 | symbolic_files := $(ALL_FILES)
121 | symbolic_main_module := VERIFICATION
122 | symbolic_syntax_module := DYNAMIC-ABSTRACT-BEACON-CHAIN-SYNTAX
123 | symbolic_main_file := verification.k
124 | symbolic_kompiled := $(symbolic_dir)/verification-kompiled/timestamp
125 |
126 | build-symbolic: $(symbolic_kompiled)
127 |
128 | $(symbolic_kompiled): $(symbolic_files)
129 | $(KOMPILE_SYMBOLIC) $(symbolic_main_file) \
130 | --main-module $(symbolic_main_module) \
131 | --syntax-module $(symbolic_syntax_module) \
132 | --directory $(symbolic_dir) \
133 | -I $(CURDIR)
134 |
135 | # Test
136 | # ----
137 |
138 | CHECK := git --no-pager diff --no-index --ignore-all-space -R
139 |
140 | .PHONY: test test-concrete test-prove
141 |
142 | test: test-concrete test-prove
143 |
144 | concrete_tests := $(wildcard tests/concrete/*.abc)
145 |
146 | tests/concrete/%.abc.run: tests/concrete/%.abc $(concrete_kompiled)
147 | krun -d $(concrete_dir) $< > $<.out
148 | $(CHECK) $<.out $<.expected
149 | rm $<.out
150 |
151 | prove_tests := $(wildcard *-spec.k)
152 |
153 | %-spec.k.prove: %-spec.k $(symbolic_kompiled) process-justification-finalization-spec.k process-justification-finalization-lemma.k
154 | kprove -d $(symbolic_dir) -m VERIFICATION -w none $< > $<.out
155 | $(CHECK) $<.out tests/success.out
156 | rm $<.out
157 |
158 | test-concrete: $(concrete_tests:=.run)
159 | test-prove: $(prove_tests:=.prove)
160 |
161 | process-justification-finalization-spec.k: process-justification-finalization-spec.md $(TANGLER)
162 | pandoc --from markdown --to "$(TANGLER)" --metadata=code:".k:not(.lemma),.proof" $< > $@
163 |
164 | process-justification-finalization-lemma.k: process-justification-finalization-spec.md $(TANGLER)
165 | pandoc --from markdown --to "$(TANGLER)" --metadata=code:".k:not(.proof),.lemma" $< > $@
166 |
--------------------------------------------------------------------------------
/dynamic/process-attestation-spec.k:
--------------------------------------------------------------------------------
1 | require "verification.k"
2 |
3 | module PROCESS-ATTESTATION-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processAttestations(As) => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(VM, _)
15 |
16 | ?Epoch -Int 1 |-> (PrevAs1:Attestations => ?PrevAs2)
17 | ?Epoch |-> (CurrAs1:Attestations => ?CurrAs2)
18 | ...
19 |
20 | ...
21 |
22 |
23 | Slot -Int 1
24 | v(ORIG_VM, ORIG_VIDs)
25 | ...
26 |
27 | ...
28 |
29 | LastJustifiedEpoch
30 | BlockMap
31 | ...
32 |
33 | requires true
34 | // types
35 | andBool Slot >=Int 1
36 | // let-bindings
37 | andBool ?Epoch ==Int epochOf(Slot)
38 | // pre-conditions
39 | andBool ?Epoch >=Int 1
40 | andBool isValidAttestationListPartial(As, Slot, LastJustifiedEpoch, BlockMap)
41 | andBool forall(x, getValidatorsA(As), VM.slashed[x]b ==K false)
42 | // invariants
43 | ensures true
44 | // post-conditions
45 | andBool ?PrevAs2 ==K revA(getAttestations(As, ?Epoch -Int 1)) ++A PrevAs1
46 | andBool ?CurrAs2 ==K revA(getAttestations(As, ?Epoch )) ++A CurrAs1
47 |
48 | rule
49 |
50 | processAttestationsAux(L_As, As) => .K ...
51 | Slot
52 |
53 |
54 | Slot
55 | v(VM, _)
56 |
57 | ?Epoch -Int 1 |-> (getAttestations(L_As, ?Epoch -Int 1) ++A PrevAs0:Attestations => ?PrevAs2)
58 | ?Epoch |-> (getAttestations(L_As, ?Epoch ) ++A CurrAs0:Attestations => ?CurrAs2)
59 | ...
60 |
61 | ...
62 |
63 |
64 | Slot -Int 1
65 | v(ORIG_VM, ORIG_VIDs)
66 | ...
67 |
68 | ...
69 |
70 | LastJustifiedEpoch
71 | BlockMap
72 | ...
73 |
74 | requires true
75 | // types
76 | andBool Slot >=Int 1
77 | // let-bindings
78 | andBool ?Epoch ==Int epochOf(Slot)
79 | andBool ?PrevAs1 ==K getAttestations(L_As, ?Epoch -Int 1) ++A PrevAs0
80 | andBool ?CurrAs1 ==K getAttestations(L_As, ?Epoch ) ++A CurrAs0
81 | // pre-conditions
82 | andBool ?Epoch >=Int 1
83 | andBool isValidAttestationListPartial(As, Slot, LastJustifiedEpoch, BlockMap)
84 | andBool forall(x, getValidatorsA(As), VM.slashed[x]b ==K false)
85 | // invariants
86 | ensures true
87 | // post-conditions
88 | andBool ?PrevAs2 ==K revA(getAttestations(As, ?Epoch -Int 1)) ++A ?PrevAs1
89 | andBool ?CurrAs2 ==K revA(getAttestations(As, ?Epoch )) ++A ?CurrAs1
90 | [matching(concatA)]
91 |
92 | endmodule
93 |
--------------------------------------------------------------------------------
/dynamic/process-block-spec.k:
--------------------------------------------------------------------------------
1 | require "verification.k"
2 |
3 | require "process-slashing-spec.k"
4 | require "process-attestation-spec.k"
5 | require "process-deposit-spec.k"
6 | require "process-validator-exit-spec.k"
7 |
8 | module PROCESS-BLOCK-SPEC
9 |
10 | imports VERIFICATION
11 |
12 | imports PROCESS-SLASHING-SPEC
13 | imports PROCESS-ATTESTATION-SPEC
14 | imports PROCESS-DEPOSIT-SPEC
15 | imports PROCESS-VALIDATOR-EXIT-SPEC
16 |
17 | rule
18 |
19 | processBlock(#Block((Slot, ID), Parent, Ss, As, Ds, VEs)) => .K ...
20 | Slot
21 |
22 |
23 | Slot
24 | v(m(SM1 => ?SM2, BM1 => ?BM2, EBM1 => ?EBM2, AEM1 => ?AEM2, AM1 => ?AM2, EM1 => ?EM2, WM1 => ?WM2), VIDs1 => ?VIDs2)
25 |
26 | ?Epoch -Int 1 |-> (PrevAs1:Attestations => ?PrevAs2)
27 | ?Epoch |-> (CurrAs1:Attestations => ?CurrAs2)
28 | ...
29 |
30 | _ => ?_
31 | ...
32 |
33 |
34 | Slot -Int 1
35 | v(m(SM1, BM1, EBM1, AEM1, AM1, EM1, WM1), VIDs1)
36 | ...
37 |
38 | ...
39 |
40 | LastJustifiedEpoch
41 | BlockMap => BlockMap [ Slot <- ID ]i
42 | Bs => Bs [ ID <- #Block((Slot, ID), Parent, Ss, As, Ds, VEs) ]k
43 | ...
44 |
45 | requires true
46 |
47 | // types
48 | andBool Slot >=Int 1
49 |
50 | // let-bindings
51 | //// processVoluntaryExits
52 | andBool ?Epoch ==Int epochOf(Slot)
53 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(VIDs1, EM1), delayedActivationExitEpoch(?Epoch))
54 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(VIDs1, AM1, EM1, ?Epoch)))
55 |
56 | ////////////////////
57 | // pre-conditions
58 | ////////////////////
59 |
60 | andBool disjoint(getValidatorsA(As), getValidatorsS(Ss)) // no attestation from validators that will be slashed in this block
61 | andBool disjoint(getValidatorsE(VEs), getValidatorsS(Ss)) // no voluntary exits from validators that will be slashed in this block
62 | andBool ?LastExitEpoch +Int sizeS(Ss) +Int sizeE(VEs) +Int MIN_VALIDATOR_WITHDRAWABILITY_DELAY =Int 0)
65 | andBool forall(x, VIDs1, EBM1[x]i >=Int 0)
66 | andBool forall(x, VIDs1, AEM1[x]i >=Int 0)
67 | andBool forall(x, VIDs1, AM1[x]i >=Int 0)
68 | andBool forall(x, VIDs1, EM1[x]i >=Int 0)
69 | andBool forall(x, VIDs1, WM1[x]i >=Int 0)
70 |
71 | //// processSlashings
72 |
73 | andBool forallS(x, Ss, isSlashableAttestation(x.attestation_1, x.attestation_2) andBool x.attestation_1.attester ==Int x.attestation_2.attester)
74 | andBool forall(x, getValidatorsS(Ss), SM1[x]b ==K false)
75 | andBool forall(x, getValidatorsS(Ss), AM1[x]i <=Int ?Epoch)
76 | andBool forall(x, getValidatorsS(Ss), WM1[x]i >Int ?Epoch)
77 | andBool distinct(getValidatorsS(Ss))
78 | andBool forall(x, getValidatorsS(Ss), x in VIDs1)
79 |
80 | //// processAttestations
81 |
82 | andBool ?Epoch >=Int 1
83 | andBool isValidAttestationListPartial(As, Slot, LastJustifiedEpoch, BlockMap [ Slot <- ID ]i)
84 | andBool forall(x, getValidatorsA(As), SM1[x]b ==K false)
85 | andBool forall(x, getValidatorsA(As), x in VIDs1)
86 |
87 | //// processDeposits
88 |
89 | andBool distinct(VIDs1)
90 | andBool isValidDeposits(Ds)
91 |
92 | //// processVoluntaryExits
93 |
94 | andBool forallE(x, VEs, isValidVoluntaryExit(x, AM1, EM1, ?Epoch))
95 | andBool distinct(getValidatorsE(VEs))
96 | andBool forall(x, getValidatorsE(VEs), x in VIDs1)
97 |
98 | ensures true
99 |
100 | ////////////////////
101 | // post-conditions
102 | ////////////////////
103 |
104 | //// processSlashings
105 |
106 | //// processAttestations
107 |
108 | andBool ?PrevAs2 ==K revA(getAttestations(As, ?Epoch -Int 1)) ++A PrevAs1
109 | andBool ?CurrAs2 ==K revA(getAttestations(As, ?Epoch )) ++A CurrAs1
110 |
111 | //// processDeposits
112 |
113 | andBool distinct(?VIDs2)
114 | andBool ?VIDs2 ==K unique(rev(getValidatorsD(Ds)) ++ VIDs1)
115 |
116 | //// processVoluntaryExits
117 |
118 | //// summary
119 |
120 | // existing validators
121 | andBool forall(x, VIDs1, #if x in getValidatorsS(Ss) #then ?SM2[x]b ==K true #else ?SM2[x]b ==K SM1[x]b #fi)
122 | andBool forall(x, VIDs1, #if x in getValidatorsS(Ss) orBool x in getValidatorsD(Ds) #then ?BM2[x]i >=Int 0 #else ?BM2[x]i ==Int BM1[x]i #fi)
123 | andBool forall(x, VIDs1, ?EBM2[x]i ==Int EBM1[x]i)
124 | andBool forall(x, VIDs1, ?AEM2[x]i ==Int AEM1[x]i)
125 | andBool forall(x, VIDs1, ?AM2[x]i ==Int AM1[x]i)
126 | andBool forall(x, VIDs1, #if (x in getValidatorsS(Ss) andBool EM1[x]i ==Int FAR_FUTURE_EPOCH) orBool x in getValidatorsE(VEs)
127 | #then ?EM2[x]i >=Int delayedActivationExitEpoch(?Epoch) andBool ?EM2[x]i =Int ?Epoch +Int EPOCHS_PER_SLASHINGS_VECTOR // TODO: andBool ?WM2[x]i =Int delayedActivationExitEpoch(?Epoch) +Int MIN_VALIDATOR_WITHDRAWABILITY_DELAY andBool ?WM2[x]i =Int 0))
137 | andBool forall(x, ?VIDs2, implies(notBool x in VIDs1, ?EBM2[x]i >=Int 0 andBool ?EBM2[x]i <=Int MAX_EFFECTIVE_BALANCE))
138 | andBool forall(x, ?VIDs2, implies(notBool x in VIDs1, ?AEM2[x]i ==Int FAR_FUTURE_EPOCH))
139 | andBool forall(x, ?VIDs2, implies(notBool x in VIDs1, ?AM2[x]i ==Int FAR_FUTURE_EPOCH))
140 | andBool forall(x, ?VIDs2, implies(notBool x in VIDs1, ?EM2[x]i ==Int FAR_FUTURE_EPOCH))
141 | andBool forall(x, ?VIDs2, implies(notBool x in VIDs1, ?WM2[x]i ==Int FAR_FUTURE_EPOCH))
142 |
143 | // no negative values
144 | andBool forall(x, ?VIDs2, ?BM2[x]i >=Int 0)
145 | andBool forall(x, ?VIDs2, ?EBM2[x]i >=Int 0)
146 | andBool forall(x, ?VIDs2, ?AEM2[x]i >=Int 0)
147 | andBool forall(x, ?VIDs2, ?AM2[x]i >=Int 0)
148 | andBool forall(x, ?VIDs2, ?EM2[x]i >=Int 0)
149 | andBool forall(x, ?VIDs2, ?WM2[x]i >=Int 0)
150 |
151 | /* TODO:
152 | - specify update
153 | - base case: when ?Epoch ==Int 0
154 | */
155 |
156 | endmodule
157 |
--------------------------------------------------------------------------------
/dynamic/process-rewards-penalties-spec.k:
--------------------------------------------------------------------------------
1 | require "verification.k"
2 |
3 | module PROCESS-REWARDS-PENALTIES-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardsPenaltiesAux(?Epoch) => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(m(SM, BM1 => ?BM2, EBM, AEM, AM, EM, WM), VIDs)
15 |
16 | ?Epoch |-> Attestations:Attestations
17 | ...
18 |
19 | ...
20 |
21 | ...
22 |
23 | ( epochOf(Slot) , LastFinalizedEpoch ) _
24 | ...
25 |
26 | requires true
27 | // types
28 | andBool Slot >=Int 0
29 | andBool ?Epoch >=Int 0
30 | andBool ?FinalityDelay >=Int 0
31 | // let-bindings
32 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
33 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
34 | andBool ?SourceAttestations ==K filterNotSlashed(SM, Attestations)
35 | andBool ?TotalActiveBalance ==Int lift(totalBalance(EBM, activeValidators(VIDs, AM, EM, ?Epoch)))
36 | // pre-conditions
37 | andBool forall(x, VIDs, BM1[x]i >=Int 0)
38 | andBool forall(x, VIDs, EBM[x]i >=Int 0)
39 | andBool distinct(VIDs)
40 | andBool forall(x, VIDs, implies(x inA ?SourceAttestations, minByInclusionDelay(x, ?SourceAttestations).inclusion_delay >=Int 1))
41 | andBool forall(x, VIDs, implies(x inA ?SourceAttestations, minByInclusionDelay(x, ?SourceAttestations).proposer in VIDs))
42 | andBool isValidAttestations(Attestations, VIDs, AM, EM, ?Epoch)
43 | // invariants
44 | ensures true
45 | // post-conditions
46 | andBool forall(x, VIDs, ?BM2[x]i <=Int BM1[x]i +Int (4 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)))
47 | andBool forall(x, VIDs, ?BM2[x]i >=Int BM1[x]i -Int (7 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)) -Int getInactivityPenalty(EBM[x]i, ?FinalityDelay))
48 | andBool forall(x, VIDs, ?BM2[x]i >=Int 0)
49 |
50 | rule
51 |
52 | processRewardsPenaltiesAux3(L_VIDs, R_VIDs, m(SM, BM0, EBM, AEM, AM, EM, WM), ?Epoch, ?FinalityDelay,
53 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
54 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .K ...
55 | Slot
56 |
57 |
58 | Slot
59 | v(m(SM, BM1 => ?BM2, EBM, AEM, AM, EM, WM), VIDs)
60 |
61 | ?Epoch |-> Attestations:Attestations
62 | ...
63 |
64 | ...
65 |
66 | ...
67 |
68 | BlockMap
69 | ( epochOf(Slot) , LastFinalizedEpoch ) _
70 | ...
71 |
72 | requires true
73 | // types
74 | andBool Slot >=Int 0
75 | andBool ?Epoch >=Int 0
76 | andBool ?FinalityDelay >=Int 0
77 | // let-bindings
78 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
79 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
80 | andBool ?SourceAttestations ==K filterNotSlashed(SM, Attestations)
81 | andBool ?TargetAttestations ==K filterByTarget(BlockMap[firstSlotOf(?Epoch)]i, ?SourceAttestations)
82 | andBool ?HeadAttestations ==K filterByHead(BlockMap, ?TargetAttestations)
83 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(EBM, getUniqueValidators(?SourceAttestations)))
84 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(EBM, getUniqueValidators(?TargetAttestations)))
85 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(EBM, getUniqueValidators(?HeadAttestations)))
86 | andBool ?TotalActiveBalance ==Int lift(totalBalance(EBM, activeValidators(VIDs, AM, EM, ?Epoch)))
87 | // pre-conditions
88 | andBool forall(x, R_VIDs, BM0[x]i >=Int 0)
89 | andBool forall(x, R_VIDs, EBM[x]i >=Int 0)
90 | andBool distinct(R_VIDs)
91 | andBool forall(x, R_VIDs, implies(x inA ?SourceAttestations, minByInclusionDelay(x, ?SourceAttestations).inclusion_delay >=Int 1))
92 | andBool forall(x, R_VIDs, implies(x inA ?SourceAttestations, minByInclusionDelay(x, ?SourceAttestations).proposer in VIDs))
93 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
94 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
95 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
96 | // invariants
97 | andBool disjoint(L_VIDs, R_VIDs)
98 | andBool forall(x, R_VIDs, x in VIDs)
99 | andBool forall(x, R_VIDs, BM1[x]i ==Int BM0[x]i)
100 | andBool forall(x, rev(L_VIDs), BM1[x]i <=Int BM0[x]i +Int (4 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)))
101 | andBool forall(x, rev(L_VIDs), BM1[x]i >=Int BM0[x]i -Int (7 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)) -Int getInactivityPenalty(EBM[x]i, ?FinalityDelay))
102 | andBool forall(x, rev(L_VIDs), BM1[x]i >=Int 0)
103 | ensures true
104 | // post-conditions
105 | andBool forall(x, rev(L_VIDs) ++ R_VIDs, ?BM2[x]i <=Int BM0[x]i +Int (4 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)))
106 | andBool forall(x, rev(L_VIDs) ++ R_VIDs, ?BM2[x]i >=Int BM0[x]i -Int (7 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)) -Int getInactivityPenalty(EBM[x]i, ?FinalityDelay))
107 | andBool forall(x, rev(L_VIDs) ++ R_VIDs, ?BM2[x]i >=Int 0)
108 |
109 | endmodule
110 |
--------------------------------------------------------------------------------
/dynamic/process-slots-spec.k:
--------------------------------------------------------------------------------
1 | require "verification.k"
2 |
3 | module PROCESS-SLOTS-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // Slot < TargetSlot - 1
8 | rule
9 |
10 | processSlots(TargetSlot)
11 | Slot => Slot +Int 1
12 |
13 |
14 | Slot
15 | Vs
16 | SB
17 | AttestedMap
18 | JustifiedMap
19 | FinalizedMap
20 |
21 | (
22 | .Bag
23 | =>
24 |
25 | Slot +Int 1
26 | Vs
27 | SB
28 | AttestedMap
29 | JustifiedMap
30 | FinalizedMap
31 |
32 | )
33 | ...
34 |
35 | B => B [ Slot +Int 1 <- B[Slot]i ]i
36 | ...
37 |
38 | requires true
39 | andBool Slot +Int 1 =Int 0
43 | ensures true
44 |
45 | // Slot == TargetSlot - 1
46 | rule
47 |
48 | processSlots(TargetSlot) => .
49 | Slot => TargetSlot
50 |
51 |
52 | Slot
53 | Vs
54 | SB
55 | AttestedMap
56 | JustifiedMap
57 | FinalizedMap
58 |
59 | (
60 | .Bag
61 | =>
62 |
63 | TargetSlot
64 | Vs
65 | SB
66 | AttestedMap
67 | JustifiedMap
68 | FinalizedMap
69 |
70 | )
71 | ...
72 |
73 | B => B [ TargetSlot <- B[Slot]i ]i
74 | ...
75 |
76 | requires true
77 | andBool Slot +Int 1 ==Int TargetSlot
78 | andBool isFirstSlotOfEpoch(Slot +Int 1) ==K false
79 | // types
80 | andBool Slot >=Int 0
81 | ensures true
82 |
83 | // Slot == TargetSlot
84 | rule
85 |
86 | processSlots(TargetSlot) => .
87 | Slot
88 |
89 |
90 | Slot
91 | Vs
92 | SB
93 | AttestedMap
94 | JustifiedMap
95 | FinalizedMap
96 |
97 | ...
98 |
99 | ...
100 |
101 | requires true
102 | andBool Slot ==Int TargetSlot
103 | // types
104 | andBool Slot >=Int 0
105 | ensures true
106 |
107 | endmodule
108 |
--------------------------------------------------------------------------------
/dynamic/process-validator-activation-eligibility-spec.k:
--------------------------------------------------------------------------------
1 | require "verification.k"
2 |
3 | module PROCESS-VALIDATOR-ACTIVATION-ELIGIBILITY-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | updateActivationEligibilities(VIDs) => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(m(SM, BM, EBM, AEM1 => ?AEM2, AM, EM, WM), VIDs)
15 | ...
16 |
17 | ...
18 |
19 | ( epochOf(Slot) , FinalizedEpoch ) _
20 | ...
21 |
22 | requires true
23 | // types
24 | andBool Slot >=Int 0
25 | // let-bindings
26 | andBool ?Epoch ==Int epochOf(Slot)
27 | // pre-conditions
28 | andBool distinct(VIDs)
29 | andBool FinalizedEpoch
40 | updateActivationEligibilitiesAux(L_VIDs, R_VIDs, m(SM, BM, EBM, AEM0, AM, EM, WM)) => .K ...
41 | Slot
42 |
43 |
44 | Slot
45 | v(m(SM, BM, EBM, AEM1 => ?AEM2, AM, EM, WM), VIDs)
46 | ...
47 |
48 | ...
49 |
50 | ( epochOf(Slot) , FinalizedEpoch ) _
51 | ...
52 |
53 | requires true
54 | // types
55 | andBool Slot >=Int 0
56 | // let-bindings
57 | andBool ?Epoch ==Int epochOf(Slot)
58 | // pre-conditions
59 | andBool distinct(R_VIDs)
60 | andBool FinalizedEpoch
9 | processValidatorActivation() => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(m(SM, BM, EBM, AEM, AM1 => ?AM2, EM, WM), VIDs)
15 | ...
16 |
17 | ...
18 |
19 | ( epochOf(Slot) , FinalizedEpoch ) _
20 | ...
21 |
22 | requires true
23 | // types
24 | andBool Slot >=Int 0
25 | // let-bindings
26 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
27 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(VIDs, AM1, EM, ?Epoch)))
28 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch)
29 | andBool ?ValidatorsToBeActivated:IntList ==K activationQueueUptoChurnLimit(VIDs, AEM, AM1, EM, FinalizedEpoch, ?Epoch)
30 | // pre-conditions
31 | andBool distinct(VIDs)
32 | andBool ?ActivationEpoch
42 | activateValidators(R_VIDs) => .K ...
43 | Slot
44 |
45 |
46 | Slot
47 | v(m(SM, BM, EBM, AEM, AM1 => ?AM2, EM, WM), VIDs)
48 | ...
49 |
50 | ...
51 |
52 | ( epochOf(Slot) , FinalizedEpoch ) _
53 | ...
54 |
55 | requires true
56 | // types
57 | andBool Slot >=Int 0
58 | // let-bindings
59 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
60 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(VIDs, AM1, EM, ?Epoch)))
61 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch)
62 | // pre-conditions
63 | andBool distinct(R_VIDs)
64 | andBool forall(x, R_VIDs, isValidValidatorToActivate(x, AEM, AM1, FinalizedEpoch))
65 | andBool forall(x, R_VIDs, x in VIDs)
66 | andBool ?ActivationEpoch
76 | activateValidatorsAux(L_VIDs, R_VIDs, m(SM, BM, EBM, AEM, AM0, EM, WM)) => .K ...
77 | Slot
78 |
79 |
80 | Slot
81 | v(m(SM, BM, EBM, AEM, AM1 => ?AM2, EM, WM), VIDs)
82 | ...
83 |
84 | ...
85 |
86 | ( epochOf(Slot) , FinalizedEpoch ) _
87 | ...
88 |
89 | requires true
90 | // types
91 | andBool Slot >=Int 0
92 | // let-bindings
93 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
94 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(VIDs, AM1, EM, ?Epoch)))
95 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch)
96 | // pre-conditions
97 | andBool distinct(R_VIDs)
98 | andBool ?ActivationEpoch
9 | processValidatorEjections(VIDs) => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(m(SM, BM, EBM, AEM, AM, EM1 => ?EM2, WM1 => ?WM2), VIDs)
15 | ...
16 |
17 | ...
18 |
19 | ...
20 |
21 | requires true
22 | // types
23 | andBool Slot >=Int 0
24 | // let-bindings
25 | andBool ?Epoch ==Int epochOf(Slot)
26 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(VIDs, EM1), delayedActivationExitEpoch(?Epoch))
27 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(VIDs, AM, EM1, ?Epoch)))
28 | // pre-conditions
29 | andBool ?LastExitEpoch +Int size(VIDs) +Int MIN_VALIDATOR_WITHDRAWABILITY_DELAY =Int delayedActivationExitEpoch(?Epoch) andBool ?EM2[x]i =Int delayedActivationExitEpoch(?Epoch) +Int MIN_VALIDATOR_WITHDRAWABILITY_DELAY andBool ?WM2[x]i
47 | processValidatorEjectionsAux(L_VIDs, R_VIDs, m(SM, BM, EBM, AEM, AM, EM0, WM0)) => .K ...
48 | Slot
49 |
50 |
51 | Slot
52 | v(m(SM, BM, EBM, AEM, AM, EM1 => ?EM2, WM1 => ?WM2), VIDs)
53 | ...
54 |
55 | ...
56 |
57 | ...
58 |
59 | requires true
60 | // types
61 | andBool Slot >=Int 0
62 | // let-bindings
63 | andBool ?Epoch ==Int epochOf(Slot)
64 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(VIDs, EM1), delayedActivationExitEpoch(?Epoch))
65 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(VIDs, AM, EM1, ?Epoch)))
66 | // pre-conditions
67 | andBool ?LastExitEpoch +Int size(R_VIDs) +Int MIN_VALIDATOR_WITHDRAWABILITY_DELAY =Int delayedActivationExitEpoch(?Epoch) andBool EM1[x]i =Int delayedActivationExitEpoch(?Epoch) +Int MIN_VALIDATOR_WITHDRAWABILITY_DELAY andBool WM1[x]i =Int delayedActivationExitEpoch(?Epoch) andBool ?EM2[x]i =Int delayedActivationExitEpoch(?Epoch) +Int MIN_VALIDATOR_WITHDRAWABILITY_DELAY andBool ?WM2[x]i
16 | processValidatorUpdates() => .K ...
17 | Slot
18 |
19 |
20 | Slot
21 | v(m(SM, BM, EBM, AEM1 => ?AEM2, AM1 => ?AM2, EM1 => ?EM2, WM1 => ?WM2), VIDs)
22 | ...
23 |
24 | ...
25 |
26 | ( epochOf(Slot) , FinalizedEpoch ) _
27 | ...
28 |
29 | requires true
30 | // types
31 | andBool Slot >=Int 0
32 | // let-bindings
33 | andBool ?Epoch ==Int epochOf(Slot)
34 | andBool ?ChurnLimitA ==Int churnLimit(size(activeValidators(VIDs, AM1, EM1, ?Epoch)))
35 | andBool ?ChurnLimitB ==Int churnLimit(size(activeValidators(VIDs, AM1, EM1, ?Epoch -Int 1)))
36 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(VIDs, EM1), delayedActivationExitEpoch(?Epoch))
37 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch -Int 1)
38 | andBool ?ValidatorsToBeActivated:IntList ==K activationQueueUptoChurnLimit(VIDs, AEM1, AM1, EM1, FinalizedEpoch, ?Epoch -Int 1)
39 | // pre-conditions
40 | andBool distinct(VIDs)
41 | andBool FinalizedEpoch =Int delayedActivationExitEpoch(?Epoch) andBool ?EM2[x]i =Int delayedActivationExitEpoch(?Epoch) +Int MIN_VALIDATOR_WITHDRAWABILITY_DELAY andBool ?WM2[x]i
10 | processJustification(Epoch) => .
11 | Slot
12 |
13 |
14 | Slot
15 | Vs
16 |
17 | Epoch |-> Attestations:Attestations
18 | ...
19 |
20 |
21 | Epoch |-> (false => true)
22 | ...
23 |
24 | _ => Epoch
25 | ...
26 |
27 |
28 | firstSlotOf(Epoch)
29 | Vs
30 | (_, EpochBoundaryBlock)
31 | ...
32 |
33 | ...
34 |
35 | ...
36 |
37 | requires Slot ==Int firstSlotOf(Epoch +Int 1)
38 | andBool Epoch >=Int 1
39 | andBool isJustifiable(Epoch, EpochBoundaryBlock, Attestations, Vs)
40 |
41 | endmodule
42 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/b-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module B-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // once processJustification(e) justifies e, then the subsequent processJustification(e) alters nothing.
8 | rule
9 |
10 | processJustification(Epoch) ~> processJustification(Epoch) => .
11 | Slot
12 |
13 |
14 | Slot
15 | Vs
16 |
17 | Epoch |-> Attestations:Attestations
18 | ...
19 |
20 |
21 | Epoch |-> (false => true)
22 | ...
23 |
24 | _ => Epoch
25 | ...
26 |
27 |
28 | firstSlotOf(Epoch)
29 | Vs
30 | (_, EpochBoundaryBlock)
31 | ...
32 |
33 | ...
34 |
35 | ...
36 |
37 | requires Slot ==Int firstSlotOf(Epoch +Int 1)
38 | andBool Epoch >=Int 1
39 | andBool isJustifiable(Epoch, EpochBoundaryBlock, Attestations, Vs)
40 |
41 | endmodule
42 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/c-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module C-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // if e has not yet been justified,
8 | // processJustification(e) updates the entry according to the justifiability of e.
9 | rule
10 |
11 | processJustification(Epoch) => .
12 | Slot
13 |
14 |
15 | Slot
16 | Vs
17 |
18 | Epoch |-> Attestations
19 | ...
20 |
21 |
22 | Epoch |-> (false => ?EpochJustifiedBlock:Bool)
23 | ...
24 |
25 | LastJustifiedEpoch => ?NewJustifiedEpoch
26 | ...
27 |
28 |
29 | firstSlotOf(Epoch)
30 | Vs
31 | (_, EpochBoundaryBlock)
32 | ...
33 |
34 | ...
35 |
36 | ...
37 |
38 | requires true
39 | andBool Epoch >=Int 1
40 | andBool Epoch ==Int epochOf(Slot) -Int 1
41 | andBool Epoch >Int LastJustifiedEpoch
42 | ensures (
43 | isJustifiable(Epoch, EpochBoundaryBlock, Attestations, Vs)
44 | andBool ?EpochJustifiedBlock ==K true
45 | andBool ?NewJustifiedEpoch ==Int Epoch
46 | ) orBool (
47 | notBool isJustifiable(Epoch, EpochBoundaryBlock, Attestations, Vs)
48 | andBool ?EpochJustifiedBlock ==K false
49 | andBool ?NewJustifiedEpoch ==Int LastJustifiedEpoch
50 | )
51 |
52 | // if e has already been justified,
53 | // processJustification(e) does nothing even if e is justifiable.
54 | rule
55 |
56 | processJustification(Epoch) => .
57 | Slot
58 |
59 |
60 | Slot
61 | Vs
62 |
63 | Epoch |-> Attestations
64 | ...
65 |
66 |
67 | Epoch |-> true
68 | ...
69 |
70 | Epoch
71 | ...
72 |
73 |
74 | firstSlotOf(Epoch)
75 | Vs
76 | (_, EpochBoundaryBlock)
77 | ...
78 |
79 | ...
80 |
81 | ...
82 |
83 | requires true
84 | andBool Epoch >=Int 1
85 | andBool Epoch ==Int epochOf(Slot) -Int 1
86 | andBool isJustifiable(Epoch, EpochBoundaryBlock, Attestations, Vs)
87 |
88 | endmodule
89 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/d-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module D-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // processJustification(e) updates the entry properly according to the justifiability of e,
8 | // even when e has been already justified.
9 | rule
10 |
11 | case(xor2(
12 | LastJustifiedEpoch processJustification(Epoch) => .
17 | Slot
18 |
19 |
20 | Slot
21 | Vs
22 |
23 | Epoch |-> Attestations
24 | ...
25 |
26 |
27 | Epoch |-> (OldEpochJustifiedBlock:Bool => ?NewEpochJustifiedBlock:Bool)
28 | ...
29 |
30 | LastJustifiedEpoch => ?NewJustifiedEpoch
31 | ...
32 |
33 |
34 | firstSlotOf(Epoch)
35 | Vs
36 | (_, EpochBoundaryBlock)
37 | ...
38 |
39 | ...
40 |
41 | ...
42 |
43 | requires true
44 | andBool Epoch >=Int 1
45 | andBool Epoch ==Int epochOf(Slot) -Int 1
46 | // invariant
47 | andBool LastJustifiedEpoch <=Int Epoch
48 | andBool implies(LastJustifiedEpoch entries properly according to the justifiability of e - 2 and e - 1,
9 | // where e is the current epoch.
10 | rule
11 |
12 | case(xor2(
13 | LastJustifiedEpoch processJustification(Epoch2)
18 | ~> processJustification(Epoch1) => .
19 | Slot
20 |
21 |
22 | firstSlotOf(Epoch2)
23 | Vs
24 | (_, Epoch2BoundaryBlock)
25 | ...
26 |
27 |
28 | firstSlotOf(Epoch1)
29 | Vs
30 | (_, Epoch1BoundaryBlock)
31 | ...
32 |
33 |
34 | Slot
35 | Vs
36 |
37 | Epoch2 |-> Attestations2:Attestations
38 | Epoch1 |-> Attestations1:Attestations
39 | ...
40 |
41 |
42 | Epoch2 |-> (OldEpoch2JustifiedBlock:Bool => ?NewEpoch2JustifiedBlock:Bool)
43 | Epoch1 |-> (OldEpoch1JustifiedBlock:Bool => ?NewEpoch1JustifiedBlock:Bool)
44 | ...
45 |
46 | LastJustifiedEpoch => ?NewJustifiedEpoch
47 | ...
48 |
49 | ...
50 |
51 | ...
52 |
53 | requires true
54 | andBool Epoch1 >=Int 1
55 | andBool Epoch1 ==Int epochOf(Slot) -Int 1
56 | andBool Epoch2 ==Int epochOf(Slot) -Int 2
57 | andBool OldEpoch1JustifiedBlock ==K false
58 | // invariant
59 | andBool LastJustifiedEpoch <=Int Epoch2
60 | andBool implies(LastJustifiedEpoch =Int 0
65 | andBool Epoch1 >=Int 0
66 | andBool Epoch2 >=Int 0
67 | andBool LastJustifiedEpoch >=Int 0
68 | ensures ?NewJustifiedEpoch >=Int 0
69 | // ensures
70 | // justification of e - 2
71 | andBool bool(xor2(
72 | isJustifiable(Epoch2, Epoch2BoundaryBlock, Attestations2, Vs)
73 | andBool ?NewEpoch2JustifiedBlock ==K true
74 | ,
75 | notBool isJustifiable(Epoch2, Epoch2BoundaryBlock, Attestations2, Vs)
76 | andBool ?NewEpoch2JustifiedBlock ==K false
77 | ))
78 | // justification of e - 1
79 | andBool bool(xor2(
80 | isJustifiable(Epoch1, Epoch1BoundaryBlock, Attestations1, Vs)
81 | andBool ?NewEpoch1JustifiedBlock ==K true
82 | ,
83 | notBool isJustifiable(Epoch1, Epoch1BoundaryBlock, Attestations1, Vs)
84 | andBool ?NewEpoch1JustifiedBlock ==K false
85 | ))
86 | // last justified epoch
87 | andBool bool(xor3(
88 | ?NewEpoch2JustifiedBlock ==K false
89 | andBool ?NewEpoch1JustifiedBlock ==K false
90 | andBool ?NewJustifiedEpoch ==Int LastJustifiedEpoch
91 | ,
92 | ?NewEpoch2JustifiedBlock ==K true
93 | andBool ?NewEpoch1JustifiedBlock ==K false
94 | andBool ?NewJustifiedEpoch ==Int Epoch2
95 | ,
96 | ?NewEpoch1JustifiedBlock ==K true
97 | andBool ?NewJustifiedEpoch ==Int Epoch1
98 | ))
99 |
100 | endmodule
101 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/f-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module F-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // processJustification(e - 2) followed by processJustification(e - 1)
8 | // update the entries properly according to the justifiability of e - 2 and e - 1,
9 | // where e is the current epoch.
10 | rule
11 |
12 | case(xor2(
13 | LastJustifiedEpoch processJustification(Epoch2)
18 | ~> processJustification(Epoch1) => .
19 | firstSlotOf(Epoch)
20 |
21 |
22 | firstSlotOf(Epoch2)
23 | Vs
24 | (_, Epoch2BoundaryBlock)
25 | ...
26 |
27 |
28 | firstSlotOf(Epoch1)
29 | Vs
30 | (_, Epoch1BoundaryBlock)
31 |
32 | Epoch2 |-> PrevAttestations2:Attestations
33 | ...
34 |
35 |
36 | Epoch2 |-> OldEpoch2JustifiedBlock:Bool
37 | ...
38 |
39 | ...
40 |
41 |
42 | firstSlotOf(Epoch)
43 | Vs
44 |
45 | Epoch2 |-> Attestations2:Attestations
46 | Epoch1 |-> Attestations1:Attestations
47 | ...
48 |
49 |
50 | Epoch2 |-> (OldEpoch2JustifiedBlock:Bool => ?NewEpoch2JustifiedBlock:Bool)
51 | Epoch1 |-> (false => ?NewEpoch1JustifiedBlock:Bool)
52 | ...
53 |
54 | LastJustifiedEpoch => ?NewJustifiedEpoch
55 | ...
56 |
57 | ...
58 |
59 | ...
60 |
61 | requires true
62 | andBool Epoch1 ==Int Epoch -Int 1
63 | andBool Epoch2 ==Int Epoch -Int 2
64 | // invariant
65 | andBool LastJustifiedEpoch <=Int Epoch2
66 | andBool implies(LastJustifiedEpoch =Int 0
71 | andBool Epoch1 >=Int 0
72 | andBool Epoch2 >=Int 0
73 | andBool LastJustifiedEpoch >=Int 0
74 | andBool Attestations2 ==K super(PrevAttestations2)
75 | ensures ?NewJustifiedEpoch >=Int 0
76 | // ensures
77 | // justification of e - 2
78 | andBool bool(xor2(
79 | isJustifiable(Epoch2, Epoch2BoundaryBlock, Attestations2, Vs)
80 | andBool ?NewEpoch2JustifiedBlock ==K true
81 | ,
82 | notBool isJustifiable(Epoch2, Epoch2BoundaryBlock, Attestations2, Vs)
83 | andBool ?NewEpoch2JustifiedBlock ==K false
84 | ))
85 | // justification of e - 1
86 | andBool bool(xor2(
87 | isJustifiable(Epoch1, Epoch1BoundaryBlock, Attestations1, Vs)
88 | andBool ?NewEpoch1JustifiedBlock ==K true
89 | ,
90 | notBool isJustifiable(Epoch1, Epoch1BoundaryBlock, Attestations1, Vs)
91 | andBool ?NewEpoch1JustifiedBlock ==K false
92 | ))
93 | // last justified epoch
94 | andBool bool(xor3(
95 | ?NewEpoch2JustifiedBlock ==K false
96 | andBool ?NewEpoch1JustifiedBlock ==K false
97 | andBool ?NewJustifiedEpoch ==Int LastJustifiedEpoch
98 | ,
99 | ?NewEpoch2JustifiedBlock ==K true
100 | andBool ?NewEpoch1JustifiedBlock ==K false
101 | andBool ?NewJustifiedEpoch ==Int Epoch2
102 | ,
103 | ?NewEpoch1JustifiedBlock ==K true
104 | andBool ?NewJustifiedEpoch ==Int Epoch1
105 | ))
106 |
107 | endmodule
108 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/f2-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module F2-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // processJustification(e - 2) followed by processJustification(e - 1)
8 | // update the entries properly according to the justifiability of e - 2 and e - 1,
9 | // where e is the current epoch.
10 | rule
11 |
12 | case(xor2(
13 | LastJustifiedEpoch processJustification(Epoch2)
18 | ~> processJustification(Epoch1) => .
19 | firstSlotOf(Epoch)
20 |
21 |
22 | firstSlotOf(Epoch2)
23 | Vs
24 | (_, Epoch2BoundaryBlock)
25 | ...
26 |
27 |
28 | firstSlotOf(Epoch1)
29 | Vs
30 | (_, Epoch1BoundaryBlock)
31 |
32 | Epoch2 |-> PrevAttestations2:Attestations
33 | ...
34 |
35 |
36 | Epoch2 |-> OldEpoch2JustifiedBlock:Bool
37 | ...
38 |
39 | ...
40 |
41 |
42 | firstSlotOf(Epoch)
43 | Vs
44 |
45 | Epoch2 |-> Attestations2:Attestations
46 | Epoch1 |-> Attestations1:Attestations
47 | ...
48 |
49 |
50 | Epoch2 |-> (OldEpoch2JustifiedBlock:Bool => ?NewEpoch2JustifiedBlock:Bool)
51 | Epoch1 |-> (false => ?NewEpoch1JustifiedBlock:Bool)
52 | ...
53 |
54 | LastJustifiedEpoch => ?NewJustifiedEpoch
55 | ...
56 |
57 | ...
58 |
59 | ...
60 |
61 | requires true
62 | andBool Epoch1 ==Int Epoch -Int 1
63 | andBool Epoch2 ==Int Epoch -Int 2
64 | // invariant
65 | andBool LastJustifiedEpoch <=Int Epoch2
66 | andBool implies(LastJustifiedEpoch =Int 0
71 | andBool Epoch1 >=Int 0
72 | andBool Epoch2 >=Int 0
73 | andBool LastJustifiedEpoch >=Int 0
74 | andBool Attestations2 ==K super(PrevAttestations2)
75 | ensures ?NewJustifiedEpoch >=Int 0
76 | //
77 | // ensures
78 | //
79 | // justification of e-2 and e-1
80 | andBool iff(?NewEpoch2JustifiedBlock ==K true, isJustifiable(Epoch2, Epoch2BoundaryBlock, Attestations2, Vs))
81 | andBool iff(?NewEpoch1JustifiedBlock ==K true, isJustifiable(Epoch1, Epoch1BoundaryBlock, Attestations1, Vs))
82 | // last justified epoch
83 | andBool implies(?NewJustifiedEpoch e-2
2 | 2. e-1 -> e-3
3 | 3. e-1 -> e-4+
4 |
5 | a. e-2 -> e-3
6 | b. e-2 -> e-4
7 | c. e-2 -> e-5+
8 |
9 |
10 | 1a. (e-2 already justified, thus e-3 already finalized)
11 | - e-1 j <=> e-2 f
12 | - e-3 f
13 | - e-4 stay
14 |
15 | 1b. (e-2 already justified)
16 | - e-1 j <=> e-2 f
17 | - e-3 j <=> e-4 f
18 | - e-3 nf
19 |
20 | 1c. (e-2 already justified)
21 | - e-1 j <=> e-2 f
22 | - e-3 nf
23 | - e-4 nf
24 |
25 | 2a. (e-1 doesn't affect)
26 | - e-2 j <=> e-3 f
27 | - e-2 nf
28 | - e-4 stay
29 |
30 | 2b. (e-3 already justified)
31 | - e-2 j <=> e-4 f
32 | - e-1 j and e-2 j <=> e-3 f
33 | - e-2 nf
34 |
35 | 2c.
36 | - e-1 j and e-2 j <=> e-3 f
37 | - e-2 nf
38 | - e-4 nf
39 |
40 | 3a. impossible
41 |
42 | 3b. (e-3 cannot be justified)
43 | - nothing finalized
44 |
45 | 3c.
46 | - nothing finalized
47 |
48 |
49 |
50 |
51 | ////
52 |
53 |
54 | e-1 -> e-2
55 | - e-2 1-f: iff e-1 j
56 | - e-3 2-f: false
57 |
58 | e-1 -> e-3
59 | - e-2 1-f: false
60 | - e-3 2-f: iff e-1 j and e-2 j
61 |
62 | e-1 -> e-4+
63 | - e-2 1-f: false
64 | - e-3 2-f: false
65 |
66 |
67 | e-2 -> e-3
68 | - e-3 1-f: iff e-2 j
69 | - e-4 2-f: false
70 |
71 | e-2 -> e-4
72 | - e-3 1-f: false
73 | - e-4 2-f: iff e-2 j and e-3 j
74 |
75 | e-2 -> e-5+
76 | - e-3 1-f: false
77 | - e-4 2-f: false
78 |
79 |
80 |
81 | e-2 f: iff e-2 1-f
82 | e-3 f: iff e-3 1-f or e-3 2-f
83 | e-4 f: iff e-4 2-f
84 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/g-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module G-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // processJustification(e - 2) followed by processJustification(e - 1)
8 | // update the entries properly according to the justifiability of e - 2 and e - 1,
9 | // where e is the current epoch.
10 | rule
11 |
12 | case(xor3(
13 | PrevLastJustifiedEpoch processJustification(Epoch2)
20 | ~> processJustification(Epoch1) => .
21 | firstSlotOf(Epoch)
22 |
23 |
24 | firstSlotOf(Epoch3)
25 | Vs
26 | (_, Epoch3BoundaryBlock)
27 | ...
28 |
29 |
30 | firstSlotOf(Epoch2)
31 | Vs
32 | (_, Epoch2BoundaryBlock)
33 | ...
34 |
35 |
36 | firstSlotOf(Epoch1)
37 | Vs
38 | (_, Epoch1BoundaryBlock)
39 |
40 | Epoch3 |-> PrevAttestations3:Attestations
41 | Epoch2 |-> PrevAttestations2:Attestations
42 | ...
43 |
44 |
45 | Epoch3 |-> PrevEpoch3JustifiedBlock:Bool
46 | Epoch2 |-> PrevEpoch2JustifiedBlock:Bool
47 | ...
48 |
49 | PrevLastJustifiedEpoch
50 | ...
51 |
52 |
53 | firstSlotOf(Epoch)
54 | Vs
55 |
56 | Epoch2 |-> Attestations2:Attestations
57 | Epoch1 |-> Attestations1:Attestations
58 | ...
59 |
60 |
61 | Epoch2 |-> (Epoch2JustifiedBlock:Bool => ?NewEpoch2JustifiedBlock:Bool)
62 | Epoch1 |-> (false => ?NewEpoch1JustifiedBlock:Bool)
63 | ...
64 |
65 | LastJustifiedEpoch => ?NewLastJustifiedEpoch
66 | ...
67 |
68 | ...
69 |
70 | ...
71 |
72 | requires true
73 | andBool Epoch1 ==Int Epoch -Int 1
74 | andBool Epoch2 ==Int Epoch -Int 2
75 | andBool Epoch3 ==Int Epoch -Int 3
76 | // invariant
77 | andBool iff(PrevEpoch3JustifiedBlock ==K true, isJustifiable(Epoch3, Epoch3BoundaryBlock, PrevAttestations3, Vs))
78 | andBool iff(PrevEpoch2JustifiedBlock ==K true, isJustifiable(Epoch2, Epoch2BoundaryBlock, PrevAttestations2, Vs))
79 | andBool implies(PrevLastJustifiedEpoch =Int 0
89 | andBool Epoch1 >=Int 0
90 | andBool Epoch2 >=Int 0
91 | andBool Epoch3 >=Int 0
92 | andBool PrevLastJustifiedEpoch >=Int 0
93 | ensures ?NewLastJustifiedEpoch >=Int 0
94 | //
95 | // ensures
96 | //
97 | // justification of e-2 and e-1
98 | andBool iff(?NewEpoch2JustifiedBlock ==K true, isJustifiable(Epoch2, Epoch2BoundaryBlock, Attestations2, Vs))
99 | andBool iff(?NewEpoch1JustifiedBlock ==K true, isJustifiable(Epoch1, Epoch1BoundaryBlock, Attestations1, Vs))
100 | // last justified epoch
101 | andBool implies(?NewLastJustifiedEpoch entries properly according to the justifiability of e - 2 and e - 1,
9 | // where e is the current epoch.
10 | rule
11 |
12 | case(xor2(
13 | PrevLastJustifiedEpoch processJustification(Epoch2)
18 | ~> processJustification(Epoch1) => .
19 | firstSlotOf(Epoch)
20 |
21 |
22 | firstSlotOf(Epoch3)
23 | Vs
24 | (_, Epoch3BoundaryBlock)
25 | ...
26 |
27 |
28 | firstSlotOf(Epoch2)
29 | Vs
30 | (_, Epoch2BoundaryBlock)
31 | ...
32 |
33 |
34 | firstSlotOf(Epoch1)
35 | Vs
36 | (_, Epoch1BoundaryBlock)
37 |
38 | Epoch3 |-> PrevAttestations3:Attestations
39 | Epoch2 |-> PrevAttestations2:Attestations
40 | ...
41 |
42 |
43 | Epoch3 |-> PrevEpoch3JustifiedBlock:Bool
44 | Epoch2 |-> PrevEpoch2JustifiedBlock:Bool
45 | ...
46 |
47 | PrevLastJustifiedEpoch
48 | ...
49 |
50 |
51 | firstSlotOf(Epoch)
52 | Vs
53 |
54 | Epoch2 |-> Attestations2:Attestations
55 | Epoch1 |-> Attestations1:Attestations
56 | ...
57 |
58 |
59 | Epoch2 |-> (Epoch2JustifiedBlock:Bool => ?NewEpoch2JustifiedBlock:Bool)
60 | Epoch1 |-> (false => ?NewEpoch1JustifiedBlock:Bool)
61 | ...
62 |
63 | LastJustifiedEpoch => ?NewLastJustifiedEpoch
64 | ...
65 |
66 | ...
67 |
68 | ...
69 |
70 | requires true
71 | andBool Epoch1 ==Int Epoch -Int 1
72 | andBool Epoch2 ==Int Epoch -Int 2
73 | andBool Epoch3 ==Int Epoch -Int 3
74 | // invariant
75 | andBool iff(PrevEpoch3JustifiedBlock ==K true, isJustifiable(Epoch3, Epoch3BoundaryBlock, PrevAttestations3, Vs))
76 | andBool iff(PrevEpoch2JustifiedBlock ==K true, isJustifiable(Epoch2, Epoch2BoundaryBlock, PrevAttestations2, Vs))
77 | andBool implies(PrevLastJustifiedEpoch =Int 0
87 | andBool Epoch1 >=Int 0
88 | andBool Epoch2 >=Int 0
89 | andBool Epoch3 >=Int 0
90 | andBool PrevLastJustifiedEpoch >=Int 0
91 | ensures ?NewLastJustifiedEpoch >=Int 0
92 | //
93 | // ensures
94 | //
95 | // justification of e-2 and e-1
96 | andBool iff(?NewEpoch2JustifiedBlock ==K true, isJustifiable(Epoch2, Epoch2BoundaryBlock, Attestations2, Vs))
97 | andBool iff(?NewEpoch1JustifiedBlock ==K true, isJustifiable(Epoch1, Epoch1BoundaryBlock, Attestations1, Vs))
98 | // last justified epoch
99 | andBool implies(?NewLastJustifiedEpoch entries properly according to the justifiability of e - 2 and e - 1,
9 | // where e is the current epoch.
10 | rule
11 |
12 | case(xor3(
13 | PrevLastJustifiedEpoch processJustification(Epoch2)
20 | ~> processJustification(Epoch1) => .
21 | firstSlotOf(Epoch)
22 |
23 |
24 | firstSlotOf(Epoch3)
25 | Vs
26 | (_, Epoch3BoundaryBlock)
27 | ...
28 |
29 |
30 | firstSlotOf(Epoch2)
31 | Vs
32 | (_, Epoch2BoundaryBlock)
33 | ...
34 |
35 |
36 | firstSlotOf(Epoch1)
37 | Vs
38 | (_, Epoch1BoundaryBlock)
39 |
40 | Epoch3 |-> PrevAttestations3:Attestations
41 | Epoch2 |-> PrevAttestations2:Attestations
42 | ...
43 |
44 |
45 | Epoch3 |-> PrevEpoch3JustifiedBlock:Bool
46 | Epoch2 |-> PrevEpoch2JustifiedBlock:Bool
47 | ...
48 |
49 | PrevLastJustifiedEpoch
50 | ...
51 |
52 |
53 | firstSlotOf(Epoch)
54 | Vs
55 |
56 | Epoch2 |-> Attestations2:Attestations
57 | Epoch1 |-> Attestations1:Attestations
58 | ...
59 |
60 |
61 | Epoch2 |-> (Epoch2JustifiedBlock:Bool => ?NewEpoch2JustifiedBlock:Bool)
62 | Epoch1 |-> (false => ?NewEpoch1JustifiedBlock:Bool)
63 | ...
64 |
65 | LastJustifiedEpoch => ?NewLastJustifiedEpoch
66 | ...
67 |
68 | ...
69 |
70 | ...
71 |
72 | requires true
73 | andBool Epoch1 ==Int Epoch -Int 1
74 | andBool Epoch2 ==Int Epoch -Int 2
75 | andBool Epoch3 ==Int Epoch -Int 3
76 | // invariant
77 | andBool isGoodState(Epoch3, Epoch3BoundaryBlock, PrevAttestations3, Vs, PrevEpoch3JustifiedBlock,
78 | Epoch2, Epoch2BoundaryBlock, PrevAttestations2, Vs, PrevEpoch2JustifiedBlock,
79 | PrevLastJustifiedEpoch)
80 | //
81 | andBool Epoch2JustifiedBlock ==K PrevEpoch2JustifiedBlock
82 | andBool LastJustifiedEpoch ==Int PrevLastJustifiedEpoch
83 | andBool Attestations2 ==K super(PrevAttestations2)
84 | // ranges
85 | andBool Epoch >=Int 0
86 | andBool Epoch1 >=Int 0
87 | andBool Epoch2 >=Int 0
88 | andBool Epoch3 >=Int 0
89 | andBool PrevLastJustifiedEpoch >=Int 0
90 | ensures ?NewLastJustifiedEpoch >=Int 0
91 | //
92 | // ensures
93 | //
94 | andBool isGoodState(Epoch2, Epoch2BoundaryBlock, Attestations2, Vs, ?NewEpoch2JustifiedBlock,
95 | Epoch1, Epoch1BoundaryBlock, Attestations1, Vs, ?NewEpoch1JustifiedBlock,
96 | ?NewLastJustifiedEpoch)
97 |
98 | endmodule
99 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/k0-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module K0-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // Slot == TargetSlot
8 | rule
9 |
10 | processSlots(TargetSlot) => .
11 | Slot
12 |
13 |
14 | Slot
15 | Vs
16 | SB
17 | AttestedMap
18 | JustifiedMap
19 | FinalizedMap
20 | (LastBlockSlot, LastBlockID)
21 | LastJustifiedEpoch
22 | LastFinalizedEpoch
23 |
24 | ...
25 |
26 | ...
27 |
28 | requires true
29 | andBool TargetSlot ==Int Slot
30 | // types
31 | andBool Slot >=Int 0
32 | andBool LastBlockSlot >=Int 0
33 | andBool LastJustifiedEpoch >=Int 0
34 | andBool LastFinalizedEpoch >=Int 0
35 | ensures true
36 |
37 | endmodule
38 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/k1a-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module K1A-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // Slot + 1 == TargetSlot
8 | // using `...`
9 | rule
10 |
11 | processSlots(TargetSlot) => .
12 | Slot => Slot +Int 1
13 |
14 |
15 | Slot
16 | Vs
17 | SB
18 | AttestedMap
19 | JustifiedMap
20 | FinalizedMap
21 | (LastBlockSlot, LastBlockID)
22 | LastJustifiedEpoch
23 | LastFinalizedEpoch
24 |
25 | (
26 | .Bag
27 | =>
28 |
29 | Slot +Int 1
30 | Vs
31 | SB
32 | AttestedMap
33 | JustifiedMap
34 | FinalizedMap
35 | (LastBlockSlot, LastBlockID)
36 | LastJustifiedEpoch
37 | LastFinalizedEpoch
38 |
39 | )
40 | ...
41 |
42 | ...
43 |
44 | requires true
45 | andBool TargetSlot ==Int Slot +Int 1
46 | andBool isFirstSlotOfEpoch(TargetSlot) ==K false
47 | // types
48 | andBool Slot >=Int 0
49 | andBool LastBlockSlot >=Int 0
50 | andBool LastJustifiedEpoch >=Int 0
51 | andBool LastFinalizedEpoch >=Int 0
52 | ensures true
53 |
54 | endmodule
55 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/k1b-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module K1B-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // Slot + 1 == TargetSlot
8 | // using `_`
9 | rule
10 |
11 | processSlots(TargetSlot) => .
12 | Slot => Slot +Int 1
13 |
14 |
15 | Slot
16 | Vs
17 | SB
18 | AttestedMap
19 | JustifiedMap
20 | FinalizedMap
21 | (LastBlockSlot, LastBlockID)
22 | LastJustifiedEpoch
23 | LastFinalizedEpoch
24 |
25 | (
26 | .Bag
27 | =>
28 |
29 | Slot +Int 1
30 | Vs
31 | SB
32 | AttestedMap
33 | JustifiedMap
34 | FinalizedMap
35 | (LastBlockSlot, LastBlockID)
36 | LastJustifiedEpoch
37 | LastFinalizedEpoch
38 |
39 | )
40 | _ // NOTE: `_` instead of `...`
41 |
42 | ...
43 |
44 | requires true
45 | andBool TargetSlot ==Int Slot +Int 1
46 | andBool isFirstSlotOfEpoch(TargetSlot) ==K false
47 | // types
48 | andBool Slot >=Int 0
49 | andBool LastBlockSlot >=Int 0
50 | andBool LastJustifiedEpoch >=Int 0
51 | andBool LastFinalizedEpoch >=Int 0
52 | ensures true
53 |
54 | endmodule
55 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/k2a-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module K2A-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // Slot + 2 == TargetSlot
8 | // explicit
9 | rule
10 |
11 | processSlots(TargetSlot) => .
12 | Slot => TargetSlot
13 |
14 |
15 | Slot
16 | Vs
17 | SB
18 | AttestedMap
19 | JustifiedMap
20 | FinalizedMap
21 | (LastBlockSlot, LastBlockID)
22 | LastJustifiedEpoch
23 | LastFinalizedEpoch
24 |
25 | (
26 | .Bag
27 | =>
28 |
29 | Slot +Int 1
30 | Vs
31 | SB
32 | AttestedMap
33 | JustifiedMap
34 | FinalizedMap
35 | (LastBlockSlot, LastBlockID)
36 | LastJustifiedEpoch
37 | LastFinalizedEpoch
38 |
39 |
40 | TargetSlot
41 | Vs
42 | SB
43 | AttestedMap
44 | JustifiedMap
45 | FinalizedMap
46 | (LastBlockSlot, LastBlockID)
47 | LastJustifiedEpoch
48 | LastFinalizedEpoch
49 |
50 | )
51 | _
52 |
53 | ...
54 |
55 | requires true
56 | andBool TargetSlot ==Int Slot +Int 2
57 | andBool isFirstSlotOfEpoch(Slot +Int 1) ==K false
58 | andBool isFirstSlotOfEpoch(TargetSlot) ==K false
59 | // types
60 | andBool Slot >=Int 0
61 | andBool LastBlockSlot >=Int 0
62 | andBool LastJustifiedEpoch >=Int 0
63 | andBool LastFinalizedEpoch >=Int 0
64 | ensures true
65 |
66 | endmodule
67 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/k2b-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module K2B-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // Slot + 2 == TargetSlot
8 | // using `?_`
9 | rule
10 |
11 | processSlots(TargetSlot) => .
12 | Slot => TargetSlot
13 |
14 |
15 | Slot
16 | Vs
17 | SB
18 | AttestedMap
19 | JustifiedMap
20 | FinalizedMap
21 | (LastBlockSlot, LastBlockID)
22 | LastJustifiedEpoch
23 | LastFinalizedEpoch
24 |
25 | (
26 | .Bag
27 | =>
28 | ?_ // NOTE: this captures (zero or more) other 's
29 |
30 | TargetSlot
31 | Vs
32 | SB
33 | AttestedMap
34 | JustifiedMap
35 | FinalizedMap
36 | (LastBlockSlot, LastBlockID)
37 | LastJustifiedEpoch
38 | LastFinalizedEpoch
39 |
40 | )
41 | _
42 |
43 | ...
44 |
45 | requires true
46 | andBool TargetSlot ==Int Slot +Int 2
47 | andBool isFirstSlotOfEpoch(Slot +Int 1) ==K false
48 | andBool isFirstSlotOfEpoch(TargetSlot) ==K false
49 | // types
50 | andBool Slot >=Int 0
51 | andBool LastBlockSlot >=Int 0
52 | andBool LastJustifiedEpoch >=Int 0
53 | andBool LastFinalizedEpoch >=Int 0
54 | ensures true
55 |
56 | endmodule
57 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/kn1-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module KN1-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // TODO: when Slot == Target, the additional cell should be idempotent
8 | // when Slot < Target, it needs to know that: lastSlotOf(epochOf(Slot)) == lastSlotOf(epochOf(Slot + 1))
9 | /*
10 | rule lastSlotOf(epochOf(Slot)) ==K lastSlotOf(epochOf(Slot +Int 1)) => true
11 | requires Slot < lastSlotOf(epochOf(Slot))
12 |
13 | rule lastSlotOf(epochOf(Slot +Int 1)) ==K lastSlotOf(epochOf(Slot)) => true
14 | requires Slot < lastSlotOf(epochOf(Slot))
15 | */
16 |
17 | // Slot + N == TargetSlot
18 | // where 0 <= N <= SLOTS_PER_EPOCH - 1
19 | // loop invariant
20 | // Slot <= TargetSlot
21 | rule
22 |
23 | processSlots(TargetSlot) => .
24 | Slot => TargetSlot
25 |
26 |
27 | Slot
28 | Vs
29 | SB
30 | AttestedMap
31 | JustifiedMap
32 | FinalizedMap
33 | (LastBlockSlot, LastBlockID)
34 | LastJustifiedEpoch
35 | LastFinalizedEpoch
36 |
37 | (
38 | .Bag
39 | =>
40 | ?_ // NOTE: this captures (zero or more) other s
41 |
42 | TargetSlot
43 | Vs
44 | SB
45 | AttestedMap
46 | JustifiedMap
47 | FinalizedMap
48 | (LastBlockSlot, LastBlockID)
49 | LastJustifiedEpoch
50 | LastFinalizedEpoch
51 |
52 | )
53 | _
54 |
55 | ...
56 |
57 | requires true
58 | andBool Slot <=Int TargetSlot
59 | andBool TargetSlot ==Int lastSlotOf(epochOf(Slot)) // NOTE: this already implies Slot <=Int TargetSlot
60 | // types
61 | andBool Slot >=Int 0
62 | andBool TargetSlot >=Int 0
63 | andBool LastBlockSlot >=Int 0
64 | andBool LastJustifiedEpoch >=Int 0
65 | andBool LastFinalizedEpoch >=Int 0
66 | ensures true
67 |
68 | endmodule
69 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/kn2-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module KN2-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // TODO: it needs to know that: Slot + N == lastSlotOf(epochOf(Slot))
8 | /*
9 | rule (Slot +Int N) %Int SLOTS_PER_EPOCH ==K 0 => false // isFirstSlotOfEpoch(Slot +Int N) => false
10 | requires (Slot +Int N) <=Int lastSlotOf(epochOf(Slot))
11 | */
12 | /* not needed
13 | rule Slot +Int (SLOTS_PER_EPOCH -Int 1) false
14 | */
15 |
16 | // Slot + N == TargetSlot
17 | // where 1 <= N <= SLOTS_PER_EPOCH - 1
18 | // loop invariant
19 | // Slot < TargetSlot
20 | rule
21 |
22 | processSlots(TargetSlot) => .
23 | Slot => TargetSlot
24 |
25 |
26 | Slot
27 | Vs
28 | SB
29 | AttestedMap
30 | JustifiedMap
31 | FinalizedMap
32 | (LastBlockSlot, LastBlockID)
33 | LastJustifiedEpoch
34 | LastFinalizedEpoch
35 |
36 | (
37 | .Bag
38 | =>
39 | ?_ // NOTE: this captures (zero or more) other s
40 |
41 | TargetSlot
42 | Vs
43 | SB
44 | AttestedMap
45 | JustifiedMap
46 | FinalizedMap
47 | (LastBlockSlot, LastBlockID)
48 | LastJustifiedEpoch
49 | LastFinalizedEpoch
50 |
51 | )
52 | _
53 |
54 | ...
55 |
56 | requires true
57 | andBool Slot =Int 0
61 | andBool TargetSlot >=Int 0
62 | andBool LastBlockSlot >=Int 0
63 | andBool LastJustifiedEpoch >=Int 0
64 | andBool LastFinalizedEpoch >=Int 0
65 | ensures true
66 |
67 | endmodule
68 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/l.smt2:
--------------------------------------------------------------------------------
1 | ;
2 | ; definitions
3 | ;
4 |
5 | (define-fun max ((x Int) (y Int)) Int (ite (> x y) x y))
6 |
7 | (define-sort M () (Array Int Int))
8 |
9 | ; return the max value of a map
10 | (declare-fun maxM (M) Int)
11 | ; axiomatization
12 | (assert (forall ((m M) (x Int) (v Int))
13 | (= (maxM (store m x v))
14 | (max v (maxM m))
15 | )
16 | ))
17 |
18 | ; count the number of the given value
19 | (declare-fun count (M Int) Int)
20 | ; axiomatization
21 | ;TODO: why this is unsat?
22 | ;(assert (forall ((m M) (x Int) (v Int))
23 | ; (= (count (store m x v) v)
24 | ; (+ (count m v) 1)
25 | ; )
26 | ;))
27 | (assert (forall ((m M) (x Int) (v Int) (w Int))
28 | (and
29 | (=> (not (= (select m x) w))
30 | (= (count (store m x v) w)
31 | (+ (count m w) (ite (= v w) 1 0))
32 | )
33 | )
34 | (=> (= (select m x) w)
35 | (= (count (store m x v) w)
36 | (+ (count m w) (ite (= v w) 0 -1))
37 | )
38 | )
39 | )
40 | ))
41 | ; count cannot be negative
42 | (assert (forall ((m M) (v Int))
43 | (>= (count m v) 0)
44 | ))
45 |
46 | ; count beyond the maximum value is zero
47 | (assert (forall ((m M) (v Int))
48 | (=> (> v (maxM m))
49 | (= (count m v) 0)
50 | )
51 | ))
52 |
53 | ;
54 | ; theorems
55 | ;
56 |
57 | ; validity property
58 | (define-fun isValid ((m M) (l Int)) Bool
59 | (forall ((e Int))
60 | (=> (and (<= 0 e) (<= e (maxM m)))
61 | (<= (count m e) l)
62 | )
63 | )
64 | )
65 |
66 | ; original map
67 | (declare-const m M)
68 | (declare-const x Int)
69 |
70 | ; e: current epoch
71 | (declare-const e Int)
72 | (assert (>= e 0))
73 |
74 | ; l = limit >= 4
75 | (declare-const l Int)
76 | (assert (>= l 4))
77 |
78 | ; v = max (maxM m) (e + 4)
79 | (declare-const v Int)
80 | (assert (= v (max (maxM m) (+ e 4))))
81 |
82 | ; w = new value
83 | (declare-const w Int)
84 | (assert (= w (ite (= (count m v) l) (+ v 1) v)))
85 |
86 | ; pre-condition: m is valid
87 | (assert (isValid m l))
88 | ; x is empty
89 | (assert (= (select m x) -1))
90 |
91 | ; updated map: m2 = m [ x <- w ]
92 | (declare-const m2 M)
93 | (assert (= m2 (store m x w)))
94 |
95 | ; verify post-condition: m2 is still valid
96 | (assert (not
97 | (isValid m2 l)
98 | ))
99 |
100 | (check-sat)
101 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/l1-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module L1-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | initiateValidatorExit(V) => .
10 | Slot
11 |
12 |
13 | Slot
14 | v(VM1 => ?VM2, _)
15 | ...
16 |
17 | ...
18 |
19 | ...
20 |
21 | requires true
22 | andBool V.exit_epoch ==Int FAR_FUTURE_EPOCH
23 | // types
24 | andBool Slot >=Int 0
25 | ensures true
26 | andBool ?VM2[V.id]v.exit_epoch >=Int delayedActivationExitEpoch(epochOf(Slot))
27 |
28 | endmodule
29 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/l2-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module L2-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | case(xor2(
10 | countValidatorsToExit(v(VM1,VIDs), ?LastExitEpoch) >=Int ?ChurnLimit
11 | ,
12 | countValidatorsToExit(v(VM1,VIDs), ?LastExitEpoch) initiateValidatorExit(V) => .
15 | Slot
16 |
17 |
18 | Slot
19 | v(VM1 => ?VM2, VIDs)
20 | ...
21 |
22 | ...
23 |
24 | ...
25 |
26 | requires true
27 | // types
28 | andBool Slot >=Int 0
29 | // let-bindings
30 | andBool ?Epoch ==Int epochOf(Slot)
31 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(v(VM1,VIDs)), delayedActivationExitEpoch(?Epoch))
32 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(VM1,VIDs), ?Epoch)))
33 | // conditions
34 | andBool V.id in VIDs
35 | andBool V.exit_epoch ==Int FAR_FUTURE_EPOCH
36 | andBool VM1[V.id]v ==K V
37 | andBool ?LastExitEpoch +Int 1 =Int delayedActivationExitEpoch(?Epoch)
43 | andBool countValidatorsToExit(v(?VM2,VIDs), ?VM2[V.id]v.exit_epoch) <=Int ?ChurnLimit
44 | /*
45 | andBool activeValidators(v(VM1,VIDs), ?Epoch) ==K activeValidators(v(?VM2,VIDs), ?Epoch)
46 | */
47 |
48 | endmodule
49 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/l3-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module L3-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | /* case(xor2(
10 | countValidatorsToExit(v(VM1,VIDs), ?LastExitEpoch) >=Int ?ChurnLimit
11 | ,
12 | countValidatorsToExit(v(VM1,VIDs), ?LastExitEpoch) */ initiateValidatorExit(V) => .K ...
15 | Slot
16 |
17 |
18 | Slot
19 | v(VM1 => VM1 [ V.id <- ?V2 ]v, VIDs)
20 | ...
21 |
22 | ...
23 |
24 | ...
25 |
26 | requires true
27 | // types
28 | andBool Slot >=Int 0
29 | // let-bindings
30 | andBool ?Epoch ==Int epochOf(Slot)
31 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(v(VM1,VIDs)), delayedActivationExitEpoch(?Epoch))
32 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(VM1,VIDs), ?Epoch)))
33 | // conditions
34 | andBool V.id in VIDs
35 | andBool V.exit_epoch ==Int FAR_FUTURE_EPOCH
36 | andBool VM1[V.id]v ==K V
37 | andBool ?LastExitEpoch +Int 1 =Int delayedActivationExitEpoch(?Epoch)
44 | andBool countValidatorsToExit(v(VM1 [ V.id <- ?V2 ]v, VIDs), ?V2.exit_epoch) <=Int ?ChurnLimit
45 | /*
46 | andBool activeValidators(v(VM1,VIDs), ?Epoch) ==K activeValidators(v(VM1 [ V.id <- ?V2 ]v, VIDs), ?Epoch)
47 | */
48 | [matching(storeV)]
49 |
50 | endmodule
51 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/l4-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module L4-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processVoluntaryExits(VEs) => .
10 | Slot
11 |
12 |
13 | Slot
14 | v(VM, VIDs) => ?VS2
15 | ...
16 |
17 | ...
18 |
19 | ...
20 |
21 | requires true
22 | // types
23 | andBool Slot >=Int 0
24 | // let-bindings
25 | andBool ?Epoch ==Int epochOf(Slot)
26 | // conditions
27 | andBool isValidVoluntaryExits(VEs, VM, ?Epoch, VIDs)
28 | ensures true
29 | // ensures
30 | andBool ?VS2 ==K storeValidatorExits(v(VM, VIDs), VEs, ?Epoch)
31 |
32 | endmodule
33 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/l5-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 | require "l3-spec.k"
3 |
4 | module L5-SPEC
5 |
6 | imports VERIFICATION
7 | imports L3-SPEC
8 |
9 | rule
10 |
11 | processVoluntaryExits(VEs) => .K ...
12 | Slot
13 |
14 |
15 | Slot
16 | v(VM1 => ?VM2, VIDs)
17 | ...
18 |
19 | ...
20 |
21 | ...
22 |
23 | requires true
24 | // types
25 | andBool Slot >=Int 0
26 | // let-bindings
27 | andBool ?Epoch ==Int epochOf(Slot)
28 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(v(VM1,VIDs)), delayedActivationExitEpoch(?Epoch))
29 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(VM1,VIDs), ?Epoch)))
30 | // conditions
31 | andBool isValidVoluntaryExits(VEs, VM1, ?Epoch, VIDs)
32 | andBool ?LastExitEpoch +Int sizeE(VEs)
9 | processVoluntaryExits(VEs) => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(m(SM, BM, EBM, AEM, AM, EM1 => ?EM2, WM1 => ?WM2), VIDs)
15 | ...
16 |
17 | ...
18 |
19 | ...
20 |
21 | requires true
22 | // types
23 | andBool Slot >=Int 0
24 | // let-bindings
25 | andBool ?Epoch ==Int epochOf(Slot)
26 | andBool ?VM1 ==K m(SM, BM, EBM, AEM, AM, EM1, WM1)
27 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(v(?VM1, VIDs)), delayedActivationExitEpoch(?Epoch))
28 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(?VM1, VIDs), ?Epoch)))
29 | // pre-conditions
30 | andBool ?LastExitEpoch +Int sizeE(VEs) =Int delayedActivationExitEpoch(?Epoch))
38 | andBool forall(x, getValidatorsE(VEs), ?EM2[x]i
43 | processVoluntaryExitsAux(L_VIDs, R_VEs, m(SM, BM, EBM, AEM, AM, EM0, WM0)) => .K ...
44 | Slot
45 |
46 |
47 | Slot
48 | v(m(SM, BM, EBM, AEM, AM, EM1 => ?EM2, WM1 => ?WM2), VIDs)
49 | ...
50 |
51 | ...
52 |
53 | ...
54 |
55 | requires true
56 | // types
57 | andBool Slot >=Int 0
58 | // let-bindings
59 | andBool ?Epoch ==Int epochOf(Slot)
60 | andBool ?VM0 ==K m(SM, BM, EBM, AEM, AM, EM0, WM0)
61 | andBool ?VM1 ==K m(SM, BM, EBM, AEM, AM, EM1, WM1)
62 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(v(?VM1, VIDs)), delayedActivationExitEpoch(?Epoch))
63 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(?VM1, VIDs), ?Epoch)))
64 | // pre-conditions
65 | andBool ?LastExitEpoch +Int sizeE(R_VEs) =Int delayedActivationExitEpoch(?Epoch))
74 | andBool forall(x, rev(L_VIDs) , EM1[x]i =Int delayedActivationExitEpoch(?Epoch))
79 | andBool forall(x, rev(L_VIDs) ++ getValidatorsE(R_VEs), ?EM2[x]i
9 | processValidatorActivation() => activateValidators(?ValidatorsToBeActivated)
10 | Slot
11 |
12 |
13 | Slot
14 | Validators
15 | FinalizedEpoch
16 | ...
17 |
18 | ...
19 |
20 | ...
21 |
22 | requires true
23 | // types
24 | andBool Slot >=Int 0
25 | // let-bindings
26 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
27 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(Validators, ?Epoch)))
28 | ensures true
29 | // ensures
30 | andBool sizeV(?ValidatorsToBeActivated) <=Int ?ChurnLimit
31 | andBool subsetV(?ValidatorsToBeActivated, activationQueue(Validators, FinalizedEpoch))
32 |
33 | // inductive case
34 | rule
35 |
36 | activateValidators(V Vs => Vs)
37 | Slot
38 |
39 |
40 | Slot
41 | v(VM1 => ?VM2, _)
42 | ...
43 |
44 | ...
45 |
46 | ...
47 |
48 | requires true
49 | // types
50 | andBool Slot >=Int 0
51 | // let-bindings
52 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
53 | ensures true
54 | // ensures
55 | andBool ?VM2[V.id]v.activation_epoch ==Int delayedActivationExitEpoch(?Epoch)
56 |
57 | // base case
58 | rule
59 |
60 | activateValidators(.ValidatorList) => .
61 | ...
62 |
63 |
64 | endmodule
65 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/m2-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module M2-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processValidatorActivation() => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(VM1 => ?VM2, VIDs)
15 | FinalizedEpoch
16 | ...
17 |
18 | ...
19 |
20 | ...
21 |
22 | requires true
23 | // types
24 | andBool Slot >=Int 0
25 | // let-bindings
26 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
27 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(VM1, VIDs), ?Epoch)))
28 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch)
29 | andBool ?ValidatorsToBeActivated ==K activationQueueUptoChurnLimit(v(VM1, VIDs), FinalizedEpoch, ?Epoch)
30 | // conditions
31 | andBool ?ActivationEpoch
41 | activateValidators(Vs) => .K ...
42 | Slot
43 |
44 |
45 | Slot
46 | v(VM1 => ?VM2, VIDs)
47 | FinalizedEpoch
48 | ...
49 |
50 | ...
51 |
52 | ...
53 |
54 | requires true
55 | // types
56 | andBool Slot >=Int 0
57 | // let-bindings
58 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
59 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(VM1, VIDs), ?Epoch)))
60 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch)
61 | // conditions
62 | andBool ?ActivationEpoch
9 | processValidatorActivation() => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(m(SM, BM, EBM, AEM, AM1 => ?AM2, EM, WM), VIDs)
15 | FinalizedEpoch
16 | ...
17 |
18 | ...
19 |
20 | ...
21 |
22 | requires true
23 | // types
24 | andBool Slot >=Int 0
25 | // let-bindings
26 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
27 | andBool ?VM1 ==K m(SM, BM, EBM, AEM, AM1, EM, WM)
28 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(?VM1, VIDs), ?Epoch)))
29 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch)
30 | andBool ?ValidatorsToBeActivated ==K activationQueueUptoChurnLimit(v(?VM1, VIDs), FinalizedEpoch, ?Epoch)
31 | // pre-conditions
32 | andBool distinct(VIDs)
33 | andBool ?ActivationEpoch
43 | activateValidators(R_VIDs) => .K ...
44 | Slot
45 |
46 |
47 | Slot
48 | v(m(SM, BM, EBM, AEM, AM1 => ?AM2, EM, WM), VIDs)
49 | FinalizedEpoch
50 | ...
51 |
52 | ...
53 |
54 | ...
55 |
56 | requires true
57 | // types
58 | andBool Slot >=Int 0
59 | // let-bindings
60 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
61 | andBool ?VM1 ==K m(SM, BM, EBM, AEM, AM1, EM, WM)
62 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(?VM1, VIDs), ?Epoch)))
63 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch)
64 | // pre-conditions
65 | andBool distinct(R_VIDs)
66 | andBool forall(x, R_VIDs, isValidValidatorToActivate(x, ?VM1, FinalizedEpoch))
67 | andBool forall(x, R_VIDs, x in VIDs)
68 | andBool ?ActivationEpoch
78 | activateValidatorsAux(L_VIDs, R_VIDs, m(SM, BM, EBM, AEM, AM0, EM, WM)) => .K ...
79 | Slot
80 |
81 |
82 | Slot
83 | v(m(SM, BM, EBM, AEM, AM1 => ?AM2, EM, WM), VIDs)
84 | FinalizedEpoch
85 | ...
86 |
87 | ...
88 |
89 | ...
90 |
91 | requires true
92 | // types
93 | andBool Slot >=Int 0
94 | // let-bindings
95 | andBool ?Epoch ==Int epochOf(Slot) -Int 1
96 | andBool ?VM0 ==K m(SM, BM, EBM, AEM, AM0, EM, WM)
97 | andBool ?VM1 ==K m(SM, BM, EBM, AEM, AM1, EM, WM)
98 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(?VM1, VIDs), ?Epoch)))
99 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch)
100 | // pre-conditions
101 | andBool distinct(R_VIDs)
102 | andBool ?ActivationEpoch = x 0))
12 | (assert (>= y 0))
13 | (assert (>= z 0))
14 | (assert (>= n 0))
15 |
16 | (assert (>= b 0))
17 | (assert (>= a 0))
18 | (assert (>= t 0))
19 | (assert (>= d 0))
20 |
21 | ; rule getBaseReward(EffectiveBalance, TotalActiveBalance)
22 | ; => EffectiveBalance *Int BASE_REWARD_FACTOR
23 | ; /Int sqrtInt(TotalActiveBalance)
24 | ; /Int BASE_REWARDS_PER_EPOCH
25 | (define-fun getBaseReward ((b Int) (sqrt_t Int)) Int (div (div (* b 64) sqrt_t) 4))
26 |
27 | (declare-const sqrt_t Int)
28 | (assert (>= sqrt_t 0))
29 |
30 | (push)
31 | ; rule getBaseReward(B, T) <=Int B => true requires B >=Int 0 andBool T >=Int 256
32 | (assert (not (=>
33 | (and
34 | (>= (^ sqrt_t 2) 256)
35 | )
36 | (<= (getBaseReward b sqrt_t) b)
37 | )))
38 | (check-sat)
39 | (pop)
40 |
41 | (push)
42 | ; rule getBaseReward(B, T) >=Int 0 => true requires B >=Int 0 andBool T >=Int 1
43 | (assert (not (=>
44 | (and
45 | (>= (^ sqrt_t 2) 1)
46 | )
47 | (>= (getBaseReward b sqrt_t) 0)
48 | )))
49 | (check-sat)
50 | (pop)
51 |
52 | ; rule getMatchingReward(BaseReward, AttestingBalance, TotalActiveBalance)
53 | ; => BaseReward *Int (AttestingBalance /Int EFFECTIVE_BALANCE_INCREMENT)
54 | ; /Int (TotalActiveBalance /Int EFFECTIVE_BALANCE_INCREMENT)
55 | (define-const c Int (^ 10 9))
56 | (define-fun getMatchingReward ((b Int) (a Int) (t Int)) Int (div (* b (div a c)) (div t c)))
57 |
58 | (push)
59 | ; rule getMatchingReward(B, A, T) <=Int B => true requires B >=Int 0 andBool A >=Int 0 andBool T >=Int EFFECTIVE_BALANCE_INCREMENT andBool A <=Int T
60 | (assert (not (=>
61 | (and
62 | (>= t c)
63 | (<= a t)
64 | )
65 | (<= (getMatchingReward b a t) b)
66 | )))
67 | (check-sat)
68 | (pop)
69 |
70 | (push)
71 | ; rule getMatchingReward(B, A, T) >=Int 0 => true requires B >=Int 0 andBool A >=Int 0 andBool T >=Int EFFECTIVE_BALANCE_INCREMENT
72 | (assert (not (=>
73 | (and
74 | (>= t c)
75 | )
76 | (>= (getMatchingReward b a t) 0)
77 | )))
78 | (check-sat)
79 | (pop)
80 |
81 | ; rule getInclusionReward(BaseReward, InclusionDelay)
82 | ; => (BaseReward -Int BaseReward /Int PROPOSER_REWARD_QUOTIENT) /Int InclusionDelay
83 | (define-fun getInclusionReward ((b Int) (d Int)) Int (div (- b (div b 8)) d))
84 |
85 | (push)
86 | ; rule getInclusionReward(B, D) <=Int B => true requires B >=Int 0 andBool D >=Int 1
87 | (assert (not (=>
88 | (and
89 | (>= d 1)
90 | )
91 | (<= (getInclusionReward b d) b)
92 | )))
93 | (check-sat)
94 | (pop)
95 |
96 | (push)
97 | ; rule getInclusionReward(B, D) >=Int 0 => true requires B >=Int 0 andBool D >=Int 1
98 | (assert (not (=>
99 | (and
100 | (>= d 1)
101 | )
102 | (>= (getInclusionReward b d) 0)
103 | )))
104 | (check-sat)
105 | (pop)
106 |
107 | ; rule getInactivityPenalty(EffectiveBalance, FinalityDelay)
108 | ; => EffectiveBalance *Int FinalityDelay /Int INACTIVITY_PENALTY_QUOTIENT
109 | (define-fun getInactivityPenalty ((b Int) (d Int)) Int (div (* b d) (^ 2 25)))
110 |
111 | (push)
112 | ; rule getInactivityPenalty(B, D) >=Int 0 => true requires B >=Int 0 andBool D >=Int 0
113 | (assert (not (=>
114 | (and
115 | true
116 | )
117 | (>= (getInactivityPenalty b d) 0)
118 | )))
119 | (check-sat)
120 | (pop)
121 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/n1-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module N1-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardPenalty(V, ?Epoch, ?FinalityDelay, ?BaseReward,
10 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
11 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .
12 | Slot
13 |
14 |
15 | Slot
16 | v(VM1 => ?VM2, VIDs)
17 |
18 | Epoch |-> Attestations:Attestations
19 | ...
20 |
21 | LastFinalizedEpoch
22 | ...
23 |
24 |
25 | firstSlotOf(Epoch)
26 | (_, EpochBoundaryBlock)
27 | ...
28 |
29 | BM
30 | ...
31 |
32 | ...
33 |
34 | requires true
35 |
36 | andBool ( isActiveValidator(V, ?Epoch) orBool ( V.slashed andBool ?Epoch +Int 1 =Int 1)
43 |
44 | // types
45 | andBool Slot >=Int 0
46 | andBool ?Epoch >=Int 0
47 | andBool ?FinalityDelay >=Int 0
48 | andBool ?BaseReward >=Int 0
49 | andBool ?SourceAttestingBalance >=Int 0
50 | andBool ?TargetAttestingBalance >=Int 0
51 | andBool ?HeadAttestingBalance >=Int 0
52 | andBool ?TotalActiveBalance >=Int 0
53 | // let-bindings
54 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
55 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
56 | andBool ?BaseReward ==Int getBaseReward(V, ?TotalActiveBalance)
57 | andBool ?SourceAttestations ==K filterNotSlashed(VM1, Attestations)
58 | andBool ?TargetAttestations ==K filterByTarget(EpochBoundaryBlock, ?SourceAttestations)
59 | andBool ?HeadAttestations ==K filterByHead(BM, ?TargetAttestations)
60 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?SourceAttestations)))
61 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?TargetAttestations)))
62 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?HeadAttestations)))
63 | andBool ?TotalActiveBalance ==Int lift(totalBalance(VM1, activeValidators(v(VM1,VIDs), ?Epoch)))
64 | // conditions
65 | andBool ?Epoch >=Int 2
66 | // invariants
67 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
68 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
69 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
70 | // consistency conditions
71 | andBool V.id in VIDs andBool VM1[V.id]v ==K V
72 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).proposer in VIDs)
73 | ensures true
74 | // ensures
75 |
76 | andBool ?VM2[V.id]v.balance <=Int VM1[V.id]v.balance +Int ?BaseReward +Int ?BaseReward +Int ?BaseReward +Int ?BaseReward
77 |
78 | andBool ?VM2[V.id]v.balance ==Int VM1[V.id]v.balance +Int (?BaseReward *Int (?SourceAttestingBalance /Int EFFECTIVE_BALANCE_INCREMENT)
79 | /Int (?TotalActiveBalance /Int EFFECTIVE_BALANCE_INCREMENT))
80 | +Int (?BaseReward *Int (?TargetAttestingBalance /Int EFFECTIVE_BALANCE_INCREMENT)
81 | /Int (?TotalActiveBalance /Int EFFECTIVE_BALANCE_INCREMENT))
82 | +Int (?BaseReward *Int (?HeadAttestingBalance /Int EFFECTIVE_BALANCE_INCREMENT)
83 | /Int (?TotalActiveBalance /Int EFFECTIVE_BALANCE_INCREMENT))
84 | +Int ((?BaseReward -Int ?BaseReward /Int PROPOSER_REWARD_QUOTIENT) /Int minByInclusionDelay(V.id, ?SourceAttestations).inclusion_delay)
85 |
86 | endmodule
87 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/n2-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module N2-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardPenalty(V, ?Epoch, ?FinalityDelay, ?BaseReward,
10 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
11 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .
12 | Slot
13 |
14 |
15 | Slot
16 | v(VM1 => ?VM2, VIDs)
17 |
18 | Epoch |-> Attestations:Attestations
19 | ...
20 |
21 | LastFinalizedEpoch
22 | ...
23 |
24 |
25 | firstSlotOf(Epoch)
26 | (_, EpochBoundaryBlock)
27 | ...
28 |
29 | BM
30 | ...
31 |
32 | ...
33 |
34 | requires true
35 |
36 | andBool ( isActiveValidator(V, ?Epoch) orBool ( V.slashed andBool ?Epoch +Int 1 =Int 1)
43 |
44 | // types
45 | andBool Slot >=Int 0
46 | andBool ?Epoch >=Int 0
47 | andBool ?FinalityDelay >=Int 0
48 | andBool ?BaseReward >=Int 0
49 | andBool ?SourceAttestingBalance >=Int 0
50 | andBool ?TargetAttestingBalance >=Int 0
51 | andBool ?HeadAttestingBalance >=Int 0
52 | andBool ?TotalActiveBalance >=Int 0
53 | // let-bindings
54 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
55 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
56 | andBool ?BaseReward ==Int getBaseReward(V, ?TotalActiveBalance)
57 | andBool ?SourceAttestations ==K filterNotSlashed(VM1, Attestations)
58 | andBool ?TargetAttestations ==K filterByTarget(EpochBoundaryBlock, ?SourceAttestations)
59 | andBool ?HeadAttestations ==K filterByHead(BM, ?TargetAttestations)
60 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?SourceAttestations)))
61 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?TargetAttestations)))
62 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?HeadAttestations)))
63 | andBool ?TotalActiveBalance ==Int lift(totalBalance(VM1, activeValidators(v(VM1,VIDs), ?Epoch)))
64 | // conditions
65 | andBool ?Epoch >=Int 2
66 | // invariants
67 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
68 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
69 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
70 | // consistency conditions
71 | andBool V.id in VIDs andBool VM1[V.id]v ==K V
72 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).proposer in VIDs)
73 | ensures true
74 | // ensures
75 |
76 | andBool ?VM2[V.id]v.balance ==Int VM1[V.id]v.balance -Int ?BaseReward *Int 3
77 |
78 | endmodule
79 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/n3-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module N3-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardPenalty(V, ?Epoch, ?FinalityDelay, ?BaseReward,
10 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
11 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .
12 | Slot
13 |
14 |
15 | Slot
16 | v(VM1 => ?VM2, VIDs)
17 |
18 | Epoch |-> Attestations:Attestations
19 | ...
20 |
21 | LastFinalizedEpoch
22 | ...
23 |
24 |
25 | firstSlotOf(Epoch)
26 | (_, EpochBoundaryBlock)
27 | ...
28 |
29 | BM
30 | ...
31 |
32 | ...
33 |
34 | requires true
35 |
36 | andBool ( isActiveValidator(V, ?Epoch) orBool ( V.slashed andBool ?Epoch +Int 1 Int MIN_EPOCHS_TO_INACTIVITY_PENALTY
41 | andBool implies(V.id inA ?SourceAttestations, V.id =/=Int minByInclusionDelay(V.id, ?SourceAttestations).proposer)
42 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).inclusion_delay >=Int 1)
43 |
44 | // types
45 | andBool Slot >=Int 0
46 | andBool ?Epoch >=Int 0
47 | andBool ?FinalityDelay >=Int 0
48 | andBool ?BaseReward >=Int 0
49 | andBool ?SourceAttestingBalance >=Int 0
50 | andBool ?TargetAttestingBalance >=Int 0
51 | andBool ?HeadAttestingBalance >=Int 0
52 | andBool ?TotalActiveBalance >=Int 0
53 | // let-bindings
54 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
55 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
56 | andBool ?BaseReward ==Int getBaseReward(V, ?TotalActiveBalance)
57 | andBool ?SourceAttestations ==K filterNotSlashed(VM1, Attestations)
58 | andBool ?TargetAttestations ==K filterByTarget(EpochBoundaryBlock, ?SourceAttestations)
59 | andBool ?HeadAttestations ==K filterByHead(BM, ?TargetAttestations)
60 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?SourceAttestations)))
61 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?TargetAttestations)))
62 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?HeadAttestations)))
63 | andBool ?TotalActiveBalance ==Int lift(totalBalance(VM1, activeValidators(v(VM1,VIDs), ?Epoch)))
64 | // conditions
65 | andBool ?Epoch >=Int 2
66 | // invariants
67 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
68 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
69 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
70 | // consistency conditions
71 | andBool V.id in VIDs andBool VM1[V.id]v ==K V
72 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).proposer in VIDs)
73 | ensures true
74 | // ensures
75 |
76 | andBool ?VM2[V.id]v.balance <=Int VM1[V.id]v.balance +Int ?BaseReward +Int ?BaseReward +Int ?BaseReward +Int ?BaseReward +Int (0 -Int BASE_REWARDS_PER_EPOCH *Int ?BaseReward)
77 |
78 | andBool ?VM2[V.id]v.balance ==Int VM1[V.id]v.balance +Int (?BaseReward *Int (?SourceAttestingBalance /Int EFFECTIVE_BALANCE_INCREMENT)
79 | /Int (?TotalActiveBalance /Int EFFECTIVE_BALANCE_INCREMENT))
80 | +Int (?BaseReward *Int (?TargetAttestingBalance /Int EFFECTIVE_BALANCE_INCREMENT)
81 | /Int (?TotalActiveBalance /Int EFFECTIVE_BALANCE_INCREMENT))
82 | +Int (?BaseReward *Int (?HeadAttestingBalance /Int EFFECTIVE_BALANCE_INCREMENT)
83 | /Int (?TotalActiveBalance /Int EFFECTIVE_BALANCE_INCREMENT))
84 | +Int ((?BaseReward -Int ?BaseReward /Int PROPOSER_REWARD_QUOTIENT) /Int minByInclusionDelay(V.id, ?SourceAttestations).inclusion_delay)
85 | +Int (0 -Int BASE_REWARDS_PER_EPOCH *Int ?BaseReward)
86 |
87 | endmodule
88 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/n4-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module N4-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardPenalty(V, ?Epoch, ?FinalityDelay, ?BaseReward,
10 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
11 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .
12 | Slot
13 |
14 |
15 | Slot
16 | v(VM1 => ?VM2, VIDs)
17 |
18 | Epoch |-> Attestations:Attestations
19 | ...
20 |
21 | LastFinalizedEpoch
22 | ...
23 |
24 |
25 | firstSlotOf(Epoch)
26 | (_, EpochBoundaryBlock)
27 | ...
28 |
29 | BM
30 | ...
31 |
32 | ...
33 |
34 | requires true
35 |
36 | andBool ( isActiveValidator(V, ?Epoch) orBool ( V.slashed andBool ?Epoch +Int 1 Int MIN_EPOCHS_TO_INACTIVITY_PENALTY
41 | andBool implies(V.id inA ?SourceAttestations, V.id =/=Int minByInclusionDelay(V.id, ?SourceAttestations).proposer)
42 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).inclusion_delay >=Int 1)
43 |
44 | // types
45 | andBool Slot >=Int 0
46 | andBool ?Epoch >=Int 0
47 | andBool ?FinalityDelay >=Int 0
48 | andBool ?BaseReward >=Int 0
49 | andBool ?SourceAttestingBalance >=Int 0
50 | andBool ?TargetAttestingBalance >=Int 0
51 | andBool ?HeadAttestingBalance >=Int 0
52 | andBool ?TotalActiveBalance >=Int 0
53 | // let-bindings
54 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
55 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
56 | andBool ?BaseReward ==Int getBaseReward(V, ?TotalActiveBalance)
57 | andBool ?SourceAttestations ==K filterNotSlashed(VM1, Attestations)
58 | andBool ?TargetAttestations ==K filterByTarget(EpochBoundaryBlock, ?SourceAttestations)
59 | andBool ?HeadAttestations ==K filterByHead(BM, ?TargetAttestations)
60 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?SourceAttestations)))
61 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?TargetAttestations)))
62 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?HeadAttestations)))
63 | andBool ?TotalActiveBalance ==Int lift(totalBalance(VM1, activeValidators(v(VM1,VIDs), ?Epoch)))
64 | // conditions
65 | andBool ?Epoch >=Int 2
66 | // invariants
67 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
68 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
69 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
70 | // consistency conditions
71 | andBool V.id in VIDs andBool VM1[V.id]v ==K V
72 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).proposer in VIDs)
73 | ensures true
74 | // ensures
75 |
76 | andBool ?VM2[V.id]v.balance ==Int VM1[V.id]v.balance -Int ?BaseReward *Int 7
77 | -Int V.effective_balance *Int ?FinalityDelay /Int INACTIVITY_PENALTY_QUOTIENT
78 |
79 | endmodule
80 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/n5-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module N5-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardPenalty(V, ?Epoch, ?FinalityDelay, ?BaseReward,
10 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
11 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .
12 | Slot
13 |
14 |
15 | Slot
16 | v(VM1 => ?VM2, VIDs)
17 |
18 | Epoch |-> Attestations:Attestations
19 | ...
20 |
21 | LastFinalizedEpoch
22 | ...
23 |
24 |
25 | firstSlotOf(Epoch)
26 | (_, EpochBoundaryBlock)
27 | ...
28 |
29 | BM
30 | ...
31 |
32 | ...
33 |
34 | requires true
35 |
36 | andBool ( isActiveValidator(V, ?Epoch) orBool ( V.slashed andBool ?Epoch +Int 1 =Int 1)
40 |
41 | // types
42 | andBool Slot >=Int 0
43 | andBool ?Epoch >=Int 0
44 | andBool ?FinalityDelay >=Int 0
45 | andBool ?BaseReward >=Int 0
46 | andBool ?SourceAttestingBalance >=Int 0
47 | andBool ?TargetAttestingBalance >=Int 0
48 | andBool ?HeadAttestingBalance >=Int 0
49 | andBool ?TotalActiveBalance >=Int 0
50 | // let-bindings
51 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
52 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
53 | andBool ?BaseReward ==Int getBaseReward(V, ?TotalActiveBalance)
54 | andBool ?SourceAttestations ==K filterNotSlashed(VM1, Attestations)
55 | andBool ?TargetAttestations ==K filterByTarget(EpochBoundaryBlock, ?SourceAttestations)
56 | andBool ?HeadAttestations ==K filterByHead(BM, ?TargetAttestations)
57 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?SourceAttestations)))
58 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?TargetAttestations)))
59 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?HeadAttestations)))
60 | andBool ?TotalActiveBalance ==Int lift(totalBalance(VM1, activeValidators(v(VM1,VIDs), ?Epoch)))
61 | // conditions
62 | andBool ?Epoch >=Int 2
63 | // invariants
64 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
65 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
66 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
67 | // consistency conditions
68 | andBool V.id in VIDs andBool VM1[V.id]v ==K V
69 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).proposer in VIDs)
70 | ensures true
71 | // ensures
72 |
73 | andBool ?VM2[V.id]v.balance <=Int VM1[V.id]v.balance +Int ?BaseReward +Int ?BaseReward +Int ?BaseReward +Int ?BaseReward
74 | andBool ?VM2[V.id]v.balance >=Int VM1[V.id]v.balance +Int (0 -Int ?BaseReward) +Int (0 -Int ?BaseReward) +Int (0 -Int ?BaseReward)
75 |
76 | endmodule
77 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/n6-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module N6-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardPenalty(V, ?Epoch, ?FinalityDelay, ?BaseReward,
10 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
11 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .
12 | Slot
13 |
14 |
15 | Slot
16 | v(VM1 => ?VM2, VIDs)
17 |
18 | Epoch |-> Attestations:Attestations
19 | ...
20 |
21 | LastFinalizedEpoch
22 | ...
23 |
24 |
25 | firstSlotOf(Epoch)
26 | (_, EpochBoundaryBlock)
27 | ...
28 |
29 | BM
30 | ...
31 |
32 | ...
33 |
34 | requires true
35 |
36 | andBool ( isActiveValidator(V, ?Epoch) orBool ( V.slashed andBool ?Epoch +Int 1 Int MIN_EPOCHS_TO_INACTIVITY_PENALTY
38 | andBool implies(V.id inA ?SourceAttestations, V.id =/=Int minByInclusionDelay(V.id, ?SourceAttestations).proposer)
39 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).inclusion_delay >=Int 1)
40 |
41 | // types
42 | andBool Slot >=Int 0
43 | andBool ?Epoch >=Int 0
44 | andBool ?FinalityDelay >=Int 0
45 | andBool ?BaseReward >=Int 0
46 | andBool ?SourceAttestingBalance >=Int 0
47 | andBool ?TargetAttestingBalance >=Int 0
48 | andBool ?HeadAttestingBalance >=Int 0
49 | andBool ?TotalActiveBalance >=Int 0
50 | // let-bindings
51 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
52 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
53 | andBool ?BaseReward ==Int getBaseReward(V, ?TotalActiveBalance)
54 | andBool ?SourceAttestations ==K filterNotSlashed(VM1, Attestations)
55 | andBool ?TargetAttestations ==K filterByTarget(EpochBoundaryBlock, ?SourceAttestations)
56 | andBool ?HeadAttestations ==K filterByHead(BM, ?TargetAttestations)
57 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?SourceAttestations)))
58 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?TargetAttestations)))
59 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(VM1, getValidators(?HeadAttestations)))
60 | andBool ?TotalActiveBalance ==Int lift(totalBalance(VM1, activeValidators(v(VM1,VIDs), ?Epoch)))
61 | // conditions
62 | andBool ?Epoch >=Int 2
63 | // invariants
64 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
65 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
66 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
67 | // consistency conditions
68 | andBool V.id in VIDs andBool VM1[V.id]v ==K V
69 | andBool implies(V.id inA ?SourceAttestations, minByInclusionDelay(V.id, ?SourceAttestations).proposer in VIDs)
70 | ensures true
71 | // ensures
72 |
73 | andBool ?VM2[V.id]v.balance <=Int VM1[V.id]v.balance +Int ?BaseReward +Int ?BaseReward +Int ?BaseReward +Int ?BaseReward
74 | +Int (0 -Int BASE_REWARDS_PER_EPOCH *Int ?BaseReward)
75 | +Int #if V.id inA ?TargetAttestations
76 | #then 0
77 | #else (0 -Int V.effective_balance *Int ?FinalityDelay /Int INACTIVITY_PENALTY_QUOTIENT)
78 | #fi
79 |
80 | andBool ?VM2[V.id]v.balance >=Int VM1[V.id]v.balance +Int (0 -Int ?BaseReward) +Int (0 -Int ?BaseReward) +Int (0 -Int ?BaseReward)
81 | +Int (0 -Int BASE_REWARDS_PER_EPOCH *Int ?BaseReward)
82 | +Int #if V.id inA ?TargetAttestations
83 | #then 0
84 | #else (0 -Int V.effective_balance *Int ?FinalityDelay /Int INACTIVITY_PENALTY_QUOTIENT)
85 | #fi
86 |
87 | endmodule
88 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/n7-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module N7-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardPenalty(VID, m(SM, BM1, EBM, AEM, AM, EM, WM), ?Epoch, ?FinalityDelay, ?BaseReward,
10 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
11 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .K ...
12 | Slot
13 |
14 |
15 | Slot
16 | v(m(SM, BM1 => ?BM2, EBM, AEM, AM, EM, WM), VIDs)
17 |
18 | ?Epoch |-> Attestations:Attestations
19 | ...
20 |
21 | LastFinalizedEpoch
22 | ...
23 |
24 |
25 | firstSlotOf(?Epoch)
26 | (_, EpochBoundaryBlock)
27 | ...
28 |
29 | ...
30 |
31 | BM
32 | ...
33 |
34 | requires true
35 |
36 | andBool implies(VID inA ?SourceAttestations, VID =/=Int minByInclusionDelay(VID, ?SourceAttestations).proposer)
37 |
38 | // types
39 | andBool Slot >=Int 0
40 | andBool ?Epoch >=Int 0
41 | andBool ?FinalityDelay >=Int 0
42 | andBool ?BaseReward >=Int 0
43 | andBool ?SourceAttestingBalance >=Int 0
44 | andBool ?TargetAttestingBalance >=Int 0
45 | andBool ?HeadAttestingBalance >=Int 0
46 | andBool ?TotalActiveBalance >=Int 0
47 | // let-bindings
48 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
49 | andBool ?VM1 ==K m(SM, BM1, EBM, AEM, AM, EM, WM)
50 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
51 | andBool ?BaseReward ==Int getBaseReward(EBM[VID]i, ?TotalActiveBalance)
52 | andBool ?SourceAttestations ==K filterNotSlashed(?VM1, Attestations)
53 | andBool ?TargetAttestations ==K filterByTarget(EpochBoundaryBlock, ?SourceAttestations)
54 | andBool ?HeadAttestations ==K filterByHead(BM, ?TargetAttestations)
55 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(?VM1, getValidators(?SourceAttestations)))
56 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(?VM1, getValidators(?TargetAttestations)))
57 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(?VM1, getValidators(?HeadAttestations)))
58 | andBool ?TotalActiveBalance ==Int lift(totalBalance(?VM1, activeValidators(v(?VM1, VIDs), ?Epoch)))
59 | // pre-conditions
60 | andBool ?Epoch >=Int 2
61 | andBool EBM[VID]i >=Int 0
62 | andBool implies(VID inA ?SourceAttestations, minByInclusionDelay(VID, ?SourceAttestations).inclusion_delay >=Int 1)
63 | andBool implies(VID inA ?SourceAttestations, minByInclusionDelay(VID, ?SourceAttestations).proposer in VIDs)
64 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
65 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
66 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
67 | andBool VID in VIDs // andBool VM1[V.id]v ==K V
68 | ensures true
69 | // ensures
70 |
71 | andBool implies(
72 | notBool ( isActiveValidator(VID, ?VM1, ?Epoch) orBool ( SM[VID]b andBool ?Epoch +Int 1 =Int BM1[VID]i -Int (3 *Int ?BaseReward)
89 | )
90 | andBool
91 | implies(
92 | // inactive case
93 | ?FinalityDelay >Int MIN_EPOCHS_TO_INACTIVITY_PENALTY
94 | ,
95 | // max: + 0
96 | ?BM2[VID]i <=Int BM1[VID]i
97 | andBool
98 | // min: - 7 * BaseReward - (EffectiveBalance * FinalityDelay / 33,554,432)
99 | ?BM2[VID]i >=Int BM1[VID]i -Int (7 *Int ?BaseReward) -Int getInactivityPenalty(EBM[VID]i, ?FinalityDelay)
100 | )
101 | )
102 |
103 | // max: + 4 * BaseReward
104 | andBool ?BM2[VID]i <=Int BM1[VID]i +Int (4 *Int ?BaseReward)
105 |
106 | // min: - 7 * BaseReward - (EffectiveBalance * FinalityDelay / 33,554,432)
107 | andBool ?BM2[VID]i >=Int BM1[VID]i -Int (7 *Int ?BaseReward) -Int getInactivityPenalty(EBM[VID]i, ?FinalityDelay)
108 |
109 | endmodule
110 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/n8-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module N8-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processRewardsPenaltiesAux3(L_VIDs, R_VIDs, m(SM, BM0, EBM, AEM, AM, EM, WM), ?Epoch, ?FinalityDelay,
10 | ?SourceAttestations, ?TargetAttestations, ?HeadAttestations,
11 | ?SourceAttestingBalance, ?TargetAttestingBalance, ?HeadAttestingBalance, ?TotalActiveBalance) => .K ...
12 | Slot
13 |
14 |
15 | Slot
16 | v(m(SM, BM1 => ?BM2, EBM, AEM, AM, EM, WM), VIDs)
17 |
18 | ?Epoch |-> Attestations:Attestations
19 | ...
20 |
21 | LastFinalizedEpoch
22 | ...
23 |
24 |
25 | firstSlotOf(?Epoch)
26 | (_, EpochBoundaryBlock)
27 | ...
28 |
29 | ...
30 |
31 | BM
32 | ...
33 |
34 | requires true
35 | // types
36 | andBool Slot >=Int 0
37 | andBool ?Epoch >=Int 0
38 | andBool ?FinalityDelay >=Int 0
39 | andBool ?SourceAttestingBalance >=Int 0
40 | andBool ?TargetAttestingBalance >=Int 0
41 | andBool ?HeadAttestingBalance >=Int 0
42 | andBool ?TotalActiveBalance >=Int 0
43 | // let-bindings
44 | andBool ?Epoch ==Int epochOf(Slot) -Int 2
45 | andBool ?VM0 ==K m(SM, BM0, EBM, AEM, AM, EM, WM)
46 | andBool ?VM1 ==K m(SM, BM1, EBM, AEM, AM, EM, WM)
47 | andBool ?FinalityDelay ==Int ?Epoch -Int LastFinalizedEpoch
48 | andBool ?SourceAttestations ==K filterNotSlashed(?VM0, Attestations)
49 | andBool ?TargetAttestations ==K filterByTarget(EpochBoundaryBlock, ?SourceAttestations)
50 | andBool ?HeadAttestations ==K filterByHead(BM, ?TargetAttestations)
51 | andBool ?SourceAttestingBalance ==Int lift(totalBalance(?VM0, getValidators(?SourceAttestations)))
52 | andBool ?TargetAttestingBalance ==Int lift(totalBalance(?VM0, getValidators(?TargetAttestations)))
53 | andBool ?HeadAttestingBalance ==Int lift(totalBalance(?VM0, getValidators(?HeadAttestations)))
54 | andBool ?TotalActiveBalance ==Int lift(totalBalance(?VM0, activeValidators(v(?VM0, VIDs), ?Epoch)))
55 | // pre-conditions
56 | andBool ?Epoch >=Int 2
57 | andBool forall(x, R_VIDs, EBM[x]i >=Int 0)
58 | andBool distinct(R_VIDs)
59 | andBool forall(x, R_VIDs, implies(x inA ?SourceAttestations, minByInclusionDelay(x, ?SourceAttestations).inclusion_delay >=Int 1))
60 | andBool forall(x, R_VIDs, implies(x inA ?SourceAttestations, minByInclusionDelay(x, ?SourceAttestations).proposer in VIDs))
61 | andBool ?SourceAttestingBalance <=Int ?TotalActiveBalance
62 | andBool ?TargetAttestingBalance <=Int ?TotalActiveBalance
63 | andBool ?HeadAttestingBalance <=Int ?TotalActiveBalance
64 | // invariants
65 | andBool disjoint(L_VIDs, R_VIDs)
66 | andBool forall(x, R_VIDs, x in VIDs)
67 | andBool forall(x, R_VIDs, BM1[x]i ==Int BM0[x]i)
68 | andBool forall(x, rev(L_VIDs), BM1[x]i <=Int BM0[x]i +Int (4 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)))
69 | andBool forall(x, rev(L_VIDs), BM1[x]i >=Int BM0[x]i -Int (7 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)) -Int getInactivityPenalty(EBM[x]i, ?FinalityDelay))
70 | ensures true
71 | // post-conditions
72 | andBool forall(x, rev(L_VIDs) ++ R_VIDs, ?BM2[x]i <=Int BM0[x]i +Int (4 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)))
73 | andBool forall(x, rev(L_VIDs) ++ R_VIDs, ?BM2[x]i >=Int BM0[x]i -Int (7 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)) -Int getInactivityPenalty(EBM[x]i, ?FinalityDelay))
74 |
75 | endmodule
76 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/o1-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module O1-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | updateActivationEligibilitiesAux(L_VIDs, R_VIDs, m(SM, BM, EBM, AEM0, AM, EM, WM)) => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(m(SM, BM, EBM, AEM1 => ?AEM2, AM, EM, WM), VIDs)
15 | ...
16 |
17 | ...
18 |
19 | ...
20 |
21 | requires true
22 | // types
23 | andBool Slot >=Int 0
24 | // let-bindings
25 | andBool ?Epoch ==Int epochOf(Slot)
26 | andBool ?VM0 ==K m(SM, BM, EBM, AEM0, AM, EM, WM)
27 | // pre-conditions
28 | andBool distinct(R_VIDs)
29 | // invariants
30 | andBool disjoint(L_VIDs, R_VIDs)
31 | andBool forall(x, R_VIDs, x in VIDs)
32 | andBool forall(x, R_VIDs, AEM1[x]i ==K AEM0[x]i)
33 | andBool forall(x, rev(L_VIDs), AEM1[x]i ==Int #if isActivationEligible(x, ?VM0) #then ?Epoch #else AEM0[x]i #fi)
34 | ensures true
35 | // post-conditions
36 | andBool forall(x, rev(L_VIDs) ++ R_VIDs, ?AEM2[x]i ==Int #if isActivationEligible(x, ?VM0) #then ?Epoch #else AEM0[x]i #fi)
37 |
38 | endmodule
39 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/o2-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 | require "o1-spec.k"
3 |
4 | module O2-SPEC
5 |
6 | imports VERIFICATION
7 | imports O1-SPEC
8 |
9 | rule
10 |
11 | updateActivationEligibilities(VIDs) => .K ...
12 | Slot
13 |
14 |
15 | Slot
16 | v(m(SM, BM, EBM, AEM1 => ?AEM2, AM, EM, WM), VIDs)
17 | ...
18 |
19 | ...
20 |
21 | ...
22 |
23 | requires true
24 | // types
25 | andBool Slot >=Int 0
26 | // let-bindings
27 | andBool ?Epoch ==Int epochOf(Slot)
28 | andBool ?VM1 ==K m(SM, BM, EBM, AEM1, AM, EM, WM)
29 | // pre-conditions
30 | andBool distinct(VIDs)
31 | // invariants
32 | ensures true
33 | // post-conditions
34 | andBool forall(x, VIDs, ?AEM2[x]i ==Int #if isActivationEligible(x, ?VM1) #then ?Epoch #else AEM1[x]i #fi)
35 |
36 | endmodule
37 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/p1-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | module P1-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | rule
8 |
9 | processValidatorEjectionsAux(L_VIDs, R_VIDs, m(SM, BM, EBM, AEM, AM, EM0, WM0)) => .K ...
10 | Slot
11 |
12 |
13 | Slot
14 | v(m(SM, BM, EBM, AEM, AM, EM1 => ?EM2, WM1 => ?WM2), VIDs)
15 | ...
16 |
17 | ...
18 |
19 | ...
20 |
21 | requires true
22 | // types
23 | andBool Slot >=Int 0
24 | // let-bindings
25 | andBool ?Epoch ==Int epochOf(Slot)
26 | andBool ?VM0 ==K m(SM, BM, EBM, AEM, AM, EM0, WM0)
27 | andBool ?VM1 ==K m(SM, BM, EBM, AEM, AM, EM1, WM1)
28 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(v(?VM1, VIDs)), delayedActivationExitEpoch(?Epoch))
29 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(?VM1, VIDs), ?Epoch)))
30 | // pre-conditions
31 | andBool ?LastExitEpoch +Int size(R_VIDs) =Int delayedActivationExitEpoch(?Epoch) andBool EM1[x]i =Int delayedActivationExitEpoch(?Epoch) andBool ?EM2[x]i
11 | processValidatorEjections(VIDs) => .K ...
12 | Slot
13 |
14 |
15 | Slot
16 | v(m(SM, BM, EBM, AEM, AM, EM1 => ?EM2, WM1 => ?WM2), VIDs)
17 | ...
18 |
19 | ...
20 |
21 | ...
22 |
23 | requires true
24 | // types
25 | andBool Slot >=Int 0
26 | // let-bindings
27 | andBool ?Epoch ==Int epochOf(Slot)
28 | andBool ?VM1 ==K m(SM, BM, EBM, AEM, AM, EM1, WM1)
29 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(v(?VM1, VIDs)), delayedActivationExitEpoch(?Epoch))
30 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(v(?VM1, VIDs), ?Epoch)))
31 | // pre-conditions
32 | andBool ?LastExitEpoch +Int size(VIDs) =Int delayedActivationExitEpoch(?Epoch) andBool ?EM2[x]i
14 | begin
15 | ~> processRewardsPenalties(?Epoch -Int 2)
16 | ~> processValidatorUpdates() => .K ...
17 | Slot
18 |
19 |
20 | Slot
21 | v(m(SM, BM1 => ?BM2, EBM, AEM1 => ?AEM2, AM1 => ?AM2, EM1 => ?EM2, WM1 => ?WM2), VIDs)
22 |
23 | ?Epoch -Int 2 |-> Attestations:Attestations
24 | ...
25 |
26 | LastFinalizedEpoch
27 | ...
28 |
29 |
30 | firstSlotOf(?Epoch -Int 2)
31 | ...
32 |
33 | ...
34 |
35 | ...
36 |
37 | requires true
38 | // types
39 | andBool Slot >=Int 0
40 | andBool ?Epoch >=Int 0
41 | andBool ?FinalityDelay >=Int 0
42 | // let-bindings
43 | andBool ?Epoch ==Int epochOf(Slot)
44 | andBool ?FinalityDelay ==Int ?Epoch -Int 2 -Int LastFinalizedEpoch
45 | andBool ?SourceAttestations ==K filterNotSlashed(SM, Attestations)
46 | andBool ?TotalActiveBalance ==Int lift(totalBalance(EBM, activeValidators(VIDs, AM1, EM1, ?Epoch -Int 2)))
47 | //
48 | andBool ?ChurnLimitA ==Int churnLimit(size(activeValidators(VIDs, AM1, EM1, ?Epoch)))
49 | andBool ?ChurnLimitB ==Int churnLimit(size(activeValidators(VIDs, AM1, EM1, ?Epoch -Int 1)))
50 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(VIDs, EM1), delayedActivationExitEpoch(?Epoch))
51 | andBool ?ActivationEpoch ==Int delayedActivationExitEpoch(?Epoch -Int 1)
52 | andBool ?ValidatorsToBeActivated ==K activationQueueUptoChurnLimit(VIDs, AEM1, AM1, EM1, LastFinalizedEpoch, ?Epoch -Int 1)
53 | // pre-conditions
54 | andBool ?Epoch >=Int 4
55 | andBool forall(x, VIDs, EBM[x]i >=Int 0)
56 | andBool distinct(VIDs)
57 | andBool forall(x, VIDs, implies(x inA ?SourceAttestations, minByInclusionDelay(x, ?SourceAttestations).inclusion_delay >=Int 1))
58 | andBool forall(x, VIDs, implies(x inA ?SourceAttestations, minByInclusionDelay(x, ?SourceAttestations).proposer in VIDs))
59 | andBool isValidAttestations(Attestations, VIDs, AM1, EM1, ?Epoch -Int 2)
60 | //
61 | andBool LastFinalizedEpoch =Int BM1[x]i -Int (7 *Int getBaseReward(EBM[x]i, ?TotalActiveBalance)) -Int getInactivityPenalty(EBM[x]i, ?FinalityDelay))
71 | //
72 | // processValidatorEjections
73 | andBool forall(x, VIDs, #if isActiveValidator(x, AM1, EM1, ?Epoch -Int 1) andBool EBM[x]i <=Int EJECTION_BALANCE andBool EM1[x]i ==Int FAR_FUTURE_EPOCH
74 | #then ?EM2[x]i >=Int delayedActivationExitEpoch(?Epoch) andBool ?EM2[x]i
10 | processSlots(TargetSlot) => .
11 | Slot
12 |
13 |
14 | Slot
15 | Vs
16 | SB
17 | AttestedMap
18 | JustifiedMap
19 | FinalizedMap
20 |
21 | ...
22 |
23 | ...
24 |
25 | requires true
26 | andBool Slot ==Int TargetSlot
27 | // types
28 | andBool Slot >=Int 0
29 | ensures true
30 |
31 | endmodule
32 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/process-slots-base1-spec.k:
--------------------------------------------------------------------------------
1 | require "verification.k"
2 |
3 | module PROCESS-SLOTS-BASE1-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // Slot == TargetSlot - 1
8 | rule
9 |
10 | processSlots(TargetSlot) => .
11 | Slot => TargetSlot
12 |
13 |
14 | Slot
15 | Vs
16 | SB
17 | AttestedMap
18 | JustifiedMap
19 | FinalizedMap
20 |
21 | (
22 | .Bag
23 | =>
24 |
25 | TargetSlot
26 | Vs
27 | SB
28 | AttestedMap
29 | JustifiedMap
30 | FinalizedMap
31 |
32 | )
33 | ...
34 |
35 | B => B [ TargetSlot <- B[Slot]i ]i
36 | ...
37 |
38 | requires true
39 | andBool Slot +Int 1 ==Int TargetSlot
40 | andBool isFirstSlotOfEpoch(Slot +Int 1) ==K false
41 | // types
42 | andBool Slot >=Int 0
43 | ensures true
44 |
45 | endmodule
46 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/process-slots-inductive-spec.k:
--------------------------------------------------------------------------------
1 | require "verification.k"
2 |
3 | module PROCESS-SLOTS-INDUCTIVE-SPEC
4 |
5 | imports VERIFICATION
6 |
7 | // Slot < TargetSlot - 1
8 | rule
9 |
10 | processSlots(TargetSlot)
11 | Slot => Slot +Int 1
12 |
13 |
14 | Slot
15 | Vs
16 | SB
17 | AttestedMap
18 | JustifiedMap
19 | FinalizedMap
20 |
21 | (
22 | .Bag
23 | =>
24 |
25 | Slot +Int 1
26 | Vs
27 | SB
28 | AttestedMap
29 | JustifiedMap
30 | FinalizedMap
31 |
32 | )
33 | ...
34 |
35 | B => B [ Slot +Int 1 <- B[Slot]i ]i
36 | ...
37 |
38 | requires true
39 | andBool Slot +Int 1 =Int 0
43 | ensures true
44 |
45 | endmodule
46 |
--------------------------------------------------------------------------------
/dynamic/tests/symbolic/q2-spec.k:
--------------------------------------------------------------------------------
1 | require "../../verification.k"
2 |
3 | require "../../process-deposit-spec.k"
4 | require "../../process-validator-exit-spec.k"
5 |
6 | module Q2-SPEC
7 |
8 | imports VERIFICATION
9 |
10 | imports PROCESS-DEPOSIT-SPEC
11 | imports PROCESS-VALIDATOR-EXIT-SPEC
12 |
13 | rule
14 |
15 | begin
16 | ~> processDeposits(Ds)
17 | ~> processVoluntaryExits(VEs) => .K ...
18 | Slot
19 |
20 |
21 | Slot
22 | v(m(SM1 => ?SM2, BM1 => ?BM2, EBM1 => ?EBM2, AEM1 => ?AEM2, AM1 => ?AM2, EM1 => ?EM2, WM1 => ?WM2), VIDs1 => ?VIDs2)
23 | ...
24 |
25 | ...
26 |
27 | ...
28 |
29 | requires true
30 | // types
31 | andBool Slot >=Int 0
32 | // let-bindings
33 | //// processVoluntaryExits
34 | andBool ?Epoch ==Int epochOf(Slot)
35 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(VIDs1, EM1), delayedActivationExitEpoch(?Epoch))
36 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(VIDs1, AM1, EM1, ?Epoch)))
37 | // pre-conditions
38 | //// processDeposits
39 | andBool distinct(VIDs1)
40 | andBool isValidDeposits(Ds)
41 | //// processVoluntaryExits
42 | andBool ?LastExitEpoch +Int sizeE(VEs) =Int #if x in VIDs1 #then BM1[x]i #else 0 #fi)
54 | andBool forall(x, ?VIDs2, ?EBM2[x]i >=Int #if x in VIDs1 #then EBM1[x]i #else 0 #fi)
55 | andBool forall(x, ?VIDs2, ?EBM2[x]i <=Int #if x in VIDs1 #then EBM1[x]i #else MAX_EFFECTIVE_BALANCE #fi)
56 | andBool forall(x, ?VIDs2, ?AEM2[x]i ==Int #if x in VIDs1 #then AEM1[x]i #else FAR_FUTURE_EPOCH #fi)
57 | andBool forall(x, ?VIDs2, ?AM2[x]i ==Int #if x in VIDs1 #then AM1[x]i #else FAR_FUTURE_EPOCH #fi)
58 | /*
59 | andBool forall(x, ?VIDs2, ?EM2[x]i ==Int #if x in VIDs1 #then EM1[x]i #else FAR_FUTURE_EPOCH #fi)
60 | andBool forall(x, ?VIDs2, ?WM2[x]i ==Int #if x in VIDs1 #then WM1[x]i #else FAR_FUTURE_EPOCH #fi)
61 | */
62 | //// processVoluntaryExits
63 | andBool forall(x, getValidatorsE(VEs), ?EM2[x]i >=Int delayedActivationExitEpoch(?Epoch))
64 | andBool forall(x, getValidatorsE(VEs), ?EM2[x]i
70 | processDeposits(Ds) => .K ...
71 | Slot
72 |
73 |
74 | Slot
75 | v(m(SM1 => ?SM2, BM1 => ?BM2, EBM1 => ?EBM2, AEM1 => ?AEM2, AM1 => ?AM2, EM1 => ?EM2, WM1 => ?WM2), VIDs1 => ?VIDs2)
76 | ...
77 |
78 | ...
79 |
80 | ...
81 |
82 | requires true
83 | // types
84 | andBool Slot >=Int 0
85 | // let-bindings
86 | // pre-conditions
87 | andBool distinct(VIDs1)
88 | andBool isValidDeposits(Ds)
89 | // invariants
90 | ensures true
91 | // post-conditions
92 | andBool distinct(?VIDs2)
93 | andBool ?VIDs2 ==K unique(rev(getValidatorsD(Ds)) ++ VIDs1)
94 | andBool forall(x, ?VIDs2, ?SM2[x]b ==K #if x in VIDs1 #then SM1[x]b #else false #fi)
95 | andBool forall(x, ?VIDs2, ?BM2[x]i >=Int #if x in VIDs1 #then BM1[x]i #else 0 #fi)
96 | andBool forall(x, ?VIDs2, ?EBM2[x]i >=Int #if x in VIDs1 #then EBM1[x]i #else 0 #fi)
97 | andBool forall(x, ?VIDs2, ?EBM2[x]i <=Int #if x in VIDs1 #then EBM1[x]i #else MAX_EFFECTIVE_BALANCE #fi)
98 | andBool forall(x, ?VIDs2, ?AEM2[x]i ==Int #if x in VIDs1 #then AEM1[x]i #else FAR_FUTURE_EPOCH #fi)
99 | andBool forall(x, ?VIDs2, ?AM2[x]i ==Int #if x in VIDs1 #then AM1[x]i #else FAR_FUTURE_EPOCH #fi)
100 | andBool forall(x, ?VIDs2, ?EM2[x]i ==Int #if x in VIDs1 #then EM1[x]i #else FAR_FUTURE_EPOCH #fi)
101 | andBool forall(x, ?VIDs2, ?WM2[x]i ==Int #if x in VIDs1 #then WM1[x]i #else FAR_FUTURE_EPOCH #fi)
102 | [trusted]
103 |
104 | rule
105 |
106 | processVoluntaryExits(VEs) => .K ...
107 | Slot
108 |
109 |
110 | Slot
111 | v(m(SM, BM, EBM, AEM, AM, EM1 => ?EM2, WM1 => ?WM2), VIDs)
112 | ...
113 |
114 | ...
115 |
116 | ...
117 |
118 | requires true
119 | // types
120 | andBool Slot >=Int 0
121 | // let-bindings
122 | andBool ?Epoch ==Int epochOf(Slot)
123 | andBool ?LastExitEpoch ==Int maxInt(maxExitEpoch(VIDs, EM1), delayedActivationExitEpoch(?Epoch))
124 | andBool ?ChurnLimit ==Int churnLimit(size(activeValidators(VIDs, AM, EM1, ?Epoch)))
125 | // pre-conditions
126 | andBool ?LastExitEpoch +Int sizeE(VEs) =Int delayedActivationExitEpoch(?Epoch))
134 | andBool forall(x, getValidatorsE(VEs), ?EM2[x]i
10 | processSlot() => .
11 | Slot
12 |
13 | ...
14 |
15 | Slot
16 | Vs
17 | Ss
18 | As
19 | Js
20 | Fs
21 | (LastBlockSlot, LastBlockID)
22 | LastJustifiedEpoch
23 | LastFinalizedEpoch
24 |
25 |
26 | ...
27 |
28 |
29 | // processSlots(s) does nothing if s is the current slot.
30 | rule
31 |
32 | processSlots(Slot) => .
33 | Slot
34 |
35 | ...
36 |
37 | Slot
38 | Vs
39 | Ss
40 | As
41 | Js
42 | Fs
43 | (LastBlockSlot, LastBlockID)
44 | LastJustifiedEpoch
45 | LastFinalizedEpoch
46 |
47 |
48 | ...
49 |
50 |
51 | // processJustification(e) does nothing if no validator exist.
52 | rule
53 |
54 | processJustification(Epoch) => .
55 | Slot
56 |
57 | ...
58 |
59 | firstSlotOf(Epoch)
60 | v(m(.BMap, .IMap, .IMap, .IMap, .IMap, .IMap, .IMap), .IntList)
61 | (_, EpochBoundaryBlock)
62 | ...
63 |
64 |
65 | Slot
66 | v(m(.BMap, .IMap, .IMap, .IMap, .IMap, .IMap, .IMap), .IntList)
67 |
68 | Epoch |-> .Attestations
69 | ...
70 |
71 | ...
72 |
73 |
74 | ...
75 |
76 | // TODO: why is this condition not needed?
77 | // requires Slot ==Int firstSlotOf(Epoch +Int 1)
78 |
79 | endmodule
80 |
--------------------------------------------------------------------------------
/fork-choice-rule/preliminary-analysis-fork-choice-rule.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/runtimeverification/beacon-chain-verification/7563b9b338eef019a11edadb8d8e520775a165bf/fork-choice-rule/preliminary-analysis-fork-choice-rule.pdf
--------------------------------------------------------------------------------
/resources/Notes-on-justification-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/runtimeverification/beacon-chain-verification/7563b9b338eef019a11edadb8d8e520775a165bf/resources/Notes-on-justification-diagram.png
--------------------------------------------------------------------------------
/resources/pdf-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/runtimeverification/beacon-chain-verification/7563b9b338eef019a11edadb8d8e520775a165bf/resources/pdf-icon.png
--------------------------------------------------------------------------------
/weak-subjectivity/Makefile:
--------------------------------------------------------------------------------
1 | TARGET=paper
2 |
3 | LATEX=pdflatex
4 | BIBTEX=bibtex
5 | TEXFILES = ${wildcard *.tex} ${wildcard tables/*.tex} ${wildcard */*.tex}
6 | BIBFILES = ${wildcard *.bib} ${wildcard bibtex/*.bib}
7 | FIGFILES = $(wildcard figs/*.pdf)
8 | DOTFILES = ${wildcard figs/*.dot}
9 | FIGFILES +=${DOTFILES:%.dot=%.ps}
10 | FIGFILES +=${wildcard figs/*.tex} ${wildcard figs/*.ps} ${wildcard figs/*.eps}
11 | CONFFILES += ${wildcard *.sty} ${wildcard *.cls}
12 |
13 | .PRECIOUS: %.ps %.pdf
14 |
15 | .PHONY: $(TARGET) $(TARGET).pdf clean clean-full
16 |
17 | $(TARGET): $(TARGET).pdf
18 |
19 | $(TARGET).pdf: $(TEXFILES) $(FIGFILES) $(BIBFILES) $(CONFILES)
20 | -rm -f *.aux
21 | $(LATEX) $(TARGET).tex
22 | ifneq ($(shell grep "cite{.*}" $(TEXFILES)),)
23 | $(BIBTEX) $(TARGET)
24 | $(LATEX) $(TARGET).tex
25 | endif
26 | $(LATEX) $(TARGET).tex
27 | @/bin/echo ""
28 | @/bin/echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
29 | @/bin/echo " ++++ ANY UNDEFINED REFERENCES ++++"
30 | -@grep -i undef $(TARGET).log || echo "No undefined references."
31 | @/bin/echo " ++++ ANY EMPTY REFERENCES ++++"
32 | -@egrep -i -n -e 'cite{ *}' -e 'ref{ *}' $(TEXFILES) $(FIGFILES) || echo "No empty references."
33 | @/bin/echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
34 | @/bin/echo ""
35 |
36 | clean:
37 | rm -f *.aux *.bbl *.dvi *.lof *.log *.toc *.lot *.blg *.out *.cut *._paper.pdf
38 |
39 | clean-full: clean
40 | rm -f $(TARGET).pdf
41 |
42 | %.pdf: %.dvi
43 | dvipdfmx -o $@ $<
44 |
--------------------------------------------------------------------------------
/weak-subjectivity/after-n-epoch-balance-top-ups.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/runtimeverification/beacon-chain-verification/7563b9b338eef019a11edadb8d8e520775a165bf/weak-subjectivity/after-n-epoch-balance-top-ups.pdf
--------------------------------------------------------------------------------
/weak-subjectivity/after-n-epoch.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/runtimeverification/beacon-chain-verification/7563b9b338eef019a11edadb8d8e520775a165bf/weak-subjectivity/after-n-epoch.pdf
--------------------------------------------------------------------------------
/weak-subjectivity/balance-top-ups.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/runtimeverification/beacon-chain-verification/7563b9b338eef019a11edadb8d8e520775a165bf/weak-subjectivity/balance-top-ups.pdf
--------------------------------------------------------------------------------
/weak-subjectivity/discussion.tex:
--------------------------------------------------------------------------------
1 | \section{Discussion}
2 |
3 | Compared to the limit of the validator activations and exits, the per-epoch limit of balance top-ups is quite high. In the current configuration, while the activation/exit limit is $\max(4, N \cdot 2^{-16})$, the balance top-up limit is 512 regardless of the total number of validators $N$. The high limit of balance top-ups causes the weak subjectivity period to quickly decrease as the average balance decreases.
4 | As shown in Table~\ref{tbl:weak-subjectivity}, the weak subjectivity period becomes too small to be practically maintained even for a reasonably large validator set, if the average balance falls below a certain threshold, say 24 ETH. This shows that the current limit of balance top-ups is too high, and it is recommended to significantly decrease the top-up limit.
5 | Note that it is \emph{not} recommended to merely increase the validator ejection balance (currently 16 ETH). Although it could help to increase the lower bound of the average balance, it is risky because a higher ejection balance could be abused by adversaries to make it easier to forcibly eject honest validators.
6 |
7 | \begin{table}[t]
8 | \caption[Weak Subjectivity Period]{Weak subjectivity period (in number of epochs) for dynamic validator set with balance top-ups,\footnotemark~where the safety decay $D = 10\%$, the maximum effective balance $T = 32$ ETH, the balance top-up limit $\Delta = 512$, and the activation/exit limit $\delta = 4$.}
9 | \label{tbl:weak-subjectivity}
10 | \centering
11 | \begingroup
12 | \newdimen{\colWidth}
13 | \settowidth{\colWidth}{262,144} % column size fit to the given text
14 | \setlength{\tabcolsep}{4pt}
15 | \begin{tabular}{cr|rrrrrrr}
16 | %\hline
17 | & & \multicolumn{7}{c}{Validator Set Size ($N$)} \\
18 | & & \makebox[\colWidth][r]{262,144}
19 | & \makebox[\colWidth][r]{131,072}
20 | & \makebox[\colWidth][r]{ 65,536}
21 | & \makebox[\colWidth][r]{ 32,768}
22 | & \makebox[\colWidth][r]{ 16,384}
23 | & \makebox[\colWidth][r]{ 8,192}
24 | & \makebox[\colWidth][r]{ 4,096} \\
25 | \hline
26 | \multirow{9}{*}{\rotatebox{90}{Average Balance ($t$)}}
27 | & 32 & 3,276 & 1,638 & 819 & 409 & 204 & 102 & 51 \\
28 | & 30 & 2,659 & 1,329 & 664 & 332 & 166 & 83 & 41 \\
29 | & 28 & 1,985 & 992 & 496 & 248 & 124 & 62 & 31 \\
30 | & 26 & 1,248 & 624 & 312 & 156 & 78 & 39 & 19 \\
31 | & 24 & 436 & 218 & 109 & 54 & 27 & 13 & 6 \\
32 | & 22 & 169 & 84 & 42 & 21 & 11 & 5 & 3 \\
33 | & 20 & 128 & 64 & 32 & 16 & 8 & 4 & 2 \\
34 | & 18 & 99 & 49 & 25 & 12 & 6 & 3 & 2 \\
35 | & 16 & 77 & 38 & 19 & 10 & 5 & 2 & 1 \\
36 | %\hline
37 | \end{tabular}
38 | \endgroup
39 | \end{table}
40 | \footnotetext{The entries of the first low for $t = 32$ agree with the table presented in~\cite{weak-subjectivity-aditya}. The off-by-one difference is due to the use of the floor function instead of ceiling.}
41 |
42 | On the other hands, as a workaround for the small weak subjectivity period problem, a relaxed notion of weak subjectivity has been proposed by others. The relaxed notion does \emph{not} aim to prevent conflicting finalized blocks from being descendants of the latest weak subjectivity checkpoint, thus does \emph{not} guarantee the unique finalized block to be identified by the fork choice rule. Instead, it relies on the withdrawal delay (currently 256 epochs $\approx$ 27 hours), so that arguably the slashable validators can be indeed slashed. However, the implication of the relaxed notion of weak subjectivity has not been thoroughly analyzed, thus it is not recommended to adopt it until more detailed analysis has been made.
43 |
44 | \paragraph{Limitation.}
45 |
46 | It is not yet known whether the period given in Theorem~\ref{thm:weak-subjectivity-balance-top-ups} is indeed the lower bound (i.e., $\E_2$) or not.
47 | This means that the weak subjectivity period in the setting of dynamic validator set with balance top-ups might need to be much smaller.
48 | However, when $N$ is not large enough, the given weak subjectivity period is already very small, thus does not affect the practical implication.
49 |
50 | On the other hands, if the balance top-up limit $\Delta$ is reduced to close to the activation/exit limit $\delta$, then Theorem~\ref{thm:weak-subjectivity-balance-top-ups} is no longer directly applicable as it assumes $\Delta \gg \delta$.
51 |
--------------------------------------------------------------------------------
/weak-subjectivity/header.tex:
--------------------------------------------------------------------------------
1 | % Packages
2 | \usepackage[T1]{fontenc}
3 | \usepackage{hyperref} %\usepackage[hidelinks]{hyperref}
4 |
5 | % break long URLs
6 | \def\UrlBreaks{\do\/\do-}
7 |
8 | %\usepackage[disable]{todonotes}
9 | \usepackage{todonotes}
10 |
11 | \usepackage{amsmath}
12 | \usepackage{amssymb}
13 | \usepackage{xspace}
14 | \usepackage{graphicx}
15 | \usepackage{fancyvrb}
16 | \usepackage[super]{nth}
17 | %\usepackage{enumitem}
18 | %\usepackage{relsize}
19 | %\usepackage{wrapfig}
20 | \usepackage{multirow}
21 | %\usepackage{enumitem}
22 |
23 | % % Theorems
24 | % \usepackage{amsthm}
25 | % \newtheorem{theorem}{Theorem}
26 | % \newtheorem{lemma}{Lemma}
27 | % \newtheorem{corollary}{Corollary}
28 | % \newtheorem{proposition}{Proposition}
29 | % \newtheorem{definition}{Definition}
30 | % \newtheorem{question}{Question}
31 | % \newtheorem{example}{Example}
32 |
33 | % General
34 | \newcommand{\N}{\mathbb{N}}
35 | \newcommand{\Z}{\mathbb{Z}}
36 | \renewcommand{\i}{\item}
37 | \newcommand{\OR}{\;|\;}
38 | \newcommand{\etal}{\textit{et al.}\xspace}
39 | \renewcommand{\th}{\ensuremath{{\m{th}}}}
40 | \newcommand{\w}[1]{\ensuremath{\textit{#1}}}
41 | \renewcommand{\t}[1]{\ensuremath{\texttt{#1}}}
42 | \newcommand{\m}[1]{\ensuremath{\textrm{#1}}}
43 | \newcommand{\s}[1]{\ensuremath{\textsf{#1}}}
44 | \newcommand{\p}[1]{\ensuremath{\left(#1\right)}}
45 | \newcommand{\pl}[1]{\ensuremath{\left\langle#1\right\rangle}}
46 | \newcommand{\finto}{\ensuremath{\stackrel{\mathtt{fin}}{\longrightarrow}}}
47 | \newcommand{\defeq}{\ensuremath{\stackrel{\mathtt{def}}{=}}}
48 | \newcommand{\cond}[1]{\ensuremath{\left\{\begin{array}{ll} #1 \end{array}\right.}}
49 | \newcommand{\lst}[1]{\begin{itemize} {#1} \end{itemize}}
50 | \newcommand{\tlist}[2]{\paragraph{#1} \begin{itemize} {#2} \end{itemize}}
51 | \newcommand{\floor}[1]{\ensuremath{\left\lfloor {#1} \right\rfloor}}
52 | \newcommand{\ceil}[1]{\ensuremath{\left\lceil {#1} \right\rceil}}
53 | \newcommand{\get}{\leftarrow}
54 | \newcommand{\dom}{\ensuremath{\textit{dom}}\xspace}
55 | \newcommand{\sem}[1]{\ensuremath{[\![{#1}]\!]}}
56 |
57 | % Specific
58 | \newcommand{\E}{\ensuremath{\mathsf{E}}}
59 | \newcommand{\twothird}{\ensuremath{\frac{2}{3}}}
60 | \newcommand{\ST}{\ensuremath{\w{SV}}}
61 | \newcommand{\T}{\ensuremath{\mathcal{S}}}
62 |
--------------------------------------------------------------------------------
/weak-subjectivity/intro.tex:
--------------------------------------------------------------------------------
1 | \section{Introduction}
2 |
3 | Weak subjectivity~\cite{weak-subjectivity} is a social-consensus-driven approach for solving the fundamental ``nothing-at-stake'' problem of proof-of-stake protocols. In particular, it addresses the problem in the presence of long-range forks, while the slashing mechanism handles the case of short-range forks. Specifically, the current weak subjectivity mechanism deals with the following two types of long-range attacks:\footnote{It is unknown whether this mechanism can deal with other types of long-range attacks, if any, in general.}
4 | \begin{itemize}
5 | \item
6 | \emph{Exploiting retired validators}: Adversaries can create and reveal a new chain branching from a certain block on the canonical chain, after $2/3$ of validators who were active for the block have exited. Note that such validators can still justify and finalize conflicting blocks at earlier slots without being slashed after they have exited.
7 | \item
8 | \emph{Exploiting diverging validator sets}: Adversaries can build a new chain until the validator set for the new chain is sufficiently different from that of the canonical chain. The larger the difference between the two validator sets, the lower the accountable safety tolerance. For example, if the intersection of the two sets is smaller than $2/3$ of each set, then it is possible to have conflicting blocks to be finalized without any validators violating the slashing conditions.
9 | \end{itemize}
10 | The current weak subjectivity mechanism employs a social consensus layer in parallel to maintain sufficiently many checkpoints (called weak subjectivity checkpoints) so that there exist no conflicting finalized blocks that are descendants of the latest weak subjectivity checkpoint. In other words, the purpose of the latest weak subjectivity checkpoints is to \emph{deterministically} identify the unique canonical chain even in the presence of conflicting finalized blocks caused by the long-range attacks.
11 |
--------------------------------------------------------------------------------
/weak-subjectivity/paper.tex:
--------------------------------------------------------------------------------
1 | \documentclass[runningheads]{llncs}
2 | %\documentclass{llncs}
3 |
4 | \input{header.tex}
5 |
6 | \begin{document}
7 |
8 | \title{Analysis on Weak Subjectivity in Ethereum 2.0}
9 | %\subtitle{subtitle}
10 | %\titlerunning{Abbreviated paper title}
11 |
12 | \author{Daejun Park\inst{1}%\orcidID{0000-0003-1551-2597}
13 | \and Aditya Asgaonkar\inst{2}
14 | }
15 | %\authorrunning{D. Park et al.}
16 |
17 | \institute{Runtime Verification, Inc.
18 | \\\email{daejun.park@runtimeverification.com}
19 | \and Ethereum Research
20 | \\\email{aditya.asgaonkar@ethereum.org}
21 | }
22 |
23 | \maketitle
24 |
25 | \begin{center}
26 | \vspace{-1\baselineskip}
27 | December 7, 2020
28 | %\today
29 | \end{center}
30 |
31 | %\begin{abstract}
32 | %We present an analysis on the weak subjectivity period in Ethereum 2.0.
33 | %\end{abstract}
34 |
35 | \input{intro.tex}
36 | \input{ws-period.tex}
37 | \input{discussion.tex}
38 |
39 | %\newpage
40 | \bibliographystyle{splncs04}
41 | \bibliography{ref}
42 |
43 | \newpage
44 | \appendix
45 |
46 | \end{document}
47 |
--------------------------------------------------------------------------------
/weak-subjectivity/ref.bib:
--------------------------------------------------------------------------------
1 | @misc{beacon-chain-spec,
2 | title = {{Ethereum 2.0 Specifications}},
3 | author = {{Ethereum Foundation}},
4 | howpublished = {\url{https://github.com/ethereum/eth2.0-specs}}
5 | }
6 |
7 | @misc{weak-subjectivity,
8 | title = {{Proof of Stake: How I Learned to Love Weak Subjectivity}},
9 | author = {{Vitalik Buterin}},
10 | howpublished = {\url{https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/}}
11 | }
12 |
13 | @misc{weak-subjectivity-aditya,
14 | title = {{Weak Subjectivity in Eth2.0}},
15 | author = {{Aditya Asgaonkar}},
16 | howpublished = {\url{https://notes.ethereum.org/@adiasg/weak-subjectvity-eth2}}
17 | }
18 |
--------------------------------------------------------------------------------
/weak-subjectivity/weak-subjectivity-analysis.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/runtimeverification/beacon-chain-verification/7563b9b338eef019a11edadb8d8e520775a165bf/weak-subjectivity/weak-subjectivity-analysis.pdf
--------------------------------------------------------------------------------