aboutsummaryrefslogtreecommitdiffstats
path: root/src/document/signatures.rs
Commit message (Collapse)AuthorAgeFilesLines
* signatures: a transfer carries one signature per writer in ittv38 hours1-40/+97
| | | | | | | | | | | | | | | | | | | | | | Under a policy requiring signatures, a node takes a change only once a signature vouches for it: one of the change itself, or of a later change of the same writer. A writer is a node's run, each start, rejoin or drop making a fresh actor, so an epoch gathers writers for as long as it lasts, and a transfer of its whole history (a joiner pulling the document, a delta) must carry a signature for each of them, or the joiner waits for the rest for good. A message's signatures are now chosen by what it carries: * changes, up to 256 signed among them: each one's signature; * more (a whole document pulled): each writer's latest signed change among them, found by the document's change metadata (`Signatures::for_changes`), vouching for the rest; * a delta: each writer with changes in it (`get_changes_meta(from)`), its latest verified signature (`for_delta`). A message carries up to 65536 (6 MiB), and as many wait at the receiver for their changes (a delta's come after it). So a transfer leaves writers unvouched only in an epoch with more than 65536 runs writing since it began; a remake starts the count again. Wire version 48.
* signatures: a listed signed path takes `*`, as everything else doestv39 hours1-3/+16
| | | | | | | | | | Review 4, appendix: whether a write is signed because `_continuum/access/signed` lists its path compared the listed paths by prefix (`signatures::related`), so a `*` there was a literal key, while api.md says the list holds paths as capabilities name them, which take `*` since 1259, and signed values already read the same list as patterns (`envelope::reaches_signed`). A listed `metrics/*/alerts` signed nothing. It compares by `access::agree` now: within or above the pattern, `*` for any one key.
* signatures: up to 4096 in a message, each actor's latest past themtv39 hours1-2/+5
| | | | | | | | | | | | | | | | Review 4, F5: a delta, and a message whose changes held more than 256 signatures (a whole document pulled, of any real history), carried each actor's latest signature, the 256 that became latest last. An actor is a node's run, so past 256 runs writing in an epoch, some actors' changes arrived unvouched at the puller under a policy requiring signatures, waited, and every resend carried the same 256: a joiner never finished. A message now carries up to 4096 signatures (`MAX_PER_MESSAGE`, as many as wait for their changes, `MAX_PENDING`: 384 KiB at most), all of its changes' up to there, each actor's latest past it and for a delta, and a receiver takes as many (wire version 47). An epoch with more than 4096 runs writing would still leave some unvouched in such a transfer, which the constant says; sending each actor of the transfer its own latest would need the actors of a delta's changes, which only rebuilding their metadata gives.
* signatures: the latest unsigned change of each own actor signed, at start ↵tv39 hours1-36/+46
| | | | | | | | | | | | | | | | | | | | | and after a swap Review 4, F2 (the honest case) and claim 2: a node signed at start its own changes at the heads that nothing vouched for (1216), and after a swap only its current actor's latest. An own change left unsigned can sit below the heads: a drop (`drop_taken`) takes away a signed change and keeps an earlier unsigned one, and the node writes on under a fresh actor, building on it; or a node's change is built on by another's concurrently with the signed one the drop took. Nothing signed it again, and under a policy requiring signatures every node pulling it (a joiner) waited for good, and for everything built on it. Now the latest change of each of the node's actors (`RemakeState::own_actors`, the current one among them) that no signature vouches for is signed (`Signatures::sign_own_actors`), at start and whenever the document is swapped (a drop, a switch, a rejoin), the old `sign_own_heads` and `sign_own_latest` going. One signature per actor vouches for all its changes before it. The case of a member whose signed change the rules refuse, vouching once for its earlier ones, is postponed (future-work.md, next).
* sync: a message carries the signatures of its changestv2 days1-22/+39
| | | | | | | | | | | | | | | A sync message carried the signatures its peer wasn't sent yet, by a cursor per peer. Changes sent again, as after a message taken as delivered and lost on the way, went without them: the peer was past them. Under a policy requiring signatures they waited until the writer's next signed change, or the next session. A message now carries the signatures of the changes it carries (Signatures::for_changes), whatever the peer was sent before: changes sent again arrive vouched for as the first time. Past 256 (a message carrying the batches of many writers), each writer's latest instead, as a delta carries. The cursor goes, and with it resetting it after a failed send or a new session.
* signatures: sign what is senttv2 days1-40/+24
| | | | | | | | | | | | | | | | | | | A node signed its changes no rule signs a while after them (--sign-every 1s): the change left at once, unsigned, and its signature followed on its own a second later, to every neighbour, over every link. A few writes made a cascade of SIGNATURES. Under a policy requiring signatures it signed every change as it was made instead. A node now signs its latest change, if no signature vouches for it, as a sync message takes it (--sign-every sent, the default): the signature leaves in the same message, and goes where the change goes. One signature per message, however many changes it carries, each vouching for those before it: a slow writer's every change is signed, a fast writer's batches are, at no threshold to pick. A policy requiring signatures signs what is sent too, even with `none`. `all` still signs every change as it is made; changes to protocol data, listed paths and ?signed=true writes are signed as they are made, as before. The interval, and the task signing on it, go.
* signatures: a node signs at start what it kept unsigned when it stoppedtv2 days1-0/+49
| | | | | | | | | | | | | | A node commits a change, keeps it in its document file, and may stop before any signature vouches for it. It starts again under a new actor and only ever signed its current actor's latest change: the old one stays unsigned for good. Peers pulling it then wait for a signature under a policy requiring them, and so does everything the node writes after, building on it. Signing every change at commit hid this under such a policy; signing what is sent, next, won't. At start, before anything leaves, a node signs each of its own changes at the document's heads that no signature vouches for: nothing it made since builds on them, so they are heads.
* signatures: tell held changes as the screen doestv2 days1-4/+4
| | | | | | | | | | With every message's signatures offered now (1205), Signatures::offer runs for each, and it asked get_change_meta_by_hash whether the document holds each signature's change, and each one waiting, up to 4096 of them: Automerge rebuilds the change's metadata from the document's operations to answer. Ask changes::holds instead (1197), there and in forks and kept_for; the metadata is still read where it is used.
* screen, signatures: the oldest waiting go, not the newesttv3 days1-6/+59
| | | | | | | | | | | | | | Review finding 9: once 4096 signatures waited for their changes, new ones were dropped, and the waiting changes were cut at 10 000 keeping the oldest. A member could send junk once (signatures of changes that never come, changes no signature will vouch for) and fill both for good. Every honest signature arriving before its change was then lost, so under signatures required its changes waited for the actor's next signature: a stall for quiet actors. Both now keep the newest: the oldest go. A share per sender, so a member sending junk without pause can't push out what others sent either, is in future-work.md.
* state: a document swap keeps the signatures of the changes it keepstv3 days1-0/+22
| | | | | | | | | | | | | Review 2.2: swap_document forgot every signature. After dropping changes taken unjudged (or a rejoin into the same epoch), the node could vouch for none of the changes it kept: under signatures required, those building on an actor waited for that actor's next signature, and for an actor that stopped writing, forever. Signatures::kept_for keeps the signatures of the changes the new document holds, checks each actor's latest again, and keeps those waiting for their changes. This node's replayed changes are signed at once, as before.
* screen: a signature vouches for its change and what it builds ontv3 days1-2/+21
| | | | | | | | | | | | | | | Review finding 5: vouching by (actor, seq) isn't bound to a hash. A member can make a change under another member's actor at a seq that member's signature covers. The change is then taken as vouched, and if it breaks a rule, the honest member is refused as a whole and logged as the one whose own change broke the rules. A signature now vouches for its change and the changes of its actor it builds on: in the document, as before; among received changes, those it reaches through the batch's dependencies. A received change under an actor at a seq whose change the document holds (a signature verified up to it) is a fork: refused as forged, never as its actor's node's, not told back in REFUSALS, and logged with the peer that brought it.
* access: strict policy, signed pathstv3 days1-1/+1
| | | | | | | | | "values": "signed" (strict, requiring signatures too): the registry, _continuum/access, bans and the paths in _continuum/access/userSigned (* for any key) hold values their users signed. Envelopes read as the values they hold where the node reads protocol data. Auth plan M7.
* access: signatures requiredtv3 days1-0/+48
| | | | | | | | "signatures": "required": a change counts only once a signature by its committer vouches for it, and waits until then; every node then signs every change it makes. Auth plan M6.
* access: rules by pathtv3 days1-2/+2
| | | | | | | | | | access::rules::judge: a change judged as its writer saw the document (at its dependencies): committer a member or registering itself; members' entries and votes their own; epochs and swarm ID from roots; a remake's decision by its coordinator; the rest by the registry for the user the change names. Auth plan M6.
* signatures: verified changestv3 days1-1/+0
| | | | | | | GET /admin/changes shows whether a signature by its node vouches for each change. Auth plan M5.
* signatures: with sync messagestv3 days1-17/+242
| | | | | | | Sync messages carry, for each actor's writes, the latest signature the sender checked; the receiver checks it once it holds the change. Auth plan M5.
* signatures: kept in the document filetv3 days1-1/+36
| | | | | | | A node's signatures are saved with its document (--document-file) and loaded with it. Auth plan M5.
* signatures: --sign-everytv3 days1-2/+140
| | | | | | | | Changes left unsigned are vouched for by the node's next signature: --sign-every 1s (default) signs the latest within a second, all signs every change, none only those that must be. Auth plan M5.
* signatures: changes signed by their nodetv3 days1-0/+184
Every node signs the changes it commits with its node key, an Ed25519 signature over the change's hash, kept beside the document. One signature on an actor's latest change vouches for its earlier ones. Protocol data and paths listed in _continuum/access/signed are signed, and writes with ?signed=true. Auth plan M5.