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 — " 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 — 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}