Skip to main content

byzantine/
byzantine.rs

1use vrf_pbft::{Config, ConsensusEngine, Node};
2
3fn main() {
4    // f=2: can tolerate 2 byzantine nodes, needs 7 total
5    let config = Config::new(2);
6    let mut engine = ConsensusEngine::new(config);
7
8    for i in 1..=7 {
9        let mut node = Node::new(i, 1000).expect("failed to create node");
10        // Mark first 2 nodes as byzantine (they vote against valid blocks)
11        if i <= 2 {
12            node.set_byzantine(true);
13        }
14        engine.add_node(node);
15    }
16
17    println!("Byzantine fault tolerance demo");
18    println!("  Nodes:     7 (5 honest, 2 byzantine)");
19    println!("  f=2:       system tolerates up to 2 faults");
20    println!("  Threshold: 2f+1 = {}\n", 2 * 2 + 1);
21
22    let total_rounds = 100;
23    let blocks = engine.run(total_rounds).expect("simulation failed");
24
25    println!("After {} round attempts:", engine.round());
26    println!("  Blocks committed: {}", blocks.len());
27
28    if !blocks.is_empty() {
29        println!("\n  Byzantine nodes voted AGAINST every block,");
30        println!("  but consensus still passed because 5 honest");
31        println!("  nodes exceed the threshold of 5 (2f+1).\n");
32
33        // Verify ledger consistency
34        let first_len = engine.nodes()[0].ledger().len();
35        let consistent = engine.nodes().iter().all(|n| n.ledger().len() == first_len);
36        println!(
37            "  Ledger consistency: {} ({} blocks per node)",
38            if consistent { "PASS" } else { "FAIL" },
39            first_len
40        );
41    } else {
42        println!("\n  No blocks committed (VRF didn't elect enough validators).");
43        println!("  Try running again -- VRF selection is probabilistic.");
44    }
45}