diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/access/screen.rs | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/src/access/screen.rs b/src/access/screen.rs index 89ca007..5584b2b 100644 --- a/src/access/screen.rs +++ b/src/access/screen.rs @@ -4,9 +4,11 @@ //! //! A change is judged at the heads its writer saw. Those of a batch aren't in the //! document yet, so one is judged at the changes of the document its batch ancestors -//! build on: what rules read there (the members, the user registry, remake proposals, -//! the policy, bans) is what its writer saw, unless one of those ancestors changed it. So a change that -//! does (`relevant`) is applied before the next is judged: the rest go in at once. +//! build on: what rules read there (the members, the user registry, remake records, +//! votes, the policy, bans, whether a map it makes is there) is what its writer saw, +//! unless one of those ancestors changed it. So a change that does (`relevant`), and +//! those before a change making a map where they wrote, are applied before the next is +//! judged: the rest go in at once. //! //! A member whose own change broke a rule, as its signature proves (signatures //! required), is refused as a whole (`Screening::refusing`): the node sends it nothing @@ -34,7 +36,7 @@ use std::collections::{BTreeSet, HashMap, HashSet}; use anyhow::Result; use super::rules::{self, Refusal}; -use crate::document::inspect::{Inspector, Op, Path}; +use crate::document::inspect::{Action, Inspector, Op, Path}; use crate::document::meta; use crate::document::replica::{Epoch, user_of}; use crate::document::signatures::Signatures; @@ -348,6 +350,9 @@ pub(crate) fn apply( let mut unsigned: HashSet<ChangeHash> = HashSet::new(); let mut forged: HashSet<ChangeHash> = HashSet::new(); let mut accepted: Vec<Change> = Vec::new(); + // What the accepted, not applied yet, touch: a change making a map at one of these + // paths is judged with them in (`rules`' maps made where there are none). + let mut unapplied: BTreeSet<Path> = BTreeSet::new(); for (index, change) in ready.iter().enumerate() { let hash = change.hash(); let committer = committers[index].as_deref(); @@ -404,6 +409,18 @@ pub(crate) fn apply( waiting.0.push(change.clone()); continue; } + // It makes a map where one accepted before may have: the rules read whether one + // is there, so those go in first. + if !accepted.is_empty() + && ops[index] + .iter() + .any(|op| op.action == Action::MakeMap && unapplied.contains(&op.path)) + { + screened.applied += accepted.len(); + apply_taken(doc, std::mem::take(&mut accepted), log)?; + frontier.clear(); + unapplied.clear(); + } let mut seen_at: BTreeSet<ChangeHash> = BTreeSet::new(); for dep in change.deps() { match frontier.get(dep) { @@ -439,8 +456,10 @@ pub(crate) fn apply( screened.applied += accepted.len(); apply_taken(doc, std::mem::take(&mut accepted), log)?; frontier.clear(); + unapplied.clear(); } else { frontier.insert(hash, seen_at); + unapplied.extend(paths[index].iter().cloned()); } } Err(Refusal::Unready) => { @@ -626,10 +645,12 @@ pub(crate) fn apply_bytes( } /// Whether a change touching `paths` changes what rules read: the members, the user -/// registry, remake records, the policy and the rest of `_continuum/access`, bans, the -/// protocol data as a whole; and, under a strict policy, values their users sign -/// (`reaches_signed`). A rule that reads anything else (`rules::judge`) must add it -/// here, or a batch judged at its frontier is judged at heads it doesn't hold. +/// registry, remake records, votes, the policy and the rest of `_continuum/access`, +/// bans, the protocol data as a whole; under a strict policy, values their users sign +/// (`reaches_signed`); and, for a change making a map, whether one is there, which +/// `apply` checks against what the accepted before it touch. A rule that reads anything +/// else (`rules::judge`) must add it here, or a batch judged at its frontier is judged +/// at heads it doesn't hold. fn relevant(paths: &BTreeSet<Path>) -> bool { paths.iter().any(|path| match path.as_slice() { [] => true, @@ -639,6 +660,7 @@ fn relevant(paths: &BTreeSet<Path>) -> bool { meta::MEMBERS, meta::USERS, meta::REMAKES, + meta::VOTES, meta::ACCESS, meta::BANNED, ] |
