aboutsummaryrefslogtreecommitdiffstats
path: root/src/remake/catchup.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-08 21:51:14 +0000
committertv <tv@krebsco.de>2026-11-08 22:58:54 +0100
commit40ee439f36e2afb3c978d0214dd6b8319dfa9642 (patch)
tree653af511656f582183d07e44a0d731719bb9b3ec /src/remake/catchup.rs
parenta3eadeeeff9f4ae8ce91251e51d8312a6ffbc2ca (diff)
remake: a strict remake of a strict swarm isn't followed
Review 3, R3: 1186 kept honest nodes from proposing or voting for a strict remake of a swarm strict already, but a majority of members, each with keys of its own, could still commit one, and switch and catchup followed it without asking what kind of remake made the epoch: the registry, policy and bans of a strict swarm changing by a member majority, the honest minority following. A node now refuses to switch to such an epoch (its document's policy strict, the remake's kind strict), and catchup refuses to rejoin one whose chain of epochs holds a strict remake after the swarm was strict (as the old document is, or once a remake since made it so). access.md says so.
Diffstat (limited to 'src/remake/catchup.rs')
-rw-r--r--src/remake/catchup.rs16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/remake/catchup.rs b/src/remake/catchup.rs
index 4df5c90..6ef8121 100644
--- a/src/remake/catchup.rs
+++ b/src/remake/catchup.rs
@@ -528,6 +528,22 @@ fn prepare(
.filter(|next| next.previous == previous);
let gap = target.generation - previous.generation;
+ // A strict remake of a swarm strict already isn't followed: there its registry,
+ // policy and bans change by its users' signatures, not by a majority of members
+ // (`vote::strict_taken`). Strict as our document is, or once a remake since made it so.
+ let mut strict = crate::access::policy::of(old).strict();
+ for generation in previous.generation + 1..=target.generation {
+ if let Ok(epoch) = snapshot::read_epoch_metadata(copy, generation)
+ && epoch.kind == "strict"
+ {
+ if strict {
+ return Prepared::Failed(format!(
+ "epoch generation {generation} was made by a strict remake of a swarm strict already: not followed"
+ ));
+ }
+ strict = true;
+ }
+ }
// Writes made in our epoch go through every remake since, in order.
let translator = (previous.generation + 1..=target.generation).try_fold(
Translator::default(),