code wiki / (root) / nx_commons_sybilcost.nx

nx_commons_sybilcost.nx source

↩ module page · 73 lines · 4113 B

1// nx_commons_sybilcost.nx -- what does an attack actually COST? The sybil bound, measured. 2// 3// WHY THIS EXISTS: every layer built today claims sybil resistance, and a claim is not a bound. 4// "The ring collapses because it cannot manufacture witnesses" is an ASSERTION until someone states 5// the quantity an attacker must spend and shows it does not shrink as the attack grows. 6// ★ SYBIL-RESISTANT IS NOT A PROPERTY, IT IS A PRICE. Name the price or you have said nothing. 7// 8// KNOWN GOOD: the trust-flow bound (Advogato's metric; SybilGuard / SybilLimit). Its theorem is the 9// one useful result in this area and it is counter-intuitive enough to be worth stating plainly: 10// an attacker's total influence is bounded by the number of ATTACK EDGES -- honest members who 11// vouch for a sybil -- and is INDEPENDENT of how many sybils the attacker creates. 12// Minting identities is free; being vouched for by someone honest is not. So the cost scales with 13// the only thing the attacker cannot manufacture: other people's genuine regard. 14// 15// NOTE ON SCOPE, because it is the honest half: there is no in-estate known good for proof-of- 16// personhood, and I looked -- nx_realperson is CONTENT SAFETY about real people (NCII, defamation, 17// right of publicity), not "is this account a human". I inferred otherwise from its NAME and was 18// wrong. Nor is there a good global answer: biometric uniqueness centralises and builds a honeypot, 19// government ID excludes the undocumented and is best-held by exactly the class we are excluding. 20// ★ BUT FOR A BOUNDED NEIGHBOUR COMMONS, PERSONHOOD IS THE EASY CASE, NOT THE HARD ONE -- neighbours 21// physically know each other, and the witness layer already built IS the mechanism. This organ does 22// not add a new check; it PRICES the one we have. 23// 24// Integer only. license_tier: ORIGINAL No hw writes (Rule 26). 25import "nx_syscalls.nx" 26 27const SC_PERMIL: i64 = 1000 28 29// ---- THE NAIVE RULE (negative control): standing counts vouches, whoever they come from --------- 30// This is what almost every reputation system does, and it is why almost every reputation system is 31// farmable: the attacker's return scales with identities minted, which cost nothing. 32func sc_standing_naive(n_sybils: i64, vouches_each: i64, unit: i64) -> i64 { 33 if n_sybils <= 0 { return 0 } 34 if vouches_each <= 0 { return 0 } 35 return n_sybils * vouches_each * unit 36} 37 38// ---- THE FLOW-BOUNDED RULE --------------------------------------------------------------------- 39// Standing entering the sybil region cannot exceed the total capacity of the edges CROSSING INTO it 40// from the honest region. Internal edges carry nothing across a cut they do not cross, so a ring 41// trading with itself moves exactly zero standing inward however dense it is. 42// caps[i] = capacity of attack edge i (the vouching honest member's own bounded capacity). 43func sc_standing_flowbound(caps: *i64, n_attack: i64) -> i64 { 44 if n_attack <= 0 { return 0 } 45 var total: i64 = 0 46 var i: i64 = 0 47 while i < n_attack { 48 if caps[i] > 0 { total = total + caps[i] } 49 i = i + 1 50 } 51 return total 52} 53 54// Per-identity share: the same fixed inflow divided among however many sybils exist. Minting more 55// identities DILUTES the attacker rather than multiplying it -- the property worth having. 56func sc_per_sybil(caps: *i64, n_attack: i64, n_sybils: i64) -> i64 { 57 if n_sybils <= 0 { return 0 } 58 return sc_standing_flowbound(caps, n_attack) / n_sybils 59} 60 61// The price: attack edges required per unit of standing obtained, in permil. Higher is safer. 62// An attacker must corrupt or earn this many honest vouches for each unit of standing it gains. 63func sc_cost_permil(n_attack: i64, standing: i64) -> i64 { 64 if standing <= 0 { return 0 } 65 return (n_attack * SC_PERMIL) / standing 66} 67 68// Does the honest region lose anything when the attack grows? It must not: a defence that degrades 69// honest members in order to bound an attacker has simply moved the damage. 70func sc_honest_unchanged(before: i64, after: i64) -> i64 { 71 if before == after { return 1 } 72 return 0 73}