code wiki / _hdl_build / nx_mp_relay_gate.nx
nx_mp_relay_gate.nx source
↩ module page · 86 lines · 4462 B
1// nx_mp_relay_gate.nx -- proves the sovereign daemon roster serializer (nx_mp_relay) over nx_room_relay.
2// NO JS, NO curl: a pure-nx gate. The daemon serializes OTHER live players into [len][frame] records that
3// the wasm parses with gi_net_ingest_roster. This is the /roster GET body, proven sovereignly.
4// 1) serialize 2 peers in a room -> 2 records, frame bytes byte-EXACT, in slot order
5// 2) room isolation (neg): a peer in another room is not in the body
6// 3) self excluded (neg): the requesting player never sees itself
7// 4) staleness (neg): a peer past TTL is dropped from the body
8// Built nx_cc_sovereign -> nxasm_x86 (no gcc, no .sh). license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_gate_emit_lib.nx"
11import "nx_mp_relay.nx" // brings nx_room_relay (rr_*) transitively -- do NOT also import it directly (double-import -> expand_imports fail)
12import "nx_gate_verdict.nx"
13
14func rec_eq(body: *u8, o: i64, expect: *u8, n: i64) -> i64 {
15 if (body[o] as i64) != n { return 0 }
16 var k: i64 = 0
17 while k < n { if body[o + 1 + k] != expect[k] { return 0 } k = k + 1 }
18 return 1
19}
20
21func main() -> i64 {
22 g_puts("nx_mp_relay gate (sovereign daemon /roster serializer, NO js/curl)\n" as *u8)
23 var pass: i64 = 0; var total: i64 = 0
24
25 let N: i64 = 8
26 let SB: i64 = 64
27 let st: *i64 = sys_mmap((2 + 5*N) * 8) as *i64
28 let arena: *u8 = sys_mmap(N * SB)
29 rr_init(st, N, SB)
30
31 let FL: i64 = 11
32 let fa: *u8 = sys_mmap(64); var i: i64=0; while i<FL { fa[i]=(100+i) as u8; i=i+1 }
33 let fb: *u8 = sys_mmap(64); i=0; while i<FL { fb[i]=(40+i) as u8; i=i+1 }
34 let fd: *u8 = sys_mmap(64); i=0; while i<FL { fd[i]=(7+i) as u8; i=i+1 }
35
36 let ROOM_A: i64 = 0x7E70
37 let ROOM_B: i64 = 0x9999
38 rr_post(st, arena, ROOM_A, 100, 1000, 1, fa, FL)
39 rr_post(st, arena, ROOM_A, 101, 1000, 1, fb, FL)
40 rr_post(st, arena, ROOM_B, 200, 1000, 1, fd, FL)
41
42 let body: *u8 = sys_mmap(1024)
43 let tb: i64 = mp_roster_body(st, arena, SB, ROOM_A, 999, 1000, 8000, body)
44 let nrec: i64 = mp_roster_count(body, tb)
45 g_puts(" [measure] roster body = " as *u8); g_pn(tb); g_puts(" bytes, " as *u8); g_pn(nrec); g_puts(" records\n" as *u8)
46
47 // 1) two records, frame bytes exact, slot order (100 -> fa at offset 0, 101 -> fb at offset 12)
48 var r1: i64 = 1
49 if nrec != 2 { r1 = 0 }
50 if rec_eq(body, 0, fa, FL) != 1 { r1 = 0 }
51 if rec_eq(body, 1 + FL, fb, FL) != 1 { r1 = 0 } // second record starts after [len:1][11 bytes]
52 pass = pass + g_check("serialize: 2 records, frames byte-exact, slot order" as *u8, r1); total=total+1
53
54 // 2) room isolation -- room B's peer 200 never appears (its frame fd is absent)
55 var r2: i64 = 1
56 var found_b: i64 = 0
57 var o: i64 = 0
58 while o < tb { let fl: i64 = body[o] as i64; if rec_eq(body, o, fd, FL) == 1 { found_b = 1 } o = o + 1 + fl }
59 if found_b != 0 { r2 = 0 }
60 pass = pass + g_check("room isolation: other-room peer absent from body (neg)" as *u8, r2); total=total+1
61
62 // 3) self excluded -- request as peer 100, must not contain fa
63 let tb2: i64 = mp_roster_body(st, arena, SB, ROOM_A, 100, 1000, 8000, body)
64 var r3: i64 = 1
65 var found_self: i64 = 0
66 o = 0
67 while o < tb2 { let fl: i64 = body[o] as i64; if rec_eq(body, o, fa, FL) == 1 { found_self = 1 } o = o + 1 + fl }
68 if found_self != 0 { r3 = 0 }
69 if mp_roster_count(body, tb2) != 1 { r3 = 0 } // only peer 101 remains
70 pass = pass + g_check("self excluded from own roster (neg)" as *u8, r3); total=total+1
71
72 // 4) staleness -- advance now past TTL; body empties
73 let tb3: i64 = mp_roster_body(st, arena, SB, ROOM_A, 999, 20000, 8000, body)
74 pass = pass + g_check("stale peers dropped from body (neg)" as *u8, tb3 == 0); total=total+1
75
76 g_puts("---- mp-relay gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
77 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
78 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
79 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
80 let ctr__dry: *i64 = gv_ctr()
81 ctr__dry[0] = pass
82 ctr__dry[1] = total
83 let rc__dry: i64 = gv_verdict("MP-RELAY-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
84 sys_exit(rc__dry)
85 return rc__dry
86}