#lang ivy1.7 include tendermint include abstract_tendermint # Here we prove the second accountability property: no well-behaved node is # ever 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 complete=fo 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