From 2bc5b24c52ccd8a2f7d04f0c9b55fbd34400d537 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 19 May 2022 10:22:57 +0200 Subject: [PATCH 1/3] Start --- starky/src/fibonacci_stark.rs | 14 ++++++- starky/src/stark_testing.rs | 69 ++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/starky/src/fibonacci_stark.rs b/starky/src/fibonacci_stark.rs index 3db38cda..c7d7ca32 100644 --- a/starky/src/fibonacci_stark.rs +++ b/starky/src/fibonacci_stark.rs @@ -142,7 +142,7 @@ mod tests { verify_stark_proof_circuit, }; use crate::stark::Stark; - use crate::stark_testing::test_stark_low_degree; + use crate::stark_testing::{test_stark_circuit_constraints, test_stark_low_degree}; use crate::verifier::verify_stark_proof; fn fibonacci(n: usize, x0: F, x1: F) -> F { @@ -184,6 +184,18 @@ mod tests { test_stark_low_degree(stark) } + #[test] + fn test_fibonacci_stark_circuit() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + type S = FibonacciStark; + + let num_rows = 1 << 5; + let stark = S::new(num_rows); + test_stark_circuit_constraints(stark) + } + #[test] fn test_recursive_stark_verifier() -> Result<()> { init_logger(); diff --git a/starky/src/stark_testing.rs b/starky/src/stark_testing.rs index 222ebf39..ff341f20 100644 --- a/starky/src/stark_testing.rs +++ b/starky/src/stark_testing.rs @@ -3,12 +3,15 @@ use plonky2::field::extension_field::Extendable; use plonky2::field::field_types::Field; use plonky2::field::polynomial::{PolynomialCoeffs, PolynomialValues}; use plonky2::hash::hash_types::RichField; +use plonky2::iop::witness::{PartialWitness, Witness}; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::util::transpose; use plonky2_util::{log2_ceil, log2_strict}; -use crate::constraint_consumer::ConstraintConsumer; +use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; use crate::stark::Stark; -use crate::vars::StarkEvaluationVars; +use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars}; const WITNESS_SIZE: usize = 1 << 5; @@ -71,6 +74,68 @@ where Ok(()) } +/// Tests that the circuit constraints imposed by the given STARK are coherent with the native constraints. +pub fn test_stark_circuit_constraints< + F: RichField + Extendable, + S: Stark, + const D: usize, +>( + stark: S, +) -> Result<()> +where + [(); S::COLUMNS]:, + [(); S::PUBLIC_INPUTS]:, +{ + let vars = StarkEvaluationVars { + local_values: &F::Extension::rand_arr::<{ S::COLUMNS }>(), + next_values: &F::Extension::rand_arr::<{ S::COLUMNS }>(), + public_inputs: &F::Extension::rand_arr::<{ S::PUBLIC_INPUTS }>(), + }; + let alphas = F::Extension::rand_vec(1); + let z_last = F::Extension::rand(); + let lagrange_first = F::Extension::rand(); + let lagrange_last = F::Extension::rand(); + let mut consumer = + ConstraintConsumer::::new(alphas, z_last, lagrange_first, lagrange_last); + stark.eval_ext(vars, &mut consumer); + let native_eval = consumer.accumulators()[0]; + dbg!(native_eval); + + let circuit_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(circuit_config); + let mut pw = PartialWitness::::new(); + + let locals_t = builder.add_virtual_extension_targets(S::COLUMNS); + pw.set_extension_targets(&locals_t, vars.local_values); + let nexts_t = builder.add_virtual_extension_targets(S::COLUMNS); + pw.set_extension_targets(&nexts_t, vars.next_values); + let pis_t = builder.add_virtual_extension_targets(S::PUBLIC_INPUTS); + pw.set_extension_targets(&pis_t, vars.public_inputs); + let alphas_t = builder.add_virtual_extension_targets(1); + pw.set_extension_targets(&alphas_t, &alphas); + let z_last_t = builder.add_virtual_extension_target(); + pw.set_extension_target(z_last_t, z_last); + let lagrange_first_t = builder.add_virtual_extension_target(); + pw.set_extension_target(lagrange_first_t, lagrange_first); + let lagrange_last_t = builder.add_virtual_extension_target(); + pw.set_extension_target(lagrange_last_t, lagrange_last); + + let circuit_vars = StarkEvaluationTargets { + local_values: &locals_t.try_into().unwrap(), + next_values: &nexts_t.try_into().unwrap(), + public_inputs: &pis_t.try_into().unwrap(), + }; + let mut consumer = RecursiveConstraintConsumer::::new( + builder.zero_extension(), + alphas_t, + z_last_t, + lagrange_first_t, + lagrange_last_t, + ); + + Ok(()) +} + fn random_low_degree_matrix(num_polys: usize, rate_bits: usize) -> Vec> { let polys = (0..num_polys) .map(|_| random_low_degree_values(rate_bits)) From b3f873c66a94c5265b2a818fa6d328ce1cc4949e Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 19 May 2022 11:10:10 +0200 Subject: [PATCH 2/3] Finish test --- evm/src/cpu/cpu_stark.rs | 36 ++++++++++++++ evm/src/keccak/keccak_stark.rs | 36 ++++++++++++++ evm/src/stark_testing.rs | 90 +++++++++++++++++++++++++++++++++- starky/src/fibonacci_stark.rs | 2 +- starky/src/stark_testing.rs | 39 +++++++++++---- 5 files changed, 190 insertions(+), 13 deletions(-) diff --git a/evm/src/cpu/cpu_stark.rs b/evm/src/cpu/cpu_stark.rs index 710c9df5..33f402f4 100644 --- a/evm/src/cpu/cpu_stark.rs +++ b/evm/src/cpu/cpu_stark.rs @@ -44,3 +44,39 @@ impl, const D: usize> Stark for CpuStark>::F; + type S = CpuStark; + + let stark = S { + f: Default::default(), + }; + test_stark_low_degree(stark).unwrap() + } + + #[test] + fn test_stark_circuit() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + type S = CpuStark; + + let stark = S { + f: Default::default(), + }; + test_stark_circuit_constraints::(stark) + } +} diff --git a/evm/src/keccak/keccak_stark.rs b/evm/src/keccak/keccak_stark.rs index cf75bf96..dd12d278 100644 --- a/evm/src/keccak/keccak_stark.rs +++ b/evm/src/keccak/keccak_stark.rs @@ -44,3 +44,39 @@ impl, const D: usize> Stark for KeccakStark>::F; + type S = KeccakStark; + + let stark = S { + f: Default::default(), + }; + test_stark_low_degree(stark).unwrap() + } + + #[test] + fn test_stark_circuit() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + type S = KeccakStark; + + let stark = S { + f: Default::default(), + }; + test_stark_circuit_constraints::(stark) + } +} diff --git a/evm/src/stark_testing.rs b/evm/src/stark_testing.rs index 222ebf39..3fbcf83a 100644 --- a/evm/src/stark_testing.rs +++ b/evm/src/stark_testing.rs @@ -1,14 +1,21 @@ use anyhow::{ensure, Result}; use plonky2::field::extension_field::Extendable; +use plonky2::field::extension_field::FieldExtension; use plonky2::field::field_types::Field; use plonky2::field::polynomial::{PolynomialCoeffs, PolynomialValues}; use plonky2::hash::hash_types::RichField; +use plonky2::iop::witness::PartialWitness; +use plonky2::iop::witness::Witness; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::CircuitConfig; +use plonky2::plonk::config::GenericConfig; +use plonky2::plonk::config::Hasher; use plonky2::util::transpose; use plonky2_util::{log2_ceil, log2_strict}; -use crate::constraint_consumer::ConstraintConsumer; +use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; use crate::stark::Stark; -use crate::vars::StarkEvaluationVars; +use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars}; const WITNESS_SIZE: usize = 1 << 5; @@ -71,6 +78,85 @@ where Ok(()) } +/// Tests that the circuit constraints imposed by the given STARK are coherent with the native constraints. +pub fn test_stark_circuit_constraints< + F: RichField + Extendable, + C: GenericConfig, + S: Stark, + const D: usize, +>( + stark: S, +) -> Result<()> +where + [(); S::COLUMNS]:, + [(); S::PUBLIC_INPUTS]:, + [(); C::Hasher::HASH_SIZE]:, +{ + // Compute native constraint evaluation on random values. + let vars = StarkEvaluationVars { + local_values: &F::Extension::rand_arr::<{ S::COLUMNS }>(), + next_values: &F::Extension::rand_arr::<{ S::COLUMNS }>(), + public_inputs: &F::Extension::rand_arr::<{ S::PUBLIC_INPUTS }>(), + }; + let alphas = F::rand_vec(1); + let z_last = F::Extension::rand(); + let lagrange_first = F::Extension::rand(); + let lagrange_last = F::Extension::rand(); + let mut consumer = ConstraintConsumer::::new( + alphas + .iter() + .copied() + .map(F::Extension::from_basefield) + .collect(), + z_last, + lagrange_first, + lagrange_last, + ); + stark.eval_ext(vars, &mut consumer); + let native_eval = consumer.accumulators()[0]; + + // Compute circuit constraint evaluation on same random values. + let circuit_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(circuit_config); + let mut pw = PartialWitness::::new(); + + let locals_t = builder.add_virtual_extension_targets(S::COLUMNS); + pw.set_extension_targets(&locals_t, vars.local_values); + let nexts_t = builder.add_virtual_extension_targets(S::COLUMNS); + pw.set_extension_targets(&nexts_t, vars.next_values); + let pis_t = builder.add_virtual_extension_targets(S::PUBLIC_INPUTS); + pw.set_extension_targets(&pis_t, vars.public_inputs); + let alphas_t = builder.add_virtual_targets(1); + pw.set_target(alphas_t[0], alphas[0]); + let z_last_t = builder.add_virtual_extension_target(); + pw.set_extension_target(z_last_t, z_last); + let lagrange_first_t = builder.add_virtual_extension_target(); + pw.set_extension_target(lagrange_first_t, lagrange_first); + let lagrange_last_t = builder.add_virtual_extension_target(); + pw.set_extension_target(lagrange_last_t, lagrange_last); + + let vars = StarkEvaluationTargets:: { + local_values: &locals_t.try_into().unwrap(), + next_values: &nexts_t.try_into().unwrap(), + public_inputs: &pis_t.try_into().unwrap(), + }; + let mut consumer = RecursiveConstraintConsumer::::new( + builder.zero_extension(), + alphas_t, + z_last_t, + lagrange_first_t, + lagrange_last_t, + ); + stark.eval_ext_circuit(&mut builder, vars, &mut consumer); + let circuit_eval = consumer.accumulators()[0]; + let native_eval_t = builder.constant_extension(native_eval); + builder.connect_extension(circuit_eval, native_eval_t); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) +} + fn random_low_degree_matrix(num_polys: usize, rate_bits: usize) -> Vec> { let polys = (0..num_polys) .map(|_| random_low_degree_values(rate_bits)) diff --git a/starky/src/fibonacci_stark.rs b/starky/src/fibonacci_stark.rs index c7d7ca32..85683d09 100644 --- a/starky/src/fibonacci_stark.rs +++ b/starky/src/fibonacci_stark.rs @@ -193,7 +193,7 @@ mod tests { let num_rows = 1 << 5; let stark = S::new(num_rows); - test_stark_circuit_constraints(stark) + test_stark_circuit_constraints::(stark) } #[test] diff --git a/starky/src/stark_testing.rs b/starky/src/stark_testing.rs index ff341f20..65ae64b0 100644 --- a/starky/src/stark_testing.rs +++ b/starky/src/stark_testing.rs @@ -1,11 +1,13 @@ use anyhow::{ensure, Result}; -use plonky2::field::extension_field::Extendable; +use plonky2::field::extension_field::{Extendable, FieldExtension}; use plonky2::field::field_types::Field; use plonky2::field::polynomial::{PolynomialCoeffs, PolynomialValues}; use plonky2::hash::hash_types::RichField; use plonky2::iop::witness::{PartialWitness, Witness}; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::CircuitConfig; +use plonky2::plonk::config::GenericConfig; +use plonky2::plonk::config::Hasher; use plonky2::util::transpose; use plonky2_util::{log2_ceil, log2_strict}; @@ -77,6 +79,7 @@ where /// Tests that the circuit constraints imposed by the given STARK are coherent with the native constraints. pub fn test_stark_circuit_constraints< F: RichField + Extendable, + C: GenericConfig, S: Stark, const D: usize, >( @@ -85,22 +88,32 @@ pub fn test_stark_circuit_constraints< where [(); S::COLUMNS]:, [(); S::PUBLIC_INPUTS]:, + [(); C::Hasher::HASH_SIZE]:, { + // Compute native constraint evaluation on random values. let vars = StarkEvaluationVars { local_values: &F::Extension::rand_arr::<{ S::COLUMNS }>(), next_values: &F::Extension::rand_arr::<{ S::COLUMNS }>(), public_inputs: &F::Extension::rand_arr::<{ S::PUBLIC_INPUTS }>(), }; - let alphas = F::Extension::rand_vec(1); + let alphas = F::rand_vec(1); let z_last = F::Extension::rand(); let lagrange_first = F::Extension::rand(); let lagrange_last = F::Extension::rand(); - let mut consumer = - ConstraintConsumer::::new(alphas, z_last, lagrange_first, lagrange_last); + let mut consumer = ConstraintConsumer::::new( + alphas + .iter() + .copied() + .map(F::Extension::from_basefield) + .collect(), + z_last, + lagrange_first, + lagrange_last, + ); stark.eval_ext(vars, &mut consumer); let native_eval = consumer.accumulators()[0]; - dbg!(native_eval); + // Compute circuit constraint evaluation on same random values. let circuit_config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(circuit_config); let mut pw = PartialWitness::::new(); @@ -111,8 +124,8 @@ where pw.set_extension_targets(&nexts_t, vars.next_values); let pis_t = builder.add_virtual_extension_targets(S::PUBLIC_INPUTS); pw.set_extension_targets(&pis_t, vars.public_inputs); - let alphas_t = builder.add_virtual_extension_targets(1); - pw.set_extension_targets(&alphas_t, &alphas); + let alphas_t = builder.add_virtual_targets(1); + pw.set_target(alphas_t[0], alphas[0]); let z_last_t = builder.add_virtual_extension_target(); pw.set_extension_target(z_last_t, z_last); let lagrange_first_t = builder.add_virtual_extension_target(); @@ -120,20 +133,26 @@ where let lagrange_last_t = builder.add_virtual_extension_target(); pw.set_extension_target(lagrange_last_t, lagrange_last); - let circuit_vars = StarkEvaluationTargets { + let vars = StarkEvaluationTargets:: { local_values: &locals_t.try_into().unwrap(), next_values: &nexts_t.try_into().unwrap(), public_inputs: &pis_t.try_into().unwrap(), }; - let mut consumer = RecursiveConstraintConsumer::::new( + let mut consumer = RecursiveConstraintConsumer::::new( builder.zero_extension(), alphas_t, z_last_t, lagrange_first_t, lagrange_last_t, ); + stark.eval_ext_circuit(&mut builder, vars, &mut consumer); + let circuit_eval = consumer.accumulators()[0]; + let native_eval_t = builder.constant_extension(native_eval); + builder.connect_extension(circuit_eval, native_eval_t); - Ok(()) + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) } fn random_low_degree_matrix(num_polys: usize, rate_bits: usize) -> Vec> { From 12a3155baf41019a07969cc7863c57a92c6b9136 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 May 2022 08:34:25 +0200 Subject: [PATCH 3/3] Ignore test instead of failing --- evm/src/cpu/cpu_stark.rs | 6 +++--- evm/src/keccak/keccak_stark.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/evm/src/cpu/cpu_stark.rs b/evm/src/cpu/cpu_stark.rs index 33f402f4..00c03ec6 100644 --- a/evm/src/cpu/cpu_stark.rs +++ b/evm/src/cpu/cpu_stark.rs @@ -54,8 +54,8 @@ mod tests { use crate::stark_testing::{test_stark_circuit_constraints, test_stark_low_degree}; #[test] - #[should_panic] // TODO: fix this when constraints are no longer all 0. - fn test_stark_degree() { + #[ignore] // TODO: remove this when constraints are no longer all 0. + fn test_stark_degree() -> Result<()> { const D: usize = 2; type C = PoseidonGoldilocksConfig; type F = >::F; @@ -64,7 +64,7 @@ mod tests { let stark = S { f: Default::default(), }; - test_stark_low_degree(stark).unwrap() + test_stark_low_degree(stark) } #[test] diff --git a/evm/src/keccak/keccak_stark.rs b/evm/src/keccak/keccak_stark.rs index dd12d278..0a8a49f6 100644 --- a/evm/src/keccak/keccak_stark.rs +++ b/evm/src/keccak/keccak_stark.rs @@ -54,8 +54,8 @@ mod tests { use crate::stark_testing::{test_stark_circuit_constraints, test_stark_low_degree}; #[test] - #[should_panic] // TODO: fix this when constraints are no longer all 0. - fn test_stark_degree() { + #[ignore] // TODO: remove this when constraints are no longer all 0. + fn test_stark_degree() -> Result<()> { const D: usize = 2; type C = PoseidonGoldilocksConfig; type F = >::F; @@ -64,7 +64,7 @@ mod tests { let stark = S { f: Default::default(), }; - test_stark_low_degree(stark).unwrap() + test_stark_low_degree(stark) } #[test]