aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/document/signatures.rs22
-rw-r--r--src/state/host.rs7
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);