code wiki / _hdl_build / nx_games_manifest_native.nx

nx_games_manifest_native.nx source

↩ module page · 277 lines · 13056 B

1// nx_games_manifest_native.nx -- sovereign game-update manifest generator, driven from the NATIVE STORE 2// (nx_native_config games-reg-, NO pipe file) -- Steam-depot / itch-wharf equivalent, sovereign + no-tsv. 3// Reads the games registry (id/title/path/channel), SHA-256 hashes each game's served bytes (staged at 4// /tmp/games_live/<id>), and emits /tmp/games_manifest.json = {generator, hash, games:[{id,title,path, 5// channel,version(=content sha256 prefix),sha256,bytes}]}. Deployed to the hub docroot -> served at 6// /games-manifest.json by the gateway (which already serves docroot files; no gateway code change). 7// SHA-256 (FIPS 180-4) inlined from nx_game_manifest (the canonical core imports RV64 nx_syscalls which 8// collides, so we inline the pure core; KAT sha256("abc") gates first). Ed25519 signing = next rung. 9// license_tier: ORIGINAL (sha256 core: INDEPENDENT_REDERIVE nx_sha256.nx) 10import "nx_syscalls.nx" 11import "nx_native_config.nx" 12const K_MAGIC_65536: i64 = 65536 13 14// ===================== SHA-256 (inlined, pure -- KAT-verified) ===================== 15struct Sha256 { 16 h0: i64, h1: i64, h2: i64, h3: i64, 17 h4: i64, h5: i64, h6: i64, h7: i64, 18 idx: i64, bit_len: i64, bufptr: i64, kptr: i64, wptr: i64, 19} 20const M32: i64 = 0xFFFFFFFF 21func sha256_k(i: i64) -> i64 { 22 if i == 0 { return 0x428a2f98 } 23 if i == 1 { return 0x71374491 } 24 if i == 2 { return 0xb5c0fbcf } 25 if i == 3 { return 0xe9b5dba5 } 26 if i == 4 { return 0x3956c25b } 27 if i == 5 { return 0x59f111f1 } 28 if i == 6 { return 0x923f82a4 } 29 if i == 7 { return 0xab1c5ed5 } 30 if i == 8 { return 0xd807aa98 } 31 if i == 9 { return 0x12835b01 } 32 if i == 10 { return 0x243185be } 33 if i == 11 { return 0x550c7dc3 } 34 if i == 12 { return 0x72be5d74 } 35 if i == 13 { return 0x80deb1fe } 36 if i == 14 { return 0x9bdc06a7 } 37 if i == 15 { return 0xc19bf174 } 38 if i == 16 { return 0xe49b69c1 } 39 if i == 17 { return 0xefbe4786 } 40 if i == 18 { return 0x0fc19dc6 } 41 if i == 19 { return 0x240ca1cc } 42 if i == 20 { return 0x2de92c6f } 43 if i == 21 { return 0x4a7484aa } 44 if i == 22 { return 0x5cb0a9dc } 45 if i == 23 { return 0x76f988da } 46 if i == 24 { return 0x983e5152 } 47 if i == 25 { return 0xa831c66d } 48 if i == 26 { return 0xb00327c8 } 49 if i == 27 { return 0xbf597fc7 } 50 if i == 28 { return 0xc6e00bf3 } 51 if i == 29 { return 0xd5a79147 } 52 if i == 30 { return 0x06ca6351 } 53 if i == 31 { return 0x14292967 } 54 if i == 32 { return 0x27b70a85 } 55 if i == 33 { return 0x2e1b2138 } 56 if i == 34 { return 0x4d2c6dfc } 57 if i == 35 { return 0x53380d13 } 58 if i == 36 { return 0x650a7354 } 59 if i == 37 { return 0x766a0abb } 60 if i == 38 { return 0x81c2c92e } 61 if i == 39 { return 0x92722c85 } 62 if i == 40 { return 0xa2bfe8a1 } 63 if i == 41 { return 0xa81a664b } 64 if i == 42 { return 0xc24b8b70 } 65 if i == 43 { return 0xc76c51a3 } 66 if i == 44 { return 0xd192e819 } 67 if i == 45 { return 0xd6990624 } 68 if i == 46 { return 0xf40e3585 } 69 if i == 47 { return 0x106aa070 } 70 if i == 48 { return 0x19a4c116 } 71 if i == 49 { return 0x1e376c08 } 72 if i == 50 { return 0x2748774c } 73 if i == 51 { return 0x34b0bcb5 } 74 if i == 52 { return 0x391c0cb3 } 75 if i == 53 { return 0x4ed8aa4a } 76 if i == 54 { return 0x5b9cca4f } 77 if i == 55 { return 0x682e6ff3 } 78 if i == 56 { return 0x748f82ee } 79 if i == 57 { return 0x78a5636f } 80 if i == 58 { return 0x84c87814 } 81 if i == 59 { return 0x8cc70208 } 82 if i == 60 { return 0x90befffa } 83 if i == 61 { return 0xa4506ceb } 84 if i == 62 { return 0xbef9a3f7 } 85 if i == 63 { return 0xc67178f2 } 86 return 0 87} 88func blk_byte(c: *Sha256, n: i64) -> i64 { let p: *u8 = c.bufptr as *u8; return p[n] as i64 } 89func blk_set_byte(c: *Sha256, n: i64, v: i64) -> i64 { let p: *u8 = c.bufptr as *u8; p[n] = v & 0xFF; return 0 } 90func blk_word(c: *Sha256, i: i64) -> i64 { 91 let off: i64 = i * 4 92 let b0: i64 = blk_byte(c, off + 0); let b1: i64 = blk_byte(c, off + 1) 93 let b2: i64 = blk_byte(c, off + 2); let b3: i64 = blk_byte(c, off + 3) 94 return ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3) & M32 95} 96func sha256_compress(c: *Sha256) -> i64 { 97 let w: *i64 = c.wptr as *i64 98 let k: *i64 = c.kptr as *i64 99 var i: i64 = 0 100 while i < 16 { w[i] = blk_word(c, i); i = i + 1 } 101 i = 16 102 while i < 64 { 103 let x15: i64 = w[i - 15] 104 let x2: i64 = w[i - 2] 105 let s0: i64 = (((x15 >> 7) | (x15 << 25)) ^ ((x15 >> 18) | (x15 << 14)) ^ (x15 >> 3)) & M32 106 let s1: i64 = (((x2 >> 17) | (x2 << 15)) ^ ((x2 >> 19) | (x2 << 13)) ^ (x2 >> 10)) & M32 107 w[i] = (w[i - 16] + s0 + w[i - 7] + s1) & M32 108 i = i + 1 109 } 110 var a: i64 = c.h0; var b: i64 = c.h1; var cc: i64 = c.h2; var d: i64 = c.h3 111 var e: i64 = c.h4; var ff: i64 = c.h5; var g: i64 = c.h6; var h: i64 = c.h7 112 i = 0 113 while i < 64 { 114 let S1: i64 = (((e >> 6) | (e << 26)) ^ ((e >> 11) | (e << 21)) ^ ((e >> 25) | (e << 7))) & M32 115 let ch: i64 = ((e & ff) ^ ((e ^ M32) & g)) & M32 116 let t1: i64 = (h + S1 + ch + k[i] + w[i]) & M32 117 let S0: i64 = (((a >> 2) | (a << 30)) ^ ((a >> 13) | (a << 19)) ^ ((a >> 22) | (a << 10))) & M32 118 let mj: i64 = ((a & b) ^ (a & cc) ^ (b & cc)) & M32 119 let t2: i64 = (S0 + mj) & M32 120 h = g; g = ff; ff = e; e = (d + t1) & M32; d = cc; cc = b; b = a; a = (t1 + t2) & M32 121 i = i + 1 122 } 123 c.h0 = (c.h0 + a) & M32; c.h1 = (c.h1 + b) & M32; c.h2 = (c.h2 + cc) & M32; c.h3 = (c.h3 + d) & M32 124 c.h4 = (c.h4 + e) & M32; c.h5 = (c.h5 + ff) & M32; c.h6 = (c.h6 + g) & M32; c.h7 = (c.h7 + h) & M32 125 return 0 126} 127func sha256_init(c: *Sha256) -> i64 { 128 c.h0 = 0x6a09e667; c.h1 = 0xbb67ae85; c.h2 = 0x3c6ef372; c.h3 = 0xa54ff53a 129 c.h4 = 0x510e527f; c.h5 = 0x9b05688c; c.h6 = 0x1f83d9ab; c.h7 = 0x5be0cd19 130 c.bufptr = sys_mmap(64) as i64 131 c.kptr = sys_mmap(64 * 8) as i64 132 c.wptr = sys_mmap(64 * 8) as i64 133 let kp: *i64 = c.kptr as *i64 134 var i: i64 = 0 135 while i < 64 { kp[i] = sha256_k(i); i = i + 1 } 136 let bp: *u8 = c.bufptr as *u8 137 i = 0 138 while i < 64 { bp[i] = 0; i = i + 1 } 139 c.idx = 0; c.bit_len = 0 140 return 0 141} 142func sha256_update(c: *Sha256, bytes: *u8, n: i64) -> i64 { 143 var i: i64 = 0 144 while i < n { 145 blk_set_byte(c, c.idx, bytes[i] as i64) 146 c.idx = c.idx + 1; c.bit_len = c.bit_len + 8 147 if c.idx == 64 { sha256_compress(c); c.idx = 0 } 148 i = i + 1 149 } 150 return 0 151} 152func sha256_final(c: *Sha256, out: *u8) -> i64 { 153 let total_bits: i64 = c.bit_len 154 blk_set_byte(c, c.idx, 0x80); c.idx = c.idx + 1 155 if c.idx > 56 { 156 while c.idx < 64 { blk_set_byte(c, c.idx, 0); c.idx = c.idx + 1 } 157 sha256_compress(c); c.idx = 0 158 } 159 while c.idx < 56 { blk_set_byte(c, c.idx, 0); c.idx = c.idx + 1 } 160 blk_set_byte(c, 56, (total_bits >> 56) & 0xFF); blk_set_byte(c, 57, (total_bits >> 48) & 0xFF) 161 blk_set_byte(c, 58, (total_bits >> 40) & 0xFF); blk_set_byte(c, 59, (total_bits >> 32) & 0xFF) 162 blk_set_byte(c, 60, (total_bits >> 24) & 0xFF); blk_set_byte(c, 61, (total_bits >> 16) & 0xFF) 163 blk_set_byte(c, 62, (total_bits >> 8) & 0xFF); blk_set_byte(c, 63, total_bits & 0xFF) 164 sha256_compress(c) 165 out[0]=(c.h0>>24)&0xFF; out[1]=(c.h0>>16)&0xFF; out[2]=(c.h0>>8)&0xFF; out[3]=c.h0&0xFF 166 out[4]=(c.h1>>24)&0xFF; out[5]=(c.h1>>16)&0xFF; out[6]=(c.h1>>8)&0xFF; out[7]=c.h1&0xFF 167 out[8]=(c.h2>>24)&0xFF; out[9]=(c.h2>>16)&0xFF; out[10]=(c.h2>>8)&0xFF; out[11]=c.h2&0xFF 168 out[12]=(c.h3>>24)&0xFF; out[13]=(c.h3>>16)&0xFF; out[14]=(c.h3>>8)&0xFF; out[15]=c.h3&0xFF 169 out[16]=(c.h4>>24)&0xFF; out[17]=(c.h4>>16)&0xFF; out[18]=(c.h4>>8)&0xFF; out[19]=c.h4&0xFF 170 out[20]=(c.h5>>24)&0xFF; out[21]=(c.h5>>16)&0xFF; out[22]=(c.h5>>8)&0xFF; out[23]=c.h5&0xFF 171 out[24]=(c.h6>>24)&0xFF; out[25]=(c.h6>>16)&0xFF; out[26]=(c.h6>>8)&0xFF; out[27]=c.h6&0xFF 172 out[28]=(c.h7>>24)&0xFF; out[29]=(c.h7>>16)&0xFF; out[30]=(c.h7>>8)&0xFF; out[31]=c.h7&0xFF 173 return 0 174} 175func sha256_digest(bytes: *u8, n: i64, out: *u8) -> i64 { 176 let ctx_raw: *u8 = sys_mmap(256) 177 let ctx: *Sha256 = ctx_raw as *Sha256 178 sha256_init(ctx); sha256_update(ctx, bytes, n); sha256_final(ctx, out) 179 return 0 180} 181 182// ===================== JSON helpers ===================== 183func mf_puts(buf: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var i: i64=0; while s[i]!=(0 as u8){buf[o]=s[i];o=o+1;i=i+1} return o } 184func mf_putdec(buf: *u8, off: i64, v: i64) -> i64 { 185 if v == 0 { buf[off] = 48 as u8; return off + 1 } 186 let tmp: *u8 = sys_mmap(32); var k: i64=0; var x: i64=v 187 while x > 0 { tmp[k] = (48 + (x - (x / 10) * 10)) as u8; x = x / 10; k = k + 1 } 188 var o: i64=off; var ri: i64=k-1 189 while ri >= 0 { buf[o] = tmp[ri]; o = o + 1; ri = ri - 1 } 190 return o 191} 192// 32-byte digest -> up to `nch` lowercase hex chars. 193func mf_hexn(buf: *u8, off: i64, dig: *u8, nch: i64) -> i64 { 194 let hx: *u8 = "0123456789abcdef" as *u8 195 var o: i64=off; var i: i64=0 196 while i * 2 < nch { 197 let b: i64 = dig[i] as i64 198 buf[o] = hx[(b >> 4) & 0xF]; o = o + 1 199 if o - off < nch { buf[o] = hx[b & 0xF]; o = o + 1 } 200 i = i + 1 201 } 202 return o 203} 204func mf_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 205 206func main() -> i64 { 207 // --- SHA-256 KAT: sha256("abc") = ba7816bf... (abort rather than publish bad integrity) --- 208 let kat: *u8 = sys_mmap(32) 209 sha256_digest("abc" as *u8, 3, kat) 210 if (kat[0] as i64) != 0xba { return 90 } 211 if (kat[1] as i64) != 0x78 { return 91 } 212 if (kat[2] as i64) != 0x16 { return 92 } 213 214 let h: *i64 = ncfg_open("knowledge/store/games-reg-\x00" as *u8) 215 if (h as i64) == 0 { mf_w("nx_games_manifest_native: games-reg store missing -- run nx_games_reg_seed\n\x00" as *u8); return 5 } 216 let cnt: i64 = ncfg_count(h, "game\x00" as *u8) 217 218 let reg: *u8 = sys_mmap(K_MAGIC_65536) 219 var ro: i64 = 0 220 ro = mf_puts(reg, ro, "{\"generator\":\"nx_games_manifest_native\",\"hash\":\"sha256\",\"games\":[" as *u8) 221 let rk: *i64 = sys_mmap(8 * 8) as *i64 222 let rv: *i64 = sys_mmap(8 * 8) as *i64 223 let lenp: *i64 = sys_mmap(8) as *i64 224 let dig: *u8 = sys_mmap(32) 225 let fp: *u8 = sys_mmap(512) 226 var emitted: i64 = 0 227 var live: i64 = 0 228 var i: i64 = 0 229 while i < cnt { 230 let nf: i64 = ncfg_row(h, "game\x00" as *u8, i, rk, rv, 8) 231 if nf > 0 { 232 let id: *u8 = ncfg_field(rk, rv, nf, "id\x00" as *u8) 233 let title: *u8 = ncfg_field(rk, rv, nf, "title\x00" as *u8) 234 let engine: *u8 = ncfg_field(rk, rv, nf, "engine\x00" as *u8) 235 let path: *u8 = ncfg_field(rk, rv, nf, "path\x00" as *u8) 236 let dep: *u8 = ncfg_field(rk, rv, nf, "deployed\x00" as *u8) 237 // ALL games are cataloged (the one space); deployed=1 also get a content-addressed hash. 238 if emitted > 0 { ro = mf_puts(reg, ro, "," as *u8) } 239 ro = mf_puts(reg, ro, "{\"id\":\"" as *u8); ro = mf_puts(reg, ro, id) 240 ro = mf_puts(reg, ro, "\",\"title\":\"" as *u8); ro = mf_puts(reg, ro, title) 241 ro = mf_puts(reg, ro, "\",\"engine\":\"" as *u8); ro = mf_puts(reg, ro, engine) 242 ro = mf_puts(reg, ro, "\",\"path\":\"" as *u8); ro = mf_puts(reg, ro, path) 243 if (dep[0] as i64) == 49 { 244 // deployed: hash the staged live bytes (/tmp/games_live/<id>) -> version = sha256 prefix. 245 var fo: i64 = mf_puts(fp, 0, "/tmp/games_live/\x00" as *u8) 246 var j: i64 = 0 247 while id[j] != (0 as u8) { fp[fo] = id[j]; fo = fo + 1; j = j + 1 } 248 fp[fo] = 0 as u8 249 let data: *u8 = sys_read_file(fp, lenp) 250 if (data as i64) != 0 { 251 let nbytes: i64 = lenp[0] 252 sha256_digest(data, nbytes, dig) 253 ro = mf_puts(reg, ro, "\",\"deployed\":true,\"version\":\"" as *u8); ro = mf_hexn(reg, ro, dig, 12) 254 ro = mf_puts(reg, ro, "\",\"sha256\":\"" as *u8); ro = mf_hexn(reg, ro, dig, 64) 255 ro = mf_puts(reg, ro, "\",\"bytes\":" as *u8); ro = mf_putdec(reg, ro, nbytes) 256 ro = mf_puts(reg, ro, "}" as *u8) 257 live = live + 1 258 } else { 259 ro = mf_puts(reg, ro, "\",\"deployed\":true,\"sha256\":null}" as *u8) 260 } 261 } else { 262 ro = mf_puts(reg, ro, "\",\"deployed\":false}" as *u8) 263 } 264 emitted = emitted + 1 265 } 266 i = i + 1 267 } 268 ro = mf_puts(reg, ro, "]}" as *u8) 269 let fd: i64 = sys_openat_wr("/tmp/games_manifest.json\x00" as *u8, 420) 270 if fd < 0 { mf_w("nx_games_manifest_native: cannot write /tmp/games_manifest.json\n\x00" as *u8); return 6 } 271 sys_write(fd, reg, ro) 272 sys_close(fd) 273 mf_w("nx_games_manifest_native: wrote /tmp/games_manifest.json (sha256 KAT ok) games=\x00" as *u8) 274 mf_w(reg) 275 mf_w("\n\x00" as *u8) 276 return 0 277}