diff options
| author | tv <tv@krebsco.de> | 2026-11-08 15:46:28 +0000 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-08 17:12:19 +0100 |
| commit | ab595dfb91e66a8beda9b2dd407a4fceebe3b977 (patch) | |
| tree | b9831f30ec150bf810d46dcee81747305fc6e2cb /src/access | |
| parent | ed27acb707d940c5b796b1079d3d74698484aeba (diff) | |
refusals: a drop taking much waits for a second member, and shows
A node told (REFUSALS) that it holds a change the swarm's rules refuse,
and whose own rules refuse it too, dropped it and everything built on
it on one peer's word, however much that was; its own writes among them
went to the quarantine, the others' nowhere.
* A drop taking more than 100 changes, or more than ten and a tenth of
the document, now
waits until a second member names the same change: the node's rules
and one peer's word could both be off. Logged as an error, counted in
/admin/stats (sync.dropsHeld).
* The others' changes dropped are listed with the refused (GET
/admin/refused, "taken unjudged, dropped"), for operators to see.
The cheap half of asking the others (future-work.md, Telling a
malicious change from a wrong policy).
Diffstat (limited to 'src/access')
| -rw-r--r-- | src/access/screen.rs | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/access/screen.rs b/src/access/screen.rs index e15b407..89ca007 100644 --- a/src/access/screen.rs +++ b/src/access/screen.rs @@ -70,6 +70,9 @@ pub(crate) struct Screening { refusals: Refusals, /// The members refused as a whole, by node ID (`refusing`). refusing: std::collections::BTreeMap<String, Refusing>, + /// Changes this node holds that peers say the swarm's rules refuse, and its own do + /// too, whose drop would take much: each with the peers that said so (`hold_drop`). + held_drops: HashMap<ChangeHash, BTreeSet<String>>, } /// A member refused as a whole: since when, for which change of its, and why. @@ -139,6 +142,30 @@ impl Screening { } } + /// `peer` says `root`, held here, is refused by the swarm's rules, its drop taking + /// much (`AppState::drop_taken`): how many peers said so of it, this one with them. + pub(crate) fn hold_drop(&mut self, root: ChangeHash, peer: &str) -> usize { + let named = self.held_drops.entry(root).or_default(); + named.insert(peer.to_owned()); + named.len() + } + + /// Drops held, for another peer to say so too (`hold_drop`). + pub(crate) fn drops_held(&self) -> usize { + self.held_drops.len() + } + + /// `dropped`, changes this node took unjudged and dropped (`AppState::drop_taken`), + /// kept with those refused, the oldest going past `MAX_REFUSED`; logged once, there. + pub(crate) fn keep_dropped(&mut self, dropped: Vec<Refused>) { + for dropped in dropped { + self.refused.push_back(dropped); + if self.refused.len() > MAX_REFUSED { + self.refused.pop_front(); + } + } + } + /// Those refused, oldest first. pub(crate) fn refused(&self) -> impl DoubleEndedIterator<Item = &Refused> { self.refused.iter() |
