diff --git a/CHANGELOG.md b/CHANGELOG.md index 925d7f32fc..84f0e46bd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog ## v0.30.0 (Unreleased) +#### Changes + +- [BREAKING] `verify`, `Verifier::verify`, and `Verifier::verify_partial` now borrow the proof and the claim instead of consuming them. +- [BREAKING] Renamed the `AdviceMutation::ExtendMap` field `other` to `map` and the `AdviceMutation::ExtendMerkleStore` field `infos` to `inner_nodes`. + ## v0.29.0 (2026-08-04) #### Changes diff --git a/benches/blake3-bench/src/lib.rs b/benches/blake3-bench/src/lib.rs index 56919a90f2..dda09bf244 100644 --- a/benches/blake3-bench/src/lib.rs +++ b/benches/blake3-bench/src/lib.rs @@ -165,7 +165,7 @@ pub fn prove_and_verify_once(fixture: &Blake3Fixture) { stack_outputs, ); Verifier::new() - .verify(proof, claim) + .verify(&proof, &claim) .expect("failed to verify Blake3 benchmark proof"); } diff --git a/benches/synthetic-bench/benches/synthetic_bench.rs b/benches/synthetic-bench/benches/synthetic_bench.rs index 06602c20d4..445c99ee50 100644 --- a/benches/synthetic-bench/benches/synthetic_bench.rs +++ b/benches/synthetic-bench/benches/synthetic_bench.rs @@ -352,7 +352,6 @@ fn bench_one_scenario( if axes.contains("verify") { // Reuse a proof from the `prove` axis when it ran for this scenario. This keeps prove time // out of the verify measurement without forcing an extra proof in all-axes runs. - let program_info = ProgramInfo::from(program.clone()); let (stack_outputs, proof) = cached_proof.borrow().clone().unwrap_or_else(|| { let mut host = DefaultHost::default(); prove_sync( @@ -365,19 +364,13 @@ fn bench_one_scenario( ) .expect("prove for verify setup") }); + let claim = ExecutionClaim::from_program_info( + ProgramInfo::from(program.clone()), + StackInputs::default(), + stack_outputs, + ); group.bench_function("verify", |b| { - b.iter_batched( - || (program_info.clone(), StackInputs::default(), stack_outputs, proof.clone()), - |(program_info, stack_inputs, stack_outputs, proof)| { - let claim = ExecutionClaim::from_program_info( - program_info, - stack_inputs, - stack_outputs, - ); - black_box(Verifier::new().verify(proof, claim).expect("verify")); - }, - BatchSize::SmallInput, - ); + b.iter(|| black_box(Verifier::new().verify(&proof, &claim).expect("verify"))); }); } diff --git a/crates/precompiles/benches/precompiles_bench/support.rs b/crates/precompiles/benches/precompiles_bench/support.rs index 9b6223633f..c65ca15ae3 100644 --- a/crates/precompiles/benches/precompiles_bench/support.rs +++ b/crates/precompiles/benches/precompiles_bench/support.rs @@ -113,6 +113,6 @@ pub fn verify_once( stack_outputs, ); Verifier::new() - .verify(proof, claim) + .verify(&proof, &claim) .expect("failed to verify precompile benchmark proof"); } diff --git a/crates/test-utils/src/lib.rs b/crates/test-utils/src/lib.rs index e73ef0d6d3..00a9317a1c 100644 --- a/crates/test-utils/src/lib.rs +++ b/crates/test-utils/src/lib.rs @@ -696,11 +696,11 @@ impl Test { StackOutputs::new(&elements).expect("stack outputs should fit the VM stack"); let claim = ExecutionClaim::from_program_info(program_info, stack_inputs, stack_outputs); - assert!(verify(proof, claim).is_err()); + assert!(verify(&proof, &claim).is_err()); } else { let claim = ExecutionClaim::from_program_info(program_info, stack_inputs, stack_outputs); - let result = verify(proof, claim); + let result = verify(&proof, &claim); assert!(result.is_ok(), "error: {result:?}"); } } diff --git a/miden-vm/README.md b/miden-vm/README.md index 59a9370b76..41baa80889 100644 --- a/miden-vm/README.md +++ b/miden-vm/README.md @@ -142,8 +142,8 @@ assert_eq!(8, outputs.first().unwrap().as_canonical_u64()); To verify program execution, use `Verifier::new().verify(...)`. The verifier takes the following parameters: -- `proof: ExecutionProof` - the proof generated during program execution. -- `claim: ExecutionClaim` - the claimed program information, stack inputs, and stack outputs. +- `proof: &ExecutionProof` - the proof generated during program execution. +- `claim: &ExecutionClaim` - the claimed program information, stack inputs, and stack outputs. Stack inputs are expected to be ordered as if they would be pushed onto the stack one by one. Thus, their expected order on the stack will be the reverse of the order in which they are provided, and the last value in the `stack_inputs` is expected to be the value at the top of the stack. @@ -172,7 +172,7 @@ let claim = ExecutionClaim::from_program_info( ); // Verify the execution claim. -match Verifier::new().verify(proof, claim) { +match Verifier::new().verify(&proof, &claim) { Ok(_) => println!("Execution verified!"), Err(err) => eprintln!("Verification failed: {err}"), } diff --git a/miden-vm/src/cli/verify.rs b/miden-vm/src/cli/verify.rs index 85d6133b2a..05bdaad03a 100644 --- a/miden-vm/src/cli/verify.rs +++ b/miden-vm/src/cli/verify.rs @@ -77,7 +77,7 @@ impl VerifyCmd { let stack_outputs = outputs_data.stack_outputs().map_err(Report::msg)?; let claim = miden_vm::ExecutionClaim::from_program_info(program_info, stack_inputs, stack_outputs); - miden_vm::verify(proof, claim) + miden_vm::verify(&proof, &claim) .into_diagnostic() .wrap_err("Program failed verification!")?; diff --git a/miden-vm/src/lib.rs b/miden-vm/src/lib.rs index 14de04b46e..2acd19d66e 100644 --- a/miden-vm/src/lib.rs +++ b/miden-vm/src/lib.rs @@ -36,6 +36,6 @@ pub mod internal; /// /// Wire-backed deferred proofs are partial/delegable proof material and are rejected here; use /// [`Verifier::verify_partial`] to verify and hydrate wire-backed partial proofs. -pub fn verify(proof: ExecutionProof, claim: ExecutionClaim) -> Result { +pub fn verify(proof: &ExecutionProof, claim: &ExecutionClaim) -> Result { miden_verifier::verify(proof, claim) } diff --git a/miden-vm/tests/integration/prove_verify.rs b/miden-vm/tests/integration/prove_verify.rs index dcd75b4752..7bd17c9993 100644 --- a/miden-vm/tests/integration/prove_verify.rs +++ b/miden-vm/tests/integration/prove_verify.rs @@ -56,7 +56,7 @@ fn assert_prove_verify( println!("Verifying proof..."); let claim = ExecutionClaim::from_program_info(program.into(), stack_inputs, stack_outputs); - let security_level = verify(proof, claim).expect("Verification failed"); + let security_level = verify(&proof, &claim).expect("Verification failed"); println!("Verification successful! Security level: {security_level}"); } @@ -338,7 +338,7 @@ mod fast_parallel { // Verify the proof let claim = ExecutionClaim::from_program_info(program.into(), stack_inputs, fast_stack_outputs); - verify(proof, claim).expect("Verification failed"); + verify(&proof, &claim).expect("Verification failed"); } #[test] @@ -368,7 +368,7 @@ mod fast_parallel { .expect("prove_from_trace_sync failed"); let claim = ExecutionClaim::from_program_info(program.into(), stack_inputs, stack_outputs); - verify(proof, claim).expect("Verification failed"); + verify(&proof, &claim).expect("Verification failed"); } #[test] @@ -401,7 +401,7 @@ mod fast_parallel { assert_eq!(proof.deferred_proof().as_wire(), Some(&expected_wire)); let claim = ExecutionClaim::from_program_info(program.into(), stack_inputs, stack_outputs); let (_, pending) = miden_verifier::Verifier::new() - .verify_partial(proof, claim) + .verify_partial(&proof, &claim) .expect("partial verification failed"); assert_ne!(pending.root(), miden_core::deferred::TRUE_DIGEST); let _state = pending.into_state(); @@ -463,18 +463,18 @@ fn prove_partial_fixture() -> (ExecutionClaim, ExecutionProof) { fn test_partial_obligation_flow() { // the default prover emits final deferred material: `verify` accepts it directly let (claim, proof) = prove_fixture(); - verify(proof, claim).expect("final verification should pass"); + verify(&proof, &claim).expect("final verification should pass"); // a partial (wire-backed) package is refused by final verification... let (claim, partial) = prove_partial_fixture(); assert!(matches!( - verify(partial.clone(), claim.clone()), + verify(&partial, &claim), Err(VerificationError::UnsupportedDeferredProof) )); // ...and verified by the partial path, which returns the linear obligation let (_, pending) = Verifier::new() - .verify_partial(partial, claim) + .verify_partial(&partial, &claim) .expect("partial verification should pass"); assert_eq!(pending.root(), miden_core::deferred::TRUE_DIGEST); let _state = pending.into_state(); @@ -509,7 +509,7 @@ fn test_deferred_stark_proof_requires_exact_encoding_and_bound_root() { .expect("Proving failed"); let claim = ExecutionClaim::from_program_info(program.into(), stack_inputs, stack_outputs); - verify(proof.clone(), claim.clone()).expect("untampered deferred proof should verify"); + verify(&proof, &claim).expect("untampered deferred proof should verify"); // The proof encoding is exact: an otherwise-valid proof with a trailing byte is rejected. let stark = proof.miden_proof(); @@ -519,12 +519,12 @@ fn test_deferred_stark_proof_requires_exact_encoding_and_bound_root() { StarkProof::new(proof_bytes, stark.hash_fn()), proof.deferred_proof().clone(), ); - verify(trailing, claim.clone()).expect_err("trailing proof bytes must be rejected"); + verify(&trailing, &claim).expect_err("trailing proof bytes must be rejected"); // The deferred root is statement-bound: replacing it with TRUE must fail. let tampered = ExecutionProof::new( StarkProof::new(stark.bytes().to_vec(), stark.hash_fn()), DeferredProof::empty(), ); - assert!(verify(tampered, claim).is_err()); + assert!(verify(&tampered, &claim).is_err()); } diff --git a/processor/src/host/advice/mod.rs b/processor/src/host/advice/mod.rs index 3436496702..da7a2a5b7a 100644 --- a/processor/src/host/advice/mod.rs +++ b/processor/src/host/advice/mod.rs @@ -185,11 +185,11 @@ impl AdviceProvider { AdviceMutation::ExtendStack { stack } => { self.extend_advice_stack(stack)?; }, - AdviceMutation::ExtendMap { other } => { - self.extend_map(&other)?; + AdviceMutation::ExtendMap { map } => { + self.extend_map(&map)?; }, - AdviceMutation::ExtendMerkleStore { infos } => { - self.extend_merkle_store(infos)?; + AdviceMutation::ExtendMerkleStore { inner_nodes } => { + self.extend_merkle_store(inner_nodes)?; }, } Ok(()) diff --git a/processor/src/host/mod.rs b/processor/src/host/mod.rs index 2db7517959..39d78e21f2 100644 --- a/processor/src/host/mod.rs +++ b/processor/src/host/mod.rs @@ -30,8 +30,8 @@ pub use mast_forest_store::{LoadedMastForest, MastForestStore, MemMastForestStor #[derive(Debug, PartialEq, Eq)] pub enum AdviceMutation { ExtendStack { stack: AdviceStack }, - ExtendMap { other: AdviceMap }, - ExtendMerkleStore { infos: Vec }, + ExtendMap { map: AdviceMap }, + ExtendMerkleStore { inner_nodes: Vec }, } impl AdviceMutation { @@ -39,12 +39,12 @@ impl AdviceMutation { Self::ExtendStack { stack } } - pub fn extend_map(other: AdviceMap) -> Self { - Self::ExtendMap { other } + pub fn extend_map(map: AdviceMap) -> Self { + Self::ExtendMap { map } } - pub fn extend_merkle_store(infos: impl IntoIterator) -> Self { - Self::ExtendMerkleStore { infos: Vec::from_iter(infos) } + pub fn extend_merkle_store(inner_nodes: impl IntoIterator) -> Self { + Self::ExtendMerkleStore { inner_nodes: Vec::from_iter(inner_nodes) } } } // HOST TRAIT diff --git a/verifier/README.md b/verifier/README.md index ae8d762b57..852fe03b80 100644 --- a/verifier/README.md +++ b/verifier/README.md @@ -5,7 +5,7 @@ While [Miden](../miden-vm) crate also contains verifier functionality, if a proj ## Usage -Use `verify(proof, claim)` to verify a final `ExecutionProof`. The `ExecutionClaim` contains the +Use `verify(&proof, &claim)` to verify a final `ExecutionProof`. The `ExecutionClaim` contains the program information and public stack inputs and outputs. The function returns the proof's security level, or a `VerificationError` if verification fails. diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index 524077f5ad..12d4d87527 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -90,8 +90,8 @@ impl Verifier { /// public root. pub fn verify( &self, - proof: ExecutionProof, - claim: ExecutionClaim, + proof: &ExecutionProof, + claim: &ExecutionClaim, ) -> Result { let miden_security_level = proof.security_level(); let (final_deferred_root, precompile_security_level) = @@ -122,8 +122,8 @@ impl Verifier { /// deferred root. pub fn verify_partial( &self, - proof: ExecutionProof, - claim: ExecutionClaim, + proof: &ExecutionProof, + claim: &ExecutionClaim, ) -> Result<(u32, Unsettled), VerificationError> { let security_level = proof.security_level(); let deferred_state = @@ -167,7 +167,7 @@ impl Unsettled { /// - The provided proof does not prove a correct execution of the claim. /// - The proof carries wire-backed deferred proof material, which is a partial/delegable form. /// - The proof's STARK-backed deferred proof, if present, does not verify against its public root. -pub fn verify(proof: ExecutionProof, claim: ExecutionClaim) -> Result { +pub fn verify(proof: &ExecutionProof, claim: &ExecutionClaim) -> Result { Verifier::default().verify(proof, claim) } @@ -212,7 +212,7 @@ fn stark_security_level(_proof: &StarkProof) -> u32 { } fn verify_stark( - claim: ExecutionClaim, + claim: &ExecutionClaim, final_deferred_root: Word, stark_proof: &StarkProof, ) -> Result<(), VerificationError> {