code wiki / (root) / nx_fec_xor_test.nx

nx_fec_xor_test.nx source

↩ module page · 90 lines · 3668 B

1// nx_fec_xor_test.nx -- 1:1 KAT for sovereign XOR FEC (nx_fec_xor.nx). 2// Encode a known LxD grid, then prove: row parity recovers random loss, 3// 2-D peeling recovers a burst row-only can't, an over-budget loss is 4// HONESTLY unrecoverable (reported, never corrupted), and redundancy is 5// sized adaptively from the loss estimate. 6// 7// expect_exit: 0 8// license_tier: ORIGINAL 9 10import "nx_fec_xor.nx" 11 12const KL: i64 = 4 // columns 13const KD: i64 = 3 // rows 14const KS: i64 = 4 // bytes/packet 15// K = 12 source packets 16 17func main() -> i64 { 18 let K: i64 = KL * KD 19 let golden: *u8 = sys_mmap(K * KS) 20 let src: *u8 = sys_mmap(K * KS) 21 let rows: *u8 = sys_mmap(KD * KS) 22 let cols: *u8 = sys_mmap(KL * KS) 23 let present: *i64 = sys_mmap(K * 8) as *i64 24 let rp: *i64 = sys_mmap(KD * 8) as *i64 25 let cp: *i64 = sys_mmap(KL * 8) as *i64 26 27 // fill golden with distinct data 28 var i: i64 = 0 29 while i < K * KS { golden[i] = ((i * 7 + 1) & 0xff) as u8; i = i + 1 } 30 // copy -> src, encode repairs from the clean grid 31 i = 0 32 while i < K * KS { src[i] = golden[i]; i = i + 1 } 33 fec_encode_rows(src, KL, KD, KS, rows) 34 fec_encode_cols(src, KL, KD, KS, cols) 35 // repairs all present in every test 36 i = 0 37 while i < KD { rp[i] = 1; i = i + 1 } 38 i = 0 39 while i < KL { cp[i] = 1; i = i + 1 } 40 41 // ---- T1: row parity recovers 1 RANDOM loss per row ---- 42 fec_reset(golden, src, present, K, KS) 43 fec_drop(src, present, 2, KS) // row0 44 fec_drop(src, present, 5, KS) // row1 45 fec_drop(src, present, 9, KS) // row2 46 if fec_decode_2d(src, KL, KD, KS, present, rows, rp, cols, cp) != 0 { return 1 } 47 if fec_cmp(golden, src, K * KS) != 0 { return 2 } 48 49 // ---- T2: 2-D peeling recovers a BURST row-parity alone cannot ---- 50 fec_reset(golden, src, present, K, KS) 51 fec_drop(src, present, 5, KS) // row1 col1 52 fec_drop(src, present, 6, KS) // row1 col2 (2 in row1 -> rows stuck) 53 if fec_decode_2d(src, KL, KD, KS, present, rows, rp, cols, cp) != 0 { return 3 } 54 if fec_cmp(golden, src, K * KS) != 0 { return 4 } 55 56 // ---- T3: over-budget 2x2 block -> HONESTLY unrecoverable (no corrupt) ---- 57 fec_reset(golden, src, present, K, KS) 58 fec_drop(src, present, 5, KS); fec_drop(src, present, 6, KS) // row1 col1,2 59 fec_drop(src, present, 9, KS); fec_drop(src, present, 10, KS) // row2 col1,2 60 if fec_decode_2d(src, KL, KD, KS, present, rows, rp, cols, cp) != 4 { return 5 } 61 62 // ---- T4: adaptive redundancy sized from the loss estimate ---- 63 if fec_scheme_for_loss(0) != FEC_NONE { return 6 } 64 if fec_scheme_for_loss(3) != FEC_ROW { return 7 } 65 if fec_scheme_for_loss(10) != FEC_2D { return 8 } 66 if fec_overhead_pct(FEC_ROW, KL, KD) != 25 { return 9 } // 3 row repairs / 12 = 25% 67 if fec_overhead_pct(FEC_2D, KL, KD) != 58 { return 10 } // (3+4)/12 = 58% 68 69 sys_write(1, "FEC-XOR KAT PASS (row recovers random loss, 2-D recovers burst, honest unrecoverable, adaptive sizing)\n", 102) 70 return 0 71} 72 73// helpers (defined after main; prepass registers them) 74func fec_reset(golden: *u8, src: *u8, present: *i64, K: i64, S: i64) -> i64 { 75 var i: i64 = 0 76 while i < K * S { src[i] = golden[i]; i = i + 1 } 77 i = 0 78 while i < K { present[i] = 1; i = i + 1 } 79 return 0 80} 81func fec_drop(src: *u8, present: *i64, idx: i64, S: i64) -> i64 { 82 fec_zero(fec_pkt(src, idx, S), S) // simulate loss = zeroed payload 83 present[idx] = 0 84 return 0 85} 86func fec_cmp(a: *u8, b: *u8, n: i64) -> i64 { 87 var i: i64 = 0 88 while i < n { if (a[i] & 0xff) != (b[i] & 0xff) { return 1 } i = i + 1 } 89 return 0 90}