nx_etg_byzantine_test.nx source
↩ module page · 124 lines · 5478 B
1// nx_etg_byzantine_test.nx -- KAT for E2.5 Byzantine M-of-N agreement.
2//
3// Verifies:
4// T1 Unanimous: 5 replicas all CONFIRMED, m=5 -> CONFIRMED.
5// T2 Majority: 3 CONFIRMED + 2 FALSIFIED, m=3 -> CONFIRMED.
6// T3 Bare-majority: 3 CONFIRMED + 2 FALSIFIED, m=2 -> CONFIRMED
7// (lowest-id tie-break since FALSIFIED also has count >= 2).
8// T4 Below threshold: 2 CONFIRMED + 3 different outcomes, m=3
9// -> NO_AGREEMENT.
10// T5 All different: 5 distinct outcomes, m=2 -> NO_AGREEMENT.
11// T6 Tie-break determinism: 2 CONFIRMED + 2 FALSIFIED, m=2 ->
12// CONFIRMED (lower outcome id) -- proves walk order.
13// T7 N=0 -> NO_AGREEMENT.
14// T8 m_required <= 0 -> NO_AGREEMENT.
15// T9 m_required > n -> NO_AGREEMENT.
16// T10 Counting helper exposes audit confidence: a 3-CONFIRMED-
17// majority should report exactly count==3 when queried.
18
19import "nx_syscalls.nx"
20import "nx_etg.nx"
21import "nx_etg_byzantine.nx"
22
23func main() -> i64 {
24 let buf: *u8 = sys_mmap(128)
25 let outcomes: *i64 = buf as *i64
26
27 // ----- T1 Unanimous agreement -----
28 outcomes[0] = NX_ETG_OUTCOME_CONFIRMED
29 outcomes[1] = NX_ETG_OUTCOME_CONFIRMED
30 outcomes[2] = NX_ETG_OUTCOME_CONFIRMED
31 outcomes[3] = NX_ETG_OUTCOME_CONFIRMED
32 outcomes[4] = NX_ETG_OUTCOME_CONFIRMED
33 let r1: i64 = nx_etg_byzantine_outcome_agree(outcomes, 5, 5)
34 if r1 != NX_ETG_OUTCOME_CONFIRMED { return 1 }
35
36 // ----- T2 Majority agreement -----
37 outcomes[0] = NX_ETG_OUTCOME_CONFIRMED
38 outcomes[1] = NX_ETG_OUTCOME_CONFIRMED
39 outcomes[2] = NX_ETG_OUTCOME_CONFIRMED
40 outcomes[3] = NX_ETG_OUTCOME_FALSIFIED
41 outcomes[4] = NX_ETG_OUTCOME_FALSIFIED
42 let r2: i64 = nx_etg_byzantine_outcome_agree(outcomes, 5, 3)
43 if r2 != NX_ETG_OUTCOME_CONFIRMED { return 2 }
44
45 // ----- T3 Bare-majority + tie-break by lowest id -----
46 // CONFIRMED (id 1) has 3, FALSIFIED (id 4) has 2; m=2 means both
47 // reach threshold. Walk order returns CONFIRMED (lower id) first.
48 let r3: i64 = nx_etg_byzantine_outcome_agree(outcomes, 5, 2)
49 if r3 != NX_ETG_OUTCOME_CONFIRMED { return 3 }
50
51 // ----- T4 Below threshold -----
52 outcomes[0] = NX_ETG_OUTCOME_CONFIRMED
53 outcomes[1] = NX_ETG_OUTCOME_CONFIRMED
54 outcomes[2] = NX_ETG_OUTCOME_FALSIFIED
55 outcomes[3] = NX_ETG_OUTCOME_INCONCLUSIVE
56 outcomes[4] = NX_ETG_OUTCOME_THROTTLED
57 let r4: i64 = nx_etg_byzantine_outcome_agree(outcomes, 5, 3)
58 if r4 != NX_ETG_BYZ_NO_AGREEMENT { return 4 }
59
60 // ----- T5 All different -----
61 outcomes[0] = NX_ETG_OUTCOME_CONFIRMED
62 outcomes[1] = NX_ETG_OUTCOME_VENDOR_LIED_OMISSION
63 outcomes[2] = NX_ETG_OUTCOME_FALSIFIED
64 outcomes[3] = NX_ETG_OUTCOME_PAYWALLED_BUT_RESPONSIVE
65 outcomes[4] = NX_ETG_OUTCOME_RECLAIMED
66 let r5: i64 = nx_etg_byzantine_outcome_agree(outcomes, 5, 2)
67 if r5 != NX_ETG_BYZ_NO_AGREEMENT { return 5 }
68
69 // ----- T6 Tie-break: 2 CONFIRMED (id 1) + 2 FALSIFIED (id 4) -----
70 // Both reach m=2. Walk returns CONFIRMED (lower id) first.
71 outcomes[0] = NX_ETG_OUTCOME_CONFIRMED
72 outcomes[1] = NX_ETG_OUTCOME_CONFIRMED
73 outcomes[2] = NX_ETG_OUTCOME_FALSIFIED
74 outcomes[3] = NX_ETG_OUTCOME_FALSIFIED
75 let r6: i64 = nx_etg_byzantine_outcome_agree(outcomes, 4, 2)
76 if r6 != NX_ETG_OUTCOME_CONFIRMED { return 6 }
77
78 // Inverse: 2 FALSIFIED + 2 CONFIRMED. Result still CONFIRMED
79 // because walk order is by outcome id, not by input position.
80 outcomes[0] = NX_ETG_OUTCOME_FALSIFIED
81 outcomes[1] = NX_ETG_OUTCOME_FALSIFIED
82 outcomes[2] = NX_ETG_OUTCOME_CONFIRMED
83 outcomes[3] = NX_ETG_OUTCOME_CONFIRMED
84 let r6b: i64 = nx_etg_byzantine_outcome_agree(outcomes, 4, 2)
85 if r6b != NX_ETG_OUTCOME_CONFIRMED { return 7 }
86
87 // ----- T7 N=0 -----
88 let r7: i64 = nx_etg_byzantine_outcome_agree(outcomes, 0, 1)
89 if r7 != NX_ETG_BYZ_NO_AGREEMENT { return 8 }
90 // N negative: still NO_AGREEMENT (no underflow).
91 let r7b: i64 = nx_etg_byzantine_outcome_agree(outcomes, 0 - 1, 1)
92 if r7b != NX_ETG_BYZ_NO_AGREEMENT { return 9 }
93
94 // ----- T8 m_required <= 0 -----
95 let r8: i64 = nx_etg_byzantine_outcome_agree(outcomes, 4, 0)
96 if r8 != NX_ETG_BYZ_NO_AGREEMENT { return 10 }
97 let r8b: i64 = nx_etg_byzantine_outcome_agree(outcomes, 4, 0 - 1)
98 if r8b != NX_ETG_BYZ_NO_AGREEMENT { return 11 }
99
100 // ----- T9 m_required > n -----
101 let r9: i64 = nx_etg_byzantine_outcome_agree(outcomes, 4, 5)
102 if r9 != NX_ETG_BYZ_NO_AGREEMENT { return 12 }
103
104 // ----- T10 Counting helper audit confidence -----
105 outcomes[0] = NX_ETG_OUTCOME_CONFIRMED
106 outcomes[1] = NX_ETG_OUTCOME_CONFIRMED
107 outcomes[2] = NX_ETG_OUTCOME_CONFIRMED
108 outcomes[3] = NX_ETG_OUTCOME_FALSIFIED
109 outcomes[4] = NX_ETG_OUTCOME_INCONCLUSIVE
110 let c_conf: i64 = nx_etg_byzantine_count_outcome(outcomes, 5, NX_ETG_OUTCOME_CONFIRMED)
111 if c_conf != 3 { return 20 }
112 let c_fal: i64 = nx_etg_byzantine_count_outcome(outcomes, 5, NX_ETG_OUTCOME_FALSIFIED)
113 if c_fal != 1 { return 21 }
114 let c_inc: i64 = nx_etg_byzantine_count_outcome(outcomes, 5, NX_ETG_OUTCOME_INCONCLUSIVE)
115 if c_inc != 1 { return 22 }
116 // Outcomes never voted for return 0.
117 let c_rec: i64 = nx_etg_byzantine_count_outcome(outcomes, 5, NX_ETG_OUTCOME_RECLAIMED)
118 if c_rec != 0 { return 23 }
119 // Count with n=0 returns 0 (no underflow).
120 let c_zero: i64 = nx_etg_byzantine_count_outcome(outcomes, 0, NX_ETG_OUTCOME_CONFIRMED)
121 if c_zero != 0 { return 24 }
122
123 return 0
124}