diff --git a/air/src/lib.rs b/air/src/lib.rs index d954eef7fa..f347914e13 100644 --- a/air/src/lib.rs +++ b/air/src/lib.rs @@ -9,8 +9,8 @@ use vm_core::{ ExtensionOf, ProgramInfo, StackInputs, StackOutputs, ONE, ZERO, }; use winter_air::{ - Air, AirContext, Assertion, AuxTraceRandElements, EvaluationFrame, - ProofOptions as WinterProofOptions, TraceInfo, TransitionConstraintDegree, + Air, AirContext, Assertion, AuxTraceRandElements, EvaluationFrame, TraceInfo, + TransitionConstraintDegree, }; mod constraints; @@ -37,7 +37,7 @@ pub use vm_core::{ utils::{DeserializationError, ToElements}, Felt, FieldElement, StarkField, }; -pub use winter_air::FieldExtension; +pub use winter_air::{FieldExtension, ProofOptions as WinterProofOptions}; // PROCESSOR AIR // ================================================================================================ diff --git a/air/src/options.rs b/air/src/options.rs index 4cbc995a60..3848b4843f 100644 --- a/air/src/options.rs +++ b/air/src/options.rs @@ -1,6 +1,6 @@ use super::{ExecutionOptionsError, HashFunction}; +use super::{FieldExtension, WinterProofOptions}; use crate::trace::MIN_TRACE_LEN; -use winter_air::{FieldExtension, ProofOptions as WinterProofOptions}; // PROVING OPTIONS // ================================================================================================ diff --git a/miden/src/cli/verify.rs b/miden/src/cli/verify.rs index 4bb88d25a9..9e81863b26 100644 --- a/miden/src/cli/verify.rs +++ b/miden/src/cli/verify.rs @@ -2,7 +2,6 @@ use super::data::{InputFile, OutputFile, ProgramHash, ProofFile}; use clap::Parser; use miden::{Kernel, ProgramInfo}; use std::{path::PathBuf, time::Instant}; -use verifier::AcceptableOptions; #[derive(Debug, Clone, Parser)] #[clap(about = "Verify a miden program")] @@ -50,15 +49,8 @@ impl VerifyCmd { let program_info = ProgramInfo::new(program_hash, kernel); // verify proof - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - verifier::verify( - program_info, - stack_inputs, - outputs_data.stack_outputs()?, - proof, - &min_opts, - ) - .map_err(|err| format!("Program failed verification! - {}", err))?; + verifier::verify(program_info, stack_inputs, outputs_data.stack_outputs()?, proof) + .map_err(|err| format!("Program failed verification! - {}", err))?; println!("Verification complete in {} ms", now.elapsed().as_millis()); diff --git a/miden/src/examples/mod.rs b/miden/src/examples/mod.rs index 3d97d0c046..df1a234184 100644 --- a/miden/src/examples/mod.rs +++ b/miden/src/examples/mod.rs @@ -3,7 +3,6 @@ use miden::{ExecutionProof, Host, Program, ProgramInfo, ProvingOptions, StackInp use processor::{ExecutionOptions, ExecutionOptionsError, ONE, ZERO}; use std::io::Write; use std::time::Instant; -use verifier::AcceptableOptions; pub mod fibonacci; @@ -122,11 +121,10 @@ impl ExampleOptions { // verify that executing a program with a given hash and given inputs // results in the expected output let proof = ExecutionProof::from_bytes(&proof_bytes).unwrap(); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); let now = Instant::now(); let program_info = ProgramInfo::from(program); - match miden::verify(program_info, stack_inputs, stack_outputs, proof, &min_opts) { + match miden::verify(program_info, stack_inputs, stack_outputs, proof) { Ok(_) => println!("Execution verified in {} ms", now.elapsed().as_millis()), Err(err) => println!("Failed to verify execution: {}", err), } @@ -162,12 +160,11 @@ where let kernel = miden::Kernel::default(); let program_info = ProgramInfo::new(program.hash(), kernel); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); if fail { outputs.stack_mut()[0] += 1; - assert!(miden::verify(program_info, stack_inputs, outputs, proof, &min_opts).is_err()) + assert!(miden::verify(program_info, stack_inputs, outputs, proof).is_err()) } else { - assert!(miden::verify(program_info, stack_inputs, outputs, proof, &min_opts).is_ok()); + assert!(miden::verify(program_info, stack_inputs, outputs, proof).is_ok()); } } diff --git a/miden/tests/integration/air/chiplets/bitwise.rs b/miden/tests/integration/air/chiplets/bitwise.rs index 3818466481..f36323024b 100644 --- a/miden/tests/integration/air/chiplets/bitwise.rs +++ b/miden/tests/integration/air/chiplets/bitwise.rs @@ -1,4 +1,4 @@ -use test_utils::{build_op_test, build_test, AcceptableOptions}; +use test_utils::{build_op_test, build_test}; #[test] fn bitwise_and() { @@ -6,8 +6,7 @@ fn bitwise_and() { let asm_op = "u32checked_and push.0 u32checked_and push.0 u32checked_and push.65535 push.137 u32checked_and"; let pub_inputs = vec![1, 1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -16,8 +15,7 @@ fn bitwise_or() { let asm_op = "u32checked_or push.0 u32checked_or not push.0 u32checked_or push.65535 push.137 u32checked_or"; let pub_inputs = vec![1, 1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -26,8 +24,7 @@ fn bitwise_xor() { let asm_op = "u32checked_xor push.0 u32checked_xor push.1 u32checked_xor push.65535 push.137 u32checked_xor"; let pub_inputs = vec![1, 1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -35,6 +32,5 @@ fn all_operations() { let source = "begin u32checked_and push.0 u32checked_or push.0 u32checked_xor end"; let pub_inputs = vec![1, 1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, false); } diff --git a/miden/tests/integration/air/chiplets/hasher.rs b/miden/tests/integration/air/chiplets/hasher.rs index ecce110ef3..84e20ed869 100644 --- a/miden/tests/integration/air/chiplets/hasher.rs +++ b/miden/tests/integration/air/chiplets/hasher.rs @@ -2,7 +2,7 @@ use test_utils::{ build_op_test, crypto::{init_merkle_leaf, init_merkle_store, MerkleStore, MerkleTree, Rpo256}, rand::rand_vector, - AcceptableOptions, StarkField, Word, + StarkField, Word, }; #[test] @@ -10,8 +10,7 @@ fn hperm() { let asm_op = "hperm"; let pub_inputs = rand_vector::(8); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -19,8 +18,7 @@ fn hmerge() { let asm_op = "hmerge"; let pub_inputs = rand_vector::(8); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -40,12 +38,8 @@ fn mtree_get() { tree.depth() as u64, ]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &stack_inputs, &[], store).prove_and_verify( - stack_inputs.to_vec(), - &min_opts, - false, - ); + build_op_test!(asm_op, &stack_inputs, &[], store) + .prove_and_verify(stack_inputs.to_vec(), false); } #[test] @@ -53,12 +47,8 @@ fn mtree_set() { let asm_op = "mtree_set"; let (stack_inputs, store, _leaves) = build_mtree_update_test_inputs(); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &stack_inputs, &[], store).prove_and_verify( - stack_inputs.to_vec(), - &min_opts, - false, - ); + build_op_test!(asm_op, &stack_inputs, &[], store) + .prove_and_verify(stack_inputs.to_vec(), false); } #[test] @@ -82,12 +72,8 @@ fn mtree_verify() { leaves[index][3].as_int(), ]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &stack_inputs, &[], store).prove_and_verify( - stack_inputs.to_vec(), - &min_opts, - false, - ); + build_op_test!(asm_op, &stack_inputs, &[], store) + .prove_and_verify(stack_inputs.to_vec(), false); } #[test] @@ -127,12 +113,8 @@ fn mtree_merge() { root_merged[3].as_int(), ]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &stack_inputs, &stack_outputs, store).prove_and_verify( - stack_inputs, - &min_opts, - false, - ); + build_op_test!(asm_op, &stack_inputs, &stack_outputs, store) + .prove_and_verify(stack_inputs, false); } /// Helper function that builds a test stack and Merkle tree for testing mtree updates. diff --git a/miden/tests/integration/air/chiplets/memory.rs b/miden/tests/integration/air/chiplets/memory.rs index b9db94ccb1..573af766fa 100644 --- a/miden/tests/integration/air/chiplets/memory.rs +++ b/miden/tests/integration/air/chiplets/memory.rs @@ -1,11 +1,10 @@ -use test_utils::{build_op_test, build_test, AcceptableOptions, ToElements}; +use test_utils::{build_op_test, build_test, ToElements}; #[test] fn mem_load() { let asm_op = "mem_load.0 swap"; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op).prove_and_verify(vec![], &min_opts, false); + build_op_test!(asm_op).prove_and_verify(vec![], false); } #[test] @@ -13,8 +12,7 @@ fn mem_store() { let asm_op = "mem_store.0"; let pub_inputs = vec![1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -43,8 +41,7 @@ fn helper_mem_store() { fn mem_loadw() { let asm_op = "mem_loadw.0"; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op).prove_and_verify(vec![], &min_opts, false); + build_op_test!(asm_op).prove_and_verify(vec![], false); } #[test] @@ -52,8 +49,7 @@ fn mem_storew() { let asm_op = "mem_storew.0"; let pub_inputs = vec![1, 2, 3, 4]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -62,8 +58,7 @@ fn write_read() { let pub_inputs = vec![4, 3, 2, 1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -85,8 +80,7 @@ fn update() { let source = "begin push.0.0.0.0 mem_loadw.0 mem_storew.0 swapw end"; let pub_inputs = vec![8, 7, 6, 5, 4, 3, 2, 1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -94,6 +88,5 @@ fn incr_write_addr() { let source = "begin mem_storew.0 mem_storew.1 end"; let pub_inputs = vec![4, 3, 2, 1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, false); } diff --git a/miden/tests/integration/air/chiplets/mod.rs b/miden/tests/integration/air/chiplets/mod.rs index ecfff00c22..aa59571d73 100644 --- a/miden/tests/integration/air/chiplets/mod.rs +++ b/miden/tests/integration/air/chiplets/mod.rs @@ -1,4 +1,4 @@ -use test_utils::{build_test, rand::rand_vector, AcceptableOptions}; +use test_utils::{build_test, rand::rand_vector}; mod bitwise; mod hasher; @@ -14,6 +14,5 @@ fn chiplets() { end"; let pub_inputs = rand_vector::(8); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_test!(source, &pub_inputs).prove_and_verify(pub_inputs, false); } diff --git a/miden/tests/integration/air/range.rs b/miden/tests/integration/air/range.rs index d097a14c1d..aa7796b392 100644 --- a/miden/tests/integration/air/range.rs +++ b/miden/tests/integration/air/range.rs @@ -1,4 +1,4 @@ -use test_utils::{build_op_test, build_test, AcceptableOptions}; +use test_utils::{build_op_test, build_test}; /// Range checks the result of 1 + 1. This results in 2 range checks, one for each 16-bit limb of /// the 32-bit result (2 and 0). @@ -7,8 +7,7 @@ fn range_check_once() { let asm_op = "u32overflowing_add"; let stack = vec![1, 1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &stack).prove_and_verify(stack, &min_opts, false); + build_op_test!(asm_op, &stack).prove_and_verify(stack, false); } /// Range checks multiple values a varying number of times, since each value is checked as an input. @@ -18,8 +17,7 @@ fn range_check_multi() { let source = "begin u32checked_add u32checked_add end"; let stack = vec![5, 5, 5]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_test!(source, &stack).prove_and_verify(stack, &min_opts, false); + build_test!(source, &stack).prove_and_verify(stack, false); } /// Range checks the result of 1 + u32::MAX - 1, which is u32::MAX. Therefore, it requires range @@ -29,6 +27,5 @@ fn range_check_u16max() { let asm_op = "u32overflowing_add"; let stack = vec![1, (u32::MAX - 1) as u64]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(asm_op, &stack).prove_and_verify(stack, &min_opts, false); + build_op_test!(asm_op, &stack).prove_and_verify(stack, false); } diff --git a/miden/tests/integration/air/stack/field_ops.rs b/miden/tests/integration/air/stack/field_ops.rs index 8fe185cac6..50509525e9 100644 --- a/miden/tests/integration/air/stack/field_ops.rs +++ b/miden/tests/integration/air/stack/field_ops.rs @@ -1,12 +1,11 @@ -use test_utils::{build_op_test, AcceptableOptions}; +use test_utils::build_op_test; #[test] fn incr() { let asm_op = "add.1 add.1 push.0 add.1 add.1 eq assert"; let pub_inputs = vec![0]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -14,8 +13,7 @@ fn neg() { let asm_op = "dup.0 neg add eq.0 assert"; let pub_inputs = vec![7]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -23,8 +21,7 @@ fn not() { let asm_op = "dup.0 not add eq.1 assert"; let pub_inputs = vec![1]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } #[test] @@ -33,6 +30,5 @@ fn expacc() { let asm_op = "push.10 exp eq.3486784401 assert"; let pub_inputs = vec![9]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } diff --git a/miden/tests/integration/air/stack/mod.rs b/miden/tests/integration/air/stack/mod.rs index b5a413a696..3ba80691be 100644 --- a/miden/tests/integration/air/stack/mod.rs +++ b/miden/tests/integration/air/stack/mod.rs @@ -1,4 +1,4 @@ -use test_utils::{build_op_test, AcceptableOptions}; +use test_utils::build_op_test; mod field_ops; mod stack_manipualtion_ops; @@ -9,8 +9,7 @@ fn empty_input() { let asm_op = "push.1 drop"; let pub_inputs = vec![]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } /// Test an empty starting stack but enough outputs that the overflow table is non-empty at the end. @@ -19,8 +18,7 @@ fn empty_input_overflow_output() { let asm_ops = "push.17 push.18"; let pub_inputs = vec![]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_ops, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_ops, &pub_inputs).prove_and_verify(pub_inputs, false); } /// Test starting stack with some inputs but not full with no overflow outputs. @@ -29,8 +27,7 @@ fn some_inputs() { let asm_op = "push.5 drop"; let pub_inputs = vec![1, 2, 3, 4]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } /// Test full starting stack with no overflow outputs. @@ -39,8 +36,7 @@ fn full_inputs() { let asm_op = "push.17 drop"; let pub_inputs = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } /// Test a script that finishes with enough outputs that the overflow table is non-empty at the end. @@ -49,8 +45,7 @@ fn full_inputs_overflow_outputs() { let asm_ops = "push.17 push.18"; let pub_inputs = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_ops, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_ops, &pub_inputs).prove_and_verify(pub_inputs, false); } /// Test a script initialized with enough inputs that the overflow table is non-empty at the start @@ -61,8 +56,7 @@ fn overflow_inputs() { let pub_inputs = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } /// Test a script initialized with enough inputs that the overflow table is non-empty at the start @@ -72,6 +66,5 @@ fn overflow_inputs_overflow_outputs() { let asm_op = "push.19 push.20"; let pub_inputs = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } diff --git a/miden/tests/integration/air/stack/stack_manipualtion_ops.rs b/miden/tests/integration/air/stack/stack_manipualtion_ops.rs index 0f32cb1bc6..9d38c6385d 100644 --- a/miden/tests/integration/air/stack/stack_manipualtion_ops.rs +++ b/miden/tests/integration/air/stack/stack_manipualtion_ops.rs @@ -1,4 +1,4 @@ -use test_utils::{build_op_test, AcceptableOptions}; +use test_utils::build_op_test; #[test] fn swap() { @@ -6,6 +6,5 @@ fn swap() { let asm_op = "swap push.0 swap push.34 swap drop drop"; let pub_inputs = vec![7, 69]; - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, &min_opts, false); + build_op_test!(&asm_op, &pub_inputs).prove_and_verify(pub_inputs, false); } diff --git a/miden/tests/integration/flow_control/mod.rs b/miden/tests/integration/flow_control/mod.rs index be67acbb87..aec1e0c046 100644 --- a/miden/tests/integration/flow_control/mod.rs +++ b/miden/tests/integration/flow_control/mod.rs @@ -1,4 +1,4 @@ -use test_utils::{build_test, AcceptableOptions, AdviceInputs, StackInputs, Test, TestError}; +use test_utils::{build_test, AdviceInputs, StackInputs, Test, TestError}; // SIMPLE FLOW CONTROL TESTS // ================================================================================================ @@ -158,8 +158,7 @@ fn local_fn_call() { let test = build_test!(source, &inputs); test.expect_stack(&[2, 1]); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - test.prove_and_verify(inputs, &min_opts, false); + test.prove_and_verify(inputs, false); } #[test] @@ -181,8 +180,7 @@ fn local_fn_call_with_mem_access() { let test = build_test!(source, &[3, 7]); test.expect_stack(&[1]); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - test.prove_and_verify(vec![3, 7], &min_opts, false); + test.prove_and_verify(vec![3, 7], false); } #[test] @@ -209,8 +207,7 @@ fn simple_syscall() { }; test.expect_stack(&[3]); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - test.prove_and_verify(vec![1, 2], &min_opts, false); + test.prove_and_verify(vec![1, 2], false); } // DYNAMIC CODE EXECUTION @@ -268,7 +265,6 @@ fn simple_dyn_exec() { test.expect_stack(&[6]); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); test.prove_and_verify( vec![ 3, @@ -279,7 +275,6 @@ fn simple_dyn_exec() { 1, 2, ], - &min_opts, false, ); } @@ -344,7 +339,6 @@ fn simple_dyncall() { test.expect_stack(&[6]); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); test.prove_and_verify( vec![ 3, @@ -355,7 +349,6 @@ fn simple_dyncall() { 1, 2, ], - &min_opts, false, ); } diff --git a/miden/tests/integration/main.rs b/miden/tests/integration/main.rs index 56cb0485bc..dc695672cb 100644 --- a/miden/tests/integration/main.rs +++ b/miden/tests/integration/main.rs @@ -1,4 +1,4 @@ -use test_utils::{build_test, AcceptableOptions}; +use test_utils::build_test; mod air; mod cli; @@ -17,6 +17,5 @@ fn simple_program() { #[test] fn multi_output_program() { let test = build_test!("begin mul movup.2 drop end", &[1, 2, 3]); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - test.prove_and_verify(vec![1, 2, 3], &min_opts, false); + test.prove_and_verify(vec![1, 2, 3], false); } diff --git a/miden/tests/integration/operations/fri_ops.rs b/miden/tests/integration/operations/fri_ops.rs index 7332a33688..3c14c71694 100644 --- a/miden/tests/integration/operations/fri_ops.rs +++ b/miden/tests/integration/operations/fri_ops.rs @@ -1,4 +1,4 @@ -use test_utils::{build_test, rand::rand_array, AcceptableOptions, Felt, FieldElement, StarkField}; +use test_utils::{build_test, rand::rand_array, Felt, FieldElement, StarkField}; // FRI_EXT2FOLD4 // ================================================================================================ @@ -36,6 +36,5 @@ fn fri_ext2fold4() { assert_eq!(stack_state[15], Felt::new(end_ptr)); // make sure STARK proof can be generated and verified - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - test.prove_and_verify(inputs, &min_opts, false); + test.prove_and_verify(inputs, false); } diff --git a/miden/tests/integration/operations/io_ops/env_ops.rs b/miden/tests/integration/operations/io_ops/env_ops.rs index 61faa65aab..52ea6cc394 100644 --- a/miden/tests/integration/operations/io_ops/env_ops.rs +++ b/miden/tests/integration/operations/io_ops/env_ops.rs @@ -1,7 +1,6 @@ use processor::FMP_MIN; use test_utils::{ - build_op_test, build_test, AcceptableOptions, AdviceInputs, StackInputs, StarkField, Test, - Word, STACK_TOP_SIZE, + build_op_test, build_test, AdviceInputs, StackInputs, StarkField, Test, Word, STACK_TOP_SIZE, }; use vm_core::{code_blocks::CodeBlock, Operation}; @@ -157,8 +156,7 @@ fn caller() { let bar_hash = build_bar_hash(); test.expect_stack(&[bar_hash[3], bar_hash[2], bar_hash[1], bar_hash[0], 1]); - let min_opts = AcceptableOptions::MinConjecturedSecurity(80); - test.prove_and_verify(vec![1, 2, 3, 4, 5], &min_opts, false); + test.prove_and_verify(vec![1, 2, 3, 4, 5], false); } fn build_bar_hash() -> [u64; 4] { diff --git a/prover/src/gpu.rs b/prover/src/gpu.rs index 4ff74c2211..93d868bce6 100644 --- a/prover/src/gpu.rs +++ b/prover/src/gpu.rs @@ -16,9 +16,10 @@ use processor::{ }; use std::time::Instant; use winter_prover::{ - crypto::MerkleTree, + crypto::{ElementHasher, Hasher, MerkleTree}, matrix::{build_segments, get_evaluation_offsets, Segment}, - ColMatrix, CompositionPoly, ConstraintCommitment, Prover, RowMatrix, StarkDomain, + ColMatrix, CompositionPoly, CompositionPolyTrace, ConstraintCommitment, EvaluationFrame, + Prover, RowMatrix, StarkDomain, TraceInfo, TraceLayout, TraceLde, TracePolyTable, }; const RPO_RATE: usize = Rpo256::RATE_RANGE.end - Rpo256::RATE_RANGE.start; @@ -37,6 +38,10 @@ where type Trace = as Prover>::Trace; type HashFn = Rpo256; type RandomCoin = R; + type TraceLde> = + DefaultGpuTraceLde; + type ConstraintEvaluator<'a, E: air::FieldElement> = + as Prover>::ConstraintEvaluator<'a, E>; fn options(&self) -> &WinterProofOptions { self.0.options() @@ -46,95 +51,6 @@ where self.0.get_pub_inputs(trace) } - /// Computes a low-degree extension (LDE) of the provided execution trace over the specified - /// domain and builds a commitment to the extended trace. - /// - /// The extension is performed by interpolating each column of the execution trace into a - /// polynomial of degree = trace_length - 1, and then evaluating the polynomial over the LDE - /// domain. - /// - /// Trace commitment is computed by hashing each row of the extended execution trace, and then - /// building a Merkle tree from the resulting hashes. - /// - /// Interpolations and evaluations are computed on the CPU while hashes are simultaneously - /// computed on the GPU: - /// - /// ```text - /// ────────────────────────────────────────────────────── - /// ┌───┐ ┌────┐ ┌───┐ ┌────┐ ┌───┐ - /// CPU: ... ──┤fft├─┬─┤ifft├───┤fft├─┬─┤ifft├───┤fft├─┬─ ... - /// └───┘ │ └────┘ └───┘ │ └────┘ └───┘ │ - /// ╴╴╴╴╴╴╴╴╴╴╴╴╴┼╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┼╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┼╴╴╴╴╴╴ - /// │ ┌──────────┐ │ ┌──────────┐ │ - /// GPU: └─┤ hash │ └─┤ hash │ └─ ... - /// └──────────┘ └──────────┘ - /// ────┼────────┼────────┼────────┼────────┼────────┼──── - /// t=n t=n+1 t=n+2 t=n+3 t=n+4 t=n+5 - /// ``` - fn build_trace_commitment( - &self, - trace: &ColMatrix, - domain: &StarkDomain, - ) -> (RowMatrix, MerkleTree, ColMatrix) - where - E: air::FieldElement, - { - // interpolate the execution trace - let now = Instant::now(); - let inv_twiddles = fft::get_inv_twiddles::(trace.num_rows()); - let trace_polys = trace.columns().map(|col| { - let mut poly = col.to_vec(); - fft::interpolate_poly(&mut poly, &inv_twiddles); - poly - }); - - // extend the execution trace and generate hashes on the gpu - let lde_segments = FrozenVec::new(); - let lde_domain_size = domain.lde_domain_size(); - let num_base_columns = trace.num_base_cols(); - let rpo_requires_padding = num_base_columns % RPO_RATE != 0; - let rpo_padded_segment_idx = rpo_requires_padding.then_some(num_base_columns / RPO_RATE); - let mut row_hasher = GpuRpo256RowMajor::::new(lde_domain_size, rpo_requires_padding); - let mut rpo_padded_segment: Vec<[Felt; RPO_RATE]>; - let mut lde_segment_generator = SegmentGenerator::new(trace_polys, domain); - let mut lde_segment_iter = lde_segment_generator.gen_segment_iter().enumerate(); - for (segment_idx, segment) in &mut lde_segment_iter { - let segment = lde_segments.push_get(Box::new(segment)); - // check if the segment requires padding - if rpo_padded_segment_idx.map_or(false, |pad_idx| pad_idx == segment_idx) { - // duplicate and modify the last segment with Rpo256's padding - // rule ("1" followed by "0"s). Our segments are already - // padded with "0"s we only need to add the "1"s. - let rpo_pad_column = num_base_columns % RPO_RATE; - rpo_padded_segment = unsafe { page_aligned_uninit_vector(lde_domain_size) }; - rpo_padded_segment.copy_from_slice(segment); - rpo_padded_segment.iter_mut().for_each(|row| row[rpo_pad_column] = ONE); - row_hasher.update(&rpo_padded_segment); - assert!(lde_segment_iter.next().is_none(), "padded segment should be the last"); - break; - } - row_hasher.update(segment); - } - let row_hashes = block_on(row_hasher.finish()); - let tree_nodes = gen_rpo_merkle_tree(&row_hashes); - // aggregate segments at the same time as the GPU generates the merkle tree nodes - let lde_segments = lde_segments.into_vec().into_iter().map(|p| *p).collect(); - let trace_lde = RowMatrix::from_segments(lde_segments, num_base_columns); - let trace_polys = lde_segment_generator.into_polys().unwrap(); - let nodes = block_on(tree_nodes).into_iter().map(RpoDigest::new).collect(); - let leaves = row_hashes.into_iter().map(RpoDigest::new).collect(); - let trace_tree = MerkleTree::from_raw_parts(nodes, leaves).unwrap(); - debug!( - "Extended (on CPU) and committed (on GPU) to an execution trace of {} columns from 2^{} to 2^{} steps in {} ms", - trace_polys.num_cols(), - trace_polys.num_rows().ilog2(), - trace_lde.num_rows().ilog2(), - now.elapsed().as_millis() - ); - - (trace_lde, trace_tree, trace_polys) - } - /// Evaluates constraint composition polynomial over the LDE domain and builds a commitment /// to these evaluations. /// @@ -164,21 +80,23 @@ where // * https://github.com/0xPolygonMiden/miden-vm/issues/877 fn build_constraint_commitment( &self, - composition_poly: &CompositionPoly, + composition_poly: CompositionPolyTrace, + num_trace_poly_columns: usize, domain: &StarkDomain, - ) -> ConstraintCommitment + ) -> (ConstraintCommitment, CompositionPoly) where E: FieldElement, { // evaluate composition polynomial columns over the LDE domain let now = Instant::now(); - let polys = composition_poly.data(); + let polys = CompositionPoly::new(composition_poly, domain, num_trace_poly_columns); let blowup = domain.trace_to_lde_blowup(); - let offsets = get_evaluation_offsets::(polys.num_rows(), blowup, domain.offset()); - let segments = build_segments(composition_poly.data(), domain.trace_twiddles(), &offsets); + let offsets = + get_evaluation_offsets::(composition_poly.num_rows(), blowup, domain.offset()); + let segments = build_segments(polys.data(), domain.trace_twiddles(), &offsets); debug!( "Evaluated {} composition polynomial columns over LDE domain (2^{} elements) in {} ms", - polys.num_cols(), + polys.num_columns(), offsets.len().ilog2(), now.elapsed().as_millis() ); @@ -186,7 +104,7 @@ where // build constraint evaluation commitment let now = Instant::now(); let lde_domain_size = domain.lde_domain_size(); - let num_base_columns = polys.num_base_cols(); + let num_base_columns = polys.num_columns() * ::EXTENSION_DEGREE; let rpo_requires_padding = num_base_columns % RPO_RATE != 0; let rpo_padded_segment_idx = rpo_requires_padding.then_some(num_base_columns / RPO_RATE); let mut row_hasher = GpuRpo256RowMajor::::new(lde_domain_size, rpo_requires_padding); @@ -220,7 +138,31 @@ where constraint_commitment.tree_depth(), now.elapsed().as_millis() ); - constraint_commitment + (constraint_commitment, polys) + } + + fn new_trace_lde( + &self, + trace_info: &TraceInfo, + main_trace: &ColMatrix, + domain: &StarkDomain, + ) -> (Self::TraceLde, TracePolyTable) + where + E: FieldElement, + { + DefaultGpuTraceLde::new(trace_info, main_trace, domain) + } + + fn new_evaluator<'a, E>( + &self, + air: &'a Self::Air, + aux_rand_elements: winter_prover::AuxTraceRandElements, + composition_coefficients: winter_prover::ConstraintCompositionCoefficients, + ) -> Self::ConstraintEvaluator<'a, E> + where + E: FieldElement, + { + self.0.new_evaluator(air, aux_rand_elements, composition_coefficients) } } @@ -301,6 +243,227 @@ where } } +// TRACE LOW DEGREE EXTENSION +// ================================================================================================ +/// Contains all segments of the extended execution trace, the commitments to these segments, the +/// LDE blowup factor, and the [TraceInfo]. +/// +/// Segments are stored in two groups: +/// - Main segment: this is the first trace segment generated by the prover. Values in this segment +/// will always be elements in the base field (even when an extension field is used). +/// - Auxiliary segments: a list of 0 or more segments for traces generated after the prover +/// commits to the first trace segment. Currently, at most 1 auxiliary segment is possible. +pub struct DefaultGpuTraceLde< + E: FieldElement, + H: ElementHasher, +> { + // low-degree extension of the main segment of the trace + main_segment_lde: RowMatrix, + // commitment to the main segment of the trace + main_segment_tree: MerkleTree, + // low-degree extensions of the auxiliary segments of the trace + aux_segment_ldes: Vec>, + // commitment to the auxiliary segments of the trace + aux_segment_trees: Vec>, + blowup: usize, + trace_info: TraceInfo, +} + +impl, H: ElementHasher> + DefaultGpuTraceLde +{ + /// Takes the main trace segment columns as input, interpolates them into polynomials in + /// coefficient form, evaluates the polynomials over the LDE domain, commits to the + /// polynomial evaluations, and creates a new [DefaultTraceLde] with the LDE of the main trace + /// segment and the commitment. + /// + /// Returns a tuple containing a [TracePolyTable] with the trace polynomials for the main trace + /// segment and the new [DefaultTraceLde]. + pub fn new( + trace_info: &TraceInfo, + main_trace: &ColMatrix, + domain: &StarkDomain, + ) -> (Self, TracePolyTable) { + // extend the main execution trace and build a Merkle tree from the extended trace + let (main_segment_lde, main_segment_tree, main_segment_polys) = + build_trace_commitment::(main_trace, domain); + + let trace_poly_table = TracePolyTable::new(main_segment_polys); + let trace_lde = DefaultGpuTraceLde { + main_segment_lde, + main_segment_tree, + aux_segment_ldes: Vec::new(), + aux_segment_trees: Vec::new(), + blowup: domain.trace_to_lde_blowup(), + trace_info: trace_info.clone(), + }; + + (trace_lde, trace_poly_table) + } + + // TEST HELPERS + // -------------------------------------------------------------------------------------------- + + /// Returns number of columns in the main segment of the execution trace. + #[cfg(test)] + pub fn main_segment_width(&self) -> usize { + self.main_segment_lde.num_cols() + } + + /// Returns a reference to [Matrix] representing the main trace segment. + #[cfg(test)] + pub fn get_main_segment(&self) -> &RowMatrix { + &self.main_segment_lde + } + + /// Returns the entire trace for the column at the specified index. + #[cfg(test)] + pub fn get_main_segment_column(&self, col_idx: usize) -> Vec { + (0..self.main_segment_lde.num_rows()) + .map(|row_idx| self.main_segment_lde.get(col_idx, row_idx)) + .collect() + } +} + +impl TraceLde for DefaultGpuTraceLde +where + E: FieldElement, + H: ElementHasher, +{ + type HashFn = H; + + /// Returns the commitment to the low-degree extension of the main trace segment. + fn get_main_trace_commitment(&self) -> ::Digest { + let root_hash = self.main_segment_tree.root(); + *root_hash + } + + /// Takes auxiliary trace segment columns as input, interpolates them into polynomials in + /// coefficient form, evaluates the polynomials over the LDE domain, and commits to the + /// polynomial evaluations. + /// + /// Returns a tuple containing the column polynomials in coefficient from and the commitment + /// to the polynomial evaluations over the LDE domain. + /// + /// # Panics + /// + /// This function will panic if any of the following are true: + /// - the number of rows in the provided `aux_trace` does not match the main trace. + /// - this segment would exceed the number of segments specified by the trace layout. + fn add_aux_segment( + &mut self, + aux_trace: &ColMatrix, + domain: &StarkDomain, + ) -> (ColMatrix, ::Digest) { + // extend the auxiliary trace segment and build a Merkle tree from the extended trace + let (aux_segment_lde, aux_segment_tree, aux_segment_polys) = + build_trace_commitment::(aux_trace, domain); + + // check errors + assert!( + self.aux_segment_ldes.len() < self.trace_info.layout().num_aux_segments(), + "the specified number of auxiliary segments has already been added" + ); + assert_eq!( + self.main_segment_lde.num_rows(), + aux_segment_lde.num_rows(), + "the number of rows in the auxiliary segment must be the same as in the main segment" + ); + + // save the lde and commitment + self.aux_segment_ldes.push(aux_segment_lde); + let root_hash = *aux_segment_tree.root(); + self.aux_segment_trees.push(aux_segment_tree); + + (aux_segment_polys, root_hash) + } + + /// Reads current and next rows from the main trace segment into the specified frame. + fn read_main_trace_frame_into( + &self, + lde_step: usize, + frame: &mut EvaluationFrame, + ) { + // at the end of the trace, next state wraps around and we read the first step again + let next_lde_step = (lde_step + self.blowup()) % self.trace_len(); + + // copy main trace segment values into the frame + frame.current_mut().copy_from_slice(self.main_segment_lde.row(lde_step)); + frame.next_mut().copy_from_slice(self.main_segment_lde.row(next_lde_step)); + } + + /// Reads current and next rows from the auxiliary trace segment into the specified frame. + /// + /// # Panics + /// This currently assumes that there is exactly one auxiliary trace segment, and will panic + /// otherwise. + fn read_aux_trace_frame_into(&self, lde_step: usize, frame: &mut EvaluationFrame) { + // at the end of the trace, next state wraps around and we read the first step again + let next_lde_step = (lde_step + self.blowup()) % self.trace_len(); + + // copy auxiliary trace segment values into the frame + let segment = &self.aux_segment_ldes[0]; + frame.current_mut().copy_from_slice(segment.row(lde_step)); + frame.next_mut().copy_from_slice(segment.row(next_lde_step)); + } + + /// Returns trace table rows at the specified positions along with Merkle authentication paths + /// from the commitment root to these rows. + fn query(&self, positions: &[usize]) -> Vec { + // build queries for the main trace segment + let mut result = vec![build_segment_queries( + &self.main_segment_lde, + &self.main_segment_tree, + positions, + )]; + + // build queries for auxiliary trace segments + for (i, segment_tree) in self.aux_segment_trees.iter().enumerate() { + let segment_lde = &self.aux_segment_ldes[i]; + result.push(build_segment_queries(segment_lde, segment_tree, positions)); + } + + result + } + + /// Returns the number of rows in the execution trace. + fn trace_len(&self) -> usize { + self.main_segment_lde.num_rows() + } + + /// Returns blowup factor which was used to extend original execution trace into trace LDE. + fn blowup(&self) -> usize { + self.blowup + } + + /// Returns the trace layout of the execution trace. + fn trace_layout(&self) -> &TraceLayout { + self.trace_info.layout() + } +} + +fn build_segment_queries( + segment_lde: &RowMatrix, + segment_tree: &MerkleTree, + positions: &[usize], +) -> Queries +where + E: FieldElement, + H: ElementHasher, +{ + // for each position, get the corresponding row from the trace segment LDE and put all these + // rows into a single vector + let trace_states = + positions.iter().map(|&pos| segment_lde.row(pos).to_vec()).collect::>(); + + // build Merkle authentication paths to the leaves specified by positions + let trace_proof = segment_tree + .prove_batch(positions) + .expect("failed to generate a Merkle proof for trace queries"); + + Queries::new(trace_proof, trace_states) +} + struct SegmentIterator<'a, 'b, E, I, const N: usize>(&'b mut SegmentGenerator<'a, E, I, N>) where E: FieldElement, @@ -318,6 +481,95 @@ where } } +/// Computes a low-degree extension (LDE) of the provided execution trace over the specified +/// domain and builds a commitment to the extended trace. +/// +/// The extension is performed by interpolating each column of the execution trace into a +/// polynomial of degree = trace_length - 1, and then evaluating the polynomial over the LDE +/// domain. +/// +/// Trace commitment is computed by hashing each row of the extended execution trace, and then +/// building a Merkle tree from the resulting hashes. +/// +/// Interpolations and evaluations are computed on the CPU while hashes are simultaneously +/// computed on the GPU: +/// +/// ```text +/// ────────────────────────────────────────────────────── +/// ┌───┐ ┌────┐ ┌───┐ ┌────┐ ┌───┐ +/// CPU: ... ──┤fft├─┬─┤ifft├───┤fft├─┬─┤ifft├───┤fft├─┬─ ... +/// └───┘ │ └────┘ └───┘ │ └────┘ └───┘ │ +/// ╴╴╴╴╴╴╴╴╴╴╴╴╴┼╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┼╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┼╴╴╴╴╴╴ +/// │ ┌──────────┐ │ ┌──────────┐ │ +/// GPU: └─┤ hash │ └─┤ hash │ └─ ... +/// └──────────┘ └──────────┘ +/// ────┼────────┼────────┼────────┼────────┼────────┼──── +/// t=n t=n+1 t=n+2 t=n+3 t=n+4 t=n+5 +/// ``` +fn build_trace_commitment( + trace: &ColMatrix, + domain: &StarkDomain, +) -> (RowMatrix, MerkleTree, ColMatrix) +where + E: FieldElement, + H: ElementHasher, +{ + // interpolate the execution trace + let now = Instant::now(); + let inv_twiddles = fft::get_inv_twiddles::(trace.num_rows()); + let trace_polys = trace.columns().map(|col| { + let mut poly = col.to_vec(); + fft::interpolate_poly(&mut poly, &inv_twiddles); + poly + }); + + // extend the execution trace and generate hashes on the gpu + let lde_segments = FrozenVec::new(); + let lde_domain_size = domain.lde_domain_size(); + let num_base_columns = trace.num_base_cols(); + let rpo_requires_padding = num_base_columns % RPO_RATE != 0; + let rpo_padded_segment_idx = rpo_requires_padding.then_some(num_base_columns / RPO_RATE); + let mut row_hasher = GpuRpo256RowMajor::::new(lde_domain_size, rpo_requires_padding); + let mut rpo_padded_segment: Vec<[Felt; RPO_RATE]>; + let mut lde_segment_generator = SegmentGenerator::new(trace_polys, domain); + let mut lde_segment_iter = lde_segment_generator.gen_segment_iter().enumerate(); + for (segment_idx, segment) in &mut lde_segment_iter { + let segment = lde_segments.push_get(Box::new(segment)); + // check if the segment requires padding + if rpo_padded_segment_idx.map_or(false, |pad_idx| pad_idx == segment_idx) { + // duplicate and modify the last segment with Rpo256's padding + // rule ("1" followed by "0"s). Our segments are already + // padded with "0"s we only need to add the "1"s. + let rpo_pad_column = num_base_columns % RPO_RATE; + rpo_padded_segment = unsafe { page_aligned_uninit_vector(lde_domain_size) }; + rpo_padded_segment.copy_from_slice(segment); + rpo_padded_segment.iter_mut().for_each(|row| row[rpo_pad_column] = ONE); + row_hasher.update(&rpo_padded_segment); + assert!(lde_segment_iter.next().is_none(), "padded segment should be the last"); + break; + } + row_hasher.update(segment); + } + let row_hashes = block_on(row_hasher.finish()); + let tree_nodes = gen_rpo_merkle_tree(&row_hashes); + // aggregate segments at the same time as the GPU generates the merkle tree nodes + let lde_segments = lde_segments.into_vec().into_iter().map(|p| *p).collect(); + let trace_lde = RowMatrix::from_segments(lde_segments, num_base_columns); + let trace_polys = lde_segment_generator.into_polys().unwrap(); + let nodes = block_on(tree_nodes).into_iter().map(RpoDigest::new).collect(); + let leaves = row_hashes.into_iter().map(RpoDigest::new).collect(); + let trace_tree = MerkleTree::from_raw_parts(nodes, leaves).unwrap(); + debug!( + "Extended (on CPU) and committed (on GPU) to an execution trace of {} columns from 2^{} to 2^{} steps in {} ms", + trace_polys.num_cols(), + trace_polys.num_rows().ilog2(), + trace_lde.num_rows().ilog2(), + now.elapsed().as_millis() + ); + + (trace_lde, trace_tree, trace_polys) +} + // TESTS // ================================================================================================ diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index ab5f46d8a8..e369ecc6e0 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -249,12 +249,7 @@ impl Test { /// Compiles the test's code into a program, then generates and verifies a proof of execution /// using the given public inputs and the specified number of stack outputs. When `test_fail` /// is true, this function will force a failure by modifying the first output. - pub fn prove_and_verify( - &self, - pub_inputs: Vec, - acceptable_opt: &AcceptableOptions, - test_fail: bool, - ) { + pub fn prove_and_verify(&self, pub_inputs: Vec, test_fail: bool) { let stack_inputs = StackInputs::try_from_values(pub_inputs).unwrap(); let program = self.compile(); let host = DefaultHost::new(MemAdviceProvider::from(self.advice_inputs.clone())); @@ -264,17 +259,9 @@ impl Test { let program_info = ProgramInfo::from(program); if test_fail { stack_outputs.stack_mut()[0] += 1; - assert!(verifier::verify( - program_info, - stack_inputs, - stack_outputs, - proof, - acceptable_opt - ) - .is_err()); + assert!(verifier::verify(program_info, stack_inputs, stack_outputs, proof).is_err()); } else { - let result = - verifier::verify(program_info, stack_inputs, stack_outputs, proof, acceptable_opt); + let result = verifier::verify(program_info, stack_inputs, stack_outputs, proof); assert!(result.is_ok(), "error: {result:?}"); } } diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index 454fc9340d..267fca61bb 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std)] +use air::{FieldExtension, WinterProofOptions}; use air::{HashFunction, ProcessorAir, PublicInputs}; use core::fmt; use vm_core::crypto::{ @@ -43,11 +44,18 @@ pub fn verify( stack_inputs: StackInputs, stack_outputs: StackOutputs, proof: ExecutionProof, - acceptable_opt: &AcceptableOptions, ) -> Result { // get security level of the proof let security_level = proof.security_level(); + // define a set of acceptable proof options by the verifier + let acceptable_opt: AcceptableOptions = AcceptableOptions::OptionSet(vec![ + WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 4, 7), + WinterProofOptions::new(27, 8, 16, FieldExtension::Quadratic, 8, 255), + WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 4, 7), + WinterProofOptions::new(27, 16, 21, FieldExtension::Cubic, 8, 255), + ]); + // build public inputs and try to verify the proof let pub_inputs = PublicInputs::new(program_info, stack_inputs, stack_outputs); let (hash_fn, proof) = proof.into_parts(); @@ -55,15 +63,15 @@ pub fn verify( HashFunction::Blake3_192 => verify_proof::>( proof, pub_inputs, - acceptable_opt, + &acceptable_opt, ), HashFunction::Blake3_256 => verify_proof::>( proof, pub_inputs, - acceptable_opt, + &acceptable_opt, ), HashFunction::Rpo256 => { - verify_proof::(proof, pub_inputs, acceptable_opt) + verify_proof::(proof, pub_inputs, &acceptable_opt) } } .map_err(VerificationError::VerifierError)?;