code wiki / _hdl_build / nx_coe_witness.nx

nx_coe_witness.nx source

↩ module page · 221 lines · 7410 B

1// nx_coe_witness.nx -- CHAIN-OF-EVIDENCE TRANSPARENCY-LOG WITNESS (F713, Rekor-class) 2// Builds a SHA-256 Merkle tree over the frame-hash leaves of the signed evidence chain 3// (knowledge/status/coe_signed.log), computes the tree ROOT (a signed-tree-head), emits an 4// INCLUSION PROOF (audit path) for the latest leaf, and VERIFIES it deny-by-default (the audit 5// path must recompute the exact root). Each run appends the root to coe_witness.log = the STH 6// sequence (the substrate for consistency proofs). This is the transparency-log property Sigstore 7// /Rekor provide; sovereign (our own sha256), append-only, never deletes. 8// Composes proven libs only: nx_str/nx_syscalls/nx_sha256. x86-lane. license_tier: ORIGINAL 9import "nx_str.nx" 10import "nx_syscalls.nx" 11import "nx_sha256.nx" 12 13const CW_CAP: i64 = 1048576 14const CW_MAXLEAF: i64 = 4096 15 16func cw_puts(s: *u8) -> i64 { sys_write(1, s, nx_str_len(s)); return 0 } 17 18func cw_pi(v: i64) -> i64 { 19 let t: *u8 = sys_mmap(32) 20 var m: i64 = v 21 var k: i64 = 0 22 if m == 0 { t[0] = 48 as u8; k = 1 } 23 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 24 let o: *u8 = sys_mmap(32) 25 var i: i64 = 0 26 while i < k { o[i] = t[k-1-i]; i = i + 1 } 27 sys_write(1, o, k) 28 return 0 29} 30 31func cw_hexn(d: *u8, n: i64, out: *u8) -> i64 { 32 let hx: *u8 = "0123456789abcdef" as *u8 33 var i: i64 = 0 34 while i < n { 35 let b: i64 = d[i] as i64 36 out[i*2] = hx[(b >> 4) & 15] 37 out[i*2+1] = hx[b & 15] 38 i = i + 1 39 } 40 out[n*2] = 0 as u8 41 return n*2 42} 43 44func cw_nib(c: i64) -> i64 { 45 if c >= 97 { return c - 87 } 46 return c - 48 47} 48 49func cw_cat(dst: *u8, off: i64, s: *u8) -> i64 { 50 var i: i64 = 0 51 while s[i] != (0 as u8) { dst[off+i] = s[i]; i = i + 1 } 52 return off + i 53} 54func cw_catn(dst: *u8, off: i64, v: i64) -> i64 { 55 let t: *u8 = sys_mmap(32) 56 var m: i64 = v 57 var k: i64 = 0 58 if m == 0 { t[0] = 48 as u8; k = 1 } 59 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 60 var i: i64 = 0 61 while i < k { dst[off+i] = t[k-1-i]; i = i + 1 } 62 return off + k 63} 64 65func cw_line_end(b: *u8, i0: i64, n: i64) -> i64 { 66 var e: i64 = i0 67 while e < n { if b[e] == (10 as u8) { return e } e = e + 1 } 68 return n 69} 70func cw_find_tab(b: *u8, i0: i64, e: i64) -> i64 { 71 var j: i64 = i0 72 while j < e { if b[j] == (9 as u8) { return j } j = j + 1 } 73 return e 74} 75 76// copy 32 bytes 77func cw_cp32(dst: *u8, src: *u8) -> i64 { var i: i64 = 0; while i < 32 { dst[i] = src[i]; i = i + 1 } return 0 } 78// 1 if equal 32 bytes else 0 79func cw_eq32(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while i < 32 { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } 80// out = sha256(left32 || right32) 81func cw_pair(l: *u8, r: *u8, out: *u8) -> i64 { 82 let b: *u8 = sys_mmap(64) 83 var i: i64 = 0 84 while i < 32 { b[i] = l[i]; i = i + 1 } 85 i = 0 86 while i < 32 { b[32+i] = r[i]; i = i + 1 } 87 sha256_digest(b, 64, out) 88 return 0 89} 90// decode 64 hex chars at src[off..] into out[0..32) 91func cw_unhex32(src: *u8, off: i64, out: *u8) -> i64 { 92 var i: i64 = 0 93 while i < 32 { 94 let hi: i64 = cw_nib(src[off + i*2] as i64) 95 let lo: i64 = cw_nib(src[off + i*2 + 1] as i64) 96 out[i] = ((hi * 16) + lo) as u8 97 i = i + 1 98 } 99 return 0 100} 101 102func main() -> i64 { 103 cw_puts("=== COE-WITNESS (F713): Merkle transparency-log over the signed chain ===\n" as *u8) 104 let plane: *u8 = "knowledge/status/coe_signed.log" as *u8 105 106 let lenp: *i64 = sys_mmap(16) as *i64 107 lenp[0] = 0 108 let vb: *u8 = sys_read_file(plane, lenp) 109 var vn: i64 = lenp[0] 110 if vn < 0 { vn = 0 } 111 if vn > CW_CAP { vn = CW_CAP } 112 113 // parse leaves = field0 (frame-hash hex, 64 chars) of each row -> 32 raw bytes 114 let leaves: *u8 = sys_mmap(CW_MAXLEAF * 32 + 16) 115 var n: i64 = 0 116 var i: i64 = 0 117 while i < vn { 118 let e: i64 = cw_line_end(vb, i, vn) 119 if e > i { 120 if n < CW_MAXLEAF { 121 let t: i64 = cw_find_tab(vb, i, e) 122 if (t - i) >= 64 { 123 cw_unhex32(vb, i, ((leaves as i64) + n*32) as *u8) 124 n = n + 1 125 } 126 } 127 } 128 i = e + 1 129 } 130 131 if n == 0 { cw_puts("COE-WITNESS RED reason=no-leaves\n" as *u8); sys_exit(1); return 1 } 132 133 // build the tree bottom-up; record the audit path for the LAST leaf (tk = n-1) 134 let lvl: *u8 = sys_mmap(CW_MAXLEAF * 32 + 16) 135 let nxt: *u8 = sys_mmap(CW_MAXLEAF * 32 + 16) 136 var c: i64 = 0 137 while c < n*32 { lvl[c] = leaves[c]; c = c + 1 } 138 139 let pathh: *u8 = sys_mmap(64 * 32 + 16) 140 let paths: *u8 = sys_mmap(80) 141 var pl: i64 = 0 142 var curn: i64 = n 143 var tk: i64 = n - 1 144 145 while curn > 1 { 146 // sibling of tk at this level 147 var si: i64 = tk + 1 148 if (tk & 1) == 1 { si = tk - 1 } 149 if si >= curn { 150 cw_cp32(((pathh as i64) + pl*32) as *u8, ((lvl as i64) + tk*32) as *u8) 151 paths[pl] = 1 as u8 152 } else { 153 cw_cp32(((pathh as i64) + pl*32) as *u8, ((lvl as i64) + si*32) as *u8) 154 if (tk & 1) == 0 { paths[pl] = 1 as u8 } else { paths[pl] = 0 as u8 } 155 } 156 pl = pl + 1 157 158 // build next level 159 var nn: i64 = 0 160 var j: i64 = 0 161 while j < curn { 162 let leftp: *u8 = ((lvl as i64) + j*32) as *u8 163 var rightp: *u8 = ((lvl as i64) + j*32) as *u8 164 if (j + 1) < curn { rightp = ((lvl as i64) + (j+1)*32) as *u8 } 165 cw_pair(leftp, rightp, ((nxt as i64) + nn*32) as *u8) 166 nn = nn + 1 167 j = j + 2 168 } 169 c = 0 170 while c < nn*32 { lvl[c] = nxt[c]; c = c + 1 } 171 curn = nn 172 tk = tk / 2 173 } 174 175 // root = lvl[0..32) 176 let roothex: *u8 = sys_mmap(80) 177 cw_hexn(lvl, 32, roothex) 178 179 // verify the inclusion proof: recompute root from leaf[n-1] + audit path 180 let h: *u8 = sys_mmap(32) 181 cw_cp32(h, ((leaves as i64) + (n-1)*32) as *u8) 182 let tmp: *u8 = sys_mmap(32) 183 var p: i64 = 0 184 while p < pl { 185 if (paths[p] as i64) == 1 { 186 cw_pair(h, ((pathh as i64) + p*32) as *u8, tmp) 187 } else { 188 cw_pair(((pathh as i64) + p*32) as *u8, h, tmp) 189 } 190 cw_cp32(h, tmp) 191 p = p + 1 192 } 193 var ok: i64 = cw_eq32(h, lvl) 194 195 // append the root to the STH witness log (transparency-log head sequence) 196 let now: i64 = sys_now_realtime_sec() 197 let wl: *u8 = sys_mmap(256) 198 var wo: i64 = 0 199 wo = cw_cat(wl, wo, roothex) 200 wl[wo] = 9 as u8; wo = wo + 1 201 wo = cw_cat(wl, wo, "leaves=" as *u8) 202 wo = cw_catn(wl, wo, n) 203 wl[wo] = 9 as u8; wo = wo + 1 204 wo = cw_catn(wl, wo, now) 205 wl[wo] = 10 as u8; wo = wo + 1 206 let fd: i64 = sys_openat_append("knowledge/status/coe_witness.log" as *u8, 0x1a4) 207 if fd >= 0 { sys_write(fd, wl, wo); sys_close(fd) } 208 209 cw_puts(" root=" as *u8); cw_puts(roothex) 210 cw_puts(" leaves=" as *u8); cw_pi(n) 211 cw_puts(" proof-depth=" as *u8); cw_pi(pl); cw_puts("\n" as *u8) 212 if ok == 1 { 213 cw_puts("COE-WITNESS GREEN merkle-root=OK inclusion-proof=OK leaves=" as *u8); cw_pi(n) 214 cw_puts(" envelope=cap:" as *u8); cw_pi(CW_CAP) 215 cw_puts("/maxleaf:" as *u8); cw_pi(CW_MAXLEAF); cw_puts("\n" as *u8) 216 return 0 217 } 218 cw_puts("COE-WITNESS RED reason=inclusion-proof-mismatch\n" as *u8) 219 sys_exit(1) 220 return 1 221}