diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f065274..54636984 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -199,7 +199,7 @@ jobs: run: cargo clippy -p warp-core --features native_rule_bootstrap,trusted_runtime,host_test,application_root_shadow --lib --tests -- -D warnings - name: cargo clippy (compiler-produced pure evaluation) - run: cargo clippy -p warp-core --features trusted_runtime --lib --test edict_pure_evaluation_tests --test edict_pure_predicates_tests --test edict_pure_unsigned_subtraction_tests --test edict_pure_byte_length_tests --test edict_byte_equality_tests --test edict_byte_slice_tests --test edict_node_read_tests --test edict_byte_concat_tests --test edict_byte_literal_tests --test edict_source_functions_tests -- -D warnings -D missing_docs + run: cargo clippy -p warp-core --features trusted_runtime --lib --test edict_pure_evaluation_tests --test edict_pure_predicates_tests --test edict_pure_unsigned_subtraction_tests --test edict_unsigned_addition_tests --test edict_pure_byte_length_tests --test edict_byte_equality_tests --test edict_byte_slice_tests --test edict_node_read_tests --test edict_byte_concat_tests --test edict_byte_literal_tests --test edict_source_functions_tests -- -D warnings -D missing_docs clippy-det-fixed: name: Clippy (det_fixed) @@ -395,7 +395,7 @@ jobs: cargo test -p warp-core --features native_rule_bootstrap,trusted_runtime,application_root_shadow,delta_validate --test application_root_shadow_tests - name: cargo test (compiler-produced pure evaluation) run: | - cargo test -p warp-core --features trusted_runtime --test edict_pure_evaluation_tests --test edict_pure_predicates_tests --test edict_pure_unsigned_subtraction_tests --test edict_pure_byte_length_tests --test edict_byte_equality_tests --test edict_byte_slice_tests --test edict_node_read_tests --test edict_byte_concat_tests --test edict_byte_literal_tests --test edict_source_functions_tests + cargo test -p warp-core --features trusted_runtime --test edict_pure_evaluation_tests --test edict_pure_predicates_tests --test edict_pure_unsigned_subtraction_tests --test edict_unsigned_addition_tests --test edict_pure_byte_length_tests --test edict_byte_equality_tests --test edict_byte_slice_tests --test edict_node_read_tests --test edict_byte_concat_tests --test edict_byte_literal_tests --test edict_source_functions_tests cargo test -p warp-core --features trusted_runtime --lib edict_pure:: - name: cargo test (delta validation and the canonical delta merge) run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index e707aa38..a40ed5d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ ### Added +- Bounded pure evaluation executes compiler-produced U32/U64 addition with + checked width bounds and ordinary work/value-storage charging. Independent + native provider judgments require same-width operands and a dominating + no-overflow proof, including legacy Core without a function table. + - Experimental feature `application_root_shadow` (M1, off by default): an incremental application root over every node, edge and attachment record of a worldline state, kept beside the legacy state root, which it neither diff --git a/crates/echo-edict-provider-lowerer/src/executable_operation/bounded_read/relation/types.rs b/crates/echo-edict-provider-lowerer/src/executable_operation/bounded_read/relation/types.rs index 36077aea..82d339dd 100644 --- a/crates/echo-edict-provider-lowerer/src/executable_operation/bounded_read/relation/types.rs +++ b/crates/echo-edict-provider-lowerer/src/executable_operation/bounded_read/relation/types.rs @@ -360,6 +360,13 @@ impl<'a> Scope<'a> { }) .collect::, _>>()?; match (name, actual.as_slice(), declared.as_slice()) { + // source_functions::validate already established the independent + // no-overflow proof before this read relation is constructed. + ("core.integer.add", [left, right], [expected @ ReadType::Unsigned(_)]) + if left == expected && right == expected => + { + Ok(expected.clone()) + } ("core.bytes.isUtf8", [actual], [expected @ ReadType::Bytes(_, _)]) if expected == actual => { diff --git a/crates/echo-edict-provider-lowerer/src/executable_operation/source_functions.rs b/crates/echo-edict-provider-lowerer/src/executable_operation/source_functions.rs index 27f572f1..ec1d5f45 100644 --- a/crates/echo-edict-provider-lowerer/src/executable_operation/source_functions.rs +++ b/crates/echo-edict-provider-lowerer/src/executable_operation/source_functions.rs @@ -2,6 +2,7 @@ // © James Ross Ω FLYING•ROBOTS //! Lowerer-owned forward type, totality, depth and deterministic cost judgment. //! Applies to the complete source-function module, including unused definitions. +mod unsigned_addition; use super::ProviderRefusalV1; use echo_edict_canonical::CanonicalValueV1 as Value; use std::collections::{BTreeMap, BTreeSet}; @@ -64,6 +65,7 @@ struct Judgment<'a> { completed: BTreeMap, active: BTreeSet, work: usize, + proven: Vec<&'a Value>, } pub(super) fn validate(core: &Value, exports: &Value, read: bool) -> Result<(), ProviderRefusalV1> { @@ -157,11 +159,12 @@ fn run(core: &Value, exports: &Value, read: bool) -> Check<()> { completed: BTreeMap::new(), active: BTreeSet::new(), work: WORK, + proven: Vec::new(), }; for name in proof.functions.keys().cloned().collect::>() { proof.function(&name, 1)?; } - if super::map_field(core, "functions").is_none() { + if super::map_field(core, "functions").is_none() && !unsigned_addition::present(core)? { return Ok(()); } for (_, intent) in members(get(core, "intents")?)? { @@ -169,7 +172,7 @@ fn run(core: &Value, exports: &Value, read: bool) -> Check<()> { } Ok(()) } -impl Judgment<'_> { +impl<'a> Judgment<'a> { fn charge(&mut self, depth: usize) -> Check<()> { self.work = self.work.checked_sub(1).ok_or(())?; if depth > DEPTH { @@ -255,7 +258,7 @@ impl Judgment<'_> { _ => Err(()), } } - fn declaration<'a>(&mut self, value: &'a Value, scope: &mut Scope<'a>) -> Check { + fn declaration(&mut self, value: &'a Value, scope: &mut Scope<'a>) -> Check { exact(value, &["id", "type", "alphaName"])?; let id = string(get(value, "id")?)?; string(get(value, "alphaName")?)?; @@ -280,6 +283,15 @@ impl Judgment<'_> { .ok_or(())?; return Ok(fact.clone()); } + // A helper has a fresh proof scope. Restore the caller on success and + // failure, so recursive checks cannot change enclosing all/not scopes. + let caller_facts = std::mem::take(&mut self.proven); + let result = self.check_function_body(name, prefix); + self.proven = caller_facts; + self.active.remove(name); + result + } + fn check_function_body(&mut self, name: &str, prefix: usize) -> Check { let function = *self.functions.get(name).ok_or(())?; self.active.insert(name.to_owned()); exact(function.body, &["locals", "bindings", "result"])?; @@ -343,14 +355,13 @@ impl Judgment<'_> { if prefix.checked_add(fact.depth).ok_or(())? > DEPTH { return Err(()); } - self.active.remove(name); self.completed.insert(name.to_owned(), fact.clone()); Ok(fact) } fn expression( &mut self, - value: &Value, - scope: &Scope<'_>, + value: &'a Value, + scope: &Scope<'a>, source: bool, prefix: usize, ) -> Check { @@ -519,6 +530,23 @@ impl Judgment<'_> { })?; Ty::Bytes(min, max) } + ("core.integer.add", [left, right], [expected @ Ty::Word(max)]) + if left == expected + && right == expected + && matches!(*max, 4_294_967_295 | 18_446_744_073_709_551_615) => + { + unsigned_addition::prove( + arguments, + *max, + &self.proven, + &mut self.work, + )?; + cost = cost.plus(Cost { + steps: 3, + bytes: 64, + })?; + expected.clone() + } ("core.integer.subtract", [left, right], [expected @ Ty::Word(_)]) if includes(expected, left) && includes(expected, right) => { @@ -561,8 +589,8 @@ impl Judgment<'_> { } fn predicate( &mut self, - value: &Value, - scope: &Scope<'_>, + value: &'a Value, + scope: &Scope<'a>, source: bool, prefix: usize, ) -> Check<(Cost, usize)> { @@ -582,11 +610,14 @@ impl Judgment<'_> { } let mut cost = Cost { steps: 1, bytes: 0 }; let mut height = 0; + let inherited = self.proven.len(); for value in values { let (child, depth) = self.predicate(value, scope, source, prefix + 1)?; cost = cost.plus(child)?; height = height.max(depth); + self.proven.push(value); } + self.proven.truncate(inherited); return Ok((cost, height + 1)); } _ => {} @@ -619,7 +650,8 @@ impl Judgment<'_> { left.depth.max(right.depth) + 1, )) } - fn intent(&mut self, intent: &Value, read: bool) -> Check<()> { + fn intent(&mut self, intent: &'a Value, read: bool) -> Check<()> { + self.proven.clear(); let body = get(intent, "body")?; exact(body, &["locals", "nodes", "result"])?; let mut pending = BTreeMap::new(); @@ -659,6 +691,7 @@ impl Judgment<'_> { self.predicate(get(constraint, "predicate")?, &scope, true, 0)? .0, )?; + self.proven.push(get(constraint, "predicate")?); } for node in list(get(body, "nodes")?)? { if read { diff --git a/crates/echo-edict-provider-lowerer/src/executable_operation/source_functions/unsigned_addition.rs b/crates/echo-edict-provider-lowerer/src/executable_operation/source_functions/unsigned_addition.rs new file mode 100644 index 00000000..36cb3e49 --- /dev/null +++ b/crates/echo-edict-provider-lowerer/src/executable_operation/source_functions/unsigned_addition.rs @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: Apache-2.0 +// © James Ross Ω FLYING•ROBOTS +//! Lowerer-owned recursive upper bounds over checked, dominating predicates. +use super::{get, list, literal, string, Check, Value}; + +pub(super) fn present(core: &Value) -> Check { + let mut pending = vec![get(core, "intents")?]; + while let Some(value) = pending.pop() { + match value { + Value::Map(fields) => { + if get(value, "kind").and_then(string) == Ok("call") + && get(value, "callee").and_then(string) == Ok("core.integer.add") + { + return Ok(true); + } + pending.extend(fields.iter().map(|(_, value)| value)); + } + Value::Array(values) => pending.extend(values), + _ => {} + } + } + Ok(false) +} + +pub(super) fn prove(args: &[Value], max: u64, facts: &[&Value], work: &mut usize) -> Check<()> { + let [left, right] = args else { return Err(()) }; + let left = bound(left, max, facts, work, 0)?; + let right = bound(right, max, facts, work, 0)?; + left.checked_add(right) + .filter(|sum| *sum <= max) + .ok_or(())?; + Ok(()) +} +fn debit(work: &mut usize, amount: usize) -> Check<()> { + *work = work.checked_sub(amount).ok_or(())?; + Ok(()) +} +fn same(a: &Value, b: &Value, work: &mut usize) -> Check { + for value in [a, b] { + let bytes = echo_edict_canonical::encode_canonical_cbor_v1(value).map_err(|_| ())?; + debit(work, bytes.len())?; + } + Ok(a == b) +} +fn bound(expr: &Value, max: u64, facts: &[&Value], work: &mut usize, depth: usize) -> Check { + debit(work, 1)?; + if depth > 64 { + return Err(()); + } + let mut upper = if string(get(expr, "kind")?)? == "call" + && string(get(expr, "callee")?)? == "core.integer.add" + { + let [left, right] = list(get(expr, "args")?)? else { + return Err(()); + }; + bound(left, max, facts, work, depth + 1)? + .checked_add(bound(right, max, facts, work, depth + 1)?) + .ok_or(())? + } else { + literal(expr).unwrap_or(max) + }; + for predicate in facts { + refine(predicate, expr, &mut upper, work, depth + 1)?; + } + Ok(upper) +} +fn refine( + predicate: &Value, + expr: &Value, + upper: &mut u64, + work: &mut usize, + depth: usize, +) -> Check<()> { + debit(work, 1)?; + if depth > 64 { + return Err(()); + } + match string(get(predicate, "kind")?)? { + "all" => { + for child in list(get(predicate, "values")?)? { + refine(child, expr, upper, work, depth + 1)?; + } + } + "compare" => { + let op = string(get(predicate, "op")?)?; + let left = get(predicate, "left")?; + let right = get(predicate, "right")?; + if matches!(op, "<=" | "==") { + if let Ok(limit) = literal(right) { + if same(left, expr, work)? { + *upper = (*upper).min(limit); + } + } + } + if op == "==" { + if let Ok(limit) = literal(left) { + if same(right, expr, work)? { + *upper = (*upper).min(limit); + } + } + } + } + _ => {} + } + Ok(()) +} diff --git a/crates/echo-edict-provider-verifier/src/executable_operation/bounded_read/audit/types.rs b/crates/echo-edict-provider-verifier/src/executable_operation/bounded_read/audit/types.rs index 52e557a3..14975252 100644 --- a/crates/echo-edict-provider-verifier/src/executable_operation/bounded_read/audit/types.rs +++ b/crates/echo-edict-provider-verifier/src/executable_operation/bounded_read/audit/types.rs @@ -342,6 +342,12 @@ impl<'a> Symbols<'a> { declared.push(self.schema(string(coordinate)?, 0)?); } match (name, actual.as_slice(), declared.as_slice()) { + // The source-function audit has independently proved totality. + ("core.integer.add", [left, right], [expected @ Schema::Word(_)]) + if left == expected && right == expected => + { + Ok(expected.clone()) + } ("core.bytes.isUtf8", [actual], [expected @ Schema::Bytes { .. }]) if expected == actual => { diff --git a/crates/echo-edict-provider-verifier/src/executable_operation/source_functions.rs b/crates/echo-edict-provider-verifier/src/executable_operation/source_functions.rs index 062ab0c9..cf5f311a 100644 --- a/crates/echo-edict-provider-verifier/src/executable_operation/source_functions.rs +++ b/crates/echo-edict-provider-verifier/src/executable_operation/source_functions.rs @@ -3,6 +3,7 @@ //! Independent verifier judgment: inventory authority, eliminate dependency leaves, //! then audit ordered lexical frames and conservative whole-operation charges. mod types; +mod unsigned_addition; use super::ProviderRefusalV1; use echo_edict_canonical::CanonicalValueV1 as Value; use std::collections::{BTreeMap, BTreeSet}; @@ -114,6 +115,7 @@ fn audit(core: &Value, exports: &Value, read: bool) -> Check<()> { "core.bytes.concat", "core.bytes.slice", "core.integer.subtract", + "core.integer.add", ] .contains(&callee) { @@ -145,6 +147,7 @@ fn audit(core: &Value, exports: &Value, read: bool) -> Check<()> { types: &mut types, definitions: &definitions, summaries: &summaries, + proven: Vec::new(), } .function(definition)?; if summary.height + 1 > 64 { @@ -168,8 +171,9 @@ fn audit(core: &Value, exports: &Value, read: bool) -> Check<()> { types: &mut types, definitions: &definitions, summaries: &summaries, + proven: Vec::new(), }; - if super::map_field(core, "functions").is_none() { + if super::map_field(core, "functions").is_none() && !unsigned_addition::present(core)? { return Ok(()); } for (_, intent) in members(get(core, "intents")?)? { @@ -277,9 +281,10 @@ struct Checker<'a, 'b> { types: &'b mut Types<'a>, definitions: &'b BTreeMap>, summaries: &'b BTreeMap, + proven: Vec<&'a Value>, } -impl Checker<'_, '_> { - fn function(&mut self, definition: &Definition<'_>) -> Check { +impl<'a> Checker<'a, '_> { + fn function(&mut self, definition: &Definition<'a>) -> Check { let declarations = sequence(get(definition.body, "locals")?)?; let mut frame = Frame::new(definition.params.iter().chain(declarations), self.types)?; let mut height = definition.result.measure()?.height; @@ -323,7 +328,12 @@ impl Checker<'_, '_> { height: height.max(value.height), }) } - fn expression(&mut self, value: &Value, frame: &Frame<'_>, depth: usize) -> Check { + fn expression( + &mut self, + value: &'a Value, + frame: &Frame<'a>, + depth: usize, + ) -> Check { self.types.step(depth)?; let mut charge = Charge { ticks: 1, @@ -455,8 +465,25 @@ impl Checker<'_, '_> { declared.push(self.types.resolve(string(coordinate)?, depth + 1)?); } height = height.max(1); - let (schema, intrinsic) = - intrinsic(name, arguments, &argument_schemas, &declared)?; + let addition_proven = if name == "core.integer.add" { + let [Schema::Word(max)] = declared.as_slice() else { + return Err(()); + }; + if !matches!(*max, 4_294_967_295 | 18_446_744_073_709_551_615) { + return Err(()); + } + unsigned_addition::prove(arguments, *max, &self.proven, self.types)?; + true + } else { + false + }; + let (schema, intrinsic) = intrinsic( + name, + arguments, + &argument_schemas, + &declared, + addition_proven, + )?; charge.append(intrinsic)?; schema } @@ -474,8 +501,8 @@ impl Checker<'_, '_> { } fn predicate( &mut self, - predicate: &Value, - frame: &Frame<'_>, + predicate: &'a Value, + frame: &Frame<'a>, depth: usize, ) -> Check<(Charge, usize)> { self.types.step(depth)?; @@ -491,11 +518,14 @@ impl Checker<'_, '_> { storage: 0, }; let mut height = 0; + let inherited = self.proven.len(); for child in values { let (charge, child_height) = self.predicate(child, frame, depth + 1)?; total.append(charge)?; height = height.max(child_height); + self.proven.push(child); } + self.proven.truncate(inherited); return Ok((total, height + 1)); } "not" => { @@ -546,7 +576,8 @@ impl Checker<'_, '_> { } Ok((charge, height)) } - fn intent(&mut self, intent: &Value, read: bool) -> Check<()> { + fn intent(&mut self, intent: &'a Value, read: bool) -> Check<()> { + self.proven.clear(); let body = get(intent, "body")?; exact(body, &["locals", "nodes", "result"])?; let mut frame = Frame::new(sequence(get(body, "locals")?)?, self.types)?; @@ -572,6 +603,7 @@ impl Checker<'_, '_> { } for constraint in sequence(get(intent, "inputConstraints")?)? { charge.append(self.predicate(get(constraint, "predicate")?, &frame, 0)?.0)?; + self.proven.push(get(constraint, "predicate")?); } for node in sequence(get(body, "nodes")?)? { if read { @@ -644,6 +676,7 @@ fn intrinsic( arguments: &[Value], actual: &[Schema], declared: &[Schema], + addition_proven: bool, ) -> Check<(Schema, Charge)> { let literal = |value: &Value| -> Check { if string(get(value, "kind")?)? != "const" { @@ -695,6 +728,17 @@ fn intrinsic( }, )) } + ("core.integer.add", [left, right], [expected @ Schema::Word(_)]) + if addition_proven && expected == left && expected == right => + { + Ok(( + expected.clone(), + Charge { + ticks: 3, + storage: 64, + }, + )) + } ("core.integer.subtract", [left, right], [expected @ Schema::Word(_)]) if expected.encloses(left) && expected.encloses(right) => { diff --git a/crates/echo-edict-provider-verifier/src/executable_operation/source_functions/types.rs b/crates/echo-edict-provider-verifier/src/executable_operation/source_functions/types.rs index 775dad00..edee4abe 100644 --- a/crates/echo-edict-provider-verifier/src/executable_operation/source_functions/types.rs +++ b/crates/echo-edict-provider-verifier/src/executable_operation/source_functions/types.rs @@ -130,6 +130,10 @@ impl<'a> Types<'a> { remaining: 65_536, } } + pub(super) fn proof_work(&mut self, bytes: usize) -> Check<()> { + self.remaining = self.remaining.checked_sub(bytes).ok_or(())?; + Ok(()) + } pub(super) fn step(&mut self, depth: usize) -> Check<()> { if depth > 64 { return Err(()); diff --git a/crates/echo-edict-provider-verifier/src/executable_operation/source_functions/unsigned_addition.rs b/crates/echo-edict-provider-verifier/src/executable_operation/source_functions/unsigned_addition.rs new file mode 100644 index 00000000..a1283926 --- /dev/null +++ b/crates/echo-edict-provider-verifier/src/executable_operation/source_functions/unsigned_addition.rs @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: Apache-2.0 +// © James Ross Ω FLYING•ROBOTS +//! Verifier-owned inventory of canonical-expression caps and independent composition. +use super::{get, sequence, string, unsigned, Check, Types, Value}; + +pub(super) fn present(core: &Value) -> Check { + let mut layers = vec![get(core, "intents")?]; + while !layers.is_empty() { + let mut next = Vec::new(); + for value in layers { + if let Value::Map(entries) = value { + if string(get(value, "kind").unwrap_or(&Value::Null)) == Ok("call") + && string(get(value, "callee").unwrap_or(&Value::Null)) + == Ok("core.integer.add") + { + return Ok(true); + } + next.extend(entries.iter().map(|(_, child)| child)); + } else if let Value::Array(entries) = value { + next.extend(entries); + } + } + layers = next; + } + Ok(false) +} + +pub(super) fn prove( + args: &[Value], + max: u64, + facts: &[&Value], + types: &mut Types<'_>, +) -> Check<()> { + let [left, right] = args else { return Err(()) }; + let mut pending: Vec<_> = facts.iter().map(|value| (*value, 0)).collect(); + let mut caps = Vec::new(); + while let Some((predicate, depth)) = pending.pop() { + types.step(depth)?; + match string(get(predicate, "kind")?)? { + "all" => pending.extend( + sequence(get(predicate, "values")?)? + .iter() + .map(|value| (value, depth + 1)), + ), + "compare" => { + let op = string(get(predicate, "op")?)?; + let a = get(predicate, "left")?; + let b = get(predicate, "right")?; + if matches!(op, "<=" | "==") { + if let Some(n) = constant(b) { + caps.push((key(a, types)?, n)); + } + } + if op == "==" { + if let Some(n) = constant(a) { + caps.push((key(b, types)?, n)); + } + } + } + _ => {} + } + } + let a = ceiling(left, max, &caps, types, 0)?; + let b = ceiling(right, max, &caps, types, 0)?; + if u128::from(a) + u128::from(b) > u128::from(max) { + return Err(()); + } + Ok(()) +} +fn constant(expr: &Value) -> Option { + if string(get(expr, "kind").ok()?).ok()? != "const" { + return None; + } + unsigned(get(get(expr, "value").ok()?, "value").ok()?).ok() +} +fn key(expr: &Value, types: &mut Types<'_>) -> Check> { + let bytes = echo_edict_canonical::encode_canonical_cbor_v1(expr).map_err(|_| ())?; + types.proof_work(bytes.len())?; + Ok(bytes) +} +fn ceiling( + expr: &Value, + max: u64, + caps: &[(Vec, u64)], + types: &mut Types<'_>, + depth: usize, +) -> Check { + types.step(depth)?; + let mut value = if string(get(expr, "kind")?)? == "call" + && string(get(expr, "callee")?)? == "core.integer.add" + { + let [a, b] = sequence(get(expr, "args")?)? else { + return Err(()); + }; + u128::from(ceiling(a, max, caps, types, depth + 1)?) + + u128::from(ceiling(b, max, caps, types, depth + 1)?) + } else { + constant(expr).map_or_else(|| u128::from(max), u128::from) + }; + let encoded = key(expr, types)?; + for (term, cap) in caps { + types.proof_work(encoded.len().min(term.len()).checked_add(1).ok_or(())?)?; + if term == &encoded { + value = value.min(u128::from(*cap)); + } + } + u64::try_from(value).map_err(|_| ()) +} diff --git a/crates/echo-edict-provider-verifier/tests/bounded_read/source_functions.rs b/crates/echo-edict-provider-verifier/tests/bounded_read/source_functions.rs index f8e62316..e39e6db0 100644 --- a/crates/echo-edict-provider-verifier/tests/bounded_read/source_functions.rs +++ b/crates/echo-edict-provider-verifier/tests/bounded_read/source_functions.rs @@ -587,3 +587,70 @@ mod imported_calls; #[path = "source_functions/utf8.rs"] mod utf8; + +#[test] +fn bounded_read_accepts_independently_proven_unsigned_addition() { + for (left, accepted) in [(1, true), (i128::from(u64::MAX), false)] { + // Rebound native control. This does not claim public producer acceptance. + let literal = |number: i128| { + map([ + ("kind", text("const")), + ( + "value", + map([ + ("kind", text("int")), + ("width", text("U64")), + ("value", Value::Integer(number)), + ]), + ), + ]) + }; + let sum = map([ + ("kind", text("call")), + ("callee", text("core.integer.add")), + ("typeArgs", Value::Array(vec![text("U64")])), + ("args", Value::Array(vec![literal(left), literal(1)])), + ]); + let constraint = map([ + ("coordinate", text("where.addition.control")), + ( + "predicate", + map([ + ("kind", text("compare")), + ("op", text("==")), + ("left", sum), + ("right", literal(2)), + ]), + ), + ]); + let mut verification = request(read_helper()); + changed_core(&mut verification, |core| { + *field_mut(intent(core), "inputConstraints") = Value::Array(vec![constraint.clone()]); + }); + changed_target(&mut verification, |intent| { + *field_mut(intent, "inputConstraints") = Value::Array(vec![constraint]); + }); + let mut source = read_helper(); + source.core = bound( + &verification.core.reference.coordinate, + &verification.core.artifact.domain, + verification.core.artifact.bytes.clone(), + ); + source.semantic_inputs[5].artifact = bound( + &verification.target_ir.reference.coordinate, + &verification.target_ir.artifact.domain, + verification.target_ir.artifact.bytes.clone(), + ); + let lowered = lower(source); + let verified = verifier::verify(verification).expect("bounded verifier response"); + let report = decode(&verified.outputs[0].artifact.bytes).expect("verification report"); + assert_eq!( + (lowered.is_ok(), field(&report, "outcome")), + ( + accepted, + &text(if accepted { "accepted" } else { "rejected" }) + ), + "both independent read relations accept proven same-width addition" + ); + } +} diff --git a/crates/echo-edict-provider-verifier/tests/source_functions/mod.rs b/crates/echo-edict-provider-verifier/tests/source_functions/mod.rs index 0f93ec8f..286e7064 100644 --- a/crates/echo-edict-provider-verifier/tests/source_functions/mod.rs +++ b/crates/echo-edict-provider-verifier/tests/source_functions/mod.rs @@ -2,6 +2,7 @@ // © James Ross Ω FLYING•ROBOTS //! Deliberately rebound native-provider tests, not compiler acceptance evidence. use super::*; +mod unsigned_addition; fn fixture_with_functions( functions: CanonicalValueV1, diff --git a/crates/echo-edict-provider-verifier/tests/source_functions/unsigned_addition.rs b/crates/echo-edict-provider-verifier/tests/source_functions/unsigned_addition.rs new file mode 100644 index 00000000..a62175a0 --- /dev/null +++ b/crates/echo-edict-provider-verifier/tests/source_functions/unsigned_addition.rs @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: Apache-2.0 +// © James Ross Ω FLYING•ROBOTS +//! Rebound native judgments; public compiler evidence is retained separately. +use super::*; + +fn add(left: CanonicalValueV1, right: CanonicalValueV1) -> CanonicalValueV1 { + let mut value = call("core.integer.add", vec![left, right]); + *map_field_mut(&mut value, "typeArgs") = list(vec![text("U64")]); + value +} + +fn addition_fixture( + guarded: bool, + unsafe_helper: bool, +) -> (FixtureNames<'static>, RawFixture, Vec) { + called_fixture(|core, target| { + let a = local("arg.0", "U64"); + let body = map_field_mut( + map_field_mut(map_field_mut(core, "functions"), "passNext"), + "body", + ); + *map_field_mut(body, "result") = + add(reference(&a), literal("U64", i128::from(unsafe_helper))); + edit_sum_intent(core, target, guarded); + }) +} + +fn edit_sum_intent(core: &mut CanonicalValueV1, target: &mut CanonicalValueV1, guarded: bool) { + let constraints = map_field(intent(core), "inputConstraints"); + let CanonicalValueV1::Array(items) = constraints else { + panic!("constraints") + }; + let original = items.first().expect("original input guard"); + let predicate = map_field(original, "predicate"); + let left = map_field(predicate, "left").clone(); + let right = map_field(predicate, "right").clone(); + let mut appended = items.clone(); + if guarded { + for (index, operand) in [left.clone(), right.clone()].into_iter().enumerate() { + let mut constraint = original.clone(); + *map_field_mut(&mut constraint, "coordinate") = text(format!("where.addition.{index}")); + *map_field_mut(&mut constraint, "predicate") = map([ + ("kind", text("compare")), + ("op", text("<=")), + ("left", operand), + ("right", literal("U64", 100)), + ]); + appended.push(constraint); + } + } + for (artifact, key) in [(&mut *core, "nodes"), (&mut *target, "pureBindings")] { + *map_field_mut(intent(artifact), "inputConstraints") = list(appended.clone()); + let body = if key == "nodes" { + map_field_mut(intent(artifact), "body") + } else { + intent(artifact) + }; + let CanonicalValueV1::Array(bindings) = map_field_mut(body, key) else { + panic!("bindings") + }; + *map_field_mut(&mut bindings[0], "value") = add(left.clone(), right.clone()); + } +} + +#[test] +fn native_judgments_accept_proven_addition_and_zero_identity_helpers() { + let (names, fixture, package) = addition_fixture(true, false); + let lower = lowerer::lower(lowering_request(names, &fixture)); + let verify = verifier_accepts(names, &fixture, package.clone()); + assert_eq!( + (lower.is_ok(), verify), + (true, true), + "both native judgments must independently support the call" + ); + assert_eq!( + lower.expect("proven native lowering").outputs[0] + .artifact + .bytes, + package + ); +} + +#[test] +fn native_judgments_refuse_missing_sum_proofs_and_unsafe_unused_helpers() { + for (guarded, unsafe_helper) in [(false, false), (true, true)] { + let (names, fixture, package) = addition_fixture(guarded, unsafe_helper); + both_refuse(names, &fixture, package, "missing addition proof"); + } +} + +#[test] +fn legacy_core_without_a_function_table_still_requires_the_addition_proof() { + for guarded in [true, false] { + let (names, fixture, package) = + edited_fixture(|core, target| edit_sum_intent(core, target, guarded)); + let lower = lowerer::lower(lowering_request(names, &fixture)); + let verify = verifier_accepts(names, &fixture, package); + assert_eq!( + (lower.is_ok(), verify), + (guarded, guarded), + "absence of a source-function table cannot skip new arithmetic validation" + ); + } +} + +#[test] +fn addition_predicate_proofs_follow_prefix_order_and_do_not_escape_negation() { + for mode in ["prefix", "late", "negated"] { + let (names, fixture, package) = edited_fixture(|core, target| { + edit_sum_intent(core, target, true); + let CanonicalValueV1::Array(clauses) = map_field(intent(core), "inputConstraints") + else { + panic!("constraints") + }; + let bounds: Vec<_> = clauses + .iter() + .skip(1) + .map(|clause| map_field(clause, "predicate").clone()) + .collect(); + let mut clause = clauses[0].clone(); + let CanonicalValueV1::Array(nodes) = + map_field(map_field(intent(core), "body"), "nodes") + else { + panic!("nodes") + }; + let sum = map_field(&nodes[0], "value").clone(); + let check = map([ + ("kind", text("compare")), + ("op", text("<=")), + ("left", sum), + ("right", literal("U64", 200)), + ]); + let items = if mode == "late" { + vec![check, bounds[0].clone(), bounds[1].clone()] + } else { + vec![bounds[0].clone(), bounds[1].clone(), check] + }; + let predicate = if mode == "negated" { + map([ + ("kind", text("not")), + ( + "value", + map([("kind", text("all")), ("values", list(bounds))]), + ), + ]) + } else { + map([("kind", text("all")), ("values", list(items))]) + }; + *map_field_mut(&mut clause, "predicate") = predicate; + for artifact in [&mut *core, &mut *target] { + *map_field_mut(intent(artifact), "inputConstraints") = list(vec![clause.clone()]); + } + }); + let lower = lowerer::lower(lowering_request(names, &fixture)).is_ok(); + let verify = verifier_accepts(names, &fixture, package); + assert_eq!( + (lower, verify), + (mode == "prefix", mode == "prefix"), + "{mode}: no self-justifying or negation-leaked arithmetic proof" + ); + } +} + +#[test] +fn native_helper_calls_cannot_leak_negated_facts_for_an_uncached_callee() { + for callee_sorts_later in [false, true] { + let (names, fixture, package) = called_fixture(|core, _target| { + let coordinate = text_field(core, "coordinate") + .expect("coordinate") + .to_owned(); + let callee_name = if callee_sorts_later { + "zProofValue" + } else { + "aProofValue" + }; + let x = local("arg.0", "U64"); + let y = local("arg.1", "U64"); + let callee = call(&format!("{coordinate}.{callee_name}"), vec![reference(&y)]); + let compare = |left, op, right| { + map([ + ("kind", text("compare")), + ("op", text(op)), + ("left", left), + ("right", right), + ]) + }; + let bound = compare(reference(&x), "<=", literal("U64", 5)); + let negated = map([ + ("kind", text("not")), + ( + "value", + map([ + ("kind", text("all")), + ( + "values", + list(vec![ + compare(callee.clone(), "==", literal("U64", 1)), + bound.clone(), + ]), + ), + ]), + ), + ]); + let condition = map([ + ("kind", text("all")), + ( + "values", + list(vec![ + bound, + negated, + compare( + add(callee, literal("U64", i128::from(u64::MAX - 1))), + "<=", + literal("U64", i128::from(u64::MAX)), + ), + ]), + ), + ]); + let caller = function( + vec![x, y], + "U64", + vec![], + vec![], + map([ + ("kind", text("if")), + ("predicate", condition), + ("then", literal("U64", 0)), + ("else", literal("U64", 0)), + ]), + ); + let value = function( + vec![local("arg.0", "U64")], + "U64", + vec![], + vec![], + literal("U64", 2), + ); + let CanonicalValueV1::Map(functions) = map_field_mut(core, "functions") else { + panic!("functions") + }; + functions.push((text("mProofCaller"), caller)); + functions.push((text(callee_name), value)); + }); + let lower = lowerer::lower(lowering_request(names, &fixture)).is_ok(); + let verify = verifier_accepts(names, &fixture, package); + assert_eq!((lower, verify), (false, false), "a negated comparison cannot prove the overflowing sum; callee_sorts_later={callee_sorts_later}"); + } +} diff --git a/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/components/lowerer.echo-dpo.component.wasm b/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/components/lowerer.echo-dpo.component.wasm index 85e89e0e..1d304026 100644 Binary files a/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/components/lowerer.echo-dpo.component.wasm and b/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/components/lowerer.echo-dpo.component.wasm differ diff --git a/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/components/verifier.echo-dpo.component.wasm b/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/components/verifier.echo-dpo.component.wasm index 569e47ae..9a766125 100644 Binary files a/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/components/verifier.echo-dpo.component.wasm and b/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/components/verifier.echo-dpo.component.wasm differ diff --git a/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/provider-manifest.echo.json b/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/provider-manifest.echo.json index 3681c45e..d54401f6 100644 --- a/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/provider-manifest.echo.json +++ b/crates/echo-wesley-gen/assets/v1/edict-provider/package/v1/provider-manifest.echo.json @@ -3,7 +3,7 @@ "providerAbi": "edict:target-provider@1.0.0", "provider": { "coordinate": "echo.edict-provider@1", - "digest": "sha256:cba96816605f54dc5e675ab6f473adf858bdaebdceae985f955e930711c8a4f9" + "digest": "sha256:2083dd7057574b040fb9c043b17990e34012004fbed39bdeda253dbb0a522bcc" }, "artifacts": [ { @@ -87,13 +87,13 @@ "artifactKind": "lowerer", "resource": { "coordinate": "echo.dpo.lowerer/component@1", - "digest": "sha256:79066cfc740da4463fd20baec36fe18c6cfb346917fed475b4ef7119fda9408a" + "digest": "sha256:04d5162202ca2ce9b4496c3eff5b7b249d31b33d72e97a23f2e2a86f8d4ed93e" }, "source": { "kind": "component", "component": { "coordinate": "echo.dpo.lowerer/component@1", - "digest": "sha256:79066cfc740da4463fd20baec36fe18c6cfb346917fed475b4ef7119fda9408a" + "digest": "sha256:04d5162202ca2ce9b4496c3eff5b7b249d31b33d72e97a23f2e2a86f8d4ed93e" } } }, @@ -178,13 +178,13 @@ "artifactKind": "verifier", "resource": { "coordinate": "echo.dpo.verifier/component@1", - "digest": "sha256:577c69937594c0aff2461dd60d43507e1f6ce0903ca2b17ff02919d73efd9b28" + "digest": "sha256:3451e95a7d084d4874c30833f90f5c21012e8341f35ed0f0888d4d268a768b11" }, "source": { "kind": "component", "component": { "coordinate": "echo.dpo.verifier/component@1", - "digest": "sha256:577c69937594c0aff2461dd60d43507e1f6ce0903ca2b17ff02919d73efd9b28" + "digest": "sha256:3451e95a7d084d4874c30833f90f5c21012e8341f35ed0f0888d4d268a768b11" } } } diff --git a/crates/echo-wesley-gen/tests/provider_package.rs b/crates/echo-wesley-gen/tests/provider_package.rs index 6dcf8978..c42b848d 100644 --- a/crates/echo-wesley-gen/tests/provider_package.rs +++ b/crates/echo-wesley-gen/tests/provider_package.rs @@ -65,7 +65,7 @@ const SEMANTIC_DIGEST: &str = const RELEASE_DIGEST: &str = "sha256:c39449495281b51f978468d08c21e93bcfa423176063b41675da61e4674b0066"; const PACKAGE_ARTIFACT_SHA256: &str = - "cba96816605f54dc5e675ab6f473adf858bdaebdceae985f955e930711c8a4f9"; + "2083dd7057574b040fb9c043b17990e34012004fbed39bdeda253dbb0a522bcc"; const OTHER_PACKAGE_ARTIFACT_SHA256: &str = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; diff --git a/crates/echo-wesley-gen/tests/provider_package_corpus.rs b/crates/echo-wesley-gen/tests/provider_package_corpus.rs index bcb3d721..13feaf52 100644 --- a/crates/echo-wesley-gen/tests/provider_package_corpus.rs +++ b/crates/echo-wesley-gen/tests/provider_package_corpus.rs @@ -11,9 +11,9 @@ use std::sync::atomic::{AtomicU64, Ordering}; use sha2::{Digest as _, Sha256}; const EXPECTED_PROVIDER_DIGEST: &str = - "sha256:cba96816605f54dc5e675ab6f473adf858bdaebdceae985f955e930711c8a4f9"; + "sha256:2083dd7057574b040fb9c043b17990e34012004fbed39bdeda253dbb0a522bcc"; const EXPECTED_MANIFEST_RAW_SHA256: &str = - "d9ec3c528d0b27434606ecef27a552eb466034866cbb3cb04d169241f772a6df"; + "933201583b043c3b0bdb4be3d6ece5fb2d21ea0aecf5c447c1a9d20639bc39a8"; const PACKAGE_PATHS: [&str; 25] = [ "components/lowerer.echo-dpo.component.wasm", diff --git a/crates/warp-core/Cargo.toml b/crates/warp-core/Cargo.toml index 1d42b766..ef55c4be 100644 --- a/crates/warp-core/Cargo.toml +++ b/crates/warp-core/Cargo.toml @@ -152,6 +152,10 @@ required-features = ["trusted_runtime"] name = "edict_byte_literal_tests" required-features = ["trusted_runtime"] +[[test]] +name = "edict_unsigned_addition_tests" +required-features = ["trusted_runtime"] + [[test]] name = "edict_pure_unsigned_subtraction_tests" required-features = ["trusted_runtime"] diff --git a/crates/warp-core/src/edict_pure/evaluate.rs b/crates/warp-core/src/edict_pure/evaluate.rs index bd3651f3..c139b44e 100644 --- a/crates/warp-core/src/edict_pure/evaluate.rs +++ b/crates/warp-core/src/edict_pure/evaluate.rs @@ -226,7 +226,7 @@ pub(crate) fn expression( validate(&value, &helper.ty, meter, depth + 1)?; Ok(value) } - Expr::UnsignedSubtract { max, left, right } => { + Expr::UnsignedSubtract { max, left, right } | Expr::UnsignedAdd { max, left, right } => { let left = expression(left, locals, helpers, meter, depth + 1)?; let right = expression(right, locals, helpers, meter, depth + 1)?; let ty = RuntimeType::Unsigned(*max); @@ -235,10 +235,14 @@ pub(crate) fn expression( let (Value::Integer(left), Value::Integer(right)) = (left, right) else { return Err(Error::InvalidArtifact); }; - let difference = left - .checked_sub(right) - .filter(|value| *value >= 0) - .ok_or(Error::InvalidArtifact)?; + let difference = if matches!(expr, Expr::UnsignedAdd { .. }) { + left.checked_add(right) + .filter(|value| *value <= i128::from(*max)) + } else { + left.checked_sub(right) + } + .filter(|value| *value >= 0) + .ok_or(Error::InvalidArtifact)?; meter.copy(&Value::Integer(difference)) } Expr::ByteUtf8 { min, max, value } => { @@ -438,6 +442,70 @@ pub(crate) fn validate( mod tests { use super::*; + #[test] + fn unsigned_addition_checks_both_widths_and_charges_the_result() -> Result<(), Error> { + let limits = EvaluationLimits { + max_package_bytes: 1024, + max_input_bytes: 1024, + max_steps: 8, + max_allocated_bytes: 192, + max_output_bytes: 1024, + }; + let sum = |max, left, right| Expr::UnsignedAdd { + max, + left: Box::new(Expr::Constant(Value::Integer(left))), + right: Box::new(Expr::Constant(Value::Integer(right))), + }; + for max in [u64::from(u32::MAX), u64::MAX] { + let expr = sum(max, i128::from(max), 0); + let mut exact = Meter::new(limits); + assert_eq!( + expression(&expr, &BTreeMap::new(), &BTreeMap::new(), &mut exact, 0)?, + Value::Integer(i128::from(max)) + ); + assert_eq!(exact.usage(), (8, 192)); + for (left, right) in [(i128::from(max), 1), (-1, 0), (i128::from(max) + 1, 0)] { + assert_eq!( + expression( + &sum(max, left, right), + &BTreeMap::new(), + &BTreeMap::new(), + &mut Meter::new(limits), + 0 + ), + Err(Error::InvalidArtifact) + ); + } + assert_eq!( + expression( + &expr, + &BTreeMap::new(), + &BTreeMap::new(), + &mut Meter::new(EvaluationLimits { + max_steps: 7, + ..limits + }), + 0 + ), + Err(Error::StepBudgetExceeded) + ); + assert_eq!( + expression( + &expr, + &BTreeMap::new(), + &BTreeMap::new(), + &mut Meter::new(EvaluationLimits { + max_allocated_bytes: 191, + ..limits + }), + 0 + ), + Err(Error::AllocationBudgetExceeded) + ); + } + Ok(()) + } + #[test] fn byte_concat_admits_both_copy_lengths_before_allocation() -> Result<(), Error> { let limits = EvaluationLimits { diff --git a/crates/warp-core/src/edict_pure/functions.rs b/crates/warp-core/src/edict_pure/functions.rs index 1b25e564..29278497 100644 --- a/crates/warp-core/src/edict_pure/functions.rs +++ b/crates/warp-core/src/edict_pure/functions.rs @@ -404,6 +404,16 @@ fn infer( min: a_min.checked_add(*b_min).ok_or(Error::InvalidArtifact)?, max: a_max.checked_add(*b_max).ok_or(Error::InvalidArtifact)?, }), + ("core.integer.add", [left, right], [expected @ RuntimeType::Unsigned(max)]) + if left == expected && right == expected => + { + let left = unsigned_ceiling(&arguments[0], *max, parser, depth + 1)?; + let right = unsigned_ceiling(&arguments[1], *max, parser, depth + 1)?; + if left.checked_add(right).is_none_or(|sum| sum > *max) { + return Err(Error::UnsupportedProgram); + } + Ok(expected.clone()) + } // No caller where proof crosses a fresh frame. This target's // first source-function subset proves partial intrinsics only // from literal offsets/operands, refusing all other cases. @@ -437,6 +447,30 @@ fn infer( } } +// Fresh helper frames receive no caller constraints. Constants and already +// checked nested additions can narrow a bound; every other term has its full +// declared width. The parser's combined work/depth ceiling covers this walk. +fn unsigned_ceiling( + value: &Value, + max: u64, + parser: &mut Parser<'_>, + depth: usize, +) -> Result { + parser.enter(depth)?; + if text_field(value, "kind")? == "const" { + return unsigned_literal(value); + } + if text_field(value, "kind")? == "call" && text_field(value, "callee")? == "core.integer.add" { + let [left, right] = array(field(value, "args")?)? else { + return Err(Error::InvalidArtifact); + }; + return unsigned_ceiling(left, max, parser, depth + 1)? + .checked_add(unsigned_ceiling(right, max, parser, depth + 1)?) + .ok_or(Error::UnsupportedProgram); + } + Ok(max) +} + fn unsigned_literal(value: &Value) -> Result { if text_field(value, "kind")? != "const" { return Err(Error::UnsupportedProgram); @@ -628,7 +662,9 @@ impl Heights<'_> { .max(self.expr(end, depth + 1)?) + 1 } - Expr::ByteConcat { left, right, .. } | Expr::UnsignedSubtract { left, right, .. } => { + Expr::ByteConcat { left, right, .. } + | Expr::UnsignedSubtract { left, right, .. } + | Expr::UnsignedAdd { left, right, .. } => { self.expr(left, depth + 1)? .max(self.expr(right, depth + 1)?) + 1 @@ -797,4 +833,63 @@ mod predicate_validation_tests { } } } + #[test] + fn source_helper_addition_proves_identity_without_borrowing_caller_bounds() { + for (width, max) in [("U32", u64::from(u32::MAX)), ("U64", u64::MAX)] { + let local = map([ + ("id", Value::Text("arg.0".into())), + ("alphaName", Value::Text("$arg0".into())), + ("type", Value::Text(width.into())), + ]); + for extra in [0, 1] { + let call = map([ + ("kind", Value::Text("call".into())), + ("callee", Value::Text("core.integer.add".into())), + ("typeArgs", Value::Array(vec![Value::Text(width.into())])), + ( + "args", + Value::Array(vec![ + map([ + ("kind", Value::Text("local".into())), + ("ref", local.clone()), + ]), + map([ + ("kind", Value::Text("const".into())), + ( + "value", + map([ + ("kind", Value::Text("int".into())), + ("width", Value::Text(width.into())), + ("value", Value::Integer(extra)), + ]), + ), + ]), + ]), + ), + ]); + let types = Value::Map(vec![]); + let mut parser = Parser { + types: &types, + coordinate: "generic.addition@1", + remaining: MAX_PROGRAM_NODES, + }; + let result = infer( + &call, + &BTreeMap::from([("arg.0", &local)]), + &BTreeMap::new(), + true, + &mut parser, + 0, + ); + assert_eq!( + result, + if extra == 0 { + Ok(RuntimeType::Unsigned(max)) + } else { + Err(Error::UnsupportedProgram) + } + ); + } + } + } } diff --git a/crates/warp-core/src/edict_pure/model.rs b/crates/warp-core/src/edict_pure/model.rs index 30941636..a826b5f1 100644 --- a/crates/warp-core/src/edict_pure/model.rs +++ b/crates/warp-core/src/edict_pure/model.rs @@ -48,6 +48,11 @@ pub(crate) enum Expr { left: Box, right: Box, }, + UnsignedAdd { + max: u64, + left: Box, + right: Box, + }, } #[derive(Debug, PartialEq, Eq)] diff --git a/crates/warp-core/src/edict_pure/syntax.rs b/crates/warp-core/src/edict_pure/syntax.rs index 0acaae06..cc24469c 100644 --- a/crates/warp-core/src/edict_pure/syntax.rs +++ b/crates/warp-core/src/edict_pure/syntax.rs @@ -188,7 +188,7 @@ impl Parser<'_> { right: Box::new(self.expr(right, depth + 1)?), }); } - if callee == "core.integer.subtract" { + if callee == "core.integer.subtract" || callee == "core.integer.add" { let ([left, right], [width]) = (args, types) else { return Err(Error::UnsupportedProgram); }; @@ -197,10 +197,12 @@ impl Parser<'_> { "U64" => u64::MAX, _ => return Err(Error::UnsupportedProgram), }; - return Ok(Expr::UnsignedSubtract { - max, - left: Box::new(self.expr(left, depth + 1)?), - right: Box::new(self.expr(right, depth + 1)?), + let left = Box::new(self.expr(left, depth + 1)?); + let right = Box::new(self.expr(right, depth + 1)?); + return Ok(if callee == "core.integer.add" { + Expr::UnsignedAdd { max, left, right } + } else { + Expr::UnsignedSubtract { max, left, right } }); } if !types.is_empty() { diff --git a/crates/warp-core/tests/edict_unsigned_addition_tests.rs b/crates/warp-core/tests/edict_unsigned_addition_tests.rs new file mode 100644 index 00000000..4e7e1ae0 --- /dev/null +++ b/crates/warp-core/tests/edict_unsigned_addition_tests.rs @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: Apache-2.0 +// © James Ross Ω FLYING•ROBOTS +//! Execute an unmodified public compiler package containing proven unsigned sums. +#![cfg(feature = "trusted_runtime")] +#![allow(clippy::unwrap_used, clippy::panic)] +use echo_edict_canonical::{ + decode_canonical_cbor_v1 as decode, encode_canonical_cbor_v1 as encode, + CanonicalValueV1 as Value, +}; +use warp_core::edict_pure::{evaluate, EvaluationError, EvaluationLimits}; + +fn package() -> Vec { + hex::decode( + include_str!( + "fixtures/edict-unsigned-addition-control/executable-operation-package.cbor.hex" + ) + .trim(), + ) + .unwrap() +} +fn pin() -> [u8; 32] { + hex::decode("75381ef9f3421a74f2fa21e256705e9737b94eda1f7549b5b23c254799254086") + .unwrap() + .try_into() + .unwrap() +} +fn limits() -> EvaluationLimits { + EvaluationLimits { + max_package_bytes: 32_768, + max_input_bytes: 4096, + max_steps: 10_000, + max_allocated_bytes: 16_777_216, + max_output_bytes: 4096, + } +} +fn record(fields: impl IntoIterator) -> Value { + Value::Map( + fields + .into_iter() + .map(|(name, value)| (Value::Text(name.into()), value)) + .collect(), + ) +} +fn input(left: u64, right: u64, counter: u64) -> Value { + record([ + ("bufferId", Value::Bytes(vec![1; 32])), + ("basisHeadId", Value::Bytes(vec![2; 32])), + ("startByte", Value::Integer(left.into())), + ("endByte", Value::Integer(right.into())), + ("counter32", Value::Integer(counter.into())), + ("replacement", Value::Bytes(vec![0x80, 0xff])), + ]) +} + +#[test] +fn public_compiler_unsigned_sums_execute_at_both_width_boundaries() { + for (left, right, counter, want64, want32, empty) in [ + (0, 0, 0, 0, 1, 1), + (0, 1, 7, 1, 8, 0), + ( + u64::MAX - 1, + 1, + u64::from(u32::MAX) - 1, + u64::MAX, + u64::from(u32::MAX), + 0, + ), + (u64::MAX - 1, 0, 0, u64::MAX - 1, 1, 0), + ] { + let result = evaluate( + &package(), + pin(), + &encode(&input(left, right, counter)).unwrap(), + limits(), + ) + .unwrap(); + let want = record([ + ("bufferId", Value::Bytes(vec![1; 32])), + ("basisHeadId", Value::Bytes(vec![2; 32])), + ("startByte", Value::Integer(left.into())), + ("endByte", Value::Integer(right.into())), + ("replacement", Value::Bytes(vec![0x80, 0xff])), + ("rangeIsEmpty", Value::Integer(empty)), + ("createdLeafCeiling", Value::Integer(4096)), + ("sum64", Value::Integer(want64.into())), + ("next32", Value::Integer(want32.into())), + ]); + assert_eq!( + decode(&result.output).unwrap(), + decode(&encode(&want).unwrap()).unwrap() + ); + } +} + +#[test] +fn public_addition_guards_refuse_inputs_outside_the_proven_domain() { + for (left, right, counter) in [(u64::MAX, 1, 0), (0, 2, 0), (0, 0, u64::from(u32::MAX))] { + assert!(matches!( + evaluate( + &package(), + pin(), + &encode(&input(left, right, counter)).unwrap(), + limits() + ), + Err(EvaluationError::InputConstraintFailed(_)) + )); + } +} + +fn source_function_package() -> (Vec, [u8; 32]) { + let bytes = hex::decode( + include_str!("fixtures/edict-unsigned-addition-source-functions/executable-operation-package.cbor.hex").trim(), + ).unwrap(); + let pin = hex::decode("a8774d9e8ba5dbe1e4eaffee4ec8f10f7b80ee9812b5569e8c2d290e57de9443") + .unwrap() + .try_into() + .unwrap(); + (bytes, pin) +} +fn arithmetic_input(left: u64, right: u64, counter: u64) -> Vec { + encode(&record([ + ("left", Value::Integer(left.into())), + ("right", Value::Integer(right.into())), + ("counter", Value::Integer(counter.into())), + ])) + .unwrap() +} + +#[test] +fn public_source_function_addition_executes_at_both_unsigned_width_boundaries() { + let (package, pin) = source_function_package(); + for (left, right, counter, want64, want32) in [ + (0, 0, 0, 0, 1), + (0, 1, 7, 1, 8), + ( + u64::MAX - 1, + 1, + u64::from(u32::MAX) - 1, + u64::MAX, + u64::from(u32::MAX), + ), + ] { + let result = evaluate( + &package, + pin, + &arithmetic_input(left, right, counter), + limits(), + ) + .unwrap(); + let want = encode(&record([ + ("sum64", Value::Integer(want64.into())), + ("next32", Value::Integer(want32.into())), + ])) + .unwrap(); + assert_eq!(decode(&result.output).unwrap(), decode(&want).unwrap()); + } +} + +#[test] +fn public_source_function_addition_refuses_inputs_outside_its_proof_domain() { + let (package, pin) = source_function_package(); + for (left, right, counter) in [(u64::MAX, 1, 0), (0, 2, 0), (0, 0, u64::from(u32::MAX))] { + assert!(matches!( + evaluate( + &package, + pin, + &arithmetic_input(left, right, counter), + limits() + ), + Err(EvaluationError::InputConstraintFailed(_)) + )); + } +} diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/README.md b/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/README.md new file mode 100644 index 00000000..6e6bd7d5 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/README.md @@ -0,0 +1,15 @@ + + +# Public unsigned-addition control + +The source and unmodified hex carriers come from Edict's public JSONL application +build, using compiler 3df3a6437f7999206b12b4dd6b5400db7a612fd8 and the retained +legacy provider package used by the byte-literal public proof. The source +adds guarded U64 and U32 sums to the ordinary returned value. It has no source +functions, graph writes, Action admission, Tick or recovery claim. + +The accepted verifier report binds package identity +`75381ef9f3421a74f2fa21e256705e9737b94eda1f7549b5b23c254799254086`. +This fixture witnesses runtime execution of a genuinely compiled new call. +It does not witness the strict source-function provider judgment or a new +provider-component promotion. Those require separate producer evidence. diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/ReplaceRange.edict b/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/ReplaceRange.edict new file mode 100644 index 00000000..b0f8dc16 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/ReplaceRange.edict @@ -0,0 +1,50 @@ +package jedit.text.replace_range@1; + +use lawpack jedit.text@1 digest "sha256:95758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e" as text; + +type ReplaceRangeInput = { + bufferId: text.BufferId, + basisHeadId: text.HeadId, + startByte: U64, + endByte: U64, + replacement: text.ReplacementBytes, + counter32: U32, +}; + +type ReplaceRangeBoundary = { + bufferId: text.BufferId, + basisHeadId: text.HeadId, + startByte: U64, + endByte: U64, + replacement: text.ReplacementBytes, + rangeIsEmpty: U32, + createdLeafCeiling: U64, + sum64: U64, + next32: U32, +}; + +intent replaceRange(input: ReplaceRangeInput) returns ReplaceRangeBoundary + profile text.replaceRange + basis input.basisHeadId + budget <= text.replaceRangeBudget + where input.startByte <= 18446744073709551614 + where input.endByte <= 1 + where input.counter32 <= 4294967294 +{ + let sum64: U64 = input.startByte + input.endByte; + let next32: U32 = input.counter32 + 1; + let createdLeafCeiling: U64 = text.maxCreatedLeafCount(); + let rangeIsEmpty = if input.startByte == input.endByte then 1u32 else 0u32; + + return { + bufferId: input.bufferId, + basisHeadId: input.basisHeadId, + startByte: input.startByte, + endByte: input.endByte, + replacement: input.replacement, + rangeIsEmpty, + createdLeafCeiling, + sum64, + next32, + }; +} diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/executable-operation-package.cbor.hex b/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/executable-operation-package.cbor.hex new file mode 100644 index 00000000..6ae60ef2 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/executable-operation-package.cbor.hex @@ -0,0 +1 @@ +aa66736368656d6178196563686f2e6f7065726174696f6e2d7061636b6167652f76316770726f6772616d592df8a7646b696e647821636f6d70696c65722d70726f64756365642d626f756e6465642d707572652f763166696e74656e746c7265706c61636552616e676566736368656d6178266563686f2e636f6d70696c65722d70726f64756365642d707572652d70726f6772616d2f76316d636f72655f61727469666163745911caa6657479706573a6715265706c61636552616e6765496e707574a2646b696e64665265636f7264666669656c6473a667656e644279746563553634686275666665724964756a656469742e7465787440312e427566666572496469636f756e74657233326355333269737461727442797465635536346b6261736973486561644964736a656469742e7465787440312e4865616449646b7265706c6163656d656e74781d6a656469742e7465787440312e5265706c6163656d656e744279746573736a656469742e7465787440312e486561644964a3646b696e64674e6f6d696e616c68636f6e7472616374736a656469742e7465787440312e4865616449646e726570726573656e746174696f6e736a656469742e7465787440312e4e6f64654964736a656469742e7465787440312e4e6f64654964a3636d61781820636d696e1820646b696e64654279746573745265706c61636552616e6765426f756e64617279a2646b696e64665265636f7264666669656c6473a96573756d363463553634666e65787433326355333267656e644279746563553634686275666665724964756a656469742e7465787440312e427566666572496469737461727442797465635536346b6261736973486561644964736a656469742e7465787440312e4865616449646b7265706c6163656d656e74781d6a656469742e7465787440312e5265706c6163656d656e7442797465736c72616e67654973456d7074796355333272637265617465644c6561664365696c696e6763553634756a656469742e7465787440312e4275666665724964a3646b696e64674e6f6d696e616c68636f6e7472616374756a656469742e7465787440312e42756666657249646e726570726573656e746174696f6e736a656469742e7465787440312e4e6f64654964781d6a656469742e7465787440312e5265706c6163656d656e744279746573a2636d61781a00100000646b696e6465427974657367696d706f72747381a263726566a26269646c6a656469742e746578744031666469676573748266736861323536582095758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e646b696e64676c61777061636b67696e74656e7473a16c7265706c61636552616e6765a764626f6479a3656e6f64657384a3646b696e64636c65746576616c7565a4646172677382a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469737461727442797465a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467656e6442797465646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e61646468747970654172677381635536346762696e64696e67a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30a3646b696e64636c65746576616c7565a4646172677382a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469636f756e7465723332a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75650165776964746863553332646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e61646468747970654172677381635533326762696e64696e67a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c31a3646b696e64636c65746576616c7565a4646172677380646b696e646463616c6c6663616c6c656578206a656469742e7465787440312e6d6178437265617465644c656166436f756e74687479706541726773806762696e64696e67a3626964676c6f63616c2e3264747970656355363469616c7068614e616d6567246c6f63616c32a3646b696e64636c65746576616c7565a464656c7365a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75650065776964746863553332646b696e64626966647468656ea2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c7565016577696474686355333269707265646963617465a4626f70623d3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469737461727442797465657269676874a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467656e64427974656762696e64696e67a3626964676c6f63616c2e3364747970656355333269616c7068614e616d6567246c6f63616c33666c6f63616c7385a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c31a3626964676c6f63616c2e3264747970656355363469616c7068614e616d6567246c6f63616c32a3626964676c6f63616c2e3364747970656355333269616c7068614e616d6567246c6f63616c3366726573756c74a2646b696e64667265636f7264666669656c6473a96573756d3634a263726566a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30646b696e64656c6f63616c666e6578743332a263726566a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c31646b696e64656c6f63616c67656e6442797465a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467656e6442797465686275666665724964a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6468627566666572496469737461727442797465a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64697374617274427974656b6261736973486561644964a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c646b62617369734865616449646b7265706c6163656d656e74a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c646b7265706c6163656d656e746c72616e67654973456d707479a263726566a3626964676c6f63616c2e3364747970656355333269616c7068614e616d6567246c6f63616c33646b696e64656c6f63616c72637265617465644c6561664365696c696e67a263726566a3626964676c6f63616c2e3264747970656355363469616c7068614e616d6567246c6f63616c32646b696e64656c6f63616c656261736973a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c646b626173697348656164496465696e707574782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e707574666f7574707574782f6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765426f756e6461727970696e707574436f6e73747261696e747383a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467656e6442797465657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c756501657769647468635536346a636f6f7264696e6174656777686572652e31a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469636f756e7465723332657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75651afffffffe657769647468635533326a636f6f7264696e6174656777686572652e32a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469737461727442797465657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75651bfffffffffffffffe657769647468635536346a636f6f7264696e6174656777686572652e3074636f72654576616c756174696f6e427564676574a3686d617853746570731a001000006e6d61784f757470757442797465731a00800000716d6178416c6c6f636174656442797465731a01000000781872657175697265644f7065726174696f6e50726f66696c65781f636f6e74696e75756d2e70726f66696c652e726561642d77726974652f76316a61706956657273696f6e6d65646963742e636f72652f76316a636f6f7264696e617465781a6a656469742e746578742e7265706c6163655f72616e6765403178187265717569726564436f72654361706162696c697469657380727461726765745f69725f6172746966616374590e98a6646b696e64707461726765744972417274696661637466646f6d61696e6f6563686f2e7370616e2d69722f763167696e74656e7473a16c7265706c61636552616e6765a8656261736973a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c646b62617369734865616449646573746570738066726573756c74a2646b696e64667265636f7264666669656c6473a96573756d3634a263726566a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30646b696e64656c6f63616c666e6578743332a263726566a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c31646b696e64656c6f63616c67656e6442797465a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467656e6442797465686275666665724964a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6468627566666572496469737461727442797465a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64697374617274427974656b6261736973486561644964a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c646b62617369734865616449646b7265706c6163656d656e74a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c646b7265706c6163656d656e746c72616e67654973456d707479a263726566a3626964676c6f63616c2e3364747970656355333269616c7068614e616d6567246c6f63616c33646b696e64656c6f63616c72637265617465644c6561664365696c696e67a263726566a3626964676c6f63616c2e3264747970656355363469616c7068614e616d6567246c6f63616c32646b696e64656c6f63616c6c7075726542696e64696e677384a3626964767265706c61636552616e67652e62696e64696e672e306576616c7565a4646172677382a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469737461727442797465a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467656e6442797465646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e61646468747970654172677381635536346762696e64696e67a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30a3626964767265706c61636552616e67652e62696e64696e672e316576616c7565a4646172677382a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469636f756e7465723332a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75650165776964746863553332646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e61646468747970654172677381635533326762696e64696e67a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c31a3626964767265706c61636552616e67652e62696e64696e672e326576616c7565a4646172677380646b696e646463616c6c6663616c6c656578206a656469742e7465787440312e6d6178437265617465644c656166436f756e74687479706541726773806762696e64696e67a3626964676c6f63616c2e3264747970656355363469616c7068614e616d6567246c6f63616c32a3626964767265706c61636552616e67652e62696e64696e672e336576616c7565a464656c7365a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75650065776964746863553332646b696e64626966647468656ea2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c7565016577696474686355333269707265646963617465a4626f70623d3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469737461727442797465657269676874a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467656e64427974656762696e64696e67a3626964676c6f63616c2e3364747970656355333269616c7068614e616d6567246c6f63616c336c726571756972656d656e74738070696e707574436f6e73747261696e747383a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467656e6442797465657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c756501657769647468635536346a636f6f7264696e6174656777686572652e31a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469636f756e7465723332657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75651afffffffe657769647468635533326a636f6f7264696e6174656777686572652e32a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065782c6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6469737461727442797465657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75651bfffffffffffffffe657769647468635536346a636f6f7264696e6174656777686572652e30706f7065726174696f6e50726f66696c65781f636f6e74696e75756d2e70726f66696c652e726561642d77726974652f763174636f72654576616c756174696f6e427564676574a3686d617853746570731a001000006e6d61784f757470757442797465731a00800000716d6178416c6c6f636174656442797465731a010000006d74617267657450726f66696c65a26269646a6563686f2e64706f403166646967657374826673686132353658202e2494121aecf5e6a2d920f5fb85408825d394765fad41484c416397c920fb046f73656d616e746963436c6f73757265a2686c61777061636b7381a26269646c6a656469742e746578744031666469676573748266736861323536582095758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e6a736f75726365436f7265a2626964781a6a656469742e746578742e7265706c6163655f72616e676540316664696765737482667368613235365820ec8d1c97adb778bfab1cdd211fe2d4fa917abbcc8996d85cb7a02c3b07bf0af474736f75726365436f7265436f6f7264696e617465781a6a656469742e746578742e7265706c6163655f72616e6765403178186c61777061636b5f6578706f7274735f617274696661637459093aa665747970657385a26a636f6f7264696e617465736a656469742e7465787440312e4e6f646549646a646566696e6974696f6e6f42797465733c65786163743d33323ea26a636f6f7264696e617465756a656469742e7465787440312e42756666657249646a646566696e6974696f6e781c4e6f6d696e616c3c6a656469742e7465787440312e4e6f646549643ea26a636f6f7264696e617465736a656469742e7465787440312e4865616449646a646566696e6974696f6e781c4e6f6d696e616c3c6a656469742e7465787440312e4e6f646549643ea26a636f6f7264696e617465781d6a656469742e7465787440312e5265706c6163656d656e7442797465736a646566696e6974696f6e7242797465733c6d61783d313034383537363ea26a636f6f7264696e617465781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6a646566696e6974696f6e6f537472696e673c6d61783d3235363e67656666656374738069636f6e7374616e747382a36474797065635536346576616c75651910006a636f6f7264696e617465781d6a656469742e7465787440312e6d6178437265617465644c6561766573a36474797065635536346576616c75651910006a636f6f7264696e617465781f6a656469742e7465787440312e6d6178437265617465644272616e636865736c6f62737472756374696f6e738aa36a636f6f7264696e617465781e6a656469742e7465787440312e52616e67654f72646572496e76616c69646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781d6a656469742e7465787440312e52616e67654f75744f66426f756e64736d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e61746578206a656469742e7465787440312e55746638426f756e64617279496e76616c69646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465716a656469742e7465787440312e4e6f4f706d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781e6a656469742e7465787440312e42617369734e6f7443616e6f6e6963616c6d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781f6a656469742e7465787440312e41726974686d657469634f766572666c6f776d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e61746578186a656469742e7465787440312e466163744d697373696e676d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736d7265736f757263654661756c74a36a636f6f7264696e617465781a6a656469742e7465787440312e466163744d616c666f726d65646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e61746578246a656469742e7465787440312e436f6e74656e744964656e746974794d69736d617463686d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e617465781a6a656469742e7465787440312e4d616c666f726d6564526f70656d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c746d7075726546756e6374696f6e7381a864626f6479a264626f6479a3666c6f63616c738066726573756c74a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c7565191000657769647468635536346862696e64696e67738066706172616d738066736f757263656565646963746a636f6f7264696e61746578206a656469742e7465787440312e6d6178437265617465644c656166436f756e746a72657475726e54797065635536346c636f737454656d706c617465781f6a656469742e7465787440312e7265706c61636552616e67654275646765746e706172616d657465725479706573806e74797065506172616d6574657273807064657465726d696e69736d436c61737365746f74616c716f7065726174696f6e50726f66696c6573a178196a656469742e7465787440312e7265706c61636552616e6765a26d6f7074696354656d706c617465a6696f707469634b696e64736166666563745265696e746567726174696f6e6c626f756e646172794b696e64666166666563746d626173697354656d706c617465781b6a656469742e7465787440312e65786163744865616442617369736d737570706f7274506f6c696379781e6a656469742e7465787440312e6261736973426f756e64537570706f72746f6c6f7373446973706f736974696f6e756a656469742e7465787440312e6c6f73736c657373736170657274757265526571756972656d656e74a26372656678226a656469742e7465787440312e7265706c61636552616e6765466f6f747072696e74646b696e64781b6162737472616374466f6f747072696e744f626c69676174696f6e6f65666665637450726564696361746578206a656469742e7465787440312e7265706c61636552616e676545666665637473781a726573756c745f70726f6a656374696f6e5f617274696661637459038da566736368656d61781a65646963742e726573756c742d70726f6a656374696f6e2f76316a65787072657373696f6ea2646b696e64667265636f7264666669656c6473a96573756d3634a3646b696e6466736f7572636564706174688066736f75726365a2646b696e646b7075726542696e64696e676962696e64696e674964767265706c61636552616e67652e62696e64696e672e30666e6578743332a3646b696e6466736f7572636564706174688066736f75726365a2646b696e646b7075726542696e64696e676962696e64696e674964767265706c61636552616e67652e62696e64696e672e3167656e6442797465a3646b696e6466736f7572636564706174688167656e644279746566736f75726365a1646b696e64706170706c69636174696f6e496e707574686275666665724964a3646b696e6466736f7572636564706174688168627566666572496466736f75726365a1646b696e64706170706c69636174696f6e496e70757469737461727442797465a3646b696e6466736f757263656470617468816973746172744279746566736f75726365a1646b696e64706170706c69636174696f6e496e7075746b6261736973486561644964a3646b696e6466736f757263656470617468816b626173697348656164496466736f75726365a1646b696e64706170706c69636174696f6e496e7075746b7265706c6163656d656e74a3646b696e6466736f757263656470617468816b7265706c6163656d656e7466736f75726365a1646b696e64706170706c69636174696f6e496e7075746c72616e67654973456d707479a3646b696e6466736f7572636564706174688066736f75726365a2646b696e646b7075726542696e64696e676962696e64696e674964767265706c61636552616e67652e62696e64696e672e3372637265617465644c6561664365696c696e67a3646b696e6466736f7572636564706174688066736f75726365a2646b696e646b7075726542696e64696e676962696e64696e674964767265706c61636552616e67652e62696e64696e672e326a6f757470757454797065782f6a656469742e746578742e7265706c6163655f72616e676540312e5265706c61636552616e6765426f756e646172796e6d61784f757470757442797465731a00800000736f7065726174696f6e436f6f7264696e61746578276a656469742e746578742e7265706c6163655f72616e676540312e7265706c61636552616e67656c7061636b6167655f6b696e647821636f6d70696c65722d70726f64756365642d626f756e6465642d707572652f76316e6275646765745f6365696c696e67a3696d61785f73746570731a00100000706d61785f6f75747075745f62797465731a00800000736d61785f616c6c6f63617465645f62797465731a010000007073656d616e7469635f636c6f73757265a86d636f72655f6964656e746974795820ec8d1c97adb778bfab1cdd211fe2d4fa917abbcc8996d85cb7a02c3b07bf0af4706c61777061636b5f6964656e74697479582095758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e726c61777061636b5f636f6f7264696e6174656c6a656469742e746578744031727461726765745f69725f6964656e7469747958202c8b71d6a3463fd944ac73554e5a691936142afb278771706e2cb61e2c055da77565646963745f736f757263655f6964656e746974795820441d0d9fa3826e2f32ce715b6da8e05673530bffb4a1fee8c420ba6790b0a1d3781a63616e6f6e6963616c5f6d65616e696e675f6964656e746974795820ec8d1c97adb778bfab1cdd211fe2d4fa917abbcc8996d85cb7a02c3b07bf0af4781b6170706c69636174696f6e5f736368656d615f6964656e7469747958201f436d717d3f349cc6f4c3431730ff4182d65c87fb6c1233692fc40fbd71bf02781d6170706c69636174696f6e5f736368656d615f636f6f7264696e617465756a656469742e746578742e6578706f7274732f7631746f7065726174696f6e5f636f6f7264696e61746578276a656469742e746578742e7265706c6163655f72616e676540312e7265706c61636552616e6765777461726765745f70726f66696c655f6964656e7469747958202e2494121aecf5e6a2d920f5fb85408825d394765fad41484c416397c920fb04781a617574686f726974795f70726f66696c655f6964656e746974795820fbaf54b61a71d54139a37955fe1bae42ee1d013f9aff2b09f546084fe3b3ced6781b666f6f747072696e745f636f6e74726163745f6964656e746974795820bf4da382443c8f8a740b3d28b77e3cfd8b39cb1608a9b885de59e1cb05d70365781c696e7465727072657465725f70726f66696c655f6964656e746974795820dc267bf35dc047a748593bbc5eaf6d9565b6206bfd84caf3cbe29653c6f34a76 diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/verification-report.cbor.hex b/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/verification-report.cbor.hex new file mode 100644 index 00000000..27e1ac11 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-control/verification-report.cbor.hex @@ -0,0 +1 @@ +a8676f7574636f6d65686163636570746564677061636b616765a2626964782165786563757461626c652d6f7065726174696f6e2d7061636b6167652e6563686f666469676573748266736861323536582075381ef9f3421a74f2fa21e256705e9737b94eda1f7549b5b23c254799254086687461726765744972a26269646f6563686f2e7370616e2d69722f763166646967657374826673686132353658202c8b71d6a3463fd944ac73554e5a691936142afb278771706e2cb61e2c055da76a61706956657273696f6e78296563686f2e6f7065726174696f6e2d7061636b6167652d76657269666965722d7265706f72742f76316d646961676e6f73746963416269a26269647465646963742e646961676e6f73746963732f7631666469676573748266736861323536582028fd72a98223153982ca084c29dbb1b2d430623967ab3b6db9d7fee668e614b96f646961676e6f737469634279746573407165786563757461626c655375626a656374a2656279746573590151a4677061636b616765a2626964782165786563757461626c652d6f7065726174696f6e2d7061636b6167652e6563686f666469676573748266736861323536582075381ef9f3421a74f2fa21e256705e9737b94eda1f7549b5b23c254799254086687461726765744972a26269646f6563686f2e7370616e2d69722f763166646967657374826673686132353658202c8b71d6a3463fd944ac73554e5a691936142afb278771706e2cb61e2c055da76a61706956657273696f6e781a6563686f2e65786563757461626c652d7375626a6563742f7631781b6170706c69636174696f6e526573756c7450726f6a656374696f6ea262696478276a656469742e746578742e7265706c6163655f72616e676540312e7265706c61636552616e67656664696765737482667368613235365820cc9cf282dcdafae981a13f8829c9bf8ea757727392eca6152acd1577e62444cf697265666572656e6365a2626964781a6563686f2e65786563757461626c652d7375626a6563742f763166646967657374826673686132353658206303672d107679c0e15820d6e0fe9650de31146ff84a3b8aeeb0918d49191ca2781b6170706c69636174696f6e526573756c7450726f6a656374696f6ea262696478276a656469742e746578742e7265706c6163655f72616e676540312e7265706c61636552616e67656664696765737482667368613235365820cc9cf282dcdafae981a13f8829c9bf8ea757727392eca6152acd1577e62444cf diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/README.md b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/README.md new file mode 100644 index 00000000..d862741c --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/README.md @@ -0,0 +1,52 @@ + + + +# Public source-function unsigned addition fixture + +These package and verifier-report carriers are unmodified outputs of Edict's +public JSONL application build against a freshly published SourceFunctions +provider package. The authored source computes a guarded U64 sum, passes it +through an ordinary source function containing `value + 0`, and computes a +separate guarded U32 increment. The package therefore exercises the strict +source-function provider judgments as well as the runtime arithmetic path. + +The accepted report binds package pin +`a8774d9e8ba5dbe1e4eaffee4ec8f10f7b80ee9812b5569e8c2d290e57de9443`. +`provenance.json` records the compiler, independently built component identities, +provider publication and exact fixture hashes. The rebuild checks the generated +provider reference against that recorded publication before invoking the compiler. The four vendored lawpack +carriers and application manifest retain the complete public build inputs. +A repeated public build produced identical package and report bytes. + +The integration tests in `edict_unsigned_addition_tests` check exact outputs at +both unsigned width boundaries and structured refusal outside the proved input +domain. This is bounded ordinary computation. It does not create graph effects, +admit an Action, commit a Tick, or establish receipt/WAL/recovery behavior. + +To rebuild in a guarded Docker worker with copied sources, use the source and +component identities recorded in the provenance. Set `ECHO_SOURCE` to the copied +Echo root at the recorded publication snapshot, `ADDITION_FIXTURE` to this +retained fixture directory, `EDICT_BIN` to its companion Edict CLI binary and +`ADDITION_APP` to a new absolute scratch directory. The fixture may come from +a later checkout than the recorded producer snapshot. The provider publication example requires Docker. + +```sh +set -eu +python3 - "$ADDITION_FIXTURE" "$ADDITION_APP" <<'PY' +from pathlib import Path +import shutil, sys +source, app = map(Path, sys.argv[1:]) +shutil.copytree(source, app) +for carrier in app.rglob('*.hex'): + carrier.with_suffix('').write_bytes(bytes.fromhex(carrier.read_text().strip())) +(app / '.build').mkdir() +PY +cargo +1.96.0 run --locked --manifest-path "$ECHO_SOURCE/Cargo.toml" \ + -p echo-wesley-gen --example source_functions_publication_witness -- \ + "$ADDITION_APP/.build/echo-provider" +python3 "$ADDITION_APP/verify-provider-provenance.py" "$ADDITION_APP" +cd "$ADDITION_APP" +printf '%s\n' '{"schema":"edict.compiler.settings/v1","type":"compilerSettings","operation":"build","application":"edict.application.json"}' | "$EDICT_BIN" +cmp executable-operation-package.cbor .build/application/executable-operation-package.cbor +cmp verification-report.cbor .build/application/verification-report.cbor +``` diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/edict.application.json b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/edict.application.json new file mode 100644 index 00000000..922405f3 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/edict.application.json @@ -0,0 +1,20 @@ +{ + "schema": "edict.application/v1", + "coordinate": "arithmetic.unsigned@1", + "sources": [ + "src/Unsigned.edict" + ], + "lawpacks": [ + { + "manifest": "vendor/jedit-text/manifest.cbor", + "exports": "vendor/jedit-text/exports.cbor", + "adapter": "vendor/jedit-text/adapter.cbor", + "targetConfiguration": "vendor/jedit-text/echo-operation-configuration.cbor" + } + ], + "target": { + "profile": "echo.dpo@1", + "providerPackage": ".build/echo-provider" + }, + "outputDirectory": ".build/application" +} diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/executable-operation-package.cbor.hex b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/executable-operation-package.cbor.hex new file mode 100644 index 00000000..4d677428 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/executable-operation-package.cbor.hex @@ -0,0 +1 @@ +aa66736368656d6178196563686f2e6f7065726174696f6e2d7061636b6167652f76316770726f6772616d591d04a7646b696e647821636f6d70696c65722d70726f64756365642d626f756e6465642d707572652f763166696e74656e74676d65617375726566736368656d6178266563686f2e636f6d70696c65722d70726f64756365642d707572652d70726f6772616d2f76316d636f72655f617274696661637459099aa7657479706573a265496e707574a2646b696e64665265636f7264666669656c6473a3646c656674635536346572696768746355363467636f756e74657263553332664f7574707574a2646b696e64665265636f7264666669656c6473a26573756d363463553634666e65787433326355333267696d706f72747381a263726566a26269646c6a656469742e746578744031666469676573748266736861323536582095758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e646b696e64676c61777061636b67696e74656e7473a1676d656173757265a664626f6479a3656e6f64657382a3646b696e64636c65746576616c7565a4646172677381a4646172677382a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64646c656674a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64657269676874646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e6164646874797065417267738163553634646b696e646463616c6c6663616c6c6565781e61726974686d657469632e756e7369676e656440312e6964656e74697479687479706541726773806762696e64696e67a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30a3646b696e64636c65746576616c7565a4646172677382a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467636f756e746572a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75650165776964746863553332646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e61646468747970654172677381635533326762696e64696e67a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c31666c6f63616c7383a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c3166726573756c74a2646b696e64667265636f7264666669656c6473a26573756d3634a263726566a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30646b696e64656c6f63616c666e6578743332a263726566a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c31646b696e64656c6f63616c65696e707574781b61726974686d657469632e756e7369676e656440312e496e707574666f7574707574781c61726974686d657469632e756e7369676e656440312e4f757470757470696e707574436f6e73747261696e747383a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64646c656674657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75651bfffffffffffffffe657769647468635536346a636f6f7264696e6174656777686572652e30a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64657269676874657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c756501657769647468635536346a636f6f7264696e6174656777686572652e31a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467636f756e746572657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75651afffffffe657769647468635533326a636f6f7264696e6174656777686572652e3274636f72654576616c756174696f6e427564676574a3686d617853746570731a001000006e6d61784f757470757442797465731a00800000716d6178416c6c6f636174656442797465731a01000000781872657175697265644f7065726174696f6e50726f66696c65781f636f6e74696e75756d2e70726f66696c652e726561642d77726974652f76316966756e6374696f6e73a1686964656e74697479a364626f6479a3666c6f63616c738066726573756c74a4646172677382a263726566a3626964656172672e3064747970656355363469616c7068614e616d65652461726730646b696e64656c6f63616ca2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75650065776964746863553634646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e61646468747970654172677381635536346862696e64696e67738066706172616d7381a3626964656172672e3064747970656355363469616c7068614e616d656524617267306a72657475726e54797065635536346a61706956657273696f6e6d65646963742e636f72652f76316a636f6f7264696e6174657561726974686d657469632e756e7369676e6564403178187265717569726564436f72654361706162696c697469657380727461726765745f69725f6172746966616374590815a6646b696e64707461726765744972417274696661637466646f6d61696e6f6563686f2e7370616e2d69722f763167696e74656e7473a1676d656173757265a76573746570738066726573756c74a2646b696e64667265636f7264666669656c6473a26573756d3634a263726566a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30646b696e64656c6f63616c666e6578743332a263726566a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c31646b696e64656c6f63616c6c7075726542696e64696e677382a3626964716d6561737572652e62696e64696e672e306576616c7565a4646172677381a4646172677382a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64646c656674a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64657269676874646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e6164646874797065417267738163553634646b696e646463616c6c6663616c6c6565781e61726974686d657469632e756e7369676e656440312e6964656e74697479687479706541726773806762696e64696e67a3626964676c6f63616c2e3064747970656355363469616c7068614e616d6567246c6f63616c30a3626964716d6561737572652e62696e64696e672e316576616c7565a4646172677382a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467636f756e746572a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75650165776964746863553332646b696e646463616c6c6663616c6c656570636f72652e696e74656765722e61646468747970654172677381635533326762696e64696e67a3626964676c6f63616c2e3164747970656355333269616c7068614e616d6567246c6f63616c316c726571756972656d656e74738070696e707574436f6e73747261696e747383a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64646c656674657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75651bfffffffffffffffe657769647468635536346a636f6f7264696e6174656777686572652e30a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c64657269676874657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c756501657769647468635536346a636f6f7264696e6174656777686572652e31a366736f7572636565776865726569707265646963617465a4626f70623c3d646b696e6467636f6d70617265646c656674a36462617365a263726566a3626964656172672e306474797065781b61726974686d657469632e756e7369676e656440312e496e70757469616c7068614e616d65652461726730646b696e64656c6f63616c646b696e64656669656c64656669656c6467636f756e746572657269676874a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c75651afffffffe657769647468635533326a636f6f7264696e6174656777686572652e32706f7065726174696f6e50726f66696c65781f636f6e74696e75756d2e70726f66696c652e726561642d77726974652f763174636f72654576616c756174696f6e427564676574a3686d617853746570731a001000006e6d61784f757470757442797465731a00800000716d6178416c6c6f636174656442797465731a010000006d74617267657450726f66696c65a26269646a6563686f2e64706f403166646967657374826673686132353658202e2494121aecf5e6a2d920f5fb85408825d394765fad41484c416397c920fb046f73656d616e746963436c6f73757265a2686c61777061636b7381a26269646c6a656469742e746578744031666469676573748266736861323536582095758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e6a736f75726365436f7265a26269647561726974686d657469632e756e7369676e656440316664696765737482667368613235365820b47a864874ebd19efaf774dc2ee2c44aff35e342c9086f4e77a9409e061abea074736f75726365436f7265436f6f7264696e6174657561726974686d657469632e756e7369676e6564403178186c61777061636b5f6578706f7274735f617274696661637459093aa665747970657385a26a636f6f7264696e617465736a656469742e7465787440312e4e6f646549646a646566696e6974696f6e6f42797465733c65786163743d33323ea26a636f6f7264696e617465756a656469742e7465787440312e42756666657249646a646566696e6974696f6e781c4e6f6d696e616c3c6a656469742e7465787440312e4e6f646549643ea26a636f6f7264696e617465736a656469742e7465787440312e4865616449646a646566696e6974696f6e781c4e6f6d696e616c3c6a656469742e7465787440312e4e6f646549643ea26a636f6f7264696e617465781d6a656469742e7465787440312e5265706c6163656d656e7442797465736a646566696e6974696f6e7242797465733c6d61783d313034383537363ea26a636f6f7264696e617465781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6a646566696e6974696f6e6f537472696e673c6d61783d3235363e67656666656374738069636f6e7374616e747382a36474797065635536346576616c75651910006a636f6f7264696e617465781d6a656469742e7465787440312e6d6178437265617465644c6561766573a36474797065635536346576616c75651910006a636f6f7264696e617465781f6a656469742e7465787440312e6d6178437265617465644272616e636865736c6f62737472756374696f6e738aa36a636f6f7264696e617465781e6a656469742e7465787440312e52616e67654f72646572496e76616c69646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781d6a656469742e7465787440312e52616e67654f75744f66426f756e64736d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e61746578206a656469742e7465787440312e55746638426f756e64617279496e76616c69646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465716a656469742e7465787440312e4e6f4f706d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781e6a656469742e7465787440312e42617369734e6f7443616e6f6e6963616c6d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781f6a656469742e7465787440312e41726974686d657469634f766572666c6f776d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e61746578186a656469742e7465787440312e466163744d697373696e676d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736d7265736f757263654661756c74a36a636f6f7264696e617465781a6a656469742e7465787440312e466163744d616c666f726d65646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e61746578246a656469742e7465787440312e436f6e74656e744964656e746974794d69736d617463686d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e617465781a6a656469742e7465787440312e4d616c666f726d6564526f70656d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c746d7075726546756e6374696f6e7381a864626f6479a264626f6479a3666c6f63616c738066726573756c74a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c7565191000657769647468635536346862696e64696e67738066706172616d738066736f757263656565646963746a636f6f7264696e61746578206a656469742e7465787440312e6d6178437265617465644c656166436f756e746a72657475726e54797065635536346c636f737454656d706c617465781f6a656469742e7465787440312e7265706c61636552616e67654275646765746e706172616d657465725479706573806e74797065506172616d6574657273807064657465726d696e69736d436c61737365746f74616c716f7065726174696f6e50726f66696c6573a178196a656469742e7465787440312e7265706c61636552616e6765a26d6f7074696354656d706c617465a6696f707469634b696e64736166666563745265696e746567726174696f6e6c626f756e646172794b696e64666166666563746d626173697354656d706c617465781b6a656469742e7465787440312e65786163744865616442617369736d737570706f7274506f6c696379781e6a656469742e7465787440312e6261736973426f756e64537570706f72746f6c6f7373446973706f736974696f6e756a656469742e7465787440312e6c6f73736c657373736170657274757265526571756972656d656e74a26372656678226a656469742e7465787440312e7265706c61636552616e6765466f6f747072696e74646b696e64781b6162737472616374466f6f747072696e744f626c69676174696f6e6f65666665637450726564696361746578206a656469742e7465787440312e7265706c61636552616e676545666665637473781a726573756c745f70726f6a656374696f6e5f6172746966616374590151a566736368656d61781a65646963742e726573756c742d70726f6a656374696f6e2f76316a65787072657373696f6ea2646b696e64667265636f7264666669656c6473a26573756d3634a3646b696e6466736f7572636564706174688066736f75726365a2646b696e646b7075726542696e64696e676962696e64696e674964716d6561737572652e62696e64696e672e30666e6578743332a3646b696e6466736f7572636564706174688066736f75726365a2646b696e646b7075726542696e64696e676962696e64696e674964716d6561737572652e62696e64696e672e316a6f757470757454797065781c61726974686d657469632e756e7369676e656440312e4f75747075746e6d61784f757470757442797465731a00800000736f7065726174696f6e436f6f7264696e617465781d61726974686d657469632e756e7369676e656440312e6d6561737572656c7061636b6167655f6b696e647821636f6d70696c65722d70726f64756365642d626f756e6465642d707572652f76316e6275646765745f6365696c696e67a3696d61785f73746570731a00100000706d61785f6f75747075745f62797465731a00800000736d61785f616c6c6f63617465645f62797465731a010000007073656d616e7469635f636c6f73757265a86d636f72655f6964656e746974795820b47a864874ebd19efaf774dc2ee2c44aff35e342c9086f4e77a9409e061abea0706c61777061636b5f6964656e74697479582095758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e726c61777061636b5f636f6f7264696e6174656c6a656469742e746578744031727461726765745f69725f6964656e7469747958204487c28b8c0120adc6fe5fb86a47d578e0a75ea8573b771768b7c9fbf3abd56f7565646963745f736f757263655f6964656e746974795820c290b55a4e0d3465c3d170e78a8b946dfe2d4106b3a181fb6280ec8d4f4276c6781a63616e6f6e6963616c5f6d65616e696e675f6964656e746974795820b47a864874ebd19efaf774dc2ee2c44aff35e342c9086f4e77a9409e061abea0781b6170706c69636174696f6e5f736368656d615f6964656e7469747958201f436d717d3f349cc6f4c3431730ff4182d65c87fb6c1233692fc40fbd71bf02781d6170706c69636174696f6e5f736368656d615f636f6f7264696e617465756a656469742e746578742e6578706f7274732f7631746f7065726174696f6e5f636f6f7264696e617465781d61726974686d657469632e756e7369676e656440312e6d656173757265777461726765745f70726f66696c655f6964656e7469747958202e2494121aecf5e6a2d920f5fb85408825d394765fad41484c416397c920fb04781a617574686f726974795f70726f66696c655f6964656e746974795820fbaf54b61a71d54139a37955fe1bae42ee1d013f9aff2b09f546084fe3b3ced6781b666f6f747072696e745f636f6e74726163745f6964656e746974795820bf4da382443c8f8a740b3d28b77e3cfd8b39cb1608a9b885de59e1cb05d70365781c696e7465727072657465725f70726f66696c655f6964656e746974795820dc267bf35dc047a748593bbc5eaf6d9565b6206bfd84caf3cbe29653c6f34a76 diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/provenance.json b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/provenance.json new file mode 100644 index 00000000..4765fb5b --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/provenance.json @@ -0,0 +1,27 @@ +{ + "edict": "561981d9652f447cafbf602a884acee4efb23e51", + "edictMergedMain": "1d287ef519bab56fcdf6cd5435d5bdaaa01428c5", + "echoComponentSource": "80991bcfe8c7348b8d376627e6b5eb7cdb38e1a9", + "echoPublicationSnapshot": "f7a395527144dba87a5f07b6bdf53a40a49af7a4", + "providerPublication": "source-functions-v1", + "providerPackage": { + "coordinate": "echo.edict-provider@1", + "digest": "sha256:9de5d063fec20abee3f3a37f6259c19bf8fed57abba0eca8f65137182c34a21b" + }, + "componentSha256": { + "lowerer": "04d5162202ca2ce9b4496c3eff5b7b249d31b33d72e97a23f2e2a86f8d4ed93e", + "verifier": "3451e95a7d084d4874c30833f90f5c21012e8341f35ed0f0888d4d268a768b11" + }, + "packagePin": "a8774d9e8ba5dbe1e4eaffee4ec8f10f7b80ee9812b5569e8c2d290e57de9443", + "files": { + "executable-operation-package.cbor": "dd4c103c72e1cf7c11c56e1b46f10f912051eb4c650afe968a99a858e9f51165", + "verification-report.cbor": "22e8d7c89da77218bca9d41103fae6d6f7e0cd3cff3ae6fc3d1ecc617683be32", + "vendor/jedit-text/manifest.cbor": "0323ed8e9510e473d329166d421dc7d8e1da353065c1cd2dee77e6313ba9bf91", + "vendor/jedit-text/exports.cbor": "cab9c575da49cb33289e45fc45afb9d7f05558dada734be7eb3acfbbabb1d4db", + "vendor/jedit-text/adapter.cbor": "ab1437164084cbaf453f869c4302df9e648186fe6833bcb81c1e267c8dfeb6f9", + "vendor/jedit-text/echo-operation-configuration.cbor": "ea787368881f448021f2d71c72cbadbc487e59a09e9638acfc25ec3579a3609d", + "src/Unsigned.edict": "be79fdddee5008e9639d81ecbbbc5648332af1e1803bcaf58cd51e2feccf13fe", + "edict.application.json": "6c17d18fc70a0805de326d52c79da03f7f9afdb5cab75744053c521c5c459f2c" + }, + "builder": "sha256:b58697ad3d09257d8d59cbb87868e3a4145efe52931d918b948bb4999d083c85" +} diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/src/Unsigned.edict b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/src/Unsigned.edict new file mode 100644 index 00000000..5a50f7ea --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/src/Unsigned.edict @@ -0,0 +1,15 @@ +package arithmetic.unsigned@1; +use lawpack jedit.text@1 digest "sha256:95758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e" as text; +type Input = { left: U64, right: U64, counter: U32, }; +type Output = { sum64: U64, next32: U32, }; +fn identity(value: U64) -> U64 { return value + 0; } +intent measure(input: Input) returns Output + profile text.replaceRange basis none budget <= text.replaceRangeBudget + where input.left <= 18446744073709551614 + where input.right <= 1 + where input.counter <= 4294967294 +{ + let sum64 = identity(input.left + input.right); + let next32: U32 = input.counter + 1; + return { sum64, next32 }; +} diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/adapter.cbor.hex b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/adapter.cbor.hex new file mode 100644 index 00000000..3d9373fe --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/adapter.cbor.hex @@ -0,0 +1 @@ +a565636c6173736b6465636c617261746976656762756467657473a1781f6a656469742e7465787440312e7265706c61636552616e6765427564676574a3686d617853746570731a001000006e6d61784f757470757442797465731a00800000716d6178416c6c6f636174656442797465731a010000006a61706956657273696f6e781865646963742e6c61777061636b2d616461707465722f7631716f7065726174696f6e50726f66696c6573a178196a656469742e7465787440312e7265706c61636552616e6765a464636f7265781f636f6e74696e75756d2e70726f66696c652e726561642d77726974652f76316f73656d616e7469634566666563747380706275646765744f626c69676174696f6e781f6a656469742e7465787440312e7265706c61636552616e676542756467657473746172676574436f6e66696775726174696f6ea262696478286563686f2e6f7065726174696f6e2d6c6f776572696e672d636f6e66696775726174696f6e2f76316664696765737482667368613235365820bcb811b2d00d9824a256a26e48c14401c87fff509f2f75deb2ba703003a3f6d475656666656374496d706c656d656e746174696f6e73a0 diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/echo-operation-configuration.cbor.hex b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/echo-operation-configuration.cbor.hex new file mode 100644 index 00000000..7b593a56 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/echo-operation-configuration.cbor.hex @@ -0,0 +1 @@ +a26a61706956657273696f6e78286563686f2e6f7065726174696f6e2d6c6f776572696e672d636f6e66696775726174696f6e2f76316b70726f6772616d4b696e647821636f6d70696c65722d70726f64756365642d626f756e6465642d707572652f7631 diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/exports.cbor.hex b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/exports.cbor.hex new file mode 100644 index 00000000..e50eaca1 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/exports.cbor.hex @@ -0,0 +1 @@ +a665747970657385a26a636f6f7264696e617465736a656469742e7465787440312e4e6f646549646a646566696e6974696f6e6f42797465733c65786163743d33323ea26a636f6f7264696e617465756a656469742e7465787440312e42756666657249646a646566696e6974696f6e781c4e6f6d696e616c3c6a656469742e7465787440312e4e6f646549643ea26a636f6f7264696e617465736a656469742e7465787440312e4865616449646a646566696e6974696f6e781c4e6f6d696e616c3c6a656469742e7465787440312e4e6f646549643ea26a636f6f7264696e617465781d6a656469742e7465787440312e5265706c6163656d656e7442797465736a646566696e6974696f6e7242797465733c6d61783d313034383537363ea26a636f6f7264696e617465781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6a646566696e6974696f6e6f537472696e673c6d61783d3235363e67656666656374738069636f6e7374616e747382a36474797065635536346576616c75651910006a636f6f7264696e617465781d6a656469742e7465787440312e6d6178437265617465644c6561766573a36474797065635536346576616c75651910006a636f6f7264696e617465781f6a656469742e7465787440312e6d6178437265617465644272616e636865736c6f62737472756374696f6e738aa36a636f6f7264696e617465781e6a656469742e7465787440312e52616e67654f72646572496e76616c69646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781d6a656469742e7465787440312e52616e67654f75744f66426f756e64736d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e61746578206a656469742e7465787440312e55746638426f756e64617279496e76616c69646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465716a656469742e7465787440312e4e6f4f706d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781e6a656469742e7465787440312e42617369734e6f7443616e6f6e6963616c6d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e646f6d61696e4d61707061626c65a36a636f6f7264696e617465781f6a656469742e7465787440312e41726974686d657469634f766572666c6f776d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e61746578186a656469742e7465787440312e466163744d697373696e676d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736d7265736f757263654661756c74a36a636f6f7264696e617465781a6a656469742e7465787440312e466163744d616c666f726d65646d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e61746578246a656469742e7465787440312e436f6e74656e744964656e746974794d69736d617463686d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c74a36a636f6f7264696e617465781a6a656469742e7465787440312e4d616c666f726d6564526f70656d7061796c6f6164536368656d61781e6a656469742e7465787440312e4f62737472756374696f6e44657461696c6e617574686f72697479436c6173736e696e746567726974794661756c746d7075726546756e6374696f6e7381a864626f6479a264626f6479a3666c6f63616c738066726573756c74a2646b696e6465636f6e73746576616c7565a3646b696e6463696e746576616c7565191000657769647468635536346862696e64696e67738066706172616d738066736f757263656565646963746a636f6f7264696e61746578206a656469742e7465787440312e6d6178437265617465644c656166436f756e746a72657475726e54797065635536346c636f737454656d706c617465781f6a656469742e7465787440312e7265706c61636552616e67654275646765746e706172616d657465725479706573806e74797065506172616d6574657273807064657465726d696e69736d436c61737365746f74616c716f7065726174696f6e50726f66696c6573a178196a656469742e7465787440312e7265706c61636552616e6765a26d6f7074696354656d706c617465a6696f707469634b696e64736166666563745265696e746567726174696f6e6c626f756e646172794b696e64666166666563746d626173697354656d706c617465781b6a656469742e7465787440312e65786163744865616442617369736d737570706f7274506f6c696379781e6a656469742e7465787440312e6261736973426f756e64537570706f72746f6c6f7373446973706f736974696f6e756a656469742e7465787440312e6c6f73736c657373736170657274757265526571756972656d656e74a26372656678226a656469742e7465787440312e7265706c61636552616e6765466f6f747072696e74646b696e64781b6162737472616374466f6f747072696e744f626c69676174696f6e6f65666665637450726564696361746578206a656469742e7465787440312e7265706c61636552616e676545666665637473 diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/manifest.cbor.hex b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/manifest.cbor.hex new file mode 100644 index 00000000..719e2ec6 --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/vendor/jedit-text/manifest.cbor.hex @@ -0,0 +1 @@ +aa6269646a6a656469742e74657874676578706f727473a2626964756a656469742e746578742e6578706f7274732f76316664696765737482667368613235365820cbbc79fd92f09f341a1fae221a2a869bb64e15c511af39333e0453cd87fe456a6776657273696f6e6131687665726966696572a265636c6173736b6465636c617261746976656772756c65736574a2626964781c6a656469742e746578742e76657269666965722d72756c65732f76316664696765737482667368613235365820364fb4ff98ae64fcd8d793aae3d7cb133ff8a1ce661330cea47688b13a0a823f6a61706956657273696f6e7065646963742e6c61777061636b2f76316c646570656e64656e63696573806d636f6d7061746962696c697479a2626964781b6a656469742e746578742e636f6d7061746962696c6974792f763166646967657374826673686132353658202adf83f798205f52636ad64ca45178f33a8e1cc663874f8a6113484c945e30526e746172676574416461707465727381a36761646170746572a2626964781a6a656469742e746578742e6563686f2d616461707465722f76316664696765737482667368613235365820b8d9f15ef18dc99691ab1e034ca40a8b8ac52a1bc1b27597284f1edbaf84f0497061636365707465645461726765744972a26269646f6563686f2e7370616e2d69722f763166646967657374826673686132353658200057167e68f50c99dcce087b3e1cd677d17c5d1dc238bdb52d89469e1472fc2f75616363657074656454617267657450726f66696c65a26269646a6563686f2e64706f403166646967657374826673686132353658202e2494121aecf5e6a2d920f5fb85408825d394765fad41484c416397c920fb046f6163636570746564436f7265416269816d65646963742e636f72652f76317818636f6e666f726d616e636546697874757265436f72707573a262696478206a656469742e746578742e5265706c61636552616e67652e6f7261636c6540316664696765737482667368613235365820b9b4707dd5e07897cbe7af36d88928401887e6af5d167d1a88a8d6181b4dbb0e diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/verification-report.cbor.hex b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/verification-report.cbor.hex new file mode 100644 index 00000000..f34325bd --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/verification-report.cbor.hex @@ -0,0 +1 @@ +a8676f7574636f6d65686163636570746564677061636b616765a2626964782165786563757461626c652d6f7065726174696f6e2d7061636b6167652e6563686f6664696765737482667368613235365820a8774d9e8ba5dbe1e4eaffee4ec8f10f7b80ee9812b5569e8c2d290e57de9443687461726765744972a26269646f6563686f2e7370616e2d69722f763166646967657374826673686132353658204487c28b8c0120adc6fe5fb86a47d578e0a75ea8573b771768b7c9fbf3abd56f6a61706956657273696f6e78296563686f2e6f7065726174696f6e2d7061636b6167652d76657269666965722d7265706f72742f76316d646961676e6f73746963416269a26269647465646963742e646961676e6f73746963732f7631666469676573748266736861323536582028fd72a98223153982ca084c29dbb1b2d430623967ab3b6db9d7fee668e614b96f646961676e6f737469634279746573407165786563757461626c655375626a656374a2656279746573590147a4677061636b616765a2626964782165786563757461626c652d6f7065726174696f6e2d7061636b6167652e6563686f6664696765737482667368613235365820a8774d9e8ba5dbe1e4eaffee4ec8f10f7b80ee9812b5569e8c2d290e57de9443687461726765744972a26269646f6563686f2e7370616e2d69722f763166646967657374826673686132353658204487c28b8c0120adc6fe5fb86a47d578e0a75ea8573b771768b7c9fbf3abd56f6a61706956657273696f6e781a6563686f2e65786563757461626c652d7375626a6563742f7631781b6170706c69636174696f6e526573756c7450726f6a656374696f6ea2626964781d61726974686d657469632e756e7369676e656440312e6d65617375726566646967657374826673686132353658201b3f0d865468da9bd5cb20fa2f86ff847c48573d7c12c4aa94083d0299d386e1697265666572656e6365a2626964781a6563686f2e65786563757461626c652d7375626a6563742f763166646967657374826673686132353658201fc0792b3723c506277f99fdc7082470a5ac443e6a5c287aaf0101ef6dbba849781b6170706c69636174696f6e526573756c7450726f6a656374696f6ea2626964781d61726974686d657469632e756e7369676e656440312e6d65617375726566646967657374826673686132353658201b3f0d865468da9bd5cb20fa2f86ff847c48573d7c12c4aa94083d0299d386e1 diff --git a/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/verify-provider-provenance.py b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/verify-provider-provenance.py new file mode 100644 index 00000000..346cc07c --- /dev/null +++ b/crates/warp-core/tests/fixtures/edict-unsigned-addition-source-functions/verify-provider-provenance.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# © James Ross Ω FLYING•ROBOTS +"""Refuse a rebuild whose provider differs from the retained publication.""" +import json +from pathlib import Path +import sys + +app = Path(sys.argv[1]) +expected = json.loads((app / "provenance.json").read_text())["providerPackage"] +actual = json.loads( + (app / ".build/echo-provider/provider-manifest.echo.json").read_text() +)["provider"] +if actual != expected: + raise SystemExit(f"provider provenance mismatch: {actual!r} != {expected!r}") +print("Provider publication matches retained provenance") diff --git a/docs/topics/GeneratedRules.md b/docs/topics/GeneratedRules.md index 349e9c05..eb87087f 100644 --- a/docs/topics/GeneratedRules.md +++ b/docs/topics/GeneratedRules.md @@ -94,6 +94,44 @@ not use it as an application authoring escape hatch. ## Execution Corridors +### Bounded compiler-package computation + +`edict_pure::evaluate` interprets exact compiler-produced packages under an +independently selected trusted-host pin and bounded input, work, storage and +output limits. This is ordinary computation, not package admission, graph +mutation, an Action, a Tick, a receipt or recovery evidence. + +The interpreter supports `core.integer.add`. It validates both operands +against the declared unsigned width and checks the sum before copying the +result through the ordinary resource meter. Overflow and invalid operands +refuse rather than wrap. The literal-boundary witness needs eight work units +and three 64-byte value cells; one fewer work unit or storage byte refuses. +The public compiler fixture and arithmetic meter test in +`edict_unsigned_addition_tests` and `edict_pure::evaluate` cover these boundaries. + +Native lowerer and verifier source-function judgments independently require +exact same-width operands and a dominating no-overflow proof. Checked conjunctive +prefixes can bound later terms; facts cannot escape negation or flow backward. +Bounded-read relations reuse this established proof and require exactly +matching declared and operand widths. New addition calls require this judgment +even when the legacy Core function table is absent. Both implementations bound proof traversal and comparisons +using their existing work ceilings. Rebound native tests exercise these checks; +they do not establish public compiler acceptance. + +Runtime helper validation also proves addition within its fresh frame using +literal and nested-sum bounds. Other terms retain their full unsigned width, +so zero identity is total and an unbounded parameter plus one refuses. Caller +constraints do not cross into a helper frame. + +The retained public compiler fixtures cover a legacy-producer execution control +and a strict SourceFunctions publication containing an authored arithmetic helper. +The accepted public verifier report binds the unmodified package bytes; repeated +public compilation preserves both package and report identity. +Checked provider components are promoted from two byte-identical designated +builds, and the package manifest binds their exact digests. Component presence, +runtime support and native judgments alone do not authorize a package or grant +application mutation authority. + ### Provider-v1 compatibility corridor The currently implemented Edict mutation corridor is: diff --git a/schemas/edict-provider/README.md b/schemas/edict-provider/README.md index c135bfab..53167d55 100644 --- a/schemas/edict-provider/README.md +++ b/schemas/edict-provider/README.md @@ -180,10 +180,10 @@ nor manifest. Independent fresh-store replay and separate host processes reproduce all three completed outcomes identically. Both checked components remain uninstalled package material; neither they nor the generated authority-facts documents are runtime Echo authority. The promoted lowerer is -481,346 bytes with SHA-256 -`79066cfc740da4463fd20baec36fe18c6cfb346917fed475b4ef7119fda9408a`; the -promoted verifier is 497,594 bytes with SHA-256 -`577c69937594c0aff2461dd60d43507e1f6ce0903ca2b17ff02919d73efd9b28`. +485,983 bytes with SHA-256 +`04d5162202ca2ce9b4496c3eff5b7b249d31b33d72e97a23f2e2a86f8d4ed93e`; the +promoted verifier is 504,431 bytes with SHA-256 +`3451e95a7d084d4874c30833f90f5c21012e8341f35ed0f0888d4d268a768b11`. The checked schema/components also support the explicit `compiler-produced-bounded-read/v1` configuration with required `maxReads` diff --git a/schemas/edict-provider/components/v1/README.md b/schemas/edict-provider/components/v1/README.md index 2a07d277..71ab66ae 100644 --- a/schemas/edict-provider/components/v1/README.md +++ b/schemas/edict-provider/components/v1/README.md @@ -23,8 +23,8 @@ is componentized with `wit-component` 0.251.0. The source WIT is the exact 7,392-byte Edict contract with SHA-256 `2971fe44def7e51d5271dfc0f04f3088aa58754cffdc847681a587605aac749e`. -The checked component is 481,346 bytes with SHA-256 -`79066cfc740da4463fd20baec36fe18c6cfb346917fed475b4ef7119fda9408a`. +The checked component is 485,983 bytes with SHA-256 +`04d5162202ca2ce9b4496c3eff5b7b249d31b33d72e97a23f2e2a86f8d4ed93e`. Its sole contract attestation is the top-level custom section `edict:target-provider-contract` containing `edict:target-provider/lowerer@1.0.0`. Its only imports are the frozen WIT's @@ -35,9 +35,9 @@ capability imports. `verifier.echo-dpo.component.wasm` implements `edict:target-provider/verifier@1.0.0`. It uses the same immutable builder, authenticated Rust/Cargo identities, frozen WIT bytes, path-remapping law, and -`wit-component` version recorded above. Its checked component is 497,594 bytes +`wit-component` version recorded above. Its checked component is 504,431 bytes with SHA-256 -`577c69937594c0aff2461dd60d43507e1f6ce0903ca2b17ff02919d73efd9b28`. +`3451e95a7d084d4874c30833f90f5c21012e8341f35ed0f0888d4d268a768b11`. Its sole contract attestation is the top-level custom section `edict:target-provider-contract` containing `edict:target-provider/verifier@1.0.0`. Its only imports are the frozen WIT's diff --git a/schemas/edict-provider/components/v1/lowerer.echo-dpo.component.wasm b/schemas/edict-provider/components/v1/lowerer.echo-dpo.component.wasm index 85e89e0e..1d304026 100644 Binary files a/schemas/edict-provider/components/v1/lowerer.echo-dpo.component.wasm and b/schemas/edict-provider/components/v1/lowerer.echo-dpo.component.wasm differ diff --git a/schemas/edict-provider/components/v1/verifier.echo-dpo.component.wasm b/schemas/edict-provider/components/v1/verifier.echo-dpo.component.wasm index 569e47ae..9a766125 100644 Binary files a/schemas/edict-provider/components/v1/verifier.echo-dpo.component.wasm and b/schemas/edict-provider/components/v1/verifier.echo-dpo.component.wasm differ diff --git a/schemas/edict-provider/package/v1/components/lowerer.echo-dpo.component.wasm b/schemas/edict-provider/package/v1/components/lowerer.echo-dpo.component.wasm index 85e89e0e..1d304026 100644 Binary files a/schemas/edict-provider/package/v1/components/lowerer.echo-dpo.component.wasm and b/schemas/edict-provider/package/v1/components/lowerer.echo-dpo.component.wasm differ diff --git a/schemas/edict-provider/package/v1/components/verifier.echo-dpo.component.wasm b/schemas/edict-provider/package/v1/components/verifier.echo-dpo.component.wasm index 569e47ae..9a766125 100644 Binary files a/schemas/edict-provider/package/v1/components/verifier.echo-dpo.component.wasm and b/schemas/edict-provider/package/v1/components/verifier.echo-dpo.component.wasm differ diff --git a/schemas/edict-provider/package/v1/provider-manifest.echo.json b/schemas/edict-provider/package/v1/provider-manifest.echo.json index 3681c45e..d54401f6 100644 --- a/schemas/edict-provider/package/v1/provider-manifest.echo.json +++ b/schemas/edict-provider/package/v1/provider-manifest.echo.json @@ -3,7 +3,7 @@ "providerAbi": "edict:target-provider@1.0.0", "provider": { "coordinate": "echo.edict-provider@1", - "digest": "sha256:cba96816605f54dc5e675ab6f473adf858bdaebdceae985f955e930711c8a4f9" + "digest": "sha256:2083dd7057574b040fb9c043b17990e34012004fbed39bdeda253dbb0a522bcc" }, "artifacts": [ { @@ -87,13 +87,13 @@ "artifactKind": "lowerer", "resource": { "coordinate": "echo.dpo.lowerer/component@1", - "digest": "sha256:79066cfc740da4463fd20baec36fe18c6cfb346917fed475b4ef7119fda9408a" + "digest": "sha256:04d5162202ca2ce9b4496c3eff5b7b249d31b33d72e97a23f2e2a86f8d4ed93e" }, "source": { "kind": "component", "component": { "coordinate": "echo.dpo.lowerer/component@1", - "digest": "sha256:79066cfc740da4463fd20baec36fe18c6cfb346917fed475b4ef7119fda9408a" + "digest": "sha256:04d5162202ca2ce9b4496c3eff5b7b249d31b33d72e97a23f2e2a86f8d4ed93e" } } }, @@ -178,13 +178,13 @@ "artifactKind": "verifier", "resource": { "coordinate": "echo.dpo.verifier/component@1", - "digest": "sha256:577c69937594c0aff2461dd60d43507e1f6ce0903ca2b17ff02919d73efd9b28" + "digest": "sha256:3451e95a7d084d4874c30833f90f5c21012e8341f35ed0f0888d4d268a768b11" }, "source": { "kind": "component", "component": { "coordinate": "echo.dpo.verifier/component@1", - "digest": "sha256:577c69937594c0aff2461dd60d43507e1f6ce0903ca2b17ff02919d73efd9b28" + "digest": "sha256:3451e95a7d084d4874c30833f90f5c21012e8341f35ed0f0888d4d268a768b11" } } } diff --git a/xtask/src/provider_lowerer_component.rs b/xtask/src/provider_lowerer_component.rs index a35d57f7..7b40d528 100644 --- a/xtask/src/provider_lowerer_component.rs +++ b/xtask/src/provider_lowerer_component.rs @@ -53,7 +53,7 @@ const PINNED_CARGO_COMMIT: &str = "840b83a10fb0e039a83f4d70ad032892c287570a"; /// Reviewed identity that the portable promotion command is permitted to install. pub(crate) const APPROVED_CHECKED_COMPONENT_SHA256: &str = - "79066cfc740da4463fd20baec36fe18c6cfb346917fed475b4ef7119fda9408a"; + "04d5162202ca2ce9b4496c3eff5b7b249d31b33d72e97a23f2e2a86f8d4ed93e"; pub(crate) const CHECKED_COMPONENT_REPOSITORY_PATH: &str = "schemas/edict-provider/components/v1/lowerer.echo-dpo.component.wasm"; @@ -62,7 +62,7 @@ pub(crate) const VERIFIER_CHECKED_COMPONENT_REPOSITORY_PATH: &str = "schemas/edict-provider/components/v1/verifier.echo-dpo.component.wasm"; /// Approved SHA-256 identity of the checked verifier component. pub(crate) const APPROVED_CHECKED_VERIFIER_COMPONENT_SHA256: &str = - "577c69937594c0aff2461dd60d43507e1f6ce0903ca2b17ff02919d73efd9b28"; + "3451e95a7d084d4874c30833f90f5c21012e8341f35ed0f0888d4d268a768b11"; #[derive(Clone, Copy, Debug, Eq, PartialEq)] struct ProviderComponentSpec {