diff options
| author | tv <tv@krebsco.de> | 2026-11-08 18:23:04 +0000 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-08 19:29:26 +0100 |
| commit | e9813db05f2cc8590b785639a3c41ba60812909a (patch) | |
| tree | 01e2fb07f69147dac684eb1c5a4301aff9661eff /src/remake | |
| parent | d14290ab6d0ea40b97cdb72f5e07354cc2721c45 (diff) | |
strict: no strict remake of a swarm strict already
Review 2, N2: nothing checked that a strict remake's base wasn't strict
already. In a strict swarm the registry, the policy and the bans change
only as a user who may change them signs; a strict remake committed by
a majority of members, each with keys of its own, could drop any of
them (unban, remove managers, empty userSigned and the sealed
declarations), and the honest minority would follow.
A node now takes a strict remake (proposing or voting) only in a swarm
not strict yet: turning strict is done once, by a remake; after it, by
signatures.
Diffstat (limited to 'src/remake')
| -rw-r--r-- | src/remake/api.rs | 8 | ||||
| -rw-r--r-- | src/remake/vote.rs | 17 |
2 files changed, 18 insertions, 7 deletions
diff --git a/src/remake/api.rs b/src/remake/api.rs index d3df908..1da0539 100644 --- a/src/remake/api.rs +++ b/src/remake/api.rs @@ -383,22 +383,24 @@ async fn start_kind<H: Host>( // A strict remake: proposed only with a manifest this node would vote for. if kind.name() == "strict" { - let swarm = host + let (swarm, strict) = host .read_doc(|doc| { - crate::document::store::read_path( + let swarm = crate::document::store::read_path( doc, &crate::document::meta::path(&[crate::document::meta::SWARM]), ) .ok() .flatten() .and_then(|swarm| swarm.as_str().map(str::to_owned)) - .unwrap_or_default() + .unwrap_or_default(); + (swarm, crate::access::policy::of(doc).strict()) }) .await; if let Err(why) = super::vote::strict_taken( &host, prepared.content.as_deref(), &swarm, + strict, &EpochRecord::from(host.current_epoch()), request.base_heads.as_deref(), ) { diff --git a/src/remake/vote.rs b/src/remake/vote.rs index 7e678e6..ac94306 100644 --- a/src/remake/vote.rs +++ b/src/remake/vote.rs @@ -281,7 +281,7 @@ pub(super) async fn cast<H: Host>(host: &H) { // Usually there is nothing to vote on: look first, without writing. let (voter, wanted) = (me.clone(), epoch.clone()); let now = host.now_millis(); - let (due, missed, swarm) = host + let (due, missed, (swarm, strict)) = host .read_doc(move |doc| { let all = records::load_all(doc); let register = records::load_register(doc); @@ -304,7 +304,8 @@ pub(super) async fn cast<H: Host>(host: &H) { .flatten() .and_then(|swarm| swarm.as_str().map(str::to_owned)) .unwrap_or_default(); - (due, missed, swarm) + let strict = crate::access::policy::of(doc).strict(); + (due, missed, (swarm, strict)) }) .await; for id in missed { @@ -336,6 +337,7 @@ pub(super) async fn cast<H: Host>(host: &H) { host, bytes.as_deref().map(Vec::as_slice), &swarm, + strict, &proposal.from_epoch, proposal.base_heads.as_deref(), ) @@ -381,15 +383,22 @@ pub(super) async fn cast<H: Host>(host: &H) { } /// Whether this node takes a strict remake's manifest (`content`, for `swarm`): signed -/// by one of its `--strict-keys`, for the remake's epoch and base (`epoch`, `base`). Why -/// not, if not. +/// by one of its `--strict-keys`, for the remake's epoch and base (`epoch`, `base`), in +/// a swarm not strict yet (`strict`: once it is, its registry, policy and bans change by +/// their users' signatures, not by a majority of members). Why not, if not. pub(super) fn strict_taken<H: Host>( host: &H, content: Option<&[u8]>, swarm: &str, + strict: bool, epoch: &EpochRecord, base: Option<&[String]>, ) -> Result<(), String> { + if strict { + return Err( + "the swarm is strict already: its registry changes by its users' signatures".to_owned(), + ); + } let text = content .and_then(|bytes| std::str::from_utf8(bytes).ok()) .ok_or("no manifest")?; |
