aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/sync.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-09 17:32:08 +0000
committertv <tv@krebsco.de>2026-11-09 18:55:41 +0100
commitb83bd5bdd9548b0e7ca7b1c9068dd47cdb5246d9 (patch)
treef0070c32d141440986cc0a633d4674968dbcd125 /src/swarm/sync.rs
parent4a147c90bfa23d3867f7cc2e15a84ab477f72f1b (diff)
signatures: a transfer carries one signature per writer in it
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.
Diffstat (limited to 'src/swarm/sync.rs')
-rw-r--r--src/swarm/sync.rs12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/swarm/sync.rs b/src/swarm/sync.rs
index e3f6055..3a3d92c 100644
--- a/src/swarm/sync.rs
+++ b/src/swarm/sync.rs
@@ -300,11 +300,15 @@ async fn deliver_sync_to_peer(state: &AppState, peer: &str) -> Result<()> {
// With changes, the signatures of those it carries: they go where
// changes go, along the trees, so a peer that got these changes
// elsewhere got the signatures with them; and changes sent again go
- // vouched for as the first time. A delta, of any writer's changes,
- // each writer's latest. A message carrying no changes takes none.
+ // vouched for as the first time. A delta, of each writer with changes
+ // in it, its latest. A message carrying no changes takes none.
let signatures = match &body {
- Some(transport::SyncBody::Delta(_)) => replica.signatures.latest_each(),
- Some(_) => replica.signatures.for_changes(peer_state.sync.carried()),
+ Some(transport::SyncBody::Delta(spec)) => {
+ replica.signatures.for_delta(&replica.doc, &spec.from)
+ }
+ Some(_) => replica
+ .signatures
+ .for_changes(&replica.doc, peer_state.sync.carried()),
None => Vec::new(),
};
let signatures = crate::document::signatures::pack(&signatures);