From 63b34dfa41e1595145507a88901e332bf4bd3b14 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 7 Nov 2026 22:35:21 +0100 Subject: signatures: kept in the document file A node's signatures are saved with its document (--document-file) and loaded with it. Auth plan M5. --- src/document/signatures.rs | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'src/document/signatures.rs') diff --git a/src/document/signatures.rs b/src/document/signatures.rs index e92cf9c..c8af89a 100644 --- a/src/document/signatures.rs +++ b/src/document/signatures.rs @@ -154,13 +154,42 @@ impl<'de> serde::Deserialize<'de> for SignEvery { #[derive(Debug, Default)] pub(crate) struct Signatures { by_change: HashMap, + /// The changes signed, in the order their signatures came: the document file + /// appends those after the ones it wrote (`since`). + order: Vec, /// This node's latest change, if no signature vouches for it yet (`SignEvery`). unsigned: Option, } impl Signatures { + /// Signatures kept before, as `since` gave them (the document file). + pub(crate) fn from_kept(kept: Vec<(ChangeHash, [u8; 64])>) -> Self { + let mut signatures = Self::default(); + for (hash, signature) in kept { + signatures.insert(hash, signature); + } + signatures + } + pub(crate) fn insert(&mut self, hash: ChangeHash, signature: [u8; 64]) { - self.by_change.insert(hash, signature); + if self.by_change.insert(hash, signature).is_none() { + self.order.push(hash); + } + } + + /// How many signatures there are. + pub(crate) fn count(&self) -> usize { + self.order.len() + } + + /// The signatures after the first `count` (`count`), in the order they came. + pub(crate) fn since(&self, count: usize) -> Vec<(ChangeHash, [u8; 64])> { + self.order + .get(count..) + .unwrap_or_default() + .iter() + .map(|hash| (*hash, self.by_change[hash])) + .collect() } /// Signs `hash`, this node's latest change, with `key` and keeps the signature: it @@ -286,6 +315,12 @@ mod tests { signatures.left_unsigned(a); signatures.sign(b, &key); assert!(!signatures.sign_latest(&key)); + // Kept in the order they came, each once. + assert_eq!(signatures.count(), 2); + assert_eq!(signatures.since(1)[0].0, b); + assert!(signatures.since(5).is_empty()); + let again = Signatures::from_kept(signatures.since(0)); + assert_eq!(again.since(0), signatures.since(0)); } /// Protocol data, listed paths (within or above them) and asked-for writes are -- cgit v1.3.1