diff options
| author | tv <tv@krebsco.de> | 2026-11-12 01:13:54 +0000 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-12 02:47:08 +0100 |
| commit | 81dc0ca6012372ff293e19549053fda84bca1eb0 (patch) | |
| tree | 883f867ee70072d38e26b907ce4734cad40f0ba8 /src/document | |
| parent | 5b13f5e9d83a11b8a60f2d4711065360ba20f70c (diff) | |
screen: refuse a change at a seq this node made under its own actor
A node receiving a change of the actor it writes as, one it doesn't
hold, writes on as a fresh actor (another node writes as it, from a copy
of its files). Where the other node made it at a seq this node made a
change at too, the change was taken to Automerge, which refuses the
whole batch (duplicate seq): the message failed, and with it everything
else it carried. Signatures::forks found it forged only where a
signature verified a change of the actor at that seq, and this node
signs its own latest change only as it sends it.
forks now also finds a change forged where its actor is the one the
document writes as and the document's latest change of it
(get_last_local_change) is at its seq or later. apply_bytes switches to
the fresh actor after judging the batch, not before, so the check still
sees the actor; also where judging fails.
Diffstat (limited to 'src/document')
| -rw-r--r-- | src/document/signatures.rs | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/src/document/signatures.rs b/src/document/signatures.rs index 4f34ecb..79c8569 100644 --- a/src/document/signatures.rs +++ b/src/document/signatures.rs @@ -603,11 +603,15 @@ impl Signatures { /// Whether `change`, not in `doc`, forks its actor's changes: `doc` holds a change /// a signature verified of that actor at a seq as late, so its real change at /// `change`'s seq too. Anyone can make a change under any actor; only its node can - /// sign one. + /// sign one. Or the actor is the one `doc` writes as, and it made a change at a seq + /// as late: another node writing as it too made this one. pub(crate) fn forks(&self, doc: &Document, change: &super::Change) -> bool { self.latest.get(change.actor_id()).is_some_and(|latest| { latest.seq >= change.seq() && super::changes::holds(doc, &latest.hash) - }) + }) || (change.actor_id() == doc.get_actor() + && doc + .get_last_local_change() + .is_some_and(|own| own.seq() >= change.seq())) } /// Whether a signature vouches for `actor`'s change `seq`. |
