code wiki / (root) / nx_fruiting.nx

nx_fruiting.nx source

↩ module page · 334 lines · 13121 B

1// nx_fruiting.nx -- content-addressed many-to-many broadcast (mushroom 2// fruiting body releasing spores). 3// 4// Per user 2026-05-19: *"not just peer but we should also have torrent 5// aka the fruiting or whatever"* -- the underground mycelium (nx_hypha) 6// is point-to-point peer share; the ABOVE-GROUND fruiting body is the 7// many-to-many broadcast layer. Mushrooms release spores that disperse 8// via wind / water / animal / ballistospory; spores find new substrate 9// and germinate. Substrate equivalent: content-addressed fragment 10// dispersal where any peer holding fragment-N can serve it to any 11// receiver requesting fragment-N (BitTorrent-class but biology-named). 12// 13// Per [[feedback-naming-discipline-no-industry-competitor-overlap]]: 14// "torrent" is a tech-product name we avoid. "Fruiting" is biology- 15// precise + unowned in tech-product space. 16// 17// V1 ships sealed enum of dispersal modes + content-addressed fragment- 18// hash chain + per-fragment provenance + per-fruiting-body dispersal 19// budget (refuses amplification attacks). 20// 21// Distinct from nx_hypha: hypha is RECIPROCITY-REQUIRED point-to-point 22// peer exchange; fruiting is one-to-many broadcast where receivers do 23// NOT need to share back (they may, but it's not required for 24// reception). Together they're the complete fungal-network 25// distribution architecture. 26// 27// Composes: 28// nx_methyl -- each fragment carries Ed25519-signed methyl 29// marker; receiver verifies before germinating 30// nx_chromatin -- content-addressed block storage; fragments are 31// chromatin block hashes 32// nx_provenance_chain -- dispersal event chain-logged 33// nx_hypha -- peers can re-share fruiting fragments via hypha 34// point-to-point if desired (composes) 35// 36// V1 ships state-machine + classification primitives. Actual byte- 37// transport for fragment delivery is caller-supplied (V2 wires 38// content-addressed BLAKE3 fragment chain + chromatin block fetch). 39// 40// Gap list (V1 honest perf verdict): 41// - per-fragment hash chain is operator-supplied (V2 inlines 42// BLAKE3-Merkle-tree construction) 43// - dispersal-budget thresholds research-derived (V2 makes per-niche 44// policy) 45// - rare-fragment-priority (BitTorrent rarest-first) is a future 46// optimization 47// 48// genealogy_id: nishi_metacardinal_2026-05-19_forest_drift_lifecycle 49// lineage_id: substrate_fruiting_v1 50// 51// nx_safety_envelope: 52// intended_use: "Many-to-many content-addressed broadcast for 53// substrate dispersal; biology-named torrent 54// with per-fragment provenance + amplification- 55// budget gate" 56// sil_target: SIL2 57// evidence: [enum_sealed, content_addressed, 58// per_fragment_provenance, amplification_budgeted] 59// verdict: NOT_YET_EVALUATED 60 61import "nx_syscalls.nx" 62import "nx_tier.nx" 63 64// ===== Sealed enum: NxDispersalMode =============================== 65// 66// Biological spore-dispersal mechanisms mapped to substrate transport: 67// ANEMOPHILY = wind dispersal (broadcast UDP-class; any-to-any) 68// HYDROPHILY = water dispersal (sequential downstream; mesh-flow) 69// ZOOCHORY = animal dispersal (carried by a peer; targeted 70// delivery to specific endpoint) 71// BALLISTOSPORY = active shooting (push delivery; sender initiates) 72// AUTOCHORY = self-dispersal (sender stores locally + signals 73// availability; pull delivery) 74 75const NX_FR_ANEMOPHILY: nx_int = 0 // wind: broadcast many-to-many 76const NX_FR_HYDROPHILY: nx_int = 1 // water: sequential flow 77const NX_FR_ZOOCHORY: nx_int = 2 // animal: carry-and-deliver 78const NX_FR_BALLISTOSPORY: nx_int = 3 // active push 79const NX_FR_AUTOCHORY: nx_int = 4 // local store + pull-available 80const NX_FR_N_MODES: nx_int = 5 81 82// ===== Sealed enum: NxFruitingBodyState =========================== 83 84const NX_FB_DEVELOPING: nx_int = 0 // gathering fragments 85const NX_FB_READY_TO_DISPERSE: nx_int = 1 // complete + verified 86const NX_FB_DISPERSING: nx_int = 2 // actively serving fragments 87const NX_FB_QUIESCENT: nx_int = 3 // dispersal-budget exhausted 88const NX_FB_FAILED: nx_int = 4 // refused/invalid 89const NX_FB_N_STATES: nx_int = 5 90 91// ===== Sealed enum: NxFruitingVerdict ============================= 92 93const NX_FR_OK: nx_int = 0 94const NX_FR_ERR_INVALID_MODE: nx_int = 1 95const NX_FR_ERR_INVALID_STATE: nx_int = 2 96const NX_FR_ERR_BUDGET_EXHAUSTED: nx_int = 3 97const NX_FR_ERR_FRAGMENT_OUT_OF_RANGE: nx_int = 4 98const NX_FR_ERR_NULL_INPUT: nx_int = 5 99const NX_FR_ERR_INVALID_TRANSITION: nx_int = 6 100const NX_FR_N_VERDICTS: nx_int = 7 101 102// ===== Struct: NxFruitingBody ===================================== 103// 104// One content-addressed broadcast artifact (e.g., a Nishi-stack 105// release, a published audit-attestation, a peer-mesh-distributable 106// dataset). total_fragments = number of BLAKE3 content-addressed 107// blocks composing the artifact. served_count = fragments served 108// so far (for amplification-budget accounting). 109 110struct NxFruitingBody { 111 body_id: nx_int, 112 dispersal_mode: nx_int, 113 state: nx_int, 114 total_fragments: nx_int, 115 fragments_complete: nx_int, // for DEVELOPING state; reaches total 116 served_count: nx_int, // dispersal accounting 117 dispersal_budget: nx_int, // max fragments to serve before QUIESCENT 118 root_methyl_id: nx_int, // composes nx_methyl 119 created_at_us: nx_size, 120 last_served_us: nx_size, 121} 122 123const NX_FB_BYTES: nx_int = 80 124const NX_FB_DEFAULT_BUDGET_MULTIPLIER: nx_int = 100 125 126// ===== nx_fr_mode_is_valid ======================================== 127 128func nx_fr_mode_is_valid(m: nx_int) -> nx_int { 129 if m < 0 { return 0 } 130 if m >= NX_FR_N_MODES { return 0 } 131 return 1 132} 133 134// ===== nx_fb_state_is_valid ======================================= 135 136func nx_fb_state_is_valid(s: nx_int) -> nx_int { 137 if s < 0 { return 0 } 138 if s >= NX_FB_N_STATES { return 0 } 139 return 1 140} 141 142// ===== nx_fr_verdict_is_valid ===================================== 143 144func nx_fr_verdict_is_valid(v: nx_int) -> nx_int { 145 if v < 0 { return 0 } 146 if v >= NX_FR_N_VERDICTS { return 0 } 147 return 1 148} 149 150// ===== nx_fr_mode_is_broadcast ==================================== 151// 152// Predicate: returns 1 for true broadcast modes (ANEMOPHILY = wind / 153// HYDROPHILY = water-flow downstream). ZOOCHORY (single carrier), 154// BALLISTOSPORY (active push to one target), AUTOCHORY (local store) 155// are targeted/sequential. 156 157func nx_fr_mode_is_broadcast(m: nx_int) -> nx_int { 158 if m == NX_FR_ANEMOPHILY { return 1 } 159 if m == NX_FR_HYDROPHILY { return 1 } 160 return 0 161} 162 163// ===== nx_fr_mode_requires_active_sender ========================== 164// 165// Predicate: BALLISTOSPORY requires the sender to actively push to 166// a designated recipient (vs. waiting to be pulled). 167 168func nx_fr_mode_requires_active_sender(m: nx_int) -> nx_int { 169 if m == NX_FR_BALLISTOSPORY { return 1 } 170 return 0 171} 172 173// ===== nx_fb_state_is_serving ===================================== 174 175func nx_fb_state_is_serving(s: nx_int) -> nx_int { 176 if s == NX_FB_DISPERSING { return 1 } 177 return 0 178} 179 180// ===== nx_fb_state_is_terminal ==================================== 181 182func nx_fb_state_is_terminal(s: nx_int) -> nx_int { 183 if s == NX_FB_QUIESCENT { return 1 } 184 if s == NX_FB_FAILED { return 1 } 185 return 0 186} 187 188// ===== _fb_transition_allowed ===================================== 189// 190// DEVELOPING -> READY_TO_DISPERSE -> DISPERSING -> QUIESCENT 191// Any non-terminal state can transition to FAILED. 192 193func _fb_transition_allowed(from: nx_int, to: nx_int) -> nx_int { 194 if to == NX_FB_FAILED { 195 if nx_fb_state_is_terminal(from) == 1 { return 0 } 196 if nx_fb_state_is_valid(from) == 1 { return 1 } 197 return 0 198 } 199 if from == NX_FB_DEVELOPING { 200 if to == NX_FB_READY_TO_DISPERSE { return 1 } 201 return 0 202 } 203 if from == NX_FB_READY_TO_DISPERSE { 204 if to == NX_FB_DISPERSING { return 1 } 205 return 0 206 } 207 if from == NX_FB_DISPERSING { 208 if to == NX_FB_QUIESCENT { return 1 } 209 return 0 210 } 211 return 0 212} 213 214// ===== nx_fb_new ================================================== 215 216func nx_fb_new(body_id: nx_int, 217 dispersal_mode: nx_int, 218 total_fragments: nx_int, 219 root_methyl_id: nx_int, 220 created_at_us: nx_size) -> *NxFruitingBody { 221 if total_fragments <= 0 { return 0 as *NxFruitingBody } 222 let raw: *u8 = sys_mmap(NX_FB_BYTES) 223 let b: *NxFruitingBody = raw as *NxFruitingBody 224 b.body_id = body_id 225 b.dispersal_mode = dispersal_mode 226 b.state = NX_FB_DEVELOPING 227 b.total_fragments = total_fragments 228 b.fragments_complete = 0 229 b.served_count = 0 230 // Default budget: serve each fragment up to 100 times before quiesce 231 b.dispersal_budget = total_fragments * NX_FB_DEFAULT_BUDGET_MULTIPLIER 232 b.root_methyl_id = root_methyl_id 233 b.created_at_us = created_at_us 234 b.last_served_us = 0 235 return b 236} 237 238// ===== nx_fb_record_fragment_complete ============================= 239// 240// Caller signals that fragment N has been verified + added to the 241// body. When fragments_complete == total_fragments, state advances 242// to READY_TO_DISPERSE (caller must explicitly transition). 243 244func nx_fb_record_fragment_complete(b: *NxFruitingBody) -> nx_int { 245 if (b as i64) == 0 { return NX_FR_ERR_NULL_INPUT } 246 if b.state != NX_FB_DEVELOPING { return NX_FR_ERR_INVALID_STATE } 247 if b.fragments_complete >= b.total_fragments { 248 return NX_FR_ERR_FRAGMENT_OUT_OF_RANGE 249 } 250 b.fragments_complete = b.fragments_complete + 1 251 return NX_FR_OK 252} 253 254// ===== nx_fb_is_complete ========================================== 255 256func nx_fb_is_complete(b: *NxFruitingBody) -> nx_int { 257 if (b as i64) == 0 { return 0 } 258 if b.fragments_complete >= b.total_fragments { return 1 } 259 return 0 260} 261 262// ===== nx_fb_transition =========================================== 263 264func nx_fb_transition(b: *NxFruitingBody, to: nx_int) -> nx_int { 265 if (b as i64) == 0 { return NX_FR_ERR_NULL_INPUT } 266 if nx_fb_state_is_valid(to) == 0 { return NX_FR_ERR_INVALID_TRANSITION } 267 if _fb_transition_allowed(b.state, to) == 0 { 268 return NX_FR_ERR_INVALID_TRANSITION 269 } 270 if to == NX_FB_READY_TO_DISPERSE { 271 if b.fragments_complete < b.total_fragments { 272 return NX_FR_ERR_FRAGMENT_OUT_OF_RANGE 273 } 274 } 275 b.state = to 276 return NX_FR_OK 277} 278 279// ===== nx_fb_serve_fragment ======================================= 280// 281// Caller records that fragment was served to a requesting peer. 282// Increments served_count + checks against dispersal_budget. When 283// budget exhausted, state auto-transitions to QUIESCENT (refuses 284// amplification attacks). 285// 286// fragment_index is for caller's accounting + provenance (not 287// validated here; substrate trusts caller's BLAKE3 verification). 288 289func nx_fb_serve_fragment(b: *NxFruitingBody, 290 fragment_index: nx_int, 291 now_us: nx_size) -> nx_int { 292 if (b as i64) == 0 { return NX_FR_ERR_NULL_INPUT } 293 if b.state != NX_FB_DISPERSING { return NX_FR_ERR_INVALID_STATE } 294 if fragment_index < 0 { return NX_FR_ERR_FRAGMENT_OUT_OF_RANGE } 295 if fragment_index >= b.total_fragments { 296 return NX_FR_ERR_FRAGMENT_OUT_OF_RANGE 297 } 298 if b.served_count >= b.dispersal_budget { 299 // Auto-quiesce on budget exhaustion 300 b.state = NX_FB_QUIESCENT 301 return NX_FR_ERR_BUDGET_EXHAUSTED 302 } 303 b.served_count = b.served_count + 1 304 b.last_served_us = now_us 305 if b.served_count >= b.dispersal_budget { 306 b.state = NX_FB_QUIESCENT 307 } 308 return NX_FR_OK 309} 310 311// ===== nx_fb_remaining_budget ===================================== 312 313func nx_fb_remaining_budget(b: *NxFruitingBody) -> nx_int { 314 if (b as i64) == 0 { return 0 } 315 let r: nx_int = b.dispersal_budget - b.served_count 316 if r < 0 { return 0 } 317 return r 318} 319 320// ===== nx_fb_set_dispersal_budget ================================= 321// 322// Operator override of default budget (e.g., for known-high-demand 323// release, raise the budget; for sensitive release, lower it). 324// Cannot be raised once DISPERSING (additive-only-style discipline). 325 326func nx_fb_set_dispersal_budget(b: *NxFruitingBody, 327 new_budget: nx_int) -> nx_int { 328 if (b as i64) == 0 { return NX_FR_ERR_NULL_INPUT } 329 if new_budget < 0 { return NX_FR_ERR_INVALID_STATE } 330 if b.state == NX_FB_DISPERSING { return NX_FR_ERR_INVALID_STATE } 331 if b.state == NX_FB_QUIESCENT { return NX_FR_ERR_INVALID_STATE } 332 b.dispersal_budget = new_budget 333 return NX_FR_OK 334}