aboutsummaryrefslogtreecommitdiffstats
path: root/src/document
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-08 13:49:26 +0000
committertv <tv@krebsco.de>2026-11-08 15:03:58 +0100
commitb3526df29412400cfaa8c3a8d8692e37fc44d19b (patch)
treee4f1d60170d2c78d58b33072b7a23a9ce1ad00c4 /src/document
parent40907ae285317eaaf6449ff17d40b58a1a5df665 (diff)
state: a document swap keeps the signatures of the changes it keeps
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.
Diffstat (limited to 'src/document')
-rw-r--r--src/document/signatures.rs22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/document/signatures.rs b/src/document/signatures.rs
index 19c13b8..919e7b7 100644
--- a/src/document/signatures.rs
+++ b/src/document/signatures.rs
@@ -250,6 +250,22 @@ impl Signatures {
signatures
}
+ /// These for `doc`, replacing the document they are of (one without some of its
+ /// changes, or another of its epoch): those of the changes it holds, each actor's
+ /// latest checked again (`from_kept`); those waiting for their changes still wait.
+ pub(crate) fn kept_for(&self, doc: &Document) -> Self {
+ let kept = self
+ .order
+ .iter()
+ .filter(|hash| doc.get_change_meta_by_hash(hash).is_some())
+ .map(|hash| (*hash, self.by_change[hash]))
+ .collect();
+ Self {
+ pending: self.pending.clone(),
+ ..Self::from_kept(doc, kept)
+ }
+ }
+
pub(crate) fn insert(&mut self, hash: ChangeHash, signature: [u8; 64]) {
if self.by_change.insert(hash, signature).is_none() {
self.order.push(hash);
@@ -612,6 +628,12 @@ mod tests {
// Kept in a file and read again: verified as before.
let again = Signatures::from_kept(&ours, signatures.since(0));
assert!(again.verified(&actor, 3));
+
+ // For a document without the last change: those of the changes it holds.
+ let without = ours.fork_at(&[second]).unwrap();
+ let kept = signatures.kept_for(&without);
+ assert!(kept.verified(&actor, 2) && !kept.verified(&actor, 3));
+ assert_eq!(kept.since(0), vec![signed(second)]);
}
/// Protocol data, listed paths (within or above them) and asked-for writes are