diff options
| -rw-r--r-- | src/document/signatures.rs | 22 | ||||
| -rw-r--r-- | src/state/host.rs | 7 |
2 files changed, 26 insertions, 3 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 diff --git a/src/state/host.rs b/src/state/host.rs index 3210ee2..38be831 100644 --- a/src/state/host.rs +++ b/src/state/host.rs @@ -24,9 +24,10 @@ impl AppState { /// document. (Lock order doc -> peer, as in sync generation.) fn swap_document(&self, replica: &mut Replica, epoch: Epoch, doc: Document) -> Document { let old = std::mem::replace(&mut replica.doc, doc); - // The old document's signatures are of its changes; this node's replayed into - // the new one, signed at once. - replica.signatures = Default::default(); + // The old document's signatures, of the changes the new one holds too (it may + // be the old one without some, or another of its epoch); this node's replayed + // into it, signed at once. + replica.signatures = replica.signatures.kept_for(&replica.doc); if let Some(key) = &self.node_key { let replica = &mut *replica; replica.signatures.sign_own_latest(&replica.doc, key); |
