diff --git a/evm/src/all_stark.rs b/evm/src/all_stark.rs index ab105449..9af9f492 100644 --- a/evm/src/all_stark.rs +++ b/evm/src/all_stark.rs @@ -51,6 +51,9 @@ mod tests { use anyhow::Result; use plonky2::field::field_types::Field; use plonky2::field::polynomial::PolynomialValues; + use plonky2::iop::witness::PartialWitness; + use plonky2::plonk::circuit_builder::CircuitBuilder; + use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use plonky2::util::timing::TimingTree; use rand::{thread_rng, Rng}; @@ -60,17 +63,18 @@ mod tests { use crate::cpu::cpu_stark::CpuStark; use crate::cross_table_lookup::CrossTableLookup; use crate::keccak::keccak_stark::KeccakStark; + use crate::proof::AllProof; use crate::prover::prove; + use crate::recursive_verifier::{ + add_virtual_all_proof, set_all_proof_target, verify_proof_circuit, + }; use crate::verifier::verify_proof; - #[test] - fn test_all_stark() -> Result<()> { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - - let config = StarkConfig::standard_fast_config(); + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + fn get_proof(config: &StarkConfig) -> Result<(AllStark, AllProof)> { let cpu_stark = CpuStark:: { f: Default::default(), }; @@ -124,6 +128,56 @@ mod tests { &mut TimingTree::default(), )?; + Ok((all_stark, proof)) + } + + #[test] + fn test_all_stark() -> Result<()> { + let config = StarkConfig::standard_fast_config(); + let (all_stark, proof) = get_proof(&config)?; verify_proof(all_stark, proof, &config) } + + #[test] + fn test_recursive_all_stark_verifier() -> Result<()> { + init_logger(); + + let config = StarkConfig::standard_fast_config(); + let (all_stark, proof) = get_proof(&config)?; + verify_proof(all_stark.clone(), proof.clone(), &config)?; + + recursive_proof(all_stark, proof, &config, true) + } + + fn recursive_proof( + inner_all_stark: AllStark, + inner_proof: AllProof, + inner_config: &StarkConfig, + print_gate_counts: bool, + ) -> Result<()> { + let circuit_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(circuit_config); + let mut pw = PartialWitness::new(); + let degree_bits = inner_proof + .stark_proofs + .iter() + .map(|proof| proof.proof.recover_degree_bits(inner_config)) + .collect::>(); + let pt = add_virtual_all_proof(&mut builder, &inner_all_stark, inner_config, °ree_bits); + set_all_proof_target(&mut pw, &pt, &inner_proof, builder.zero()); + + verify_proof_circuit::(&mut builder, inner_all_stark, pt, inner_config); + + if print_gate_counts { + builder.print_gate_counts(0); + } + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + fn init_logger() { + let _ = env_logger::builder().format_timestamp(None).try_init(); + } } diff --git a/evm/src/recursive_verifier.rs b/evm/src/recursive_verifier.rs index 41e81121..52fd7e78 100644 --- a/evm/src/recursive_verifier.rs +++ b/evm/src/recursive_verifier.rs @@ -21,7 +21,7 @@ use crate::cross_table_lookup::{verify_cross_table_lookups_circuit, CtlCheckVars use crate::keccak::keccak_stark::KeccakStark; use crate::permutation::PermutationCheckDataTarget; use crate::proof::{ - AllProofChallengesTarget, AllProofTarget, StarkOpeningSetTarget, StarkProof, + AllProof, AllProofChallengesTarget, AllProofTarget, StarkOpeningSetTarget, StarkProof, StarkProofChallengesTarget, StarkProofTarget, StarkProofWithPublicInputs, StarkProofWithPublicInputsTarget, }; @@ -230,6 +230,45 @@ fn eval_l_1_and_l_last_circuit, const D: usize>( ) } +pub fn add_virtual_all_proof, const D: usize>( + builder: &mut CircuitBuilder, + all_stark: &AllStark, + config: &StarkConfig, + degree_bits: &[usize], +) -> AllProofTarget { + let stark_proofs = vec![ + { + let proof = add_virtual_stark_proof( + builder, + all_stark.cpu_stark, + config, + degree_bits[Table::Cpu as usize], + ); + let public_inputs = builder.add_virtual_targets(CpuStark::::PUBLIC_INPUTS); + StarkProofWithPublicInputsTarget { + proof, + public_inputs, + } + }, + { + let proof = add_virtual_stark_proof( + builder, + all_stark.keccak_stark, + config, + degree_bits[Table::Keccak as usize], + ); + let public_inputs = builder.add_virtual_targets(KeccakStark::::PUBLIC_INPUTS); + StarkProofWithPublicInputsTarget { + proof, + public_inputs, + } + }, + ]; + + assert_eq!(stark_proofs.len(), Table::num_tables()); + AllProofTarget { stark_proofs } +} + pub fn add_virtual_stark_proof_with_pis< F: RichField + Extendable, S: Stark, @@ -296,6 +335,25 @@ fn add_stark_opening_set, S: Stark, const D: } } +pub fn set_all_proof_target, W, const D: usize>( + witness: &mut W, + all_proof_target: &AllProofTarget, + all_proof: &AllProof, + zero: Target, +) where + F: RichField + Extendable, + C::Hasher: AlgebraicHasher, + W: Witness, +{ + for (pt, p) in all_proof_target + .stark_proofs + .iter() + .zip_eq(&all_proof.stark_proofs) + { + set_stark_proof_with_pis_target(witness, pt, p, zero); + } +} + pub fn set_stark_proof_with_pis_target, W, const D: usize>( witness: &mut W, stark_proof_with_pis_target: &StarkProofWithPublicInputsTarget,