code wiki / _hdl_build / nx_canon_bin_gate.nx

nx_canon_bin_gate.nx source

↩ module page · 77 lines · 5430 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" 11 12func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 13func 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 } 14func 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 } 15 16func main() -> i64 { 17 gp("=== nx_canon_bin_gate: binary-safe canonical records (substrate sibling) ===\n" as *u8) 18 19 // a binary value with EMBEDDED NUL bytes (the thing string-only canon_encode cannot carry) 20 let blob: *u8 = sys_mmap(16) 21 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 22 23 // order A: zzz, @kind, blob, name 24 let kA: *i64 = sys_mmap(64) as *i64; let vA: *i64 = sys_mmap(64) as *i64; let lA: *i64 = sys_mmap(64) as *i64 25 kA[0]="zzz\x00" as *u8 as i64; vA[0]="last\x00" as *u8 as i64; lA[0]=4 26 kA[1]="@kind\x00" as *u8 as i64; vA[1]="media\x00" as *u8 as i64; lA[1]=5 27 kA[2]="blob\x00" as *u8 as i64; vA[2]=blob as i64; lA[2]=5 28 kA[3]="name\x00" as *u8 as i64; vA[3]="Alice\x00" as *u8 as i64; lA[3]=5 29 // order B: reversed 30 let kB: *i64 = sys_mmap(64) as *i64; let vB: *i64 = sys_mmap(64) as *i64; let lB: *i64 = sys_mmap(64) as *i64 31 kB[0]="name\x00" as *u8 as i64; vB[0]="Alice\x00" as *u8 as i64; lB[0]=5 32 kB[1]="blob\x00" as *u8 as i64; vB[1]=blob as i64; lB[1]=5 33 kB[2]="@kind\x00" as *u8 as i64; vB[2]="media\x00" as *u8 as i64; lB[2]=5 34 kB[3]="zzz\x00" as *u8 as i64; vB[3]="last\x00" as *u8 as i64; lB[3]=4 35 36 let eA: *u8 = sys_mmap(4096); let nA: i64 = canon_encode_bin(kA, vA, lA, 4, eA) 37 let eB: *u8 = sys_mmap(4096); let nB: i64 = canon_encode_bin(kB, vB, lB, 4, eB) 38 39 // canonical: same fields, any order -> identical bytes 40 var canon_eq: i64 = 1 41 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 } } } 42 43 // binary-safe: extract the blob, must be FULL length 5 (string-only would stop at the first 0x00 => len 1) 44 let got: *u8 = sys_mmap(64); let gl: i64 = canon_get_bin(eA, nA, "blob\x00" as *u8, got, 64) 45 var blob_ok: i64 = 0 46 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 } } } } } } 47 48 // string field round-trips 49 let nm: *u8 = sys_mmap(64); canon_get_bin(eA, nA, "name\x00" as *u8, nm, 64); nm[5]=0 as u8 50 51 // CID reuse (substrate sha256) + determinism 52 let cid1: *u8 = sys_mmap(80); cid_of(eA, nA, cid1) 53 let cid2: *u8 = sys_mmap(80); cid_of(eB, nB, cid2) 54 var cid_eq: i64 = 0; if gstreq(cid1, cid2) == 1 { cid_eq = 1 } 55 56 // full decode: 4 fields; locate blob by offset+len IN buffer 57 let dk: *i64 = sys_mmap(64) as *i64; let dvo: *i64 = sys_mmap(64) as *i64; let dvl: *i64 = sys_mmap(64) as *i64 58 let nf: i64 = canon_decode_bin(eA, nA, dk, dvo, dvl, 16) 59 var dec_blob_ok: i64 = 0 60 var di: i64 = 0 61 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 } } 62 63 gp(" bytes=" as *u8); gnum(nA); gp(" blob_len=" as *u8); gnum(gl); gp(" canonical_eq=" as *u8); gnum(canon_eq) 64 gp(" cid=" as *u8); gp(cid1); gp(" cid_eq=" as *u8); gnum(cid_eq); gp(" nfields=" as *u8); gnum(nf); gp("\n" as *u8) 65 66 var pass: i64 = 0; var fail: i64 = 0 67 if blob_ok == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL binary-value-not-preserved (NUL truncation)\n" as *u8) } 68 if gstreq(nm, "Alice" as *u8) == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL string-field-roundtrip\n" as *u8) } 69 if canon_eq == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL not-canonical (insertion order leaked)\n" as *u8) } 70 if cid_eq == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL cid-order-dependent\n" as *u8) } 71 if nf == 4 { pass=pass+1 } else { fail=fail+1; gp(" FAIL decode-nfields!=4\n" as *u8) } 72 if dec_blob_ok == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL decode-blob-mismatch\n" as *u8) } 73 74 gp("CANON-BIN-GATE pass=" as *u8); gnum(pass); gp(" fail=" as *u8); gnum(fail) 75 if fail == 0 { gp(" verdict=GREEN (binary-safe canonical record; same CID as the substrate; order-independent)\n" as *u8); sys_exit(0); return 0 } 76 gp(" verdict=RED\n" as *u8); sys_exit(1); return 1 77}