diff options
Diffstat (limited to 'src/remake')
| -rw-r--r-- | src/remake/api.rs | 15 | ||||
| -rw-r--r-- | src/remake/vote.rs | 21 |
2 files changed, 27 insertions, 9 deletions
diff --git a/src/remake/api.rs b/src/remake/api.rs index 79b551f..7aeb675 100644 --- a/src/remake/api.rs +++ b/src/remake/api.rs @@ -393,7 +393,13 @@ async fn start_kind<H: Host>( .unwrap_or_default() }) .await; - if let Err(why) = super::vote::strict_taken(&host, prepared.content.as_deref(), &swarm) { + if let Err(why) = super::vote::strict_taken( + &host, + prepared.content.as_deref(), + &swarm, + &EpochRecord::from(host.current_epoch()), + request.base_heads.as_deref(), + ) { return error_response( StatusCode::FORBIDDEN, format!("this node takes no such manifest: {why}"), @@ -817,6 +823,7 @@ pub(crate) async fn strict_manifest<H: Host>( ) -> Response { let at = host.now_millis().as_u64(); let caller = user.0.clone(); + let epoch = EpochRecord::from(host.current_epoch()); let (manifest, values, heads) = host .read_doc(move |doc| { let read = |path: &[&str]| { @@ -832,12 +839,14 @@ pub(crate) async fn strict_manifest<H: Host>( _ => json!({"version": 1}), }; policy["values"] = json!("signed"); - let manifest = crate::access::strict::manifest_of(doc, &swarm, policy, &caller, at); + let heads = doc.get_heads(); + let manifest = + crate::access::strict::manifest_of(doc, &swarm, epoch, &heads, policy, &caller, at); let values: Vec<JsonValue> = crate::access::strict::held(doc) .into_iter() .map(|(path, value)| json!({ "path": path, "value": value })) .collect(); - let heads = records::encode_heads(&doc.get_heads()); + let heads = records::encode_heads(&heads); (manifest, values, heads) }) .await; diff --git a/src/remake/vote.rs b/src/remake/vote.rs index 073fcda..7e678e6 100644 --- a/src/remake/vote.rs +++ b/src/remake/vote.rs @@ -294,7 +294,7 @@ pub(super) async fn cast<H: Host>(host: &H) { return None; } let content = record.proposal.content.clone(); - Some((id, content, record.proposal.kind.clone())) + Some((id, content, record.proposal.clone())) }); let swarm = store::read_path( doc, @@ -319,7 +319,7 @@ pub(super) async fn cast<H: Host>(host: &H) { } } } - let Some((chosen, content, kind)) = due else { + let Some((chosen, content, proposal)) = due else { return; }; // Only with the content in hand: a committed remake must have it on a majority. @@ -331,8 +331,14 @@ pub(super) async fn cast<H: Host>(host: &H) { None => None, }; // A strict remake: only with its manifest signed by a key this node was given. - if kind == "strict" - && let Err(why) = strict_taken(host, bytes.as_deref().map(Vec::as_slice), &swarm) + if proposal.kind == "strict" + && let Err(why) = strict_taken( + host, + bytes.as_deref().map(Vec::as_slice), + &swarm, + &proposal.from_epoch, + proposal.base_heads.as_deref(), + ) { if host.remake().refuses_strict(&chosen) { warn!(remake = %chosen, why = %why, "Not voting for a strict remake"); @@ -375,11 +381,14 @@ 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`. Why not, if not. +/// by one of its `--strict-keys`, for the remake's epoch and base (`epoch`, `base`). Why +/// not, if not. pub(super) fn strict_taken<H: Host>( host: &H, content: Option<&[u8]>, swarm: &str, + epoch: &EpochRecord, + base: Option<&[String]>, ) -> Result<(), String> { let text = content .and_then(|bytes| std::str::from_utf8(bytes).ok()) @@ -387,7 +396,7 @@ pub(super) fn strict_taken<H: Host>( if host.strict_keys().is_empty() { return Err("this node has no --strict-keys".to_owned()); } - crate::access::strict::verify(text, host.strict_keys(), swarm).map(|_| ()) + crate::access::strict::verify(text, host.strict_keys(), swarm)?.for_base(epoch, base) } /// A random duration below `limit`. |
