code wiki / (root) / nx_etg_byzantine.nx

nx_etg_byzantine.nx source

↩ module page · 126 lines · 5093 B

1// nx_etg_byzantine.nx -- E2.5 Byzantine M-of-N outcome agreement. 2// 3// Anti-forgery gate for ETG attestations. Composes E1 NxEtgEntry + 4// E2 tournament selector + E3 per-tier probes by running the same 5// probe N times (across diverse-double-compile + canary-tagged 6// probe binaries per [[NISHI_RACING_CREW_ROADMAP]]) and requiring 7// M-of-N replicas to agree on the outcome before the substrate 8// commits the attestation to its journal. 9// 10// Detects: 11// - Compromised probe binary lying about silicon truth 12// - Transient measurement noise that flipped a single replica 13// - Vendor-driven runtime gating that only triggers on specific 14// probe call patterns (probe diversity defeats this) 15// - Wheeler diverse-double-compile detection of compiler-side 16// attestation forgery (different compilers should produce the 17// same outcome on the same silicon -- if they don't, agreement 18// fails loud, never silent) 19// 20// Composes: 21// [[NISHI_ETG_ROADMAP]] E2.5 (this is the gate primitive) 22// nx_etg.nx (E1 NxEtgEntry; SHIPPED) 23// [[NISHI_RACING_CREW_ROADMAP]] (Byzantine N-of-M mechanism) 24// [[feedback-racing-crew-team-honesty-threat-aware]] (the threat 25// model this gate addresses) 26// [[feedback-no-false-ok-substrate-honesty-audit]] (NO_AGREEMENT 27// is the substrate-honest verdict; never silent picks of 28// minority-majority) 29// 30// API: 31// nx_etg_byzantine_outcome_agree(outcomes, n, m_required) -> i64 32// Returns the agreed outcome (NX_ETG_OUTCOME_*) iff some outcome 33// occurs >= m_required times in the input. Else returns 34// NX_ETG_BYZ_NO_AGREEMENT. Tie-break: if multiple outcomes 35// reach the m_required threshold, returns the FIRST one found 36// by walking outcome ids 0..NX_ETG_OUTCOME_N-1 (deterministic 37// replay). 38// 39// nx_etg_byzantine_count_outcome(outcomes, n, target) -> i64 40// Counts occurrences of `target` in the outcomes array. Useful 41// for auditing (how confident was the agreement?). 42// 43// Why outcome-only agreement (not measurement_value agreement): 44// Real measurement values have noise -- syscall round-trips, 45// cache latency, even integer-ALU throughput per nx_calibrate 46// vary cycle-to-cycle. Requiring bit-equal measurement across 47// replicas would mean NO_AGREEMENT on every real probe. The 48// substrate-honest gate is OUTCOME agreement: did all replicas 49// classify into the same NX_ETG_OUTCOME_*? Measurement-aggregation 50// (median / trimmed-mean / interquartile-range) is a separate 51// primitive queued for E2.6 once the agreement layer is proven. 52 53// nx_safety_envelope: 54// intended_use: "Byzantine M-of-N outcome agreement; gates 55// ETG attestation commits; substrate-honest 56// on disagreement (NO_AGREEMENT sentinel)" 57// sil_target: SIL2 58// evidence: [kat_unanimous_agreement, 59// kat_majority_agreement, 60// kat_no_majority_no_agreement, 61// kat_threshold_boundary_correctness, 62// kat_invalid_m_returns_no_agreement, 63// kat_deterministic_tie_break] 64// hazard_register: [bug-tape-off-by-one-on-m-threshold, 65// bug-tape-tie-break-nondeterministic, 66// bug-tape-invalid-m-silently-accepted] 67// verdict: NOT_YET_EVALUATED 68 69import "nx_syscalls.nx" 70import "nx_etg.nx" 71 72// ===== Sentinel =================================================== 73 74const NX_ETG_BYZ_NO_AGREEMENT: i64 = -1 75 76// ===== Outcome counting =========================================== 77 78// Walk the outcomes array; count occurrences of `target`. Used by 79// the agreement function + exposed for auditors. 80func nx_etg_byzantine_count_outcome( 81 outcomes: *i64, 82 n: i64, 83 target: i64 84) -> i64 { 85 if n <= 0 { return 0 } 86 var i: i64 = 0 87 var count: i64 = 0 88 while i < n { 89 if outcomes[i] == target { 90 count = count + 1 91 } 92 i = i + 1 93 } 94 return count 95} 96 97// ===== M-of-N agreement =========================================== 98// 99// Returns the agreed outcome (lowest outcome id reaching the 100// threshold) or NX_ETG_BYZ_NO_AGREEMENT if no outcome does. 101// 102// Walks outcome ids 0..NX_ETG_OUTCOME_N-1 in order; for each id, 103// asks the counting helper how many of the N replicas voted for it; 104// returns the first id whose count >= m_required. Walking in id 105// order ensures deterministic tie-break (lowest id wins if two 106// outcomes reach the threshold). 107 108func nx_etg_byzantine_outcome_agree( 109 outcomes: *i64, 110 n: i64, 111 m_required: i64 112) -> i64 { 113 if n <= 0 { return NX_ETG_BYZ_NO_AGREEMENT } 114 if m_required <= 0 { return NX_ETG_BYZ_NO_AGREEMENT } 115 if m_required > n { return NX_ETG_BYZ_NO_AGREEMENT } 116 117 var oid: i64 = 0 118 while oid < NX_ETG_OUTCOME_N { 119 let c: i64 = nx_etg_byzantine_count_outcome(outcomes, n, oid) 120 if c >= m_required { 121 return oid 122 } 123 oid = oid + 1 124 } 125 return NX_ETG_BYZ_NO_AGREEMENT 126}