From 24527adf52ca2d8d3b927feb1b811e10fc55fc5c Mon Sep 17 00:00:00 2001 From: tv Date: Sun, 8 Nov 2026 22:43:19 +0000 Subject: signatures: sign what is sent 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. --- src/swarm/sync.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/swarm/sync.rs') diff --git a/src/swarm/sync.rs b/src/swarm/sync.rs index e76f5f9..0c49fa3 100644 --- a/src/swarm/sync.rs +++ b/src/swarm/sync.rs @@ -167,9 +167,12 @@ async fn deliver_sync_to_peer(state: &AppState, peer: &str) -> Result<()> { let stats = Arc::clone(&state.stats); let clock = Arc::clone(&state.clock); + let signer = state.clone(); // The session the message comes from, for its send's outcome. let (session, generated) = tokio::task::spawn_blocking( move || -> (u64, Result>) { + // This node's latest change, if this message may take it, leaves signed. + signer.sign_sent(&doc); // Label the message with the epoch of the document it was generated // from, read under the same lock. let (session, epoch, epoch_seq, body, writer, delivered, signatures) = { -- cgit v1.3.1