diff --git a/evm/src/all_stark.rs b/evm/src/all_stark.rs index 177591fd..0e2b7736 100644 --- a/evm/src/all_stark.rs +++ b/evm/src/all_stark.rs @@ -203,9 +203,10 @@ mod tests { use crate::memory::NUM_CHANNELS; use crate::proof::{AllProof, PublicValues}; use crate::prover::prove_with_traces; + use crate::recursive_verifier::tests::recursively_verify_all_proof; use crate::recursive_verifier::{ add_virtual_recursive_all_proof, all_verifier_data_recursive_stark_proof, - recursively_verify_all_proof, set_recursive_all_proof_target, RecursiveAllProof, + set_recursive_all_proof_target, RecursiveAllProof, }; use crate::stark::Stark; use crate::util::{limb_from_bits_le, trace_rows_to_poly_values}; diff --git a/evm/src/get_challenges.rs b/evm/src/get_challenges.rs index 9cb07c31..ede7c466 100644 --- a/evm/src/get_challenges.rs +++ b/evm/src/get_challenges.rs @@ -47,6 +47,8 @@ impl, C: GenericConfig, const D: usize> A ctl_challenges, } } + + #[allow(unused)] // TODO: should be used soon pub(crate) fn get_challenger_states( &self, all_stark: &AllStark, diff --git a/evm/src/proof.rs b/evm/src/proof.rs index e9002c62..4cd03a65 100644 --- a/evm/src/proof.rs +++ b/evm/src/proof.rs @@ -36,6 +36,7 @@ pub(crate) struct AllProofChallenges, const D: usiz pub ctl_challenges: GrandProductChallengeSet, } +#[allow(unused)] // TODO: should be used soon pub(crate) struct AllChallengerState, const D: usize> { /// Sponge state of the challenger before starting each proof, /// along with the final state after all proofs are done. This final state isn't strictly needed. diff --git a/evm/src/recursive_verifier.rs b/evm/src/recursive_verifier.rs index 1ef493a0..e94023a7 100644 --- a/evm/src/recursive_verifier.rs +++ b/evm/src/recursive_verifier.rs @@ -10,7 +10,7 @@ use plonky2::hash::hashing::SPONGE_WIDTH; use plonky2::iop::challenger::{Challenger, RecursiveChallenger}; use plonky2::iop::ext_target::ExtensionTarget; use plonky2::iop::target::Target; -use plonky2::iop::witness::{PartialWitness, Witness}; +use plonky2::iop::witness::Witness; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig, VerifierCircuitData, VerifierCircuitTarget}; use plonky2::plonk::config::Hasher; @@ -36,9 +36,9 @@ use crate::permutation::{ GrandProductChallengeSet, PermutationCheckDataTarget, }; use crate::proof::{ - AllChallengerState, AllProof, AllProofTarget, BlockMetadata, BlockMetadataTarget, PublicValues, - PublicValuesTarget, StarkOpeningSetTarget, StarkProof, StarkProofChallengesTarget, - StarkProofTarget, TrieRoots, TrieRootsTarget, + AllProof, AllProofTarget, BlockMetadata, BlockMetadataTarget, PublicValues, PublicValuesTarget, + StarkOpeningSetTarget, StarkProof, StarkProofChallengesTarget, StarkProofTarget, TrieRoots, + TrieRootsTarget, }; use crate::stark::Stark; use crate::util::h160_limbs; @@ -244,107 +244,6 @@ impl, C: GenericConfig, const D: usize> } } -/// Recursively verify a Stark proof. -/// Outputs the recursive proof and the associated verifier data. -#[cfg(test)] -fn recursively_verify_stark_proof< - F: RichField + Extendable, - C: GenericConfig, - S: Stark, - const D: usize, ->( - table: Table, - stark: S, - proof: &StarkProof, - cross_table_lookups: &[CrossTableLookup], - ctl_challenges: &GrandProductChallengeSet, - challenger_state_before_vals: [F; SPONGE_WIDTH], - inner_config: &StarkConfig, - circuit_config: &CircuitConfig, -) -> Result<(ProofWithPublicInputs, VerifierCircuitData)> -where - [(); S::COLUMNS]:, - [(); C::Hasher::HASH_SIZE]:, - C::Hasher: AlgebraicHasher, -{ - let mut builder = CircuitBuilder::::new(circuit_config.clone()); - let mut pw = PartialWitness::new(); - - let num_permutation_zs = stark.num_permutation_batches(inner_config); - let num_permutation_batch_size = stark.permutation_batch_size(); - let proof_target = add_virtual_stark_proof( - &mut builder, - &stark, - inner_config, - proof.recover_degree_bits(inner_config), - proof.num_ctl_zs(), - ); - set_stark_proof_target(&mut pw, &proof_target, proof, builder.zero()); - builder.register_public_inputs( - &proof_target - .trace_cap - .0 - .iter() - .flat_map(|h| h.elements) - .collect::>(), - ); - - let ctl_challenges_target = GrandProductChallengeSet { - challenges: (0..inner_config.num_challenges) - .map(|_| GrandProductChallenge { - beta: builder.add_virtual_public_input(), - gamma: builder.add_virtual_public_input(), - }) - .collect(), - }; - for i in 0..inner_config.num_challenges { - pw.set_target( - ctl_challenges_target.challenges[i].beta, - ctl_challenges.challenges[i].beta, - ); - pw.set_target( - ctl_challenges_target.challenges[i].gamma, - ctl_challenges.challenges[i].gamma, - ); - } - - let ctl_vars = CtlCheckVarsTarget::from_proof( - table, - &proof_target, - cross_table_lookups, - &ctl_challenges_target, - num_permutation_zs, - ); - - let challenger_state_before = std::array::from_fn(|_| builder.add_virtual_public_input()); - pw.set_target_arr(challenger_state_before, challenger_state_before_vals); - let mut challenger = - RecursiveChallenger::::from_state(challenger_state_before); - let challenges = proof_target.get_challenges::( - &mut builder, - &mut challenger, - num_permutation_zs > 0, - num_permutation_batch_size, - inner_config, - ); - let challenger_state_after = challenger.compact(&mut builder); - builder.register_public_inputs(&challenger_state_after); - - builder.register_public_inputs(&proof_target.openings.ctl_zs_last); - - verify_stark_proof_with_challenges_circuit::( - &mut builder, - &stark, - &proof_target, - &challenges, - &ctl_vars, - inner_config, - ); - - let data = builder.build::(); - Ok((data.prove(pw)?, data.verifier_data())) -} - /// Returns the verifier data for the recursive Stark circuit. fn verifier_data_recursive_stark_proof< F: RichField + Extendable, @@ -488,92 +387,6 @@ where ] } -/// Recursively verify every Stark proof in an `AllProof`. -#[cfg(test)] -pub fn recursively_verify_all_proof< - F: RichField + Extendable, - C: GenericConfig, - const D: usize, ->( - all_stark: &AllStark, - all_proof: &AllProof, - inner_config: &StarkConfig, - circuit_config: &CircuitConfig, -) -> Result> -where - [(); CpuStark::::COLUMNS]:, - [(); KeccakStark::::COLUMNS]:, - [(); KeccakMemoryStark::::COLUMNS]:, - [(); LogicStark::::COLUMNS]:, - [(); MemoryStark::::COLUMNS]:, - [(); C::Hasher::HASH_SIZE]:, - C::Hasher: AlgebraicHasher, -{ - let AllChallengerState { - states, - ctl_challenges, - } = all_proof.get_challenger_states(all_stark, inner_config); - Ok(RecursiveAllProof { - recursive_proofs: [ - recursively_verify_stark_proof( - Table::Cpu, - all_stark.cpu_stark, - &all_proof.stark_proofs[Table::Cpu as usize], - &all_stark.cross_table_lookups, - &ctl_challenges, - states[0], - inner_config, - circuit_config, - )? - .0, - recursively_verify_stark_proof( - Table::Keccak, - all_stark.keccak_stark, - &all_proof.stark_proofs[Table::Keccak as usize], - &all_stark.cross_table_lookups, - &ctl_challenges, - states[1], - inner_config, - circuit_config, - )? - .0, - recursively_verify_stark_proof( - Table::KeccakMemory, - all_stark.keccak_memory_stark, - &all_proof.stark_proofs[Table::KeccakMemory as usize], - &all_stark.cross_table_lookups, - &ctl_challenges, - states[2], - inner_config, - circuit_config, - )? - .0, - recursively_verify_stark_proof( - Table::Logic, - all_stark.logic_stark, - &all_proof.stark_proofs[Table::Logic as usize], - &all_stark.cross_table_lookups, - &ctl_challenges, - states[3], - inner_config, - circuit_config, - )? - .0, - recursively_verify_stark_proof( - Table::Memory, - all_stark.memory_stark, - &all_proof.stark_proofs[Table::Memory as usize], - &all_stark.cross_table_lookups, - &ctl_challenges, - states[4], - inner_config, - circuit_config, - )? - .0, - ], - }) -} - /// Recursively verifies an inner proof. fn verify_stark_proof_with_challenges_circuit< F: RichField + Extendable, @@ -1028,3 +841,219 @@ pub fn set_block_metadata_target( F::from_canonical_u64(block_metadata.block_base_fee.as_u64()), ); } + +#[cfg(test)] +pub(crate) mod tests { + use anyhow::Result; + use plonky2::field::extension::Extendable; + use plonky2::hash::hash_types::RichField; + use plonky2::hash::hashing::SPONGE_WIDTH; + use plonky2::iop::challenger::RecursiveChallenger; + use plonky2::iop::witness::{PartialWitness, Witness}; + use plonky2::plonk::circuit_builder::CircuitBuilder; + use plonky2::plonk::circuit_data::{CircuitConfig, VerifierCircuitData}; + use plonky2::plonk::config::Hasher; + use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; + use plonky2::plonk::proof::ProofWithPublicInputs; + + use crate::all_stark::{AllStark, Table}; + use crate::config::StarkConfig; + use crate::cpu::cpu_stark::CpuStark; + use crate::cross_table_lookup::{CrossTableLookup, CtlCheckVarsTarget}; + use crate::keccak::keccak_stark::KeccakStark; + use crate::keccak_memory::keccak_memory_stark::KeccakMemoryStark; + use crate::logic::LogicStark; + use crate::memory::memory_stark::MemoryStark; + use crate::permutation::{GrandProductChallenge, GrandProductChallengeSet}; + use crate::proof::{AllChallengerState, AllProof, StarkProof}; + use crate::recursive_verifier::{ + add_virtual_stark_proof, set_stark_proof_target, + verify_stark_proof_with_challenges_circuit, RecursiveAllProof, + }; + use crate::stark::Stark; + + /// Recursively verify a Stark proof. + /// Outputs the recursive proof and the associated verifier data. + fn recursively_verify_stark_proof< + F: RichField + Extendable, + C: GenericConfig, + S: Stark, + const D: usize, + >( + table: Table, + stark: S, + proof: &StarkProof, + cross_table_lookups: &[CrossTableLookup], + ctl_challenges: &GrandProductChallengeSet, + challenger_state_before_vals: [F; SPONGE_WIDTH], + inner_config: &StarkConfig, + circuit_config: &CircuitConfig, + ) -> Result<(ProofWithPublicInputs, VerifierCircuitData)> + where + [(); S::COLUMNS]:, + [(); C::Hasher::HASH_SIZE]:, + C::Hasher: AlgebraicHasher, + { + let mut builder = CircuitBuilder::::new(circuit_config.clone()); + let mut pw = PartialWitness::new(); + + let num_permutation_zs = stark.num_permutation_batches(inner_config); + let num_permutation_batch_size = stark.permutation_batch_size(); + let proof_target = add_virtual_stark_proof( + &mut builder, + &stark, + inner_config, + proof.recover_degree_bits(inner_config), + proof.num_ctl_zs(), + ); + set_stark_proof_target(&mut pw, &proof_target, proof, builder.zero()); + builder.register_public_inputs( + &proof_target + .trace_cap + .0 + .iter() + .flat_map(|h| h.elements) + .collect::>(), + ); + + let ctl_challenges_target = GrandProductChallengeSet { + challenges: (0..inner_config.num_challenges) + .map(|_| GrandProductChallenge { + beta: builder.add_virtual_public_input(), + gamma: builder.add_virtual_public_input(), + }) + .collect(), + }; + for i in 0..inner_config.num_challenges { + pw.set_target( + ctl_challenges_target.challenges[i].beta, + ctl_challenges.challenges[i].beta, + ); + pw.set_target( + ctl_challenges_target.challenges[i].gamma, + ctl_challenges.challenges[i].gamma, + ); + } + + let ctl_vars = CtlCheckVarsTarget::from_proof( + table, + &proof_target, + cross_table_lookups, + &ctl_challenges_target, + num_permutation_zs, + ); + + let challenger_state_before = std::array::from_fn(|_| builder.add_virtual_public_input()); + pw.set_target_arr(challenger_state_before, challenger_state_before_vals); + let mut challenger = + RecursiveChallenger::::from_state(challenger_state_before); + let challenges = proof_target.get_challenges::( + &mut builder, + &mut challenger, + num_permutation_zs > 0, + num_permutation_batch_size, + inner_config, + ); + let challenger_state_after = challenger.compact(&mut builder); + builder.register_public_inputs(&challenger_state_after); + + builder.register_public_inputs(&proof_target.openings.ctl_zs_last); + + verify_stark_proof_with_challenges_circuit::( + &mut builder, + &stark, + &proof_target, + &challenges, + &ctl_vars, + inner_config, + ); + + let data = builder.build::(); + Ok((data.prove(pw)?, data.verifier_data())) + } + + /// Recursively verify every Stark proof in an `AllProof`. + pub fn recursively_verify_all_proof< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + all_stark: &AllStark, + all_proof: &AllProof, + inner_config: &StarkConfig, + circuit_config: &CircuitConfig, + ) -> Result> + where + [(); CpuStark::::COLUMNS]:, + [(); KeccakStark::::COLUMNS]:, + [(); KeccakMemoryStark::::COLUMNS]:, + [(); LogicStark::::COLUMNS]:, + [(); MemoryStark::::COLUMNS]:, + [(); C::Hasher::HASH_SIZE]:, + C::Hasher: AlgebraicHasher, + { + let AllChallengerState { + states, + ctl_challenges, + } = all_proof.get_challenger_states(all_stark, inner_config); + Ok(RecursiveAllProof { + recursive_proofs: [ + recursively_verify_stark_proof( + Table::Cpu, + all_stark.cpu_stark, + &all_proof.stark_proofs[Table::Cpu as usize], + &all_stark.cross_table_lookups, + &ctl_challenges, + states[0], + inner_config, + circuit_config, + )? + .0, + recursively_verify_stark_proof( + Table::Keccak, + all_stark.keccak_stark, + &all_proof.stark_proofs[Table::Keccak as usize], + &all_stark.cross_table_lookups, + &ctl_challenges, + states[1], + inner_config, + circuit_config, + )? + .0, + recursively_verify_stark_proof( + Table::KeccakMemory, + all_stark.keccak_memory_stark, + &all_proof.stark_proofs[Table::KeccakMemory as usize], + &all_stark.cross_table_lookups, + &ctl_challenges, + states[2], + inner_config, + circuit_config, + )? + .0, + recursively_verify_stark_proof( + Table::Logic, + all_stark.logic_stark, + &all_proof.stark_proofs[Table::Logic as usize], + &all_stark.cross_table_lookups, + &ctl_challenges, + states[3], + inner_config, + circuit_config, + )? + .0, + recursively_verify_stark_proof( + Table::Memory, + all_stark.memory_stark, + &all_proof.stark_proofs[Table::Memory as usize], + &all_stark.cross_table_lookups, + &ctl_challenges, + states[4], + inner_config, + circuit_config, + )? + .0, + ], + }) + } +}