code wiki / _hdl_build / nx_nishifs_cid.nx
nx_nishifs_cid.nx source
↩ module page · 167 lines · 8703 B
1// nx_nishifs_cid.nx -- ladder C2 (the FILE SYSTEM): NishiFS CORE = a content-addressed (CID/Merkle) object store.
2//
3// This is the rung that turns the OS+FS design's headline exceed axis from DESIGN-TARGET into MEASURED reality.
4// June-2026 research (deep-research wf_b31a496b-971): dm-verity is fixed-ADDRESS Merkle (not hash-keyed retrieval),
5// composefs verifies in USERSPACE, and APFS/ext4 have NO data checksums. NishiFS goes content-ADDRESSED: every
6// object is stored BY its sha256 (the CID), git/IPFS-style, at /tmp/nishifs/<cidhex>. Properties, all proven here:
7// * content-addressed put/get: store a blob -> get its CID; retrieve BY CID -> the bytes back.
8// * INTEGRITY-ON-READ: cid_get returns bytes ONLY if they re-hash to the requested CID (tamper -> caught).
9// * DEDUP by construction: identical content -> identical CID -> one object.
10// * MERKLE directory: a dir = (name,childCID) entries; the dir's CID = sha256(serialized) -> the whole-tree
11// state is ONE root CID, so changing ANY leaf changes the root (tamper-evident whole-FS state).
12// composes nx_sha256 (CID = sha256, proven in the C3 installer) + nx_syscalls. CoW snapshots, mount/format onto a
13// C1 partition, and native encryption are the NEXT rungs.
14// NEVER-BRICK (Rule 26): writes FILES only (under /tmp/nishifs); no /dev, no firmware. expect_exit: 0 license_tier: ORIGINAL
15import "nx_syscalls.nx"
16import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
17import "nx_sha256.nx"
18
19const GET_OK: i64 = 0
20const GET_NOTFOUND: i64 = 3
21const GET_INTEGRITY_FAIL: i64 = 7
22
23func ui_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
24// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
25// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
26// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
27// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
28func ui_num(v: i64) -> i64 { nxi_out(v); return 0 }
29func ui_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
30func cid_eq(a: *u8, b: *u8) -> i64 { var i: i64=0; while i<32 { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
31
32// 32-byte CID -> 64-char lowercase hex (+ NUL) for the object filename.
33func cid_hex(cid: *u8, out: *u8) -> i64 {
34 var i: i64=0
35 while i<32 {
36 let b: i64 = cid[i] as i64
37 let hi: i64 = (b>>4)&15
38 let lo: i64 = b&15
39 var c1: i64 = 48+hi; if hi>9 { c1=87+hi }
40 var c2: i64 = 48+lo; if lo>9 { c2=87+lo }
41 out[i*2]=c1 as u8
42 out[i*2+1]=c2 as u8
43 i=i+1
44 }
45 out[64]=0 as u8
46 return 0
47}
48// object store path = /tmp/nishifs/<cidhex>
49func obj_path(hex: *u8, out: *u8) -> i64 {
50 let pre: *u8 = "/tmp/nishifs/\x00"
51 var i: i64=0
52 while pre[i]!=(0 as u8) { out[i]=pre[i]; i=i+1 }
53 var j: i64=0
54 while hex[j]!=(0 as u8) { out[i]=hex[j]; i=i+1; j=j+1 }
55 out[i]=0 as u8
56 return 0
57}
58func w_file(path: *u8, buf: *u8, n: i64) -> i64 { let fd: i64=sys_openat_wr(path, 0x1a4); if fd<=0 { return 0-1 } sys_write(fd, buf, n); sys_close(fd); return 0 }
59
60// CID put: object addressed BY its sha256; dedup by construction (same content -> same path -> one object).
61func cid_put(blob: *u8, n: i64, cidout: *u8) -> i64 {
62 sha256_digest(blob, n, cidout)
63 let hex: *u8 = sys_mmap(72)
64 cid_hex(cidout, hex)
65 let path: *u8 = sys_mmap(160)
66 obj_path(hex, path)
67 return w_file(path, blob, n)
68}
69// CID get WITH INTEGRITY-ON-READ: returns bytes only if they re-hash to the requested CID.
70func cid_get(cid: *u8, out: *u8, cap: i64, lenout: *i64) -> i64 {
71 let hex: *u8 = sys_mmap(72)
72 cid_hex(cid, hex)
73 let path: *u8 = sys_mmap(160)
74 obj_path(hex, path)
75 let lenp: *i64 = sys_mmap(8) as *i64
76 let rb: *u8 = sys_read_file(path, lenp)
77 if (rb as i64)==0 { return GET_NOTFOUND }
78 let h2: *u8 = sys_mmap(40)
79 sha256_digest(rb, lenp[0], h2)
80 if cid_eq(h2, cid)==0 { return GET_INTEGRITY_FAIL } // tamper / corruption caught by construction
81 var m: i64 = lenp[0]
82 if m > cap { m = cap }
83 var j: i64=0
84 while j<m { out[j]=rb[j]; j=j+1 }
85 lenout[0]=lenp[0]
86 return GET_OK
87}
88// Merkle directory: serialize (name + 32-byte childCID) per entry; the dir's CID = sha256(serialized).
89func dir_serialize(nA: *u8, cA: *u8, nB: *u8, cB: *u8, out: *u8) -> i64 {
90 var w: i64=0
91 var i: i64=0
92 while nA[i]!=(0 as u8) { out[w]=nA[i]; w=w+1; i=i+1 }
93 out[w]=0 as u8; w=w+1
94 i=0; while i<32 { out[w]=cA[i]; w=w+1; i=i+1 }
95 i=0; while nB[i]!=(0 as u8) { out[w]=nB[i]; w=w+1; i=i+1 }
96 out[w]=0 as u8; w=w+1
97 i=0; while i<32 { out[w]=cB[i]; w=w+1; i=i+1 }
98 return w
99}
100
101func main() -> i64 {
102 ui_puts("ladder C2: NishiFS CORE -- content-addressed (CID/Merkle) object store (the file system)\n" as *u8)
103
104 let A: *u8 = "hello nishi filesystem -- block one\x00" as *u8
105 let A2: *u8 = "hello NISHI filesystem -- block one\x00" as *u8
106 let B: *u8 = "content addressed merkle -- block two\x00" as *u8
107 let nA: i64 = ui_slen(A)
108 let nA2: i64 = ui_slen(A2)
109 let nB: i64 = ui_slen(B)
110
111 let cidA: *u8 = sys_mmap(40)
112 let cidB: *u8 = sys_mmap(40)
113 let cidA_again: *u8 = sys_mmap(40)
114 cid_put(A, nA, cidA)
115 cid_put(B, nB, cidB)
116 cid_put(A, nA, cidA_again) // dedup: same content -> same CID -> same object
117
118 // T1 content-addressed round-trip (capture BEFORE tamper)
119 let outA: *u8 = sys_mmap(256)
120 let lenA: *i64 = sys_mmap(8) as *i64
121 let rget: i64 = cid_get(cidA, outA, 256, lenA)
122 var rtmatch: i64 = 0
123 if rget==GET_OK { if lenA[0]==nA { rtmatch=1; var i: i64=0; while i<nA { if outA[i]!=A[i] { rtmatch=0; i=nA } else { i=i+1 } } } }
124
125 // T2 deterministic content-address (recompute)
126 let cidA_re: *u8 = sys_mmap(40)
127 sha256_digest(A, nA, cidA_re)
128
129 // T5 Merkle root over {a:cidA, b:cidB}, then change one leaf (A->A2) and rebuild
130 let ser: *u8 = sys_mmap(256)
131 let w1: i64 = dir_serialize("a\x00" as *u8, cidA, "b\x00" as *u8, cidB, ser)
132 let rootCID: *u8 = sys_mmap(40)
133 sha256_digest(ser, w1, rootCID)
134 let cidA2: *u8 = sys_mmap(40)
135 sha256_digest(A2, nA2, cidA2)
136 let ser2: *u8 = sys_mmap(256)
137 let w2: i64 = dir_serialize("a\x00" as *u8, cidA2, "b\x00" as *u8, cidB, ser2)
138 let rootCID2: *u8 = sys_mmap(40)
139 sha256_digest(ser2, w2, rootCID2)
140
141 // T4 tamper A's object file -> integrity-on-read must catch
142 let hexA: *u8 = sys_mmap(72)
143 cid_hex(cidA, hexA)
144 let pathA: *u8 = sys_mmap(160)
145 obj_path(hexA, pathA)
146 w_file(pathA, "TAMPERED-NOT-THE-CONTENT\x00" as *u8, 24)
147 let outT: *u8 = sys_mmap(256)
148 let lenT: *i64 = sys_mmap(8) as *i64
149 let rtamper: i64 = cid_get(cidA, outT, 256, lenT)
150
151 var pass: i64=0
152 var ttl: i64=0
153 ttl=ttl+1; ui_puts(" T1 content-addressed round-trip (put A -> get by CID -> bytes match): " as *u8); if rtmatch==1 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) }
154 ttl=ttl+1; ui_puts(" T2 CID is a deterministic content-address (sha256(A)==cidA): " as *u8); if cid_eq(cidA_re, cidA)==1 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) }
155 ttl=ttl+1; ui_puts(" T3 dedup by construction (put A twice -> identical CID -> one object): " as *u8); if cid_eq(cidA_again, cidA)==1 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) }
156 ttl=ttl+1; ui_puts(" T4 integrity-on-read catches tampering (LIAR-KILL): " as *u8); if rtamper==GET_INTEGRITY_FAIL { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) }
157 ttl=ttl+1; ui_puts(" T5 Merkle root: change ONE leaf (A->A2) -> root CID changes (whole-tree tamper-evident): " as *u8); if cid_eq(rootCID2, rootCID)==0 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) }
158 ttl=ttl+1; ui_puts(" T6 distinct content -> distinct CID (cidA != cidB): " as *u8); if cid_eq(cidA, cidB)==0 { pass=pass+1; ui_puts("PASS\n" as *u8) } else { ui_puts("FAIL\n" as *u8) }
159
160 let rh: *u8 = sys_mmap(72)
161 cid_hex(rootCID, rh)
162 ui_puts(" NishiFS root CID (one hash over the whole dir tree) = " as *u8); sys_write(1, rh, 16); ui_puts("...\n" as *u8)
163
164 ui_puts("NISHIFS-CID-GATE passed " as *u8); ui_num(pass); ui_puts("/" as *u8); ui_num(ttl)
165 if pass==ttl { ui_puts(" verdict=GREEN (content-addressed object store: CID put/get + dedup + integrity-on-read + Merkle root = the NishiFS core; CoW snapshots + mount-on-C1-partition + encryption = next rungs)\n" as *u8); sys_exit(0); return 0 }
166 ui_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1
167}