From 7323e8ed8598cda9784493aa3334d947120b53d8 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 7 Nov 2026 22:35:22 +0100 Subject: swarm: changes taken unjudged, dropped (REFUSALS) A node refusing changes a peer brought tells it which broke a rule; the peer judges them itself, and if its rules refuse them too, drops them with all built on them (its document forked without them, a fresh actor), quarantining its own writes among them. Wire version 42. Auth plan M6 (rejoin on taint). --- src/document/sync.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/document') diff --git a/src/document/sync.rs b/src/document/sync.rs index 823d4a3..b172dd1 100644 --- a/src/document/sync.rs +++ b/src/document/sync.rs @@ -212,6 +212,9 @@ pub(crate) struct SyncSession { /// The wait before answering a peer that offers again only changes we refused /// (`refused_again`). refused_backoff: Backoff, + /// When we last told the peer which of the changes it brought we refused + /// (`refusals_due`). + refusals_told: Option, /// The answer we expect to our last sync message(s), if any. pub(crate) reply: Option, @@ -264,6 +267,7 @@ impl SyncSession { assumed_lately: std::collections::VecDeque::new(), said_heads: None, refused_backoff: Backoff::new(REFUSED_WAIT, REFUSED_WAIT_MAX), + refusals_told: None, reply: None, reply_backoff, } @@ -993,6 +997,18 @@ impl SyncSession { delay } + /// Whether to tell the peer which of the changes it brought we refused, now + /// (`swarm::refusals`): at most every `refusals::TELL_EVERY`. + pub(crate) fn refusals_due(&mut self, now: Instant) -> bool { + let due = self.refusals_told.is_none_or(|told| { + now.saturating_duration_since(told) >= crate::swarm::refusals::TELL_EVERY + }); + if due { + self.refusals_told = Some(now); + } + due + } + /// The peer brought changes we took (or none refused before): answered at once again. pub(crate) fn refusals_settled(&mut self) { self.refused_backoff.reset(); -- cgit v1.3.1