TASK
Implementation
Implement PBFT: tolerates f Byzantine faults with 3f+1 nodes. Three phases: pre-prepare, prepare, commit.
Sample Test Cases
Pre-prepare phaseTimeout: 5000ms
Input
{
"src": "c0",
"dest": "n1",
"body": {
"type": "init",
"msg_id": 1,
"node_id": "n1",
"node_ids": [
"n1"
]
}
}Expected Output
{"src":"n1","dest":"c0","body":{"type":"init_ok","in_reply_to":1,"msg_id":0}}Hints
Hint 1▾
Need 3f+1 nodes to tolerate f faults
Hint 2▾
Pre-prepare, Prepare, Commit phases
Hint 3▾
Wait for 2f+1 matching messages
OVERVIEW
Theoretical Hub
Byzantine Fault Tolerance
Byzantine faults include malicious behavior. PBFT requires 3f+1 nodes to tolerate f faulty nodes. Uses 3 phases with quorum certificates.
Key Concepts
ByzantinePBFTf faults
main.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env python3
class PBFTNode:
def __init__(self, node_id, total_nodes):
self.id = node_id
self.n = total_nodes
self.f = (total_nodes - 1) // 3
self.state = {}
self.log = []
self.prepared = {} # seq -> set of nodes
self.committed = {}
def pre_prepare(self, seq, request):
# TODO: Primary broadcasts pre-prepare
pass
def prepare(self, seq, digest):
# TODO: Replica sends prepare to all
pass
def on_prepare(self, from_node, seq, digest):
# TODO: Collect 2f prepares
pass
def commit(self, seq, digest):
# TODO: Broadcast commit after prepared
pass
def on_commit(self, from_node, seq, digest):
# TODO: Execute after 2f+1 commits
pass