aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-09 15:24:00 +0000
committertv <tv@krebsco.de>2026-11-09 18:12:24 +0100
commitdfea49e0871b78d2b6856eec80c5cd5a7f501dff (patch)
treeeaddc72605305588b92750da1d1769fa48cd4275
parentacef27d042b2b9f7fa1974de0759a1c517cbb942 (diff)
signatures: up to 4096 in a message, each actor's latest past them
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.
-rw-r--r--src/document/signatures.rs7
-rw-r--r--src/transport/mod.rs6
-rw-r--r--src/transport/wire.rs2
3 files changed, 9 insertions, 6 deletions
diff --git a/src/document/signatures.rs b/src/document/signatures.rs
index a8b4713..da2df03 100644
--- a/src/document/signatures.rs
+++ b/src/document/signatures.rs
@@ -147,8 +147,11 @@ impl<'de> serde::Deserialize<'de> for SignEvery {
}
}
-/// Signatures a sync message carries at most (`for_changes`, `latest_each`).
-pub(crate) const MAX_PER_MESSAGE: usize = 256;
+/// Signatures a sync message carries at most (`for_changes`, `latest_each`), as many
+/// as wait for their changes (`MAX_PENDING`): 384 KiB of them. A whole document pulled,
+/// or a delta, carries each actor's latest, and an actor is a node's run: an epoch with
+/// more runs writing than this leaves some unvouched for in such a transfer.
+pub(crate) const MAX_PER_MESSAGE: usize = MAX_PENDING;
/// A signature as messages and the document file carry it (`pack`): the change's
/// hash (32 bytes), then the signature (64).
pub(crate) const PACKED: usize = 32 + 64;
diff --git a/src/transport/mod.rs b/src/transport/mod.rs
index e2135d1..cbb6734 100644
--- a/src/transport/mod.rs
+++ b/src/transport/mod.rs
@@ -733,9 +733,9 @@ pub(crate) struct SyncEnvelope {
/// When the sender generated it, by its clock: the receiver takes how long it took
/// to come (`swarm::hop`).
pub(crate) sent: crate::clock::UnixMillis,
- /// Signatures of changes (`document::signatures`): each actor's latest the sender
- /// verified that it didn't send this peer yet, `signatures::MAX_PER_MESSAGE` at
- /// most, as `signatures::pack` packs them.
+ /// Signatures of changes (`document::signatures`): of the changes the message
+ /// carries, or each actor's latest for a delta or past `signatures::MAX_PER_MESSAGE`
+ /// (`Signatures::for_changes`, `latest_each`), as `signatures::pack` packs them.
pub(crate) signatures: serde_bytes::ByteBuf,
}
diff --git a/src/transport/wire.rs b/src/transport/wire.rs
index 450ecb0..6784f8e 100644
--- a/src/transport/wire.rs
+++ b/src/transport/wire.rs
@@ -14,7 +14,7 @@ use super::{EncodedMessage, MessageKind, ParsedMessage};
/// The wire format's version, the first byte of every payload. Bump it with every change
/// to a message type or a codec (`golden_bytes` fails then).
-pub(crate) const VERSION: u8 = 46;
+pub(crate) const VERSION: u8 = 47;
/// What the second byte of a payload says.
fn tag(kind: MessageKind) -> u8 {