@@ -145,6 +145,7 @@ <h2 id="sotd">Status of This Document<a class="self" href="#sotd">§</a></h2>
145145< li > < a href ="#http "> < span class ="n "> 10</ span > HTTP API</ a > </ li >
146146< li > < a href ="#security "> < span class ="n "> 11</ span > Security considerations</ a > </ li >
147147< li > < a href ="#privacy "> < span class ="n "> 12</ span > Privacy considerations</ a > </ li >
148+ < li > < a href ="#federation "> < span class ="n "> 13</ span > Federation (draft)</ a > </ li >
148149< li > < a href ="#vectors "> < span class ="n "> A</ span > Test vectors</ a > </ li >
149150< li > < a href ="#references "> < span class ="n "> B</ span > References</ a > </ li >
150151</ ol > </ nav >
@@ -563,6 +564,59 @@ <h2 id="privacy"><span class="secno">12.</span>Privacy considerations<a class="s
563564expose the full graph publicly. Usernames are public by construction (they are URIs); agents who
564565need unlinkability < span class ="rfc "> should</ span > use pseudonymous names or DIDs.</ p >
565566
567+ < h2 id ="federation "> < span class ="secno "> 13.</ span > Federation
568+ < span class ="pill " style ="vertical-align:middle;margin-left:8px "> Draft</ span > < a class ="self " href ="#federation "> §</ a > </ h2 >
569+ < h3 id ="fed-model "> < span class ="secno "> 13.1</ span > Model — sovereign nodes, global agents< a class ="self " href ="#fed-model "> §</ a > </ h3 >
570+ < p > Nodes are sovereign: each holds its own ledger and answers for its own history. Agents are
571+ global: an identity is a URI or DID, so the same agent can hold trustlines on many nodes at once.
572+ A trustline (and its balance) lives on exactly < em > one</ em > node — the node both parties accepted
573+ when the line was created. There is no global state and no consensus between nodes; there are only
574+ per-node ledgers whose entries are signed by their actors (§ 9) and anchored histories that
575+ make lying provable (§ 13.3).</ p >
576+ < h3 id ="fed-gateway "> < span class ="secno "> 13.2</ span > The gateway pattern (implemented)< a class ="self " href ="#fed-gateway "> §</ a > </ h3 >
577+ < p > Cross-node value transfer composes from per-node payments through a < dfn > gateway</ dfn > — an
578+ agent with credit relationships on both nodes. For alice@A → carol@B via gateway G:</ p >
579+ < ol class ="algo ">
580+ < li > G holds (or creates, with one signed transition to each node) trust relationships:
581+ G→alice on A, carol→G on B.</ li >
582+ < li > alice pays G on node A — consuming credit G already granted.</ li >
583+ < li > G pays carol on node B — consuming credit carol already granted.</ li >
584+ </ ol >
585+ < p > Net: value crossed nodes; G's books balance across them (+x owed to it on A, −x owed by it on
586+ B). The gateway's signatures are the < em > only</ em > coordination — no node-to-node protocol is
587+ required, which is why this level ships already (the repository's
588+ < code > tools/xnode-demo.js</ code > runs it against two live nodes). The honest caveat: steps 2 and 3
589+ are < em > not atomic</ em > ; between them the gateway bears the risk, which is precisely a gateway's
590+ business (and Fugger's original inter-server design assumption).</ p >
591+ < h3 id ="fed-atomic "> < span class ="secno "> 13.3</ span > Toward atomic routes (level 2, unimplemented)< a class ="self " href ="#fed-atomic "> §</ a > </ h3 >
592+ < p > Removing the gateway's window of risk needs conditional transitions: a
593+ < code > hold</ code > reserving capacity on each leg with a TTL, released by a < code > commit</ code >
594+ carrying a hashlock preimage (HTLC-shaped), else unwound at expiry. Known dragon, named here so it
595+ is not rediscovered: holds lock capacity, so hold-griefing and liquidity-lockup are real costs —
596+ the reason Interledger moved to packetized amounts. Level 2 will specify hold/commit transitions
597+ as two further signed event kinds; nothing in the level-1 data model changes.</ p >
598+ < h3 id ="fed-anchor "> < span class ="secno "> 13.4</ span > Settlement assurance — anchoring (implemented)< a class ="self " href ="#fed-anchor "> §</ a > </ h3 >
599+ < p > Because state is a pure function of the log (§ 8.2), the only lie available to a node is
600+ presenting < em > different histories to different parties</ em > . Anchoring makes that refutable. The
601+ interface is deliberately pluggable:</ p >
602+ < pre > < code > anchor(state) → proof < span class ="c "> // commit to a state externally</ span >
603+ verify(proof) → attested time < span class ="c "> // check a commitment</ span >
604+ resolve(histA, histB) → … < span class ="c "> // which history was committed to, when</ span > </ code > </ pre >
605+ < p > The first backend is < strong > Blocktrails</ strong > [< a href ="#ref-blocktrails "> BLOCKTRAILS</ a > ]
606+ (implemented; < code > tools/anchor.js</ code > ): the anchored state is the string
607+ < code > {"node":"<origin>","seq":n,"tip":"sha256:…"}</ code > (literal key order); each anchor
608+ tweaks the trail key by the state hash (chained BIP-341 TapTweak) yielding a fresh P2TR address,
609+ and the mark transaction pays the trail's balance forward to it. The chain of spends < em > is</ em >
610+ the anchor history — ordered and timestamped by Bitcoin. One trail < span class ="rfc "> may</ span >
611+ carry many nodes' tips (a < dfn > federation trail</ dfn > ); the state names the node. A node
612+ < span class ="rfc "> must not</ span > anchor a tip whose own audit fails. Anchors are served read-only
613+ at < code > GET /api/anchors</ code > . Dispute rule: a history whose (seq, tip) was anchored at
614+ Bitcoin-attested time T refutes any competing history presented later that diverges before T —
615+ the node is caught by its own commitment.</ p >
616+ < div class ="note "> < span class ="lbl "> Note</ span > < p > This is not consensus, on purpose. The network
617+ keeps no global state to agree on; anchoring makes each node's < em > own</ em > statements
618+ progressively harder to retract. Trust stays bilateral; evidence becomes public.</ p > </ div >
619+
566620< h2 id ="vectors "> < span class ="secno "> A.</ span > Test vectors< a class ="self " href ="#vectors "> §</ a > </ h2 >
567621< p > An implementation is expected to reproduce these values exactly. Agents:
568622< code > A = https://n.example/u/alice#me</ code > , < code > B = …/u/bob#me</ code > ,
@@ -637,8 +691,9 @@ <h3>B.2 Informative</h3>
637691HTTP Auth</ a > </ li >
638692< li > [TRUSTLINE-V1] — < a href ="https://github.com/webcontracts/webcontracts.github.io/issues/4 "> trustline.v1
639693profile — Ryan Fugger's original Ripple as a web contract</ a > </ li >
640- < li > [BLOCKTRAILS] — < a href ="https://blocktrails.org "> Blocktrails: Bitcoin-anchored history</ a >
641- < em > (anchoring, level 3)</ em > </ li >
694+ < li id ="ref-blocktrails "> [BLOCKTRAILS] — < a href ="https://blocktrails.org "> Blocktrails: Bitcoin-anchored
695+ history</ a > — reference implementation < a href ="https://www.npmjs.com/package/blocktrails "> npm
696+ < code > blocktrails</ code > </ a > </ li >
642697</ ul >
643698
644699< footer >
0 commit comments