This comprehensive guide walks you through Byzantine Fault Tolerance (BFT) consensus, explaining what happens at each step, why it happens, and what you should observe to understand how BFT works.
BFT requires more than 2/3 of nodes to agree before a block is added. With 3 nodes, you need 2 votes. With 4 nodes, you need 3 votes. This ensures safety even if up to 1/3 of nodes are Byzantine (faulty or malicious).
- If only 50% were needed, Byzantine nodes could split the network
- 2/3 ensures that honest nodes always outnumber Byzantine nodes
- This guarantees that no two honest nodes will accept conflicting blocks
- Node 6001: Proposer (will propose the block)
- Node 6002: Voter (will vote on the proposal)
- Node 6003: Voter (will vote on the proposal)
- Required Votes: 2 out of 3 (67% threshold)
What happens: Node 6001 creates a new block with transaction data and mines it.
Terminal Output (Node 6001):
Node-6001> propose "Payment of $100 from Alice to Bob"
Node-6001 PROPOSING NEW BLOCK:
Data: "Payment of $100 from Alice to Bob"
MINING PHASE:
Mining block 1...
Target: Hash must start with 00
Mining attempt 10000: a7f3d2e1b5c8f9...
Mining attempt 20000: b2e8f4a9c1d7e3...
Block mined! Nonce: 23847, Hash: 00a7f3d2e1b5c8f9abc123def456...
CONSENSUS PHASE:
Required votes: 2 out of 3 nodes
Current votes: 1 (self-vote)
Broadcasting message to 2 peers...
Message sent to peer 1
Message sent to peer 2
What to Observe:
- Mining Process: The node tries different nonce values until the hash starts with "00". This simulates proof-of-work.
- Self-Vote: Node 6001 automatically votes for its own block (counts as 1 vote).
- Vote Broadcast: The node sends its vote to all connected peers (Node 6002 and Node 6003).
Why This Matters:
- The proposer doesn't wait - it immediately votes for its own block
- This ensures the proposer is counted in the consensus calculation
- The vote is broadcast to all peers simultaneously
What happens: Node 6002 and Node 6003 receive the vote message. They validate the block and vote.
Terminal Output (Node 6002):
VOTE RECEIVED:
From: Node-6001
Block: 00a7f3d2e1b5c8f9...
Current votes: 2/2
Voters: Node-6001, Node-6002
MAJORITY REACHED! Proceeding to consensus...
Terminal Output (Node 6003):
VOTE RECEIVED:
From: Node-6001
Block: 00a7f3d2e1b5c8f9...
Current votes: 2/2
Voters: Node-6001, Node-6002
MAJORITY REACHED! Proceeding to consensus...
What to Observe:
- Vote Counting: Each node tracks votes independently. When Node 6002 votes, it sees 2 votes total (Node-6001 + Node-6002).
- Threshold Check: 2 votes out of 3 nodes = 67% = MAJORITY REACHED
- Synchronization: Both Node 6002 and Node 6003 see the same vote count because they both received Node-6001's vote and Node-6002's vote.
Why This Matters:
- Each node independently verifies the block before voting
- The 2/3 threshold is checked locally by each node
- Once threshold is reached, consensus is guaranteed
Important Note:
- Node 6003 also votes, but the threshold was already reached with 2 votes
- In BFT, once 2/3 is reached, additional votes don't change the outcome
- All nodes will eventually see 3/3 votes, but consensus is achieved at 2/3
What happens: All nodes that reached the threshold add the block to their blockchain.
Terminal Output (All Nodes):
CONSENSUS REACHED!
Block 1 has been accepted by the network!
Final votes: 2/3
Block added to blockchain (Total blocks: 2)
SUCCESS! NEW BLOCK OFFICIALLY ADDED TO BLOCKCHAIN!
Block Index: 1
Block Hash: 00a7f3d2e1b5c8f9abc123def456...
Block Data: "Payment of $100 from Alice to Bob"
Consensus Votes: 2 out of 3 nodes
Added at: 19/6/2025, 8:30:15 pm
Blockchain Length: 2 blocks
All connected nodes now have this block in their blockchain!
BLOCK INFORMATION:
Index: 1
Previous Hash: 4702089da1945d07...
Timestamp: 19/6/2025, 8:30:15 pm
Data: "Payment of $100 from Alice to Bob"
Nonce: 23847
Hash: 00a7f3d2e1b5c8f9abc123def456...
Votes: 2
CURRENT BLOCKCHAIN:
Block 0: 4702089da194... | Data: "Genesis Block - The First Block"
Block 1: 00a7f3d2e1b5... | Data: "Payment of $100 from Alice to Bob"
Chain length: 2 blocks
What to Observe:
- Finality: Once consensus is reached, the block is permanent - no rollbacks
- Synchronization: All nodes have the same blockchain state
- Block Details: Every block contains a hash of the previous block, creating the chain
Why This Matters:
- Safety: No two honest nodes will have different blockchains
- Liveness: The network makes progress as long as >2/3 nodes are honest
- Agreement: All honest nodes agree on the same state
Setup:
- 4 nodes total (6001, 6002, 6003, 6004)
- Required votes: 3 out of 4 (75% threshold)
What to Observe:
CONSENSUS PHASE:
Required votes: 3 out of 4 nodes
Current votes: 1 (self-vote)
Key Learning:
- With 4 nodes, you need 75% agreement (3 votes)
- This is higher than the 67% with 3 nodes
- More nodes = higher threshold, but also more fault tolerance
Vote Progression:
- Node 6001 proposes: 1/4 votes
- Node 6002 votes: 2/4 votes (still need 1 more)
- Node 6003 votes: 3/4 votes = CONSENSUS REACHED (75%)
- Node 6004 votes: 4/4 votes (consensus already achieved)
Setup:
- 3 nodes: 6001, 6002, 6003
- Node 6003 disconnects during consensus
What Happens:
Node-6001> propose "Transaction X"
CONSENSUS PHASE:
Required votes: 2 out of 3 nodes
Current votes: 1 (self-vote)
VOTE RECEIVED:
From: Node-6002
Block: 00a7f3d2...
Current votes: 2/2
MAJORITY REACHED! Proceeding to consensus...
CONSENSUS REACHED!
Final votes: 2/3
What to Observe:
- Even with Node 6003 disconnected, consensus is reached
- Node 6001 and Node 6002 form a majority (2 out of 2 = 100%)
- This is > 67% threshold, so consensus is valid
- Node 6003 will sync when it reconnects
Key Learning:
- BFT can handle network partitions
- As long as the connected nodes form >2/3 majority, consensus continues
- Disconnected nodes catch up when they reconnect
Setup:
- Node 6001 proposes Block A
- Node 6002 proposes Block B (at nearly the same time)
What Happens:
Terminal 1 (Node 6001):
Node-6001> propose "Transaction A"
... mining ...
... voting ...
Terminal 2 (Node 6002):
Node-6002> propose "Transaction B"
... mining ...
... voting ...
Terminal 1:
VOTE RECEIVED:
From: Node-6002
Block: 00a7f3d2... (Block A)
Current votes: 2/2
MAJORITY REACHED!
Terminal 2:
VOTE RECEIVED:
From: Node-6001
Block: 00b8e4f3... (Block B)
Current votes: 2/2
MAJORITY REACHED!
What to Observe:
- Both blocks might reach consensus threshold
- The first block to be added to the blockchain wins
- The second block will fail validation (wrong previous hash)
- Only one block can be at position 1 in the chain
Key Learning:
- BFT prevents double-spending
- Only one block can be at each index
- The network naturally resolves conflicts through validation
Structure:
{
"type": "VOTE",
"blockHash": "00a7f3d2e1b5c8f9...",
"voterNodeId": "Node-6002",
"blockIndex": 1
}What Each Field Means:
type: Identifies this as a vote messageblockHash: The unique identifier of the block being voted onvoterNodeId: Which node is casting the voteblockIndex: The position this block will have in the chain
Why Block Hash?
- The hash uniquely identifies the block
- If any data changes, the hash changes
- This prevents voting on modified blocks
- What it means: System works even when some nodes are faulty/malicious
- How BFT achieves it: Requires >2/3 honest nodes
- What you see: Even if 1 node fails, the other 2 can reach consensus
- What it means: Once consensus is reached, the block is permanent
- How BFT achieves it: All honest nodes agree before adding the block
- What you see: No rollbacks, no reorganizations
- What it means: Same inputs always produce the same result
- How BFT achieves it: Fixed 2/3 threshold, deterministic voting
- What you see: Same block always gets the same votes
- What it means: All nodes have the same blockchain state
- How BFT achieves it: Consensus ensures all nodes add the same block
- What you see: All terminals show the same blockchain
- Start with 3 nodes, observe threshold (2/3 = 67%)
- Add a 4th node, observe threshold change (3/4 = 75%)
- Add a 5th node, observe threshold change (4/5 = 80%)
- Question: Why does the threshold percentage increase?
- Start 3 nodes and connect them
- Propose a block
- Disconnect one node before consensus
- Observe: Can the remaining 2 nodes reach consensus?
- Answer: Yes! 2/2 = 100% > 67% threshold
- Start 3 nodes
- Propose a block from Node 6001
- Watch the vote count: 1 → 2 → 3
- Question: At what point is consensus reached?
- Answer: At 2 votes (2/3 = 67%)
- Start 3 nodes
- Have Node 6001 propose Block A
- Immediately have Node 6002 propose Block B
- Observe: Which block gets added?
- Answer: The first to reach 2/3 votes wins
Symptoms:
CONSENSUS PHASE:
Required votes: 2 out of 3 nodes
Current votes: 1 (self-vote)
Need 1 more vote for consensus
Waiting for more nodes to vote...
Possible Causes:
- Nodes not connected: Check
networkcommand to see connected peers - Network issues: Check if nodes can communicate
- Only 2 nodes total: With 2 nodes, you need 2/2 = 100% (both must agree)
Solution:
- Use
connect <port>to connect nodes - Use
networkto verify connections - Ensure at least 3 nodes for realistic BFT behavior
Symptoms:
- Different nodes show different blockchain lengths
- Blocks appear on some nodes but not others
Possible Causes:
- Consensus not reached: Block didn't get 2/3 votes
- Node disconnected: Node missed the consensus phase
- Validation failed: Block was invalid
Solution:
- Check vote counts with
statuscommand - Reconnect disconnected nodes
- Use
validateto check blockchain integrity
After going through these examples, you should understand:
- How BFT Works: 2/3 majority voting ensures consensus
- Why 2/3: Prevents Byzantine nodes from splitting the network
- Vote Process: Propose → Mine → Vote → Consensus
- Finality: Once consensus is reached, block is permanent
- Fault Tolerance: System works even if 1/3 nodes fail
- Network Effects: More nodes = higher threshold but more resilience
Key Takeaway: BFT provides deterministic, immediate finality through majority voting, making it ideal for permissioned networks where all nodes are known and trusted equally.