code wiki / (root) / nx_hypha.nx

nx_hypha.nx source

↩ module page · 375 lines · 15732 B

1// nx_hypha.nx -- bidirectional peer share + receive (point-to-point 2// mycelium / wood-wide-web). 3// 4// Per META-CARDINAL feedback-forest-meta-vision-drift-lifecycle: every 5// EXCHANGE_* mode has a paired RECEIVE_* mode at the same peer. Pure 6// consumers are throttled per [[feedback-west-industrial-build- 7// replenish-not-buy-consume]]. A new node gets a "starter quota" of 8// EXCHANGE_* capability proportional to its niche -- no node arrives 9// with literally nothing to offer. 10// 11// Distinct from nx_fruiting (queued): nx_hypha is POINT-TO-POINT peer 12// share between two specific Nishi nodes. nx_fruiting is MANY-TO-MANY 13// content-addressed broadcast (mushroom spore release). Both compose 14// to give the complete underground-mycelium-plus-fruiting-body 15// distribution architecture. 16// 17// V1 ships sealed enum of exchange modes + reciprocity discipline 18// predicate + niche-aware capability gating + per-peer trust state. 19// 20// Composes: 21// nx_methyl -- peer-attestation Ed25519 chain (caller-supplied) 22// nx_niche -- niche gates which EXCHANGE_* modes a peer can offer 23// nx_attest_silicon -- silicon-trust gates sovereignty-critical exchanges 24// nx_immune -- runtime defense composes on suspicious-peer signal 25// 26// Gap list (V1 honest perf verdict): 27// - actual byte transport is caller-supplied (V2 wires nx_chromatin 28// content-addressed blocks + nx_http3 / libp2p-class re-derived 29// transport) 30// - reciprocity ratio thresholds are operator-tuneable per niche 31// (V2 makes data-driven) 32// - "starter quota" for new peer is the niche-default + first 100 33// interactions; V1 marks the quota; V2 enforces decay 34// 35// genealogy_id: nishi_metacardinal_2026-05-19_forest_drift_lifecycle 36// lineage_id: substrate_hypha_v1 37// 38// nx_safety_envelope: 39// intended_use: "Bidirectional point-to-point peer exchange 40// with reciprocity discipline + niche-aware 41// gating; refuses free-rider configuration" 42// sil_target: SIL2 43// evidence: [enum_sealed, reciprocity_required, 44// niche_gating_explicit, starter_quota_documented] 45// verdict: NOT_YET_EVALUATED 46 47import "nx_syscalls.nx" 48import "nx_tier.nx" 49 50// ===== Sealed enum: NxExchangeMode ================================ 51// 52// Eight canonical exchange modes shipped V1. Each mode has both a 53// SHARE direction (this node giving) and RECEIVE direction (this node 54// taking). Reciprocity discipline enforced at the substrate level: 55// a peer that only RECEIVEs and never SHAREs is throttled. 56 57const NX_EM_COMPUTE: nx_int = 0 // VRAM / cores / NPU borrow 58const NX_EM_STORAGE: nx_int = 1 // content-addressed blocks 59const NX_EM_SIGNAL: nx_int = 2 // telemetry / alerts / niche-correction 60const NX_EM_CHROMATIN: nx_int = 3 // organelle updates + audit-labels 61const NX_EM_PATHWAY: nx_int = 4 // cooperative sub-graph execution 62const NX_EM_LABEL: nx_int = 5 // triangulated audit-consensus 63const NX_EM_KNOWLEDGE: nx_int = 6 // federated-averaged small-model weights 64const NX_EM_INGEST: nx_int = 7 // one-directional consume from foreign substrate 65const NX_EM_N_MODES: nx_int = 8 66 67// ===== Sealed enum: NxExchangeDirection =========================== 68 69const NX_EM_DIR_SHARE: nx_int = 0 70const NX_EM_DIR_RECEIVE: nx_int = 1 71const NX_EM_DIR_N_DIRS: nx_int = 2 72 73// ===== Sealed enum: NxHyphaVerdict ================================ 74 75const NX_HY_OK: nx_int = 0 76const NX_HY_ERR_INVALID_MODE: nx_int = 1 77const NX_HY_ERR_INVALID_DIRECTION: nx_int = 2 78const NX_HY_ERR_RECIPROCITY_VIOLATION: nx_int = 3 // pure consumer; throttled 79const NX_HY_ERR_NICHE_INCAPABLE: nx_int = 4 // this niche can't offer this mode 80const NX_HY_ERR_TRUST_INSUFFICIENT: nx_int = 5 // silicon trust below requirement 81const NX_HY_ERR_NULL_INPUT: nx_int = 6 82const NX_HY_N_VERDICTS: nx_int = 7 83 84// ===== Struct: NxPeerExchangeState ================================ 85// 86// Per-peer state tracking what THIS local node has SHAREd + RECEIVEd 87// from the remote peer over time. Reciprocity verdict computed from 88// share_count vs receive_count. 89 90struct NxPeerExchangeState { 91 peer_id: nx_int, 92 peer_niche: nx_int, 93 peer_silicon_trust: nx_int, 94 share_counts: *u8, // array[NX_EM_N_MODES] of i64 95 receive_counts: *u8, // array[NX_EM_N_MODES] of i64 96 last_exchange_us: nx_size, 97 starter_quota_remaining: nx_int, // per-niche starter; decrements on receive 98} 99 100const NX_HY_PEER_BYTES: nx_int = 56 101const NX_HY_PER_MODE_BYTES: nx_int = 8 102const NX_HY_STARTER_QUOTA_DEFAULT: nx_int = 100 103 104// ===== nx_em_mode_is_valid ======================================== 105 106func nx_em_mode_is_valid(m: nx_int) -> nx_int { 107 if m < 0 { return 0 } 108 if m >= NX_EM_N_MODES { return 0 } 109 return 1 110} 111 112// ===== nx_em_dir_is_valid ========================================= 113 114func nx_em_dir_is_valid(d: nx_int) -> nx_int { 115 if d < 0 { return 0 } 116 if d >= NX_EM_DIR_N_DIRS { return 0 } 117 return 1 118} 119 120// ===== nx_hy_verdict_is_valid ===================================== 121 122func nx_hy_verdict_is_valid(v: nx_int) -> nx_int { 123 if v < 0 { return 0 } 124 if v >= NX_HY_N_VERDICTS { return 0 } 125 return 1 126} 127 128// ===== nx_em_niche_can_offer ====================================== 129// 130// Predicate: does this niche typically have the capacity to OFFER 131// the given exchange mode? E.g. a phone can offer SIGNAL + LABEL + 132// KNOWLEDGE but can't realistically offer COMPUTE (no spare cycles) 133// or STORAGE (limited capacity). A NAS can offer STORAGE + CHROMATIN 134// + SIGNAL but limited COMPUTE. 135// 136// niche values match NX_NICHE_* from nx_niche.nx by-value. 137 138func nx_em_niche_can_offer(niche: nx_int, mode: nx_int) -> nx_int { 139 if nx_em_mode_is_valid(mode) == 0 { return 0 } 140 // GAMING_WORKSTATION (0) / DEV_WORKSTATION (1) -- can offer all 141 if niche == 0 { return 1 } 142 if niche == 1 { return 1 } 143 // LAPTOP (2) -- can offer most; limited COMPUTE under battery 144 if niche == 2 { 145 if mode == NX_EM_PATHWAY { return 0 } // pathway needs sustained compute 146 return 1 147 } 148 // HOME_NAS (3) -- excellent STORAGE + CHROMATIN; limited COMPUTE 149 if niche == 3 { 150 if mode == NX_EM_COMPUTE { return 0 } 151 if mode == NX_EM_PATHWAY { return 0 } 152 return 1 153 } 154 // SMARTPHONE (5) -- SIGNAL / LABEL / KNOWLEDGE / INGEST only 155 if niche == 5 { 156 if mode == NX_EM_SIGNAL { return 1 } 157 if mode == NX_EM_LABEL { return 1 } 158 if mode == NX_EM_KNOWLEDGE { return 1 } 159 if mode == NX_EM_INGEST { return 1 } 160 return 0 161 } 162 // EMBEDDED_SENSOR (40) / FARM_SOIL_MONITOR (41) -- SIGNAL only 163 if niche == 40 { if mode == NX_EM_SIGNAL { return 1 } else { return 0 } } 164 if niche == 41 { if mode == NX_EM_SIGNAL { return 1 } else { return 0 } } 165 // HOME_IOT_HUB (42) -- SIGNAL + LABEL 166 if niche == 42 { 167 if mode == NX_EM_SIGNAL { return 1 } 168 if mode == NX_EM_LABEL { return 1 } 169 return 0 170 } 171 // INDUSTRIAL_* (10-13) / MEDICAL (20-21) / AUTOMOTIVE (30) -- 172 // SIGNAL + restricted others 173 if niche >= 10 { 174 if niche <= 13 { 175 if mode == NX_EM_SIGNAL { return 1 } 176 if mode == NX_EM_LABEL { return 1 } 177 return 0 178 } 179 } 180 if niche == 20 { if mode == NX_EM_SIGNAL { return 1 } else { return 0 } } 181 if niche == 21 { if mode == NX_EM_SIGNAL { return 1 } else { return 0 } } 182 if niche == 30 { if mode == NX_EM_SIGNAL { return 1 } else { return 0 } } 183 // Refused niches (50-53) -- none 184 if niche >= 50 { 185 if niche <= 53 { return 0 } 186 } 187 return 0 // unknown niche -- conservative 188} 189 190// ===== nx_hy_peer_state_new ======================================= 191 192func nx_hy_peer_state_new(peer_id: nx_int, 193 peer_niche: nx_int, 194 peer_silicon_trust: nx_int) -> *NxPeerExchangeState { 195 let raw: *u8 = sys_mmap(NX_HY_PEER_BYTES) 196 let p: *NxPeerExchangeState = raw as *NxPeerExchangeState 197 p.peer_id = peer_id 198 p.peer_niche = peer_niche 199 p.peer_silicon_trust = peer_silicon_trust 200 p.share_counts = sys_mmap(NX_EM_N_MODES * NX_HY_PER_MODE_BYTES) 201 p.receive_counts = sys_mmap(NX_EM_N_MODES * NX_HY_PER_MODE_BYTES) 202 var i: nx_int = 0 203 while i < NX_EM_N_MODES { 204 let off: nx_int = i * NX_HY_PER_MODE_BYTES 205 let s: *i64 = (p.share_counts + off) as *i64 206 let r: *i64 = (p.receive_counts + off) as *i64 207 s[0] = 0 208 r[0] = 0 209 i = i + 1 210 } 211 p.last_exchange_us = 0 212 p.starter_quota_remaining = NX_HY_STARTER_QUOTA_DEFAULT 213 return p 214} 215 216// ===== nx_hy_record_exchange ====================================== 217// 218// Record an exchange event with this peer. direction = SHARE means 219// local node gave; RECEIVE means local node took. Updates counts + 220// starter quota. Reciprocity verdict computed in separate predicate. 221 222func nx_hy_record_exchange(p: *NxPeerExchangeState, 223 mode: nx_int, 224 direction: nx_int, 225 now_us: nx_size) -> nx_int { 226 if (p as i64) == 0 { return NX_HY_ERR_NULL_INPUT } 227 if nx_em_mode_is_valid(mode) == 0 { return NX_HY_ERR_INVALID_MODE } 228 if nx_em_dir_is_valid(direction) == 0 { return NX_HY_ERR_INVALID_DIRECTION } 229 let off: nx_int = mode * NX_HY_PER_MODE_BYTES 230 if direction == NX_EM_DIR_SHARE { 231 let s: *i64 = (p.share_counts + off) as *i64 232 s[0] = s[0] + 1 233 } else { 234 let r: *i64 = (p.receive_counts + off) as *i64 235 r[0] = r[0] + 1 236 // Decrement starter quota when receiving 237 if p.starter_quota_remaining > 0 { 238 p.starter_quota_remaining = p.starter_quota_remaining - 1 239 } 240 } 241 p.last_exchange_us = now_us 242 return NX_HY_OK 243} 244 245// ===== nx_hy_share_count ========================================== 246 247func nx_hy_share_count(p: *NxPeerExchangeState, mode: nx_int) -> nx_int { 248 if (p as i64) == 0 { return 0 } 249 if nx_em_mode_is_valid(mode) == 0 { return 0 } 250 let off: nx_int = mode * NX_HY_PER_MODE_BYTES 251 let s: *i64 = (p.share_counts + off) as *i64 252 return s[0] as nx_int 253} 254 255// ===== nx_hy_receive_count ======================================== 256 257func nx_hy_receive_count(p: *NxPeerExchangeState, mode: nx_int) -> nx_int { 258 if (p as i64) == 0 { return 0 } 259 if nx_em_mode_is_valid(mode) == 0 { return 0 } 260 let off: nx_int = mode * NX_HY_PER_MODE_BYTES 261 let r: *i64 = (p.receive_counts + off) as *i64 262 return r[0] as nx_int 263} 264 265// ===== nx_hy_total_shared ========================================= 266 267func nx_hy_total_shared(p: *NxPeerExchangeState) -> nx_int { 268 if (p as i64) == 0 { return 0 } 269 var sum: nx_int = 0 270 var i: nx_int = 0 271 while i < NX_EM_N_MODES { 272 sum = sum + nx_hy_share_count(p, i) 273 i = i + 1 274 } 275 return sum 276} 277 278// ===== nx_hy_total_received ======================================= 279 280func nx_hy_total_received(p: *NxPeerExchangeState) -> nx_int { 281 if (p as i64) == 0 { return 0 } 282 var sum: nx_int = 0 283 var i: nx_int = 0 284 while i < NX_EM_N_MODES { 285 sum = sum + nx_hy_receive_count(p, i) 286 i = i + 1 287 } 288 return sum 289} 290 291// ===== nx_hy_reciprocity_verdict ================================== 292// 293// Returns OK if peer's exchange profile meets reciprocity discipline: 294// - starter_quota_remaining > 0 -> OK (new peer; grace period) 295// - share/(share+receive) >= 0.3 -> OK (at least 30% share ratio) 296// - else -> RECIPROCITY_VIOLATION (throttle) 297// 298// Per [[feedback-west-industrial-build-replenish-not-buy-consume]] -- 299// pure consumers are throttled. 300 301func nx_hy_reciprocity_verdict(p: *NxPeerExchangeState) -> nx_int { 302 if (p as i64) == 0 { return NX_HY_ERR_NULL_INPUT } 303 if p.starter_quota_remaining > 0 { return NX_HY_OK } 304 let shared: nx_int = nx_hy_total_shared(p) 305 let received: nx_int = nx_hy_total_received(p) 306 let total: nx_int = shared + received 307 if total == 0 { return NX_HY_OK } // no exchanges yet 308 // 30% threshold: shared * 10 >= total * 3 309 if (shared * 10) >= (total * 3) { return NX_HY_OK } 310 return NX_HY_ERR_RECIPROCITY_VIOLATION 311} 312 313// ===== nx_hy_reciprocity_verdict_units ============================ 314// 315// DEFECT FOUND 2026-08-06: nx_hy_reciprocity_verdict above counts EVENTS, not MAGNITUDES. Share one 316// byte, receive one terabyte, and the counts are 1:1 -> 50% -> comfortably past the 30% floor -> OK. 317// Anyone who can make their giving granular and their taking bulky walks straight through it, and 318// that is precisely the skimmer's move: many tiny rendered services, few enormous extractions. 319// 320// A COUNT IS NOT A QUANTITY. A reciprocity floor denominated in events measures politeness, 321// not reciprocity. 322// 323// ADDITIVE by law 19: the count-based verdict keeps its exact contract for every existing caller and 324// is NOT touched. New callers take this one. nx_commons_units_gate holds BOTH and asserts they 325// DISAGREE on a magnitude-skewed peer, so the discrimination this term buys stays visible and cannot 326// quietly regress to the blind form. 327// 328// Overflow-safe BY CONSTRUCTION: the 30% floor divides the total DOWN and never multiplies the 329// shared side UP. Multiplying up is exactly the nx_mycorrhiza defect fixed in the same session -- 330// the same lesson learned twice in two organs is a lesson the codebase never learned, so it is 331// written into the arithmetic here rather than into a comment. 332func nx_hy_reciprocity_verdict_units(p: *NxPeerExchangeState, 333 shared_units: nx_int, 334 received_units: nx_int) -> nx_int { 335 if (p as i64) == 0 { return NX_HY_ERR_NULL_INPUT } 336 if p.starter_quota_remaining > 0 { return NX_HY_OK } 337 var s: nx_int = shared_units 338 if s < 0 { s = 0 } 339 var r: nx_int = received_units 340 if r < 0 { r = 0 } 341 let total: nx_int = s + r 342 if total == 0 { return NX_HY_OK } 343 let floor_units: nx_int = (total / 10) * 3 + ((total % 10) * 3) / 10 344 if s >= floor_units { return NX_HY_OK } 345 return NX_HY_ERR_RECIPROCITY_VIOLATION 346} 347 348// ===== nx_hy_can_initiate_share =================================== 349// 350// Predicate: should this local node initiate a SHARE of `mode` to peer? 351// Composes: 352// - peer must be capable of offering reciprocal mode (niche check) 353// - peer reciprocity verdict OK 354// - peer trust level acceptable for mode 355 356func nx_hy_can_initiate_share(p: *NxPeerExchangeState, 357 mode: nx_int) -> nx_int { 358 if (p as i64) == 0 { return NX_HY_ERR_NULL_INPUT } 359 if nx_em_mode_is_valid(mode) == 0 { return NX_HY_ERR_INVALID_MODE } 360 let v: nx_int = nx_hy_reciprocity_verdict(p) 361 if v != NX_HY_OK { return v } 362 // Caller-supplied silicon-trust gate: sovereignty-critical modes 363 // (KNOWLEDGE, PATHWAY) require higher trust than opportunistic 364 // (SIGNAL, LABEL, INGEST). We encode a simple threshold: any 365 // commodity-class trust (>=4 per nx_attest_silicon NxSiliconTrustLevel) 366 // accepts opportunistic; sovereignty-critical requires <=3 (SBC_RPI 367 // or better). 368 if mode == NX_EM_KNOWLEDGE { 369 if p.peer_silicon_trust > 3 { return NX_HY_ERR_TRUST_INSUFFICIENT } 370 } 371 if mode == NX_EM_PATHWAY { 372 if p.peer_silicon_trust > 4 { return NX_HY_ERR_TRUST_INSUFFICIENT } 373 } 374 return NX_HY_OK 375}