|
#lang ivy1.7
|
|
|
|
include tendermint
|
|
include abstract_tendermint
|
|
|
|
# Here we prove the second accountability property: no well-behaved node is
|
|
# every observed to violate the accountability properties.
|
|
|
|
# The proof is done in two steps: first we prove the the abstract specification
|
|
# satisfies the property, and then we show by refinement that this property
|
|
# also holds in the concrete specification.
|
|
|
|
# To see what is checked in the refinement proof, use `ivy_show isolate=accountable_safety_2 accountable_safety_2.ivy`
|
|
# To see what is checked in the abstract correctness proof, use `ivy_show isolate=abstract_accountable_safety_2 accountable_safety_2.ivy`
|
|
# To check the whole proof, use `ivy_check accountable_safety_2.ivy`.
|
|
|
|
# Proof that the property holds in the abstract specification
|
|
# ============================================================
|
|
|
|
isolate abstract_accountable_safety_2 = {
|
|
|
|
instantiate abstract_tendermint
|
|
|
|
# the main property:
|
|
invariant [wb_never_punished] well_behaved(N) -> ~(observed_equivocation(N) | observed_unlawful_prevote(N))
|
|
|
|
# the main invariant for proving wb_not_punished:
|
|
invariant well_behaved(N) & precommitted(N,R,V) & ~locked(N,R,V) & V ~= value.nil -> exists R2,V2 . V2 ~= value.nil & R < R2 & precommitted(N,R2,V2) & locked(N,R2,V2)
|
|
|
|
invariant (exists N . well_behaved(N) & precommitted(N,R,V) & V ~= value.nil) -> exists Q . nset.is_quorum(Q) & forall N . nset.member(N,Q) -> observed_prevoted(N,R,V)
|
|
|
|
invariant well_behaved(N) -> (observed_prevoted(N,R,V) <-> prevoted(N,R,V))
|
|
invariant well_behaved(N) -> (observed_precommitted(N,R,V) <-> precommitted(N,R,V))
|
|
|
|
# nodes stop prevoting or precommitting in lower rounds when doing so in a higher round:
|
|
invariant well_behaved(N) & prevoted(N,R2,V2) & R1 < R2 -> left_round(N,R1)
|
|
invariant well_behaved(N) & locked(N,R2,V2) & R1 < R2 -> left_round(N,R1)
|
|
|
|
invariant [precommit_unique_per_round] well_behaved(N) & precommitted(N,R,V1) & precommitted(N,R,V2) -> V1 = V2
|
|
|
|
} with nset, round, abstract_accountable_safety_2.defs.observed_equivocation_def, abstract_accountable_safety_2.defs.observed_unlawful_prevote_def
|
|
|
|
# Proof that the property holds in the concrete specification
|
|
# ===========================================================
|
|
|
|
isolate accountable_safety_2 = {
|
|
|
|
instantiate tendermint(abstract_accountable_safety_2)
|
|
|
|
invariant well_behaved(N) -> ~(abstract_accountable_safety_2.observed_equivocation(N) | abstract_accountable_safety_2.observed_unlawful_prevote(N))
|
|
|
|
} with round, value, shim, abstract_accountable_safety_2, abstract_accountable_safety_2.defs.observed_equivocation_def, abstract_accountable_safety_2.defs.observed_unlawful_prevote_def
|