code wiki / _hdl_build / nx_seedlib.nx

nx_seedlib.nx source

↩ module page · 211 lines · 11474 B

1// nx_seedlib.nx -- LIB: the COMMUNITY SEED-LIBRARY NODE (furnishes the room the reward unlocked). This is the 2// real feature that the `host_seed_library` CAPABILITY (earned in nx_rewards) gates: only a capability-holder may 3// create a node -- proving the reward is REAL (a real feature enforces it), not a cosmetic flag. A node is a 4// local seed library on the real seed-library ethic: members BORROW seeds, grow them, save seed, and RETURN MORE 5// than they took -- so the commons grows. Additive loan ledger (rule 13). Ties the swap/rewards/lineage arcs 6// into a real shared resource. Sovereign seg-store (knowledge/store/seedlib-*, NO TSV), integer-only. license_tier: ORIGINAL 7import "nx_rewards.nx" 8import "nx_food_science.nx" 9import "nx_seg_store.nx" 10import "nx_syscalls.nx" 11const SL_MAGIC_2048: i64 = 2048 12 13const SL_CAP: *u8 = "host_seed_library" 14 15func sl_put(prefix: *u8, key: *u8, val: *u8) -> i64 { 16 let vl: i64 = as_len(val) 17 if fd_streq_store(prefix, key, val, vl) == 1 { return 0 } 18 let w: *i64 = ss_begin() 19 ss_add(w, 1, key, val, vl) 20 let seg: i64 = fd_seg_next(prefix) 21 ss_commit(prefix, w, seg) 22 return 1 23} 24 25func sl_node_key(nid: *u8, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "seedlib:node:" as *u8); o = as_append(out, o, nid); out[o] = 0 as u8; return o } 26func sl_stock_key(nid: *u8, sp: *u8, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "seedlib:stock:" as *u8); o = as_append(out, o, nid); out[o] = 58 as u8; o = o + 1; o = as_append(out, o, sp); out[o] = 0 as u8; return o } 27func sl_species_key(nid: *u8, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "seedlib:species:" as *u8); o = as_append(out, o, nid); out[o] = 0 as u8; return o } 28func sl_loann_key(nid: *u8, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "seedlib:loann:" as *u8); o = as_append(out, o, nid); out[o] = 0 as u8; return o } 29func sl_loan_key(nid: *u8, seq: i64, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "seedlib:loan:" as *u8); o = as_append(out, o, nid); out[o] = 58 as u8; o = o + 1; o = fd_apnum(out, o, seq); out[o] = 0 as u8; return o } 30 31// CREATE a node -- THE CAPABILITY GATE. Refuses (returns 0) unless host_gid holds the real host_seed_library 32// capability (earned via nx_rewards). This is what makes the reward real: a real feature enforces it. 33func sl_create_node(prefix: *u8, reward_prefix: *u8, nid: *u8, host_gid: *u8, name: *u8, area: *u8, day: i64) -> i64 { 34 if rw_can(reward_prefix, host_gid, SL_CAP) == 0 { return 0 } 35 let key: *u8 = sys_mmap(96); sl_node_key(nid, key) 36 let val: *u8 = sys_mmap(256); var v: i64 = 0 37 v = as_append(val, v, host_gid); val[v] = 9 as u8; v = v + 1 38 v = as_append(val, v, name); val[v] = 9 as u8; v = v + 1 39 v = as_append(val, v, area); val[v] = 9 as u8; v = v + 1 40 v = fd_apnum(val, v, day); val[v] = 0 as u8 41 return sl_put(prefix, key, val) 42} 43func sl_node_exists(prefix: *u8, nid: *u8) -> i64 { 44 let key: *u8 = sys_mmap(96); sl_node_key(nid, key) 45 let pq: *i64 = sys_mmap(16) as *i64 46 let lq: *i64 = sys_mmap(16) as *i64 47 if ss_get(prefix, key, pq, lq) != 1 { return 0 } 48 return 1 49} 50func sl_node_str(prefix: *u8, nid: *u8, f: i64, out: *u8) -> i64 { 51 let key: *u8 = sys_mmap(96); sl_node_key(nid, key) 52 let pq: *i64 = sys_mmap(16) as *i64 53 let lq: *i64 = sys_mmap(16) as *i64 54 if ss_get(prefix, key, pq, lq) != 1 { out[0] = 0 as u8; return 0 } 55 return fd_field(pq[0] as *u8, lq[0], f, out) 56} 57 58func sl_stock(prefix: *u8, nid: *u8, sp: *u8) -> i64 { 59 let key: *u8 = sys_mmap(96); sl_stock_key(nid, sp, key) 60 let pq: *i64 = sys_mmap(16) as *i64 61 let lq: *i64 = sys_mmap(16) as *i64 62 if ss_get(prefix, key, pq, lq) != 1 { return 0 } 63 return fd_atoi(pq[0] as *u8, lq[0]) 64} 65func sl_set_stock(prefix: *u8, nid: *u8, sp: *u8, qty: i64) -> i64 { 66 let key: *u8 = sys_mmap(96); sl_stock_key(nid, sp, key) 67 let nv: *u8 = sys_mmap(24); var o: i64 = fd_apnum(nv, 0, qty); nv[o] = 0 as u8 68 return sl_put(prefix, key, nv) 69} 70// idempotent append of species to the node's species index (for rendering/enumeration) 71func sl_species_track(prefix: *u8, nid: *u8, sp: *u8) -> i64 { 72 let key: *u8 = sys_mmap(96); sl_species_key(nid, key) 73 let pq: *i64 = sys_mmap(16) as *i64 74 let lq: *i64 = sys_mmap(16) as *i64 75 let cur: *u8 = sys_mmap(SL_MAGIC_2048) 76 var o: i64 = 0 77 if ss_get(prefix, key, pq, lq) == 1 { 78 let b: *u8 = pq[0] as *u8; let n: i64 = lq[0] 79 var i: i64 = 0; var ls: i64 = 0 80 while i <= n { 81 var sep: i64 = 0 82 if i == n { sep = 1 } else { if b[i] == (9 as u8) { sep = 1 } } 83 if sep == 1 { 84 let tl: i64 = i - ls 85 if tl > 0 { if as_len(sp) == tl { var m: i64 = 0; var eq: i64 = 1; while m < tl { if b[ls + m] != sp[m] { eq = 0 } m = m + 1 } if eq == 1 { return 0 } } } 86 ls = i + 1 87 } 88 i = i + 1 89 } 90 var u: i64 = 0; while u < n { cur[u] = b[u]; u = u + 1 } o = n 91 cur[o] = 9 as u8; o = o + 1 92 } 93 o = as_append(cur, o, sp); cur[o] = 0 as u8 94 return sl_put(prefix, key, cur) 95} 96// contribute seeds to the library (host stocking, or a member returning). Increments stock. 97func sl_contribute(prefix: *u8, nid: *u8, sp: *u8, qty: i64) -> i64 { 98 sl_species_track(prefix, nid, sp) 99 sl_set_stock(prefix, nid, sp, sl_stock(prefix, nid, sp) + qty) 100 return 1 101} 102 103func sl_loann(prefix: *u8, nid: *u8) -> i64 { 104 let key: *u8 = sys_mmap(96); sl_loann_key(nid, key) 105 let pq: *i64 = sys_mmap(16) as *i64 106 let lq: *i64 = sys_mmap(16) as *i64 107 if ss_get(prefix, key, pq, lq) != 1 { return 0 } 108 return fd_atoi(pq[0] as *u8, lq[0]) 109} 110func sl_loan_record(prefix: *u8, nid: *u8, member: *u8, sp: *u8, qty: i64, direction: *u8, day: i64) -> i64 { 111 let seq: i64 = sl_loann(prefix, nid) 112 let key: *u8 = sys_mmap(96); sl_loan_key(nid, seq, key) 113 let val: *u8 = sys_mmap(256); var v: i64 = 0 114 v = as_append(val, v, member); val[v] = 9 as u8; v = v + 1 115 v = as_append(val, v, sp); val[v] = 9 as u8; v = v + 1 116 v = fd_apnum(val, v, qty); val[v] = 9 as u8; v = v + 1 117 v = as_append(val, v, direction); val[v] = 9 as u8; v = v + 1 118 v = fd_apnum(val, v, day); val[v] = 0 as u8 119 sl_put(prefix, key, val) 120 let nk: *u8 = sys_mmap(96); sl_loann_key(nid, nk) 121 let nv: *u8 = sys_mmap(16); var no: i64 = fd_apnum(nv, 0, seq + 1); nv[no] = 0 as u8 122 sl_put(prefix, nk, nv) 123 return seq 124} 125func sl_loan_str(prefix: *u8, nid: *u8, seq: i64, f: i64, out: *u8) -> i64 { 126 let key: *u8 = sys_mmap(96); sl_loan_key(nid, seq, key) 127 let pq: *i64 = sys_mmap(16) as *i64 128 let lq: *i64 = sys_mmap(16) as *i64 129 if ss_get(prefix, key, pq, lq) != 1 { out[0] = 0 as u8; return 0 } 130 return fd_field(pq[0] as *u8, lq[0], f, out) 131} 132func sl_loan_int(prefix: *u8, nid: *u8, seq: i64, f: i64) -> i64 { 133 let fb: *u8 = sys_mmap(24) 134 let fl: i64 = sl_loan_str(prefix, nid, seq, f, fb) 135 if fl == 0 { return 0 } 136 return fd_atoi(fb, fl) 137} 138 139// BORROW seeds: only if the library has enough (can't take what isn't there). Decrements stock, logs the loan. 140// Returns 1 on success, 0 if insufficient stock (stock left unchanged). 141func sl_take(prefix: *u8, nid: *u8, member: *u8, sp: *u8, qty: i64, day: i64) -> i64 { 142 if qty <= 0 { return 0 } 143 let have: i64 = sl_stock(prefix, nid, sp) 144 if have < qty { return 0 } 145 sl_set_stock(prefix, nid, sp, have - qty) 146 sl_loan_record(prefix, nid, member, sp, qty, "take" as *u8, day) 147 return 1 148} 149// RETURN seeds (grew + saved): increments stock, logs the return. The ethic = return more than you took. 150func sl_return(prefix: *u8, nid: *u8, member: *u8, sp: *u8, qty: i64, day: i64) -> i64 { 151 if qty <= 0 { return 0 } 152 sl_contribute(prefix, nid, sp, qty) 153 sl_loan_record(prefix, nid, member, sp, qty, "return" as *u8, day) 154 return 1 155} 156// a member's NET contribution for a species (returned - taken). Positive = grew the commons. 157func sl_member_net(prefix: *u8, nid: *u8, member: *u8, sp: *u8) -> i64 { 158 let n: i64 = sl_loann(prefix, nid) 159 var net: i64 = 0 160 var i: i64 = 0 161 while i < n { 162 let mb: *u8 = sys_mmap(48); sl_loan_str(prefix, nid, i, 0, mb) 163 let s2: *u8 = sys_mmap(48); sl_loan_str(prefix, nid, i, 1, s2) 164 if fd_streq(mb, member) == 1 { if fd_streq(s2, sp) == 1 { 165 let dir: *u8 = sys_mmap(16); sl_loan_str(prefix, nid, i, 3, dir) 166 let q: i64 = sl_loan_int(prefix, nid, i, 2) 167 if fd_streq(dir, "return" as *u8) == 1 { net = net + q } else { net = net - q } 168 } } 169 i = i + 1 170 } 171 return net 172} 173 174// render the node page (stock + ethic) -- sovereign no-JS. 175func sl_render_node(prefix: *u8, nid: *u8, out: *u8) -> i64 { 176 let nm: *u8 = sys_mmap(96); sl_node_str(prefix, nid, 1, nm) 177 let area: *u8 = sys_mmap(64); sl_node_str(prefix, nid, 2, area) 178 var o: i64 = 0 179 o = as_append(out, o, "<!doctype html><html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>Seed library</title><style>body{margin:0;font-family:system-ui,sans-serif;color:#23210f;background:#f7f4e8;line-height:1.5}header{background:#6b5a1f;color:#fff;padding:22px}header h1{margin:0;font-size:1.4rem}header p{margin:4px 0 0;color:#efe6c6}main{max-width:680px;margin:0 auto;padding:16px}section{background:#fff;border-radius:14px;padding:16px 18px;margin-top:16px;box-shadow:0 1px 0 #e7e0c8}h2{font-size:1.1rem;margin:0 0 8px;color:#6b5a1f}table{border-collapse:collapse;width:100%}td,th{padding:8px 10px;text-align:left;border-top:1px solid #efe9d6}th{background:#efe9d0;color:#5a4f2a}td.n{text-align:right;font-variant-numeric:tabular-nums;font-weight:700}.muted{color:#6a6048;font-size:.88rem}</style></head><body><header><h1>" as *u8) 180 o = as_append_escaped(out, o, nm, as_len(nm)) 181 o = as_append(out, o, "</h1><p>Community seed library &mdash; " as *u8) 182 o = as_append_escaped(out, o, area, as_len(area)) 183 o = as_append(out, o, "</p></header><main><section><h2>Seeds available</h2><table><tr><th>Species</th><th>In stock</th></tr>" as *u8) 184 let sk: *u8 = sys_mmap(96); sl_species_key(nid, sk) 185 let pq: *i64 = sys_mmap(16) as *i64 186 let lq: *i64 = sys_mmap(16) as *i64 187 if ss_get(prefix, sk, pq, lq) == 1 { 188 let b: *u8 = pq[0] as *u8 189 let n: i64 = lq[0] 190 var i: i64 = 0 191 var ls: i64 = 0 192 while i <= n { 193 var sep: i64 = 0 194 if i == n { sep = 1 } else { if b[i] == (9 as u8) { sep = 1 } } 195 if sep == 1 { 196 let tl: i64 = i - ls 197 if tl > 0 { 198 let sp: *u8 = sys_mmap(48); var t: i64 = 0; while t < tl { sp[t] = b[ls + t]; t = t + 1 } sp[tl] = 0 as u8 199 o = as_append(out, o, "<tr><td>" as *u8); o = as_append_escaped(out, o, sp, as_len(sp)) 200 o = as_append(out, o, "</td><td class='n'>" as *u8); o = fd_apnum(out, o, sl_stock(prefix, nid, sp)) 201 o = as_append(out, o, "</td></tr>" as *u8) 202 } 203 ls = i + 1 204 } 205 i = i + 1 206 } 207 } 208 o = as_append(out, o, "</table></section><p class='muted'>Borrow a few, grow them out, save seed, and return more than you took &mdash; that's how the library grows. Run by a member who earned the host capability.</p></main></body></html>" as *u8) 209 out[o] = 0 as u8 210 return o 211}