code wiki / (root) / nx_blocklist_store.nx

nx_blocklist_store.nx source

↩ module page · 103 lines · 4840 B

1// nx_blocklist_store.nx -- the do-not-recover blocklist on the sovereign seg_store (NOT a TSV). Modeled on 2// nx_app_store. Append-only / immutable: each entry is a record under key "bl:<id>"; status changes 3// (pending -> approved -> retracted) are NEW versions, so the full SUPERVISED history is preserved by construction 4// (additive law) and tamper-evident by content-address. A "__blidx__" index record (newline-separated ids), advanced 5// in the SAME commit, enumerates the whole list atomically. PENDING BY DEFAULT: bl_put writes status=pending and does 6// NOT block; only an operator approve flips it to approved. Record (tab-separated): 7// dhash_hex16 <TAB> threshold <TAB> category <TAB> authority <TAB> date <TAB> ref <TAB> status 8// license_tier: ORIGINAL 9import "nx_seg_store.nx" 10const BL_MAGIC_1048576: i64 = 1048576 11 12const BL_PREFIX: *u8 = "knowledge/blocklist-" as *u8 13 14func bls_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ dst[off+i]=s[i]; i=i+1 } return off+i } 15func bls_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 16 17func bl_key(kbuf: *u8, id: *u8) -> i64 { 18 var o: i64 = bls_cat(kbuf, 0, "bl:" as *u8) 19 o = bls_cat(kbuf, o, id) 20 kbuf[o] = 0 as u8 21 return o 22} 23 24// is `id` (idlen bytes) already a line in newline-separated buf[0..n)? 25func bl_id_present(buf: *u8, n: i64, id: *u8, idlen: i64) -> i64 { 26 var ls: i64=0; var i: i64=0 27 while i <= n { 28 var eol: i64=0 29 if i==n { eol=1 } else { if buf[i]==10 as u8 { eol=1 } } 30 if eol==1 { 31 if i-ls==idlen { var m: i64=1; var c: i64=0; while c<idlen { if buf[ls+c]!=id[c] { m=0 } c=c+1 } if m==1 { return 1 } } 32 ls=i+1 33 } 34 i=i+1 35 } 36 return 0 37} 38 39// add/update entry <id> with full record bytes (additive NEW version); __blidx__ advanced in the same commit. 40func bl_put_pfx(prefix: *u8, id: *u8, record: *u8, reclen: i64) -> i64 { 41 let kbuf: *u8 = sys_mmap(256) 42 bl_key(kbuf, id) 43 // fresh max+1 segid (ss_next_segid, uncapped) -- the capped ss_manifest count clobbers past the cap 44 let segid: i64 = ss_next_segid(prefix) 45 let w: *i64 = ss_begin() 46 ss_add(w, 1, kbuf, record, reclen) 47 let ipo: *i64 = sys_mmap(16) as *i64 48 let ilo: *i64 = sys_mmap(16) as *i64 49 let idxbuf: *u8 = sys_mmap(BL_MAGIC_1048576) 50 var ilen: i64 = 0 51 if ss_get(prefix, "__blidx__" as *u8, ipo, ilo) >= 0 { 52 let src: *u8 = ipo[0] as *u8 53 var c: i64=0; while c<ilo[0] { idxbuf[ilen]=src[c]; ilen=ilen+1; c=c+1 } 54 } 55 let nl: i64 = bls_strlen(id) 56 if bl_id_present(idxbuf, ilen, id, nl)==0 { 57 var c2: i64=0; while c2<nl { idxbuf[ilen]=id[c2]; ilen=ilen+1; c2=c2+1 } 58 idxbuf[ilen]=10 as u8; ilen=ilen+1 59 } 60 ss_add(w, 1, "__blidx__" as *u8, idxbuf, ilen) 61 return ss_commit(prefix, w, segid) 62} 63 64// current record of <id> -> ptrout[0]/lenout[0]; 1=found, 0=tombstoned, -1=absent 65func bl_get_pfx(prefix: *u8, id: *u8, ptrout: *i64, lenout: *i64) -> i64 { 66 let kbuf: *u8 = sys_mmap(256) 67 bl_key(kbuf, id) 68 return ss_get(prefix, kbuf, ptrout, lenout) 69} 70 71// copy the newline-separated id index into idxbuf; returns its length (0 if empty) 72func bl_index_pfx(prefix: *u8, idxbuf: *u8) -> i64 { 73 let ipo: *i64 = sys_mmap(16) as *i64 74 let ilo: *i64 = sys_mmap(16) as *i64 75 if ss_get(prefix, "__blidx__" as *u8, ipo, ilo) < 0 { return 0 } 76 let src: *u8 = ipo[0] as *u8 77 var i: i64=0; while i<ilo[0] { idxbuf[i]=src[i]; i=i+1 } 78 return ilo[0] 79} 80 81// replace the trailing status field of <id>'s current record with `status` (writes a NEW version, history kept). 82func bl_set_status_pfx(prefix: *u8, id: *u8, status: *u8) -> i64 { 83 let po: *i64 = sys_mmap(16) as *i64 84 let lo: *i64 = sys_mmap(16) as *i64 85 if bl_get_pfx(prefix, id, po, lo) < 1 { return 0 - 1 } 86 let src: *u8 = po[0] as *u8 87 let slen: i64 = lo[0] 88 var lt: i64 = 0 - 1 89 var i: i64 = 0 90 while i < slen { if src[i]==0x09 as u8 { lt=i } i=i+1 } 91 let nbuf: *u8 = sys_mmap(slen + 64) 92 var o: i64 = 0 93 if lt >= 0 { var c: i64=0; while c<=lt { nbuf[o]=src[c]; o=o+1; c=c+1 } } else { var c2: i64=0; while c2<slen { nbuf[o]=src[c2]; o=o+1; c2=c2+1 } nbuf[o]=0x09 as u8; o=o+1 } 94 o = bls_cat(nbuf, o, status) 95 return bl_put_pfx(prefix, id, nbuf, o) 96} 97 98// production-prefix convenience wrappers 99func bl_put(id: *u8, record: *u8, reclen: i64) -> i64 { return bl_put_pfx(BL_PREFIX, id, record, reclen) } 100func bl_get(id: *u8, ptrout: *i64, lenout: *i64) -> i64 { return bl_get_pfx(BL_PREFIX, id, ptrout, lenout) } 101func bl_index(idxbuf: *u8) -> i64 { return bl_index_pfx(BL_PREFIX, idxbuf) } 102func bl_approve(id: *u8) -> i64 { return bl_set_status_pfx(BL_PREFIX, id, "approved" as *u8) } 103func bl_retract(id: *u8) -> i64 { return bl_set_status_pfx(BL_PREFIX, id, "retracted" as *u8) }