Extends bft-proposal with multiple rounds and locking. Demonstrates why locking is essential for safety across view changes.
Round 0 Round 1
| |
| A gets quorum (commits) | New leader proposes B
| Nodes lock on A |
| | Locked nodes vote A (not B)
| | B cannot reach quorum
| |
v v
The Problem Without Locking:
Round 0: A commits with {N1, N2, N3}
Round 1: B could commit with {N1, N3, N4} if N3 "forgets" it voted A
Locking prevents this: N2, N3 are locked on A and cannot vote B.
make test SPEC=bft-locking
make run SPEC=bft-locking
make verify SPEC=bft-locking| Variable | Type | Description |
|---|---|---|
status |
Node -> Status |
Which nodes are faulty |
round |
Round |
Current round number |
leader |
Round -> Node |
Leader for each round |
locked |
Node -> Lock |
What each node is locked on |
votes |
Node -> Value |
Votes cast this round |
committed |
Set[Value] |
Values committed (all rounds) |
Correct node votes for a value.
Precondition: Node is correct, hasn't voted this round
Constraint: If locked, must vote for locked value
Effect: Vote recorded, may trigger commit
Faulty node votes for any value (ignores locks).
Precondition: Node is faulty
Effect: Vote recorded, may trigger commit
Node sees quorum for a value and locks on it.
Precondition: Node is correct, value has quorum
Effect: Node locks on value at current round
Advance to next round (e.g., leader timeout).
Effect: Round increments, votes cleared, locks preserved
At most one value commits across all rounds.
committed.size() <= 1
Without locking, this attack is possible:
- Round 0: A gets quorum {N1, N2, N3}, commits
- Round 1: Faulty N1 votes B, correct N3 and N4 vote B
- Result: B commits with {N1, N3, N4} - agreement violated!
With locking:
- N2, N3 saw A reach quorum → they lock on A
- In round 1, N2 and N3 can only vote A
- B can get at most 2 votes (N1 + N4) → no quorum
A correct node that sees 2f+1 votes for value V in round R:
- Locks on (V, R)
- In all future rounds, can only vote for V (until unlocked by higher-round evidence)
This ensures: if V commits, no other value can reach quorum in any round.
A commits in round 0. Locked nodes prevent B from committing in round 1.
Shows the attack scenario that locking prevents.
Node that missed round 0 can vote differently in round 1, but locks still protect agreement.
- pbft/ - Full 3-phase protocol combining all concepts
- bft-voting/ - BFT quorum voting
- bft-proposal/ - BFT with leader proposal
- Tendermint - BFT with locking