code wiki / _hdl_build / nx_canon_bin_gate.nx

nx_canon_bin_gate.nx source

↩ module page · 85 lines · 5818 B

1// nx_canon_bin_gate.nx -- prove the binary-safe canonical primitive (the gap in the substrate). Asserts: 2// BINARY-SAFE : a value containing 0x00 bytes round-trips at FULL length (string-only canon_encode truncates it). 3// CANONICAL : the same fields in DIFFERENT insertion order encode to BYTE-IDENTICAL output (=> identical CID). 4// CID : cid_of (the REUSED substrate sha256 CID) is well-formed + deterministic. 5// DECODE : canon_decode_bin recovers every field; the binary value (via offset+len, IN-buffer) matches. 6// GREEN = the substrate now has a binary-safe canonical record (additive sibling; media can be a first-class value). 7// expect_exit: 0 license_tier: ORIGINAL 8import "nx_syscalls.nx" 9import "nx_canon_bin.nx" 10import "nx_canon_cid.nx" 11import "nx_gate_verdict.nx" 12 13func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 14func gnum(v0: i64) -> i64 { var v: i64=v0; if v<0 { sys_write(1,"-" as *u8,1); v=0-v } let b: *u8=sys_mmap(24); var k: i64=0; if v==0 {b[0]=48 as u8;k=1} while v>0 {b[k]=(48+(v%10)) as u8; v=v/10; k=k+1} let o: *u8=sys_mmap(24); var j: i64=0; while j<k {o[j]=b[k-1-j];j=j+1} sys_write(1,o,k); return 0 } 15func gstreq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 } 16 17func main() -> i64 { 18 gp("=== nx_canon_bin_gate: binary-safe canonical records (substrate sibling) ===\n" as *u8) 19 20 // a binary value with EMBEDDED NUL bytes (the thing string-only canon_encode cannot carry) 21 let blob: *u8 = sys_mmap(16) 22 blob[0]=1 as u8; blob[1]=0 as u8; blob[2]=255 as u8; blob[3]=0 as u8; blob[4]=66 as u8 // 01 00 FF 00 42, len 5 23 24 // order A: zzz, @kind, blob, name 25 let kA: *i64 = sys_mmap(64) as *i64; let vA: *i64 = sys_mmap(64) as *i64; let lA: *i64 = sys_mmap(64) as *i64 26 kA[0]="zzz\x00" as *u8 as i64; vA[0]="last\x00" as *u8 as i64; lA[0]=4 27 kA[1]="@kind\x00" as *u8 as i64; vA[1]="media\x00" as *u8 as i64; lA[1]=5 28 kA[2]="blob\x00" as *u8 as i64; vA[2]=blob as i64; lA[2]=5 29 kA[3]="name\x00" as *u8 as i64; vA[3]="Alice\x00" as *u8 as i64; lA[3]=5 30 // order B: reversed 31 let kB: *i64 = sys_mmap(64) as *i64; let vB: *i64 = sys_mmap(64) as *i64; let lB: *i64 = sys_mmap(64) as *i64 32 kB[0]="name\x00" as *u8 as i64; vB[0]="Alice\x00" as *u8 as i64; lB[0]=5 33 kB[1]="blob\x00" as *u8 as i64; vB[1]=blob as i64; lB[1]=5 34 kB[2]="@kind\x00" as *u8 as i64; vB[2]="media\x00" as *u8 as i64; lB[2]=5 35 kB[3]="zzz\x00" as *u8 as i64; vB[3]="last\x00" as *u8 as i64; lB[3]=4 36 37 let eA: *u8 = sys_mmap(4096); let nA: i64 = canon_encode_bin(kA, vA, lA, 4, eA) 38 let eB: *u8 = sys_mmap(4096); let nB: i64 = canon_encode_bin(kB, vB, lB, 4, eB) 39 40 // canonical: same fields, any order -> identical bytes 41 var canon_eq: i64 = 1 42 if nA != nB { canon_eq = 0 } else { var i: i64=0; while i<nA { if eA[i]!=eB[i] { canon_eq=0; i=nA } else { i=i+1 } } } 43 44 // binary-safe: extract the blob, must be FULL length 5 (string-only would stop at the first 0x00 => len 1) 45 let got: *u8 = sys_mmap(64); let gl: i64 = canon_get_bin(eA, nA, "blob\x00" as *u8, got, 64) 46 var blob_ok: i64 = 0 47 if gl == 5 { if got[0]==(1 as u8) { if got[1]==(0 as u8) { if got[2]==(255 as u8) { if got[3]==(0 as u8) { if got[4]==(66 as u8) { blob_ok=1 } } } } } } 48 49 // string field round-trips 50 let nm: *u8 = sys_mmap(64); canon_get_bin(eA, nA, "name\x00" as *u8, nm, 64); nm[5]=0 as u8 51 52 // CID reuse (substrate sha256) + determinism 53 let cid1: *u8 = sys_mmap(80); cid_of(eA, nA, cid1) 54 let cid2: *u8 = sys_mmap(80); cid_of(eB, nB, cid2) 55 var cid_eq: i64 = 0; if gstreq(cid1, cid2) == 1 { cid_eq = 1 } 56 57 // full decode: 4 fields; locate blob by offset+len IN buffer 58 let dk: *i64 = sys_mmap(64) as *i64; let dvo: *i64 = sys_mmap(64) as *i64; let dvl: *i64 = sys_mmap(64) as *i64 59 let nf: i64 = canon_decode_bin(eA, nA, dk, dvo, dvl, 16) 60 var dec_blob_ok: i64 = 0 61 var di: i64 = 0 62 while di < nf { if gstreq((dk[di]) as *u8, "blob\x00" as *u8) == 1 { if dvl[di]==5 { if eA[dvo[di]+2]==(255 as u8) { dec_blob_ok=1 } } di=nf } else { di=di+1 } } 63 64 gp(" bytes=" as *u8); gnum(nA); gp(" blob_len=" as *u8); gnum(gl); gp(" canonical_eq=" as *u8); gnum(canon_eq) 65 gp(" cid=" as *u8); gp(cid1); gp(" cid_eq=" as *u8); gnum(cid_eq); gp(" nfields=" as *u8); gnum(nf); gp("\n" as *u8) 66 67 var pass: i64 = 0; var fail: i64 = 0 68 if blob_ok == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL binary-value-not-preserved (NUL truncation)\n" as *u8) } 69 if gstreq(nm, "Alice" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL string-field-roundtrip\n" as *u8) } 70 if canon_eq == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL not-canonical (insertion order leaked)\n" as *u8) } 71 if cid_eq == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL cid-order-dependent\n" as *u8) } 72 if nf == 4 { pass=pass+1 } else { fail=fail+1; gp(" FAIL decode-nfields!=4\n" as *u8) } 73 if dec_blob_ok == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL decode-blob-mismatch\n" as *u8) } 74 75 gp("CANON-BIN-GATE pass=" as *u8); gnum(pass); gp(" fail=" as *u8); gnum(fail) 76 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 77 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 78 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 79 let ctr__dry: *i64 = gv_ctr() 80 ctr__dry[0] = pass 81 ctr__dry[1] = pass + fail 82 let rc__dry: i64 = gv_verdict("CANON-BIN-GATE" as *u8, ctr__dry, "binary-safe canonical record; same CID as the substrate; order-independent)" as *u8) 83 sys_exit(rc__dry) 84 return rc__dry 85}