code wiki / _hdl_build / nx_gossip.nx

nx_gossip.nx source

↩ module page · 60 lines · 3075 B

1// nx_gossip.nx -- LIB: EPIDEMIC / ANTI-ENTROPY gossip so the Napster index spreads across the mesh with NO central 2// bottleneck (operator: "lots of peers can share with lots of peers ... spoke to spoke or hub to hub"). Each node 3// holds a local content registry (nx_dist_index rows). A gossip round reconciles two nodes: exchange a compact 4// DIGEST (the set of cids each holds) -> each side selects the rows the other LACKS -> merge (idempotent by cid). 5// After a symmetric round both nodes hold the UNION -> run pairwise across the mesh and knowledge converges 6// epidemically. Composes nx_dist_index (row parsing, di_has_cid). No TLS. license_tier: ORIGINAL 7import "nx_dist_index.nx" 8import "nx_syscalls.nx" 9 10// DIGEST: newline-separated cids present in reg (the compact "I have these" summary sent to a peer). 11func gossip_digest(reg: *u8, rlen: i64, out: *u8) -> i64 { 12 var o: i64=0; var ls: i64=0 13 while ls<rlen { 14 let le: i64 = di_eol(reg, ls, rlen) 15 let t1: i64 = di_tab(reg, ls, le); let cs: i64 = t1+1; let ce: i64 = di_tab(reg, cs, le) 16 var k: i64=cs; while k<ce { out[o]=reg[k]; o=o+1; k=k+1 } out[o]=10 as u8; o=o+1 17 ls = le+1 18 } 19 out[o]=0 as u8; return o 20} 21// does a digest (newline cids) already list this cid? 22func gossip_digest_has(digest: *u8, dlen: i64, cid: *u8) -> i64 { 23 let cl: i64 = di_strlen(cid); var ls: i64=0 24 while ls<dlen { 25 let le: i64 = di_eol(digest, ls, dlen) 26 if le-ls==cl { if di_memeq((digest as i64 + ls) as *u8, cid, cl)==1 { return 1 } } 27 ls = le+1 28 } 29 return 0 30} 31// SELECT: append every row of my_reg whose cid is NOT in the peer's digest (what I can teach the peer). Returns len. 32func gossip_select(my_reg: *u8, mlen: i64, peer_digest: *u8, dlen: i64, out: *u8) -> i64 { 33 var o: i64=0; var ls: i64=0 34 while ls<mlen { 35 let le: i64 = di_eol(my_reg, ls, mlen) 36 let t1: i64 = di_tab(my_reg, ls, le); let cs: i64 = t1+1; let ce: i64 = di_tab(my_reg, cs, le) 37 let tmp: *u8 = sys_mmap(128); var j: i64=0; while cs+j<ce { tmp[j]=my_reg[cs+j]; j=j+1 } tmp[j]=0 as u8 38 if gossip_digest_has(peer_digest, dlen, tmp)==0 { 39 var k: i64=ls; while k<le { out[o]=my_reg[k]; o=o+1; k=k+1 } out[o]=10 as u8; o=o+1 40 } 41 ls = le+1 42 } 43 out[o]=0 as u8; return o 44} 45// MERGE: fold incoming rows into dst (idempotent by cid -- additive-only). Returns new dst length. 46func gossip_merge(dst: *u8, dlen: i64, incoming: *u8, ilen: i64) -> i64 { 47 var out: i64=dlen; var ls: i64=0 48 while ls<ilen { 49 let le: i64 = di_eol(incoming, ls, ilen) 50 if le>ls { 51 let t1: i64 = di_tab(incoming, ls, le); let cs: i64 = t1+1; let ce: i64 = di_tab(incoming, cs, le) 52 let tmp: *u8 = sys_mmap(128); var j: i64=0; while cs+j<ce { tmp[j]=incoming[cs+j]; j=j+1 } tmp[j]=0 as u8 53 if di_has_cid(dst, out, tmp)==0 { 54 var k: i64=ls; while k<le { dst[out]=incoming[k]; out=out+1; k=k+1 } dst[out]=10 as u8; out=out+1 55 } 56 } 57 ls = le+1 58 } 59 return out 60}