mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-20 06:54:41 +00:00
spec: merge rust-spec (#252)
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
----------------------- MODULE Isolation_001_draft ----------------------------
|
||||
(**
|
||||
* The specification of the attackers isolation at full node,
|
||||
* when it has received an evidence from the light client.
|
||||
* We check that the isolation spec produces a set of validators
|
||||
* that have more than 1/3 of the voting power.
|
||||
*
|
||||
* It follows the English specification:
|
||||
*
|
||||
* https://github.com/tendermint/spec/blob/master/rust-spec/lightclient/attacks/isolate-attackers_001_draft.md
|
||||
*
|
||||
* The assumptions made in this specification:
|
||||
*
|
||||
* - the voting power of every validator is 1
|
||||
* (add more validators, if you need more validators)
|
||||
*
|
||||
* - Tendermint security model is violated
|
||||
* (there are Byzantine validators who signed a conflicting block)
|
||||
*
|
||||
* Igor Konnov, Zarko Milosevic, Josef Widder, Informal Systems, 2020
|
||||
*)
|
||||
|
||||
|
||||
EXTENDS Integers, FiniteSets, Apalache
|
||||
|
||||
\* algorithm parameters
|
||||
CONSTANTS
|
||||
AllNodes,
|
||||
(* a set of all nodes that can act as validators (correct and faulty) *)
|
||||
COMMON_HEIGHT,
|
||||
(* an index of the block header that two peers agree upon *)
|
||||
CONFLICT_HEIGHT,
|
||||
(* an index of the block header that two peers disagree upon *)
|
||||
TRUSTING_PERIOD,
|
||||
(* the period within which the validators are trusted *)
|
||||
FAULTY_RATIO
|
||||
(* a pair <<a, b>> that limits that ratio of faulty validator in the blockchain
|
||||
from above (exclusive). Tendermint security model prescribes 1 / 3. *)
|
||||
|
||||
VARIABLES
|
||||
blockchain, (* the chain at the full node *)
|
||||
refClock, (* the reference clock at the full node *)
|
||||
Faulty, (* the set of faulty validators *)
|
||||
conflictingBlock, (* an evidence that two peers reported conflicting blocks *)
|
||||
state, (* the state of the attack isolation machine at the full node *)
|
||||
attackers (* the set of the identified attackers *)
|
||||
|
||||
vars == <<blockchain, refClock, Faulty, conflictingBlock, state>>
|
||||
|
||||
\* instantiate the chain at the full node
|
||||
ULTIMATE_HEIGHT == CONFLICT_HEIGHT + 1
|
||||
BC == INSTANCE Blockchain_003_draft
|
||||
|
||||
\* use the light client API
|
||||
TRUSTING_HEIGHT == COMMON_HEIGHT
|
||||
TARGET_HEIGHT == CONFLICT_HEIGHT
|
||||
|
||||
LC == INSTANCE LCVerificationApi_003_draft
|
||||
WITH localClock <- refClock, REAL_CLOCK_DRIFT <- 0, CLOCK_DRIFT <- 0
|
||||
|
||||
\* old-style type annotations in apalache
|
||||
a <: b == a
|
||||
|
||||
\* [LCAI-NONVALID-OUTPUT.1::TLA.1]
|
||||
ViolatesValidity(header1, header2) ==
|
||||
\/ header1.VS /= header2.VS
|
||||
\/ header1.NextVS /= header2.NextVS
|
||||
\/ header1.height /= header2.height
|
||||
\/ header1.time /= header2.time
|
||||
(* The English specification also checks the fields that we do not have
|
||||
at this level of abstraction:
|
||||
- header1.ConsensusHash != header2.ConsensusHash or
|
||||
- header1.AppHash != header2.AppHash or
|
||||
- header1.LastResultsHash header2 != ev.LastResultsHash
|
||||
*)
|
||||
|
||||
Init ==
|
||||
/\ state := "init"
|
||||
\* Pick an arbitrary blockchain from 1 to COMMON_HEIGHT + 1.
|
||||
/\ BC!InitToHeight(FAULTY_RATIO) \* initializes blockchain, Faulty, and refClock
|
||||
/\ attackers := {} <: {STRING} \* attackers are unknown
|
||||
\* Receive an arbitrary evidence.
|
||||
\* Instantiate the light block fields one by one,
|
||||
\* to avoid combinatorial explosion of records.
|
||||
/\ \E time \in Int:
|
||||
\E VS, NextVS, lastCommit, Commits \in SUBSET AllNodes:
|
||||
LET conflicting ==
|
||||
[ Commits |-> Commits,
|
||||
header |->
|
||||
[height |-> CONFLICT_HEIGHT,
|
||||
time |-> time,
|
||||
VS |-> VS,
|
||||
NextVS |-> NextVS,
|
||||
lastCommit |-> lastCommit] ]
|
||||
IN
|
||||
LET refBlock == [ header |-> blockchain[COMMON_HEIGHT],
|
||||
Commits |-> blockchain[COMMON_HEIGHT + 1].lastCommit ]
|
||||
IN
|
||||
/\ "SUCCESS" = LC!ValidAndVerifiedUntimed(refBlock, conflicting)
|
||||
\* More than third of next validators in the common reference block
|
||||
\* is faulty. That is a precondition for a fork.
|
||||
/\ 3 * Cardinality(Faulty \intersect refBlock.header.NextVS)
|
||||
> Cardinality(refBlock.header.NextVS)
|
||||
\* correct validators cannot sign an invalid block
|
||||
/\ ViolatesValidity(conflicting.header, refBlock.header)
|
||||
=> conflicting.Commits \subseteq Faulty
|
||||
/\ conflictingBlock := conflicting
|
||||
|
||||
|
||||
\* This is a specification of isolateMisbehavingProcesses.
|
||||
\*
|
||||
\* [LCAI-FUNC-MAIN.1::TLA.1]
|
||||
Next ==
|
||||
/\ state = "init"
|
||||
\* Extract the rounds from the reference block and the conflicting block.
|
||||
\* In this specification, we just pick rounds non-deterministically.
|
||||
\* The English specification calls RoundOf on the blocks.
|
||||
/\ \E referenceRound, evidenceRound \in Int:
|
||||
/\ referenceRound >= 0 /\ evidenceRound >= 0
|
||||
/\ LET reference == blockchain[CONFLICT_HEIGHT]
|
||||
referenceCommit == blockchain[CONFLICT_HEIGHT + 1].lastCommit
|
||||
evidenceHeader == conflictingBlock.header
|
||||
evidenceCommit == conflictingBlock.Commits
|
||||
IN
|
||||
IF ViolatesValidity(reference, evidenceHeader)
|
||||
THEN /\ attackers' := blockchain[COMMON_HEIGHT].NextVS \intersect evidenceCommit
|
||||
/\ state' := "Lunatic"
|
||||
ELSE IF referenceRound = evidenceRound
|
||||
THEN /\ attackers' := referenceCommit \intersect evidenceCommit
|
||||
/\ state' := "Equivocation"
|
||||
ELSE
|
||||
\* This property is shown in property
|
||||
\* Accountability of TendermintAcc3.tla
|
||||
/\ state' := "Amnesia"
|
||||
/\ \E Attackers \in SUBSET (Faulty \intersect reference.VS):
|
||||
/\ 3 * Cardinality(Attackers) > Cardinality(reference.VS)
|
||||
/\ attackers' := Attackers
|
||||
/\ blockchain' := blockchain
|
||||
/\ refClock' := refClock
|
||||
/\ Faulty' := Faulty
|
||||
/\ conflictingBlock' := conflictingBlock
|
||||
|
||||
(********************************** INVARIANTS *******************************)
|
||||
|
||||
\* This invariant ensure that the attackers have
|
||||
\* more than 1/3 of the voting power
|
||||
\*
|
||||
\* [LCAI-INV-Output.1::TLA-DETECTION-COMPLETENESS.1]
|
||||
DetectionCompleteness ==
|
||||
state /= "init" =>
|
||||
3 * Cardinality(attackers) > Cardinality(blockchain[CONFLICT_HEIGHT].VS)
|
||||
|
||||
\* This invariant ensures that only the faulty validators are detected
|
||||
\*
|
||||
\* [LCAI-INV-Output.1::TLA-DETECTION-ACCURACY.1]
|
||||
DetectionAccuracy ==
|
||||
attackers \subseteq Faulty
|
||||
|
||||
==============================================================================
|
||||
Reference in New Issue
Block a user