diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/federation.md | 82 |
1 files changed, 46 insertions, 36 deletions
diff --git a/docs/federation.md b/docs/federation.md index 5f86028..76848b9 100644 --- a/docs/federation.md +++ b/docs/federation.md @@ -20,7 +20,8 @@ holds under that policy, and nothing else changes: messages. * The code is apart where it would cost. Judging reads the policy as it does today and takes the federated rules under the federated one only; the resolved registry is - kept there only; envelopes carry their new fields there only; no message changes. + kept there only; envelopes carry their new fields there only; no message changes + for a swarm that isn't federated. * Shown at every stage by the existing tests passing untouched, and by the cost of judging a change (`bench_screening`) staying where it is for a swarm without a policy and with today's. @@ -168,8 +169,8 @@ root user, its keys and its nodes: * Every node is given a root and takes no other: the genesis root (`--genesis-root`), or, in a swarm that was remade, the ID of a later epoch. The root is what a party trusts, not what its seeds say. -* A node that doesn't know the policy's version doesn't sync at all. (Today it - receives without judging *(docs)*, which here would let anything in.) +* A node that doesn't know the policy doesn't sync at all. (Today it receives + without judging *(docs)*, which here would let anything in.) The policy changes by a decision: each number by itself, the rest as a whole (The policy changes by a decision). @@ -380,7 +381,7 @@ A user's namespace is the top-level key with its name. One rule: below `<name>`, envelopes signed by a user of that name, at the depths `userSigned` lists (for the registry, `["*", "hosts", "*"]`: a host is one signed value). A value there is replaced as today, by an envelope naming the one it replaces (`prev`). Nothing plain -is written anywhere but a node's own member entry. +is written anywhere but a node's own member entry and its own records of proposals. Delegating (another user writing below `<name>/shared`, say) would be a statement in the user's register granting a capability within its namespace: for later; the rule @@ -548,17 +549,19 @@ days. **Who votes.** The **voters** are the users the epoch's root change names. A swarm's first names the root alone. A remake names those of the next epoch: its proposal -says who, all users that count at its base (recommended), or those of a list. So -who votes is decided by those who vote, with each remake; a user brought in since -votes once a remake names it; and until the first remake the root decides alone. +says who, all users (recommended) or those of a list. All users are those there +when the remake is proposed: the users that count in the proposal's history, and +still do at the base. So who votes is decided by those who vote, with each remake; +a user brought in later, while the votes run too, votes once a remake names it; and +until the first remake the root decides alone. What to weigh in it. Every voter named counts toward what a decision takes: one that never votes stands in the way like one voting against, until it is absent, and toward the half of all even then. A swarm of many users of whom few take part gets little decided with all of them named. And all users is whoever brought users in: a -user that created sixteen has seventeen votes in the next epoch. The voters see the -list a remake would give before they vote for it (`GET /registry/decisions`), and -name one of their own where they don't like it. +user that created sixteen has seventeen votes in the next epoch. The list is fixed +with the proposal, so the voters see it before they vote for it +(`GET /registry/decisions`), and name one of their own where they don't like it. A change in who votes takes a remake because a remake is what puts the votes of before out of reach (below). @@ -683,16 +686,17 @@ user's, whenever it shows up: a user it creates then is below it like any user's So a root that disappears is replaced by two thirds of the voters present, and so is one that turns on them. (Before the first remake there is nobody to do it: a swarm -remakes once its root brought the first users in.) A root that comes back finds -itself a user like the others; it may be voted in again. While the seat's holder is away +remakes once its root brought the first users in.) A root that comes back finds itself +a user like the others; it may be voted in again. While the seat's holder is away nothing new is settled: claims count, and can be contested, until there is a root again. ### Remakes A federated swarm compacts by a remake its voters decide. A remake throws history -away, and does nothing else: what the next epoch holds isn't voted on. It is the -registry as it resolves, which every node works out itself. +away and names who votes next, and does nothing else: what the next epoch holds +isn't voted on. It is the registry as it resolves, which every node works out +itself. * **The base.** A remake is proposed and voted on like anything else; its proposal names who votes in the next epoch. Its **coordinator** is a node of the proposer, @@ -709,13 +713,12 @@ registry as it resolves, which every node works out itself. * **Every node builds the snapshot** itself once the remake is decided, from the base as it holds it, and switches after the switch delay, as today. The snapshot holds the registry as it resolves at the base: the policy that holds, with its numbers; - who the root is, and who votes (as the proposal says); the - users that count, with their names (or that they are contested), IDs, keys, nodes, - creators, vouchers and the vouches they accepted; the names held or contested, - each marked settled or not; + who the root is, and who votes (as the proposal says); the users that count, with + their names (or that they are contested), IDs, keys, nodes, creators, vouchers and + the vouches they accepted; the names held or contested, each marked settled or not; the values in the namespaces that count, as the envelopes they are; the bans that - stand; the members' entries, as today. A user that is out and not gone is in it - with all it has, and with how long it has been seen out, which counts on. + stand; the members' entries, as today. A user that is out and not gone is in it with + all it has, and with how long it has been seen out, which counts on. * **What it leaves out**: all history, and with it everything that is over. A claim released, and its release. A key retired, a node stopped, an unvouch, each with its cut: what they left out is out for good. A user gone. A proposal, its votes and @@ -787,8 +790,8 @@ Either way, what follows: out, its names waiting. Or gone, and so not in the snapshot: then no node takes the node's changes, it shows why, and its user comes in again as anyone does. * **As a voter** the user was absent, and is one in the epoch it arrives in if that - names it. A root that was away is still the root, unless a decision - gave the seat to another. + names it. A root that was away is still the root, unless a decision gave the seat to + another. * **Its old document** goes to the archive, as today. A node moves to an older epoch, or to another of the same age, only by its operator's @@ -837,8 +840,9 @@ left, with two thirds of them turned against the rest, or for a policy the other won't have. A fork is proposed, and binds nobody: * Any user proposes it: the policy to go on with (the one that holds, or another), - and, if it likes, who votes there. Where it names none, all users at the base - vote. Voters may vote for it: that shows who would go, and decides nothing. + and, if it likes, who votes there. Where it names none, all users vote that there + are when it is proposed. Voters may vote for it: that shows who would go, and + decides nothing. * The proposer's node names the base, as a remake's coordinator does, when its user says so, votes or none. * A node follows if its operator says so (`POST /admin/fork`, naming the proposal and @@ -871,12 +875,11 @@ What refusing does: * **Before.** While a proposal's votes run, a node whose bounds it breaks says so in its member entry, so the voters see who would go (`GET /registry/decisions`). -* **The epoch without it.** A node that refuses a decision moves to the epoch built - at the history of the proposal: the registry as it resolves there, the policy and - the voters as they are there, and the digest of the proposal refused, which makes - it no other epoch. Every node that refuses the same decision builds - the same epoch, whenever it does. So those who think alike meet there without - arranging it. +* **The epoch without it.** A node that refuses a decision moves to the epoch built at + the history of the proposal: the registry as it resolves there, the policy and the + voters as they are there, and the digest of the proposal refused, which makes it no + other epoch. Every node that refuses the same decision builds the same epoch, + whenever it does. So those who think alike meet there without arranging it. * **After**, as after any fork: the same swarm ID and the same history up to the base, different epochs, no syncing between them. A node carries its user's own statements over. On each side the voters who went the other way are absent after @@ -1022,7 +1025,8 @@ it. That happens by three things, and each shows: with the change and why), the dashboard, `sync.refusedPeers` *(docs)*. * **The two sides judge differently**: versions that differ, a bug in a rule. Each refuses what the other takes; a node told so judges what it holds again and logs - that the policies disagree *(docs)*. + that the policies disagree *(docs)*. Where they only resolve differently, their + stamps show it (Continuum changing under a swarm). * **An actor forked.** A node committed two changes under one actor and number and gave each to some. Automerge holds one change per actor and number, so a node holding one can't take the other, nor anything built on it *(checked)*. Both carry @@ -1041,9 +1045,8 @@ that is gone, or a cut naming a change that was dropped. Which side drops, for a fork of an actor? No rule can say: the forking node may have ground the hash of the change it kept back, and a rule by hash would let it make everyone drop a year's work. A node shows which of the two the users on its lines -hold, up to the root, and the operator follows them or doesn't. A -node that just joined and got the lone change from the forking node drops and loses -nothing. +hold, up to the root, and the operator follows them or doesn't. A node that just +joined and got the lone change from the forking node drops and loses nothing. A side that doesn't want to come back stays as it is: the same swarm ID, another history. @@ -1334,7 +1337,8 @@ root, syncs under no policy it doesn't know, takes tokens from its party only, w no sessions into the document, keeps its seeds and its user's other nodes as neighbours, answers for an epoch it left while it keeps it, takes no remake but one its voters decided, rejoins no epoch because peers advertise it, and refuses what its -bounds say. No message changes. [`trust.md`](trust.md), [`access.md`](access.md), +bounds say. On the wire: a handshake says which epochs its node keeps, and a version +speaks the one before its own too. [`trust.md`](trust.md), [`access.md`](access.md), [`remakes.md`](remakes.md) and the glossary get the federated case: party, statement, line, voter, claim, cut, late, contested, settled, out, gone, uncovered, seen for, taking a proposal up, a decision that holds, bounds, and a ban of a user beside a ban @@ -1474,7 +1478,7 @@ Decisions, the root, remakes: | # | The adversary | Honest nodes | Promise | Shown by | |---|---|---|---|---| | 42 | Forges a vote; votes as a user that isn't a voter, or one absent | Refuse | 7 | unit, decisions: `a_vote_is_a_voters` | -| 43 | Brings in many users to vote | They vote only if a remake names them, which those who vote decide, seeing the list | 7 | unit: `who_votes` | +| 43 | Brings in many users to vote, also while a remake's votes run | They vote only if a remake names them: by a list, or as all there were when it was proposed, which those who vote saw | 7 | unit: `who_votes`, `all_users_as_proposed` | | 44 | A remake that says all users, after one user brought in many | They vote in the next epoch: all users is whoever brought users in. The voters see the list before they vote, and name one of their own instead | not promised | unit: `voters_are_the_remakes` | | 45 | Records taking a proposal up without the votes, or with released ones | Its record is its own: honest nodes record what they hold, and it takes two thirds | 7 | unit: `taken_up_with_the_votes` | | 46 | Keeps votes back until they ran out, or crafts them with old dependencies, then shows them | No honest node takes the proposal up: it isn't decided. One decided by its makers' own records, long after (two thirds of their keys stolen), is held back by every node that was up, and shown | 7 | unit: `taken_up_while_the_votes_run`; sim: `a_decision_from_the_past` | @@ -1681,3 +1685,9 @@ Assumed, to be shown as it is built: * The snapshot of a federated remake, built from the resolved registry, comes out byte for byte the same on every node, as today's does from the document. * A node can answer sync for an epoch it left, from its archive. +* What was seen for long is kept as the node goes, per voter and per thing watched (a + voter silent, a user out, a thing uncovered), and costs little. +* The digest of the snapshot a node would build is cheap enough to make with every + stamp at a registry's size, and to make again at another node's stamp where both + hold the same changes. +* A version can speak the wire version before its own. |
