diff --git a/Cargo.lock b/Cargo.lock index e1884d974..b77c0a559 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1148,7 +1148,7 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "plonky2" version = "0.2.2" -source = "git+https://github.com/0xmozak/plonky2.git#7a9ba1406b45279b69236708079c0cdc882a181c" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#c7da81e88ce85476ec62fab57e78818e179d8406" dependencies = [ "ahash", "anyhow", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "plonky2_field" version = "0.2.2" -source = "git+https://github.com/0xmozak/plonky2.git#7a9ba1406b45279b69236708079c0cdc882a181c" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#c7da81e88ce85476ec62fab57e78818e179d8406" dependencies = [ "anyhow", "itertools 0.12.1", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "plonky2_maybe_rayon" version = "0.2.0" -source = "git+https://github.com/0xmozak/plonky2.git#7a9ba1406b45279b69236708079c0cdc882a181c" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#c7da81e88ce85476ec62fab57e78818e179d8406" dependencies = [ "rayon", ] @@ -1212,7 +1212,7 @@ dependencies = [ [[package]] name = "plonky2_util" version = "0.2.0" -source = "git+https://github.com/0xmozak/plonky2.git#7a9ba1406b45279b69236708079c0cdc882a181c" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#c7da81e88ce85476ec62fab57e78818e179d8406" [[package]] name = "plotters" @@ -1674,7 +1674,7 @@ dependencies = [ [[package]] name = "starky" version = "0.4.0" -source = "git+https://github.com/0xmozak/plonky2.git#7a9ba1406b45279b69236708079c0cdc882a181c" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#c7da81e88ce85476ec62fab57e78818e179d8406" dependencies = [ "ahash", "anyhow", @@ -1685,6 +1685,7 @@ dependencies = [ "plonky2", "plonky2_maybe_rayon", "plonky2_util", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e9f916ad2..634287e64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,9 @@ starky = { version = "0", default-features = false } plonky2_crypto = { git = "https://github.com/0xmozak/plonky2-crypto.git" } [patch.crates-io] -plonky2 = { git = "https://github.com/0xmozak/plonky2.git" } -plonky2_maybe_rayon = { git = "https://github.com/0xmozak/plonky2.git" } -starky = { git = "https://github.com/0xmozak/plonky2.git" } +# plonky2 = { path = "../plonky2/plonky2" } +# plonky2_maybe_rayon = { path = "../plonky2/maybe_rayon" } +# starky = { path = "../plonky2/starky" } +plonky2 = { git = "https://github.com/0xmozak/plonky2.git", branch = "matthias/looked-tables" } +plonky2_maybe_rayon = { git = "https://github.com/0xmozak/plonky2.git", branch = "matthias/looked-tables" } +starky = { git = "https://github.com/0xmozak/plonky2.git", branch = "matthias/looked-tables" } diff --git a/circuits/src/bitshift/stark.rs b/circuits/src/bitshift/stark.rs index 733abd1ef..8693ee85f 100644 --- a/circuits/src/bitshift/stark.rs +++ b/circuits/src/bitshift/stark.rs @@ -21,6 +21,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct BitshiftStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for BitshiftStark { @@ -80,6 +81,8 @@ impl, const D: usize> Stark for BitshiftStark type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -127,7 +130,10 @@ mod tests { #[test] fn test_degree() -> Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_low_degree(stark) } @@ -206,7 +212,10 @@ mod tests { #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/cpu/mul.rs b/circuits/src/cpu/mul.rs index 1a62a42fa..8b5f457a9 100644 --- a/circuits/src/cpu/mul.rs +++ b/circuits/src/cpu/mul.rs @@ -145,7 +145,10 @@ mod tests { "trace to poly", trace_rows_to_poly_values(cpu_trace) ); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let public_inputs = PublicInputs { entry_point: from_u32(program.entry_point), }; diff --git a/circuits/src/cpu/stark.rs b/circuits/src/cpu/stark.rs index da5483975..f23b07ecb 100644 --- a/circuits/src/cpu/stark.rs +++ b/circuits/src/cpu/stark.rs @@ -25,6 +25,7 @@ use crate::stark::mozak_stark::PublicInputs; #[allow(clippy::module_name_repetitions)] pub struct CpuStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for CpuStark { @@ -151,6 +152,8 @@ impl, const D: usize> Stark for CpuStark, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -194,7 +197,10 @@ mod tests { type F = >::F; type S = CpuStark; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_low_degree(stark) } @@ -205,7 +211,10 @@ mod tests { type F = >::F; type S = CpuStark; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/cross_table_lookup.rs b/circuits/src/cross_table_lookup.rs index 113c12e8f..8c1e2d955 100644 --- a/circuits/src/cross_table_lookup.rs +++ b/circuits/src/cross_table_lookup.rs @@ -1,18 +1,14 @@ use core::ops::Neg; -use anyhow::{ensure, Result}; -use itertools::{chain, iproduct, izip, zip_eq}; -use plonky2::field::extension::{Extendable, FieldExtension}; -use plonky2::field::packed::PackedField; -use plonky2::field::polynomial::PolynomialValues; +use itertools::{iproduct, izip, zip_eq}; +use plonky2::field::extension::Extendable; use plonky2::field::types::Field; use plonky2::hash::hash_types::RichField; use plonky2::iop::ext_target::ExtensionTarget; use plonky2::iop::target::Target; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::config::GenericConfig; -use starky::config::StarkConfig; -use starky::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; +use starky::constraint_consumer::RecursiveConstraintConsumer; +use starky::cross_table_lookup as starky_ctl; use starky::evaluation_frame::StarkEvaluationFrame; use starky::stark::Stark; use thiserror::Error; @@ -20,10 +16,9 @@ use thiserror::Error; pub use crate::linear_combination::Column; use crate::linear_combination::ColumnSparse; pub use crate::linear_combination_typed::ColumnWithTypedInput; -use crate::public_sub_table::PublicSubTable; -use crate::stark::mozak_stark::{all_kind, Table, TableKind, TableKindArray, TableWithTypedOutput}; +use crate::stark::mozak_stark::{Table, TableKind, TableWithTypedOutput}; use crate::stark::permutation::challenge::{GrandProductChallenge, GrandProductChallengeSet}; -use crate::stark::proof::{StarkProof, StarkProofTarget}; +use crate::stark::proof::StarkProofTarget; #[derive(Error, Debug)] pub enum LookupError { @@ -31,169 +26,6 @@ pub enum LookupError { InconsistentTableRows, } -#[derive(Clone, Default)] -pub struct CtlData { - pub(crate) zs_columns: Vec>, -} - -impl CtlData { - #[must_use] - pub fn len(&self) -> usize { self.zs_columns.len() } - - #[must_use] - pub fn is_empty(&self) -> bool { self.zs_columns.is_empty() } - - #[must_use] - pub fn z_polys(&self) -> Vec> { - self.zs_columns - .iter() - .map(|zs_column| zs_column.z.clone()) - .collect() - } -} - -/// Cross-table lookup data associated with one Z(x) polynomial. -#[derive(Clone)] -pub(crate) struct CtlZData { - pub(crate) z: PolynomialValues, - pub(crate) challenge: GrandProductChallenge, - pub(crate) columns: Vec, - pub(crate) filter_column: Column, -} - -pub(crate) fn verify_cross_table_lookups_and_public_sub_tables< - F: RichField + Extendable, - const D: usize, ->( - cross_table_lookups: &[CrossTableLookup], - public_sub_tables: &[PublicSubTable], - reduced_public_sub_table_values: &TableKindArray>, - ctl_zs_lasts: &TableKindArray>, - config: &StarkConfig, -) -> Result<()> { - let mut ctl_zs_openings = ctl_zs_lasts.each_ref().map(|v| v.iter().copied()); - for _ in 0..config.num_challenges { - for CrossTableLookup { looking_tables } in cross_table_lookups { - let looking_zs_sum = looking_tables - .iter() - .map(|table| ctl_zs_openings[table.kind].next().unwrap()) - .sum::(); - - ensure!( - looking_zs_sum == F::ZERO, - "Cross-table lookup verification failed for {:?} ({} != 0)", - looking_tables.iter().map(|table| table.kind), - looking_zs_sum, - ); - } - } - let mut reduced_public_sub_table_values_iter = reduced_public_sub_table_values - .each_ref() - .map(|v| v.iter().copied()); - for _ in 0..config.num_challenges { - for public_sub_table in public_sub_tables { - ensure!( - reduced_public_sub_table_values_iter[public_sub_table.table.kind].next() - == ctl_zs_openings[public_sub_table.table.kind].next() - ); - } - } - - Ok(()) -} - -/// Circuit version of `verify_cross_table_lookups`. Verifies all cross-table -/// lookups. -pub(crate) fn verify_cross_table_lookups_and_public_sub_table_circuit< - F: RichField + Extendable, - const D: usize, ->( - builder: &mut CircuitBuilder, - cross_table_lookups: &[CrossTableLookup], - public_sub_tables: &[PublicSubTable], - reduced_public_sub_table_targets: &TableKindArray>, - ctl_zs_lasts: &TableKindArray>, - config: &StarkConfig, -) { - let mut ctl_zs_openings = ctl_zs_lasts.each_ref().map(|v| v.iter()); - for _ in 0..config.num_challenges { - for CrossTableLookup { looking_tables } in cross_table_lookups { - let looking_zs_sum = builder.add_many( - looking_tables - .iter() - .map(|table| *ctl_zs_openings[table.kind].next().unwrap()), - ); - - let zero = builder.zero(); - - builder.connect(zero, looking_zs_sum); - } - } - - let mut reduced_public_sub_table_targets_iter = reduced_public_sub_table_targets - .each_ref() - .map(|targets| targets.iter()); - - for _ in 0..config.num_challenges { - for public_sub_table in public_sub_tables { - builder.connect( - *reduced_public_sub_table_targets_iter[public_sub_table.table.kind] - .next() - .unwrap(), - *ctl_zs_openings[public_sub_table.table.kind].next().unwrap(), - ); - } - } - debug_assert!(ctl_zs_openings.iter_mut().all(|iter| iter.next().is_none())); -} - -pub(crate) fn cross_table_lookup_data( - trace_poly_values: &TableKindArray>>, - cross_table_lookups: &[CrossTableLookup], - ctl_challenges: &GrandProductChallengeSet, -) -> TableKindArray> { - let mut ctl_data_per_table = all_kind!(|_kind| CtlData::default()); - for &challenge in &ctl_challenges.challenges { - for CrossTableLookup { looking_tables } in cross_table_lookups { - log::debug!( - "Processing CTL for {:?}", - looking_tables - .iter() - .map(|table| table.kind) - .collect::>() - ); - - let make_z = |table: &Table| { - partial_sums( - &trace_poly_values[table.kind], - &table.columns, - &table.filter_column, - challenge, - ) - }; - let zs_looking = looking_tables.iter().map(make_z); - - debug_assert_eq!( - zs_looking - .clone() - .map(|z| *z.values.last().unwrap()) - .sum::(), - F::ZERO - ); - - for (table, z) in izip!(looking_tables, zs_looking) { - ctl_data_per_table[table.kind].zs_columns.push(CtlZData { - z, - challenge, - columns: table.columns.clone(), - filter_column: table.filter_column.clone(), - }); - } - } - } - ctl_data_per_table -} - /// Treat CTL and the challenge as a single entity. /// /// Logically, the CTL specifies a linear transformation, and so does the @@ -212,45 +44,6 @@ pub fn compose_ctl_with_challenge( + challenge.gamma } -pub fn partial_sums( - trace: &[PolynomialValues], - columns: &[Column], - filter_column: &Column, - challenge: GrandProductChallenge, -) -> PolynomialValues { - // design of table looks like this - // | multiplicity | value | partial_sum | - // | 1 | x_1 | 1/combine(x_1) | - // | 0 | x_2 | 1/combine(x_1) | - // | 2 | x_3 | 1/combine(x_1) + 2/combine(x_3) | - // (where combine(vals) = gamma + reduced_sum(vals, beta)) - // transition constraint looks like - // z_next = z_local + filter_local/combine_local - - let filter_column = filter_column.to_field(); - let get_multiplicity = |&i| -> F { filter_column.eval_table(trace, i) }; - - let columns: Vec> = columns.iter().map(Column::to_field).collect(); - let prepped = compose_ctl_with_challenge(&columns, challenge); - let get_data = |&i| -> F { prepped.eval_table(trace, i) }; - - let degree = trace[0].len(); - let mut degrees = (0..degree).collect::>(); - degrees.rotate_right(1); - - let multiplicities: Vec = degrees.iter().map(get_multiplicity).collect(); - let data: Vec = degrees.iter().map(get_data).collect(); - let inv_data = F::batch_multiplicative_inverse(&data); - - izip!(multiplicities, inv_data) - .scan(F::ZERO, |partial_sum: &mut F, (multiplicity, inv)| { - *partial_sum += multiplicity * inv; - Some(*partial_sum) - }) - .collect::>() - .into() -} - #[allow(clippy::module_name_repetitions)] #[derive(Clone, Debug)] pub struct CrossTableLookupWithTypedOutput { @@ -264,6 +57,18 @@ pub struct CrossTableLookupWithTypedOutput { pub type CrossTableLookupUntyped = CrossTableLookupWithTypedOutput>; pub use CrossTableLookupUntyped as CrossTableLookup; +impl From<&CrossTableLookup> for starky_ctl::CrossTableLookup { + fn from(ctl: &CrossTableLookup) -> Self { + starky_ctl::CrossTableLookup::new_no_looked_table( + ctl.looking_tables.iter().map(Table::to_starky).collect(), + ) + } +} + +impl From for starky_ctl::CrossTableLookup { + fn from(ctl: CrossTableLookup) -> Self { Self::from(&ctl) } +} + impl> CrossTableLookupWithTypedOutput { pub fn to_untyped_output(self) -> CrossTableLookup { let looking_tables = self @@ -299,98 +104,6 @@ impl CrossTableLookupWithTypedOutput { } } -#[derive(Clone)] -pub struct CtlCheckVars<'a, F, FE, P, const D2: usize> -where - F: Field, - FE: FieldExtension, - P: PackedField, { - pub(crate) local_z: P, - pub(crate) next_z: P, - pub(crate) challenges: GrandProductChallenge, - pub(crate) columns: &'a [Column], - pub(crate) filter_column: &'a Column, -} - -impl<'a, F: RichField + Extendable, const D: usize> - CtlCheckVars<'a, F, F::Extension, F::Extension, D> -{ - pub(crate) fn from_proofs>( - proofs: &TableKindArray>, - cross_table_lookups: &'a [CrossTableLookup], - public_sub_tables: &'a [PublicSubTable], - ctl_challenges: &'a GrandProductChallengeSet, - ) -> TableKindArray> { - let mut ctl_zs = proofs - .each_ref() - .map(|p| izip!(&p.openings.ctl_zs, &p.openings.ctl_zs_next)); - - let mut ctl_vars_per_table = all_kind!(|_kind| vec![]); - let ctl_chain = cross_table_lookups - .iter() - .flat_map(|ctl| &ctl.looking_tables); - for (&challenges, table) in iproduct!(&ctl_challenges.challenges, ctl_chain) { - let (&local_z, &next_z) = ctl_zs[table.kind].next().unwrap(); - ctl_vars_per_table[table.kind].push(Self { - local_z, - next_z, - challenges, - columns: &table.columns, - filter_column: &table.filter_column, - }); - } - for (&challenges, public_sub_table) in - iproduct!(&ctl_challenges.challenges, public_sub_tables) - { - let (&local_z, &next_z) = ctl_zs[public_sub_table.table.kind].next().unwrap(); - ctl_vars_per_table[public_sub_table.table.kind].push(Self { - local_z, - next_z, - challenges, - columns: &public_sub_table.table.columns, - filter_column: &public_sub_table.table.filter_column, - }); - } - ctl_vars_per_table - } -} - -pub(crate) fn eval_cross_table_lookup_checks( - vars: &S::EvaluationFrame, - ctl_vars: &[CtlCheckVars], - consumer: &mut ConstraintConsumer

, -) where - F: RichField + Extendable, - FE: FieldExtension, - P: PackedField, - S: Stark, { - for lookup_vars in ctl_vars { - let CtlCheckVars { - local_z, - next_z, - challenges, - columns, - filter_column, - } = lookup_vars; - let local_values = vars.get_local_values(); - let next_values = vars.get_next_values(); - - let combine = |lv: &[P], nv: &[P]| -> P { - let evals = columns.iter().map(|c| c.eval(lv, nv)).collect::>(); - challenges.combine(evals.iter()) - }; - let combination = combine(local_values, next_values); - let multiplicity = |lv: &[P], nv: &[P]| -> P { filter_column.eval(lv, nv) }; - let multiplicity = multiplicity(local_values, next_values); - - // Check value of `Z(1) = filter(w^(n-1))/combined(w^(n-1))` - consumer.constraint_last_row(*next_z * combination - multiplicity); - - // Check `Z(gw) - Z(w) = filter(w)/combined(w)` - consumer.constraint_transition((*next_z - *local_z) * combination - multiplicity); - } -} - #[derive(Clone)] pub struct CtlCheckVarsTarget<'a, const D: usize> { pub local_z: ExtensionTarget, @@ -406,7 +119,6 @@ impl<'a, const D: usize> CtlCheckVarsTarget<'a, D> { table: TableKind, proof: &StarkProofTarget, cross_table_lookups: &'a [CrossTableLookup], - public_sub_tables: &'a [PublicSubTable], ctl_challenges: &'a GrandProductChallengeSet, ) -> Vec { let ctl_zs = izip!(&proof.openings.ctl_zs, &proof.openings.ctl_zs_next); @@ -414,28 +126,15 @@ impl<'a, const D: usize> CtlCheckVarsTarget<'a, D> { let ctl_chain = cross_table_lookups .iter() .flat_map(|ctl| ctl.looking_tables.iter().filter(|twc| twc.kind == table)); - let public_sub_table_chain = public_sub_tables.iter().filter_map(|twc| { - if twc.table.kind == table { - Some(&twc.table) - } else { - None - } - }); - zip_eq( - ctl_zs, - chain!( - iproduct!(&ctl_challenges.challenges, ctl_chain), - iproduct!(&ctl_challenges.challenges, public_sub_table_chain) - ), - ) - .map(|((&local_z, &next_z), (&challenges, table))| Self { - local_z, - next_z, - challenges, - columns: &table.columns, - filter_column: &table.filter_column, - }) - .collect() + zip_eq(ctl_zs, iproduct!(&ctl_challenges.challenges, ctl_chain)) + .map(|((&local_z, &next_z), (&challenges, table))| Self { + local_z, + next_z, + challenges, + columns: &table.columns, + filter_column: &table.filter_column, + }) + .collect() } } @@ -480,106 +179,4 @@ pub fn eval_cross_table_lookup_checks_circuit< } } -pub mod ctl_utils { - use std::collections::BTreeMap; - - use anyhow::Result; - use derive_more::{Deref, DerefMut}; - use plonky2::field::extension::Extendable; - use plonky2::field::polynomial::PolynomialValues; - use plonky2::hash::hash_types::RichField; - - use crate::cross_table_lookup::{CrossTableLookup, LookupError}; - use crate::linear_combination::ColumnSparse; - use crate::stark::mozak_stark::{MozakStark, Table, TableKind, TableKindArray}; - - #[derive(Clone, Debug, Default, Deref, DerefMut)] - struct MultiSet(pub BTreeMap, Vec<(TableKind, F)>>); - - impl MultiSet { - fn process_row( - &mut self, - trace_poly_values: &TableKindArray>>, - table: &Table, - ) { - let trace = &trace_poly_values[table.kind]; - let filter_column = table.filter_column.to_field(); - let columns = table - .columns - .iter() - .map(ColumnSparse::to_field) - .collect::>(); - for i in 0..trace[0].len() { - let filter = filter_column.eval_table(trace, i); - if filter.is_nonzero() { - let row = columns - .iter() - .map(|c| c.eval_table(trace, i)) - .map(|f| f.to_canonical_u64()) - .collect::>(); - self.entry(row).or_default().push((table.kind, filter)); - }; - } - } - } - pub fn check_single_ctl( - trace_poly_values: &TableKindArray>>, - // TODO(Matthias): make this one work with CrossTableLookupNamed, instead of having to - // forget the types first. That should also help with adding better debug messages. - ctl: &CrossTableLookup, - ) -> Result<(), LookupError> { - /// Sums and compares the multiplicities of the given looking and looked - /// locations previously processed. - /// - /// The CTL check holds iff `looking_multiplicity == - /// looked_multiplicity`. - fn check_multiplicities( - row: &[u64], - looking_locations: &[(TableKind, F)], - ) -> Result<(), LookupError> { - let looking_multiplicity = looking_locations.iter().map(|l| l.1).sum::(); - if looking_multiplicity != F::ZERO { - eprintln!( - "Row {row:?} has multiplicity {looking_multiplicity} != 0 in the looking tables.\n\ - Looking locations: {looking_locations:?}." - ); - return Err(LookupError::InconsistentTableRows); - } - - Ok(()) - } - - // Maps `m` with `(table.kind, multiplicity) in m[row]` - let mut looking_multiset = MultiSet::::default(); - - for looking_table in &ctl.looking_tables { - looking_multiset.process_row(trace_poly_values, looking_table); - } - - // Check that every row in the looking tables appears in the looked table the - // same number of times. - for (row, looking_locations) in &looking_multiset.0 { - check_multiplicities(row, looking_locations).map_err(|e| { - eprintln!("Looking multiset: {looking_multiset:?}"); - e - })?; - } - - Ok(()) - } - pub fn debug_ctl, const D: usize>( - traces_poly_values: &TableKindArray>>, - mozak_stark: &MozakStark, - ) { - mozak_stark - .cross_table_lookups - .iter() - .enumerate() - .for_each(|(i, ctl)| { - check_single_ctl(traces_poly_values, ctl) - .unwrap_or_else(|e| panic!("CTL {i} failed: {e:?}")); - }); - } -} - // TODO(Matthias): restore the tests from before https://github.com/0xmozak/mozak-vm/pull/1371 diff --git a/circuits/src/generation/memory.rs b/circuits/src/generation/memory.rs index b30cf1689..00283da5f 100644 --- a/circuits/src/generation/memory.rs +++ b/circuits/src/generation/memory.rs @@ -241,7 +241,10 @@ mod tests { /// Test that we have a constraint to catch, if there is no init for any memory address. fn no_init() { let _ = env_logger::try_init(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let trace: Vec> = prep_table(vec![ //is_writable addr clk is_store, is_load, is_init value diff --git a/circuits/src/lib.rs b/circuits/src/lib.rs index 6011e3734..aa3f8dd4f 100644 --- a/circuits/src/lib.rs +++ b/circuits/src/lib.rs @@ -25,7 +25,6 @@ pub mod poseidon2_output_bytes; pub mod poseidon2_sponge; pub mod program; pub mod program_multiplicities; -pub mod public_sub_table; pub mod rangecheck; pub mod rangecheck_u8; pub mod register; diff --git a/circuits/src/linear_combination.rs b/circuits/src/linear_combination.rs index 4754c18fc..7a8804851 100644 --- a/circuits/src/linear_combination.rs +++ b/circuits/src/linear_combination.rs @@ -10,6 +10,7 @@ use plonky2::field::types::Field; use plonky2::hash::hash_types::RichField; use plonky2::iop::ext_target::ExtensionTarget; use plonky2::plonk::circuit_builder::CircuitBuilder; +use starky::lookup as starky_lookup; use crate::cross_table_lookup::ColumnWithTypedInput; @@ -73,6 +74,23 @@ pub fn zip_with( pub type ColumnI64 = ColumnSparse; pub use ColumnI64 as Column; +impl Column { + #[must_use] + pub fn to_starky(&self) -> starky_lookup::Column { + starky_lookup::Column::new( + self.lv_linear_combination + .iter() + .map(|&(c, f)| (c, F::from_noncanonical_i64(f))) + .collect(), + self.nv_linear_combination + .iter() + .map(|&(c, f)| (c, F::from_noncanonical_i64(f))) + .collect(), + F::from_noncanonical_i64(self.constant), + ) + } +} + impl> From> for Column { fn from(colx: ColumnWithTypedInput) -> Self { fn to_sparse(v: impl IntoIterator) -> Vec<(usize, i64)> { diff --git a/circuits/src/memory/stark.rs b/circuits/src/memory/stark.rs index 88185f19a..f8ffcbaa7 100644 --- a/circuits/src/memory/stark.rs +++ b/circuits/src/memory/stark.rs @@ -20,6 +20,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct MemoryStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for MemoryStark { @@ -90,6 +91,8 @@ impl, const D: usize> Stark for MemoryStark, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -136,7 +139,10 @@ mod tests { #[test] fn test_degree() -> Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_low_degree(stark) } @@ -209,7 +215,10 @@ mod tests { #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/memory_fullword/stark.rs b/circuits/src/memory_fullword/stark.rs index 2f76c68fa..4274dc56b 100644 --- a/circuits/src/memory_fullword/stark.rs +++ b/circuits/src/memory_fullword/stark.rs @@ -21,6 +21,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct FullWordMemoryStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for FullWordMemoryStark { @@ -61,6 +62,8 @@ impl, const D: usize> Stark for FullWordMemor type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + // Design description - https://docs.google.com/presentation/d/1J0BJd49BMQh3UR5TrOhe3k67plHxnohFtFVrMpDJ1oc/edit?usp=sharing fn eval_packed_generic( &self, @@ -146,7 +149,10 @@ mod tests { fn test_circuit() -> anyhow::Result<()> { type C = Poseidon2GoldilocksConfig; type S = FullWordMemoryStark; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/memory_halfword/stark.rs b/circuits/src/memory_halfword/stark.rs index 9917e1fa3..97df0fb8e 100644 --- a/circuits/src/memory_halfword/stark.rs +++ b/circuits/src/memory_halfword/stark.rs @@ -20,6 +20,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct HalfWordMemoryStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for HalfWordMemoryStark { @@ -59,6 +60,8 @@ impl, const D: usize> Stark for HalfWordMemor type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -148,7 +151,10 @@ mod tests { fn test_circuit() -> anyhow::Result<()> { type C = Poseidon2GoldilocksConfig; type S = HalfWordMemoryStark; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/memory_io/stark.rs b/circuits/src/memory_io/stark.rs index 338e0a93a..ee9aae877 100644 --- a/circuits/src/memory_io/stark.rs +++ b/circuits/src/memory_io/stark.rs @@ -20,6 +20,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct StorageDeviceStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for StorageDeviceStark { @@ -86,6 +87,8 @@ impl, const D: usize> Stark for StorageDevice type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -439,7 +442,10 @@ mod tests { type C = Poseidon2GoldilocksConfig; type S = StorageDeviceStark; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/memory_zeroinit/stark.rs b/circuits/src/memory_zeroinit/stark.rs index 6d9785971..55ceea0ac 100644 --- a/circuits/src/memory_zeroinit/stark.rs +++ b/circuits/src/memory_zeroinit/stark.rs @@ -20,6 +20,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct MemoryZeroInitStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for MemoryZeroInitStark { @@ -49,6 +50,8 @@ impl, const D: usize> Stark for MemoryZeroIni type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -89,7 +92,10 @@ mod tests { #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/memoryinit/stark.rs b/circuits/src/memoryinit/stark.rs index 47dd7ab8f..20fa60864 100644 --- a/circuits/src/memoryinit/stark.rs +++ b/circuits/src/memoryinit/stark.rs @@ -20,6 +20,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct MemoryInitStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for MemoryInitStark { @@ -49,6 +50,8 @@ impl, const D: usize> Stark for MemoryInitSta type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -89,7 +92,10 @@ mod tests { #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/poseidon2/stark.rs b/circuits/src/poseidon2/stark.rs index 5d7fa248e..55788684c 100644 --- a/circuits/src/poseidon2/stark.rs +++ b/circuits/src/poseidon2/stark.rs @@ -121,6 +121,7 @@ fn matmul_internal12<'a, V, U, const STATE_SIZE: usize>( #[allow(clippy::module_name_repetitions)] pub struct Poseidon2_12Stark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for Poseidon2_12Stark { @@ -207,6 +208,8 @@ impl, const D: usize> Stark for Poseidon2_12S type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -272,7 +275,10 @@ mod tests { let step_rows = record.executed; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let trace = generate_poseidon2_trace(&step_rows); let trace_poly_values = trace_rows_to_poly_values(trace); @@ -288,12 +294,18 @@ mod tests { #[test] fn poseidon2_stark_degree() -> Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_low_degree(stark) } #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) } diff --git a/circuits/src/poseidon2_output_bytes/stark.rs b/circuits/src/poseidon2_output_bytes/stark.rs index b3ba8d492..ec47c4c50 100644 --- a/circuits/src/poseidon2_output_bytes/stark.rs +++ b/circuits/src/poseidon2_output_bytes/stark.rs @@ -21,6 +21,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct Poseidon2OutputBytesStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for Poseidon2OutputBytesStark { @@ -59,6 +60,8 @@ impl, const D: usize> Stark for Poseidon2Outp type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -122,7 +125,10 @@ mod tests { let step_rows = record.executed; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let trace = generate_poseidon2_sponge_trace(&step_rows); let trace = generate_poseidon2_output_bytes_trace(&trace); let trace_poly_values = trace_rows_to_poly_values(trace); @@ -178,12 +184,18 @@ mod tests { #[test] fn poseidon2_stark_degree() -> Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_low_degree(stark) } #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/poseidon2_sponge/stark.rs b/circuits/src/poseidon2_sponge/stark.rs index e16fdc405..86fc7f4af 100644 --- a/circuits/src/poseidon2_sponge/stark.rs +++ b/circuits/src/poseidon2_sponge/stark.rs @@ -23,6 +23,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct Poseidon2SpongeStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for Poseidon2SpongeStark { @@ -109,6 +110,8 @@ impl, const D: usize> Stark for Poseidon2Spon type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -174,7 +177,10 @@ mod tests { let step_rows = record.executed; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let trace = generate_poseidon2_sponge_trace(&step_rows); let trace_poly_values = trace_rows_to_poly_values(trace); @@ -217,12 +223,18 @@ mod tests { #[test] fn poseidon2_stark_degree() -> Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_low_degree(stark) } #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/public_sub_table.rs b/circuits/src/public_sub_table.rs deleted file mode 100644 index 9d901a185..000000000 --- a/circuits/src/public_sub_table.rs +++ /dev/null @@ -1,220 +0,0 @@ -//! To make a Subtable of given stark table public, we follow similar idea -//! used in CTL. The basic idea is to "compress" the subtable into a single -//! value which the verifier can construct on its own, and compare against. -//! Grand product argument, combined with randomness is a good option in -//! such situation. We use its equivalent, Logarithmic derivative approach -//! instead, especially because it lets us combine it with CTL proof system -//! which we have already. Essentially, given a subtable, we `combine` its rows -//! and maintain its running sum of inverses as values of z polynomial. The -//! opening of this z polynomial would be the "compressed" value, and can -//! be reproduced on verifer's end. We can also reuse the challenges used for -//! CTL to `combine`, since the procedure is preceded by commitment to trace -//! polynomials already -#![allow(clippy::module_name_repetitions)] -use itertools::{iproduct, Itertools}; -use plonky2::field::extension::Extendable; -use plonky2::field::polynomial::PolynomialValues; -use plonky2::field::types::Field; -use plonky2::hash::hash_types::RichField; -use plonky2::iop::target::Target; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::plonk_common::reduce_with_powers_circuit; - -use crate::cross_table_lookup::{partial_sums, CtlData, CtlZData}; -use crate::stark::mozak_stark::{all_kind, Table, TableKind, TableKindArray}; -use crate::stark::permutation::challenge::{GrandProductChallenge, GrandProductChallengeSet}; - -/// Specifies a Subtable with `table.columns` and `table.filter_column` -/// which the prover wants to make public. We include `num_rows` since -/// it cannot be computed from `table` alone. -#[derive(Clone, Debug)] -pub struct PublicSubTable { - pub table: Table, - pub num_rows: usize, -} -/// Actual values, as field elements, of the entries -/// of `PublicSubTable` -pub type PublicSubTableValues = Vec>; -/// Plonky2 target version of `PublicSubTableValuesTarget` -pub type PublicSubTableValuesTarget = Vec>; -impl PublicSubTable { - #[must_use] - pub fn num_zs(public_sub_tables: &[Self], table: TableKind, num_challenges: usize) -> usize { - public_sub_tables - .iter() - .filter(|twc| twc.table.kind == table) - .count() - * num_challenges - } - - /// Get `PublicSubTableValues` corresponding to `self` - #[must_use] - pub fn get_values( - &self, - trace: &TableKindArray>>, - ) -> PublicSubTableValues { - let trace_table = &trace[self.table.kind]; - let columns = self - .table - .columns - .clone() - .into_iter() - .map(|col| col.map(F::from_noncanonical_i64)) - .collect_vec(); - let filter = self - .table - .filter_column - .clone() - .map(F::from_noncanonical_i64); - let columns_if_filter_at_i = |i| -> Option> { - filter.eval_table(trace_table, i).is_one().then_some( - columns - .iter() - .map(|column| column.eval_table(trace_table, i)) - .collect_vec(), - ) - }; - (0..trace_table[0].len()) - .filter_map(columns_if_filter_at_i) - .collect_vec() - } - - /// Create the z polynomial, and fill up the data required to prove - /// in `CtlZdata` - pub(crate) fn get_ctlz_data( - &self, - trace: &TableKindArray>>, - challenge: GrandProductChallenge, - ) -> CtlZData { - let z = partial_sums( - &trace[self.table.kind], - &self.table.columns, - &self.table.filter_column, - challenge, - ); - CtlZData { - z, - challenge, - columns: self.table.columns.clone(), - filter_column: self.table.filter_column.clone(), - } - } - - /// Returns virtual targets corresponding to `PublicSubTableValues` - pub fn to_targets, const D: usize>( - &self, - builder: &mut CircuitBuilder, - ) -> PublicSubTableValuesTarget { - (0..self.num_rows) - .map(|_| { - (0..self.table.columns.len()) - .map(|_| builder.add_virtual_target()) - .collect_vec() - }) - .collect_vec() - } -} - -#[must_use] -#[allow(clippy::module_name_repetitions)] -pub fn public_sub_table_data_and_values( - trace_poly_values: &TableKindArray>>, - public_sub_tables: &[PublicSubTable], - ctl_challenges: &GrandProductChallengeSet, -) -> ( - TableKindArray>, - TableKindArray>>, -) { - let mut public_sub_table_data_per_table = all_kind!(|_kind| CtlData::default()); - let mut public_sub_table_values_per_table = all_kind!(|_kind| Vec::default()); - for (&challenge, public_sub_table) in iproduct!(&ctl_challenges.challenges, public_sub_tables) { - public_sub_table_data_per_table[public_sub_table.table.kind] - .zs_columns - .push(public_sub_table.get_ctlz_data(trace_poly_values, challenge)); - } - for public_sub_table in public_sub_tables { - public_sub_table_values_per_table[public_sub_table.table.kind] - .push(public_sub_table.get_values(trace_poly_values)); - } - ( - public_sub_table_data_per_table, - public_sub_table_values_per_table, - ) -} - -/// For each `PublicSubTableValues`, returns the compressed value -/// created according to each `challenge` -#[must_use] -pub fn reduce_public_sub_tables_values( - public_sub_table_values: &TableKindArray>>, - challenges: &GrandProductChallengeSet, -) -> TableKindArray> { - all_kind!(|kind| { - challenges - .challenges - .iter() - .flat_map(|&challenge| { - let sub_tables = &public_sub_table_values[kind]; - sub_tables - .iter() - .map(|sub_table| { - sub_table - .iter() - .map(|row| challenge.combine(row).inverse()) - .sum() - }) - .collect_vec() - }) - .collect_vec() - }) -} - -pub fn reduce_public_sub_table_targets, const D: usize>( - builder: &mut CircuitBuilder, - challenge: &GrandProductChallenge, - targets: &PublicSubTableValuesTarget, -) -> Target { - let all_targets = targets - .iter() - .map(|row| { - let mut combined = reduce_with_powers_circuit(builder, row, challenge.beta); - combined = builder.add(combined, challenge.gamma); - builder.inverse(combined) - }) - .collect_vec(); - builder.add_many(all_targets) -} - -pub fn public_sub_table_values_and_reduced_targets, const D: usize>( - builder: &mut CircuitBuilder, - public_sub_tables: &[PublicSubTable], - ctl_challenges: &GrandProductChallengeSet, -) -> ( - TableKindArray>, - TableKindArray>, -) { - let mut public_sub_table_values_targets = TableKindArray::>::default(); - for public_sub_table in public_sub_tables { - let targets = public_sub_table.to_targets(builder); - public_sub_table_values_targets[public_sub_table.table.kind].push(targets); - } - - let mut reduced_public_sub_table_targets = TableKindArray::>::default(); - - for challenge in &ctl_challenges.challenges { - let mut public_sub_table_values_targets_iter = public_sub_table_values_targets - .each_ref() - .map(|targets| targets.iter()); - for public_sub_table in public_sub_tables { - let targets = public_sub_table_values_targets_iter[public_sub_table.table.kind] - .next() - .unwrap(); - reduced_public_sub_table_targets[public_sub_table.table.kind] - .push(reduce_public_sub_table_targets(builder, challenge, targets)); - } - } - ( - public_sub_table_values_targets, - reduced_public_sub_table_targets, - ) -} diff --git a/circuits/src/rangecheck/stark.rs b/circuits/src/rangecheck/stark.rs index da9d1865c..27707374f 100644 --- a/circuits/src/rangecheck/stark.rs +++ b/circuits/src/rangecheck/stark.rs @@ -48,7 +48,10 @@ mod tests { #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/rangecheck_u8/stark.rs b/circuits/src/rangecheck_u8/stark.rs index 0ad55db4a..4635f2059 100644 --- a/circuits/src/rangecheck_u8/stark.rs +++ b/circuits/src/rangecheck_u8/stark.rs @@ -20,6 +20,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct RangeCheckU8Stark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for RangeCheckU8Stark { @@ -53,6 +54,8 @@ impl, const D: usize> Stark for RangeCheckU8S type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -93,7 +96,10 @@ mod tests { #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/register/general/stark.rs b/circuits/src/register/general/stark.rs index bb3675637..fa5a0428b 100644 --- a/circuits/src/register/general/stark.rs +++ b/circuits/src/register/general/stark.rs @@ -20,6 +20,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct RegisterStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for RegisterStark { @@ -94,6 +95,8 @@ impl, const D: usize> Stark for RegisterStark type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -139,13 +142,19 @@ mod tests { #[test] fn test_degree() -> Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_low_degree(stark) } #[test] fn test_circuit() -> Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark) } diff --git a/circuits/src/stark/mod.rs b/circuits/src/stark/mod.rs index e5b66b1ca..d5b50e6b1 100644 --- a/circuits/src/stark/mod.rs +++ b/circuits/src/stark/mod.rs @@ -5,7 +5,6 @@ #[allow(clippy::module_name_repetitions)] pub mod mozak_stark; pub mod permutation; -pub mod poly; pub mod proof; pub mod prover; pub mod recursive_verifier; diff --git a/circuits/src/stark/mozak_stark.rs b/circuits/src/stark/mozak_stark.rs index d8930321d..60672c602 100644 --- a/circuits/src/stark/mozak_stark.rs +++ b/circuits/src/stark/mozak_stark.rs @@ -9,6 +9,7 @@ use plonky2::hash::hash_types::RichField; #[allow(clippy::wildcard_imports)] use plonky2_maybe_rayon::*; use serde::{Deserialize, Serialize}; +use starky::{cross_table_lookup as starky_ctl, lookup as starky_lookup}; use crate::bitshift::columns::{Bitshift, BitshiftView}; use crate::bitshift::stark::BitshiftStark; @@ -39,7 +40,6 @@ use crate::program::columns::ProgramRom; use crate::program::stark::ProgramStark; use crate::program_multiplicities::columns::ProgramMult; use crate::program_multiplicities::stark::ProgramMultStark; -use crate::public_sub_table::PublicSubTable; use crate::rangecheck::columns::{rangecheck_looking, RangeCheckColumnsView, RangeCheckCtl}; use crate::rangecheck::stark::RangeCheckStark; use crate::rangecheck_u8::columns::RangeCheckU8; @@ -64,7 +64,6 @@ use crate::{ }; const NUM_CROSS_TABLE_LOOKUP: usize = 17; -const NUM_PUBLIC_SUB_TABLES: usize = 2; /// STARK Gadgets of Mozak-VM /// @@ -141,8 +140,8 @@ pub struct MozakStark, const D: usize> { pub poseidon2_output_bytes_stark: Poseidon2OutputBytesStark, #[StarkSet(stark_kind = "TapeCommitments")] pub tape_commitments_stark: TapeCommitmentsStark, - pub cross_table_lookups: [CrossTableLookup; NUM_CROSS_TABLE_LOOKUP], - pub public_sub_tables: [PublicSubTable; NUM_PUBLIC_SUB_TABLES], + pub cross_table_lookups: + [starky::cross_table_lookup::CrossTableLookup; NUM_CROSS_TABLE_LOOKUP], pub debug: bool, } @@ -163,7 +162,7 @@ macro_rules! mozak_stark_helpers { } impl TableKind { - const COUNT: usize = $kind_count; + pub const COUNT: usize = $kind_count; } // Generate the set builder @@ -450,11 +449,8 @@ impl, const D: usize> Default for MozakStark Poseidon2OutputBytesPoseidon2SpongeTable::lookups(), EventCommitmentTapeIOLookupTable::lookups(), CastlistCommitmentTapeIOLookupTable::lookups(), - ], - public_sub_tables: [ - crate::tape_commitments::columns::make_event_commitment_tape_public(), - crate::tape_commitments::columns::make_castlist_commitment_tape_public(), - ], + ] + .map(starky::cross_table_lookup::CrossTableLookup::from), debug: false, } } @@ -505,6 +501,36 @@ pub struct TableWithTypedOutput { pub type TableUntyped = TableWithTypedOutput>; pub use TableUntyped as Table; +impl From<&Table> for starky_ctl::TableWithColumns { + fn from(table: &Table) -> Self { + let columns = table + .columns + .iter() + .map(Column::to_starky) + .collect::>(); + // TODO(Matthias): figure out why they take a vector of filters. + let filter = starky_lookup::Filter::new(vec![], vec![table.filter_column.to_starky()]); + starky_ctl::TableWithColumns::new(table.kind as usize, columns, filter) + } +} + +impl From for starky_ctl::TableWithColumns { + fn from(table: Table) -> Self { Self::from(&table) } +} + +impl Table { + #[must_use] + pub fn to_starky(&self) -> starky_ctl::TableWithColumns { + let columns = self + .columns + .iter() + .map(Column::to_starky) + .collect::>(); + let filter = starky_lookup::Filter::new_simple(self.filter_column.to_starky()); + starky_ctl::TableWithColumns::new(self.kind as usize, columns, filter) + } +} + impl> TableWithTypedOutput { pub fn to_untyped_output(self) -> Table { Table { diff --git a/circuits/src/stark/permutation.rs b/circuits/src/stark/permutation.rs index 1b0bc464a..8229cbded 100644 --- a/circuits/src/stark/permutation.rs +++ b/circuits/src/stark/permutation.rs @@ -91,13 +91,41 @@ pub mod challenge { } } + impl From> for starky::lookup::GrandProductChallenge + where + Target: Copy + Eq + PartialEq + Debug, + { + fn from(challenge: GrandProductChallenge) -> Self { + starky::lookup::GrandProductChallenge { + beta: challenge.beta, + gamma: challenge.gamma, + } + } + } + /// [`GrandProductChallenge`] repeated for [`num_challenges`] to boost /// soundness. #[derive(Clone, Eq, PartialEq, Debug, Default)] - pub struct GrandProductChallengeSet { + pub struct GrandProductChallengeSet { pub challenges: Vec>, } + impl From> + for starky::lookup::GrandProductChallengeSet + where + Target: Copy + Eq + PartialEq + core::fmt::Debug, + { + fn from(challenges: GrandProductChallengeSet) -> Self { + starky::lookup::GrandProductChallengeSet { + challenges: challenges + .challenges + .into_iter() + .map(starky::lookup::GrandProductChallenge::from) + .collect(), + } + } + } + pub trait GrandProductChallengeTrait> { fn get_grand_product_challenge(&mut self) -> GrandProductChallenge; diff --git a/circuits/src/stark/poly.rs b/circuits/src/stark/poly.rs deleted file mode 100644 index e62e73322..000000000 --- a/circuits/src/stark/poly.rs +++ /dev/null @@ -1,166 +0,0 @@ -#![allow(clippy::too_many_arguments)] - -use plonky2::field::extension::{Extendable, FieldExtension}; -use plonky2::field::packed::PackedField; -use plonky2::field::polynomial::{PolynomialCoeffs, PolynomialValues}; -use plonky2::field::zero_poly_coset::ZeroPolyOnCoset; -use plonky2::fri::oracle::PolynomialBatch; -use plonky2::hash::hash_types::RichField; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::config::GenericConfig; -use plonky2::util::{log2_ceil, transpose}; -#[allow(clippy::wildcard_imports)] -use plonky2_maybe_rayon::*; -use starky::config::StarkConfig; -use starky::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; -use starky::evaluation_frame::StarkEvaluationFrame; -use starky::stark::Stark; - -use crate::cross_table_lookup::{ - eval_cross_table_lookup_checks, eval_cross_table_lookup_checks_circuit, CtlCheckVars, - CtlCheckVarsTarget, CtlData, -}; - -/// Computes the quotient polynomials `(sum alpha^i C_i(x)) / Z_H(x)` for -/// `alpha` in `alphas`, where the `C_i`s are the Stark constraints. -pub fn compute_quotient_polys<'a, F, P, C, S, const D: usize>( - stark: &S, - trace_commitment: &'a PolynomialBatch, - ctl_zs_commitment: &'a PolynomialBatch, - public_inputs: &[F], - ctl_data: &CtlData, - public_sub_table_data: &CtlData, - alphas: &[F], - degree_bits: usize, - config: &StarkConfig, -) -> Vec> -where - F: RichField + Extendable, - P: PackedField, - C: GenericConfig, - S: Stark, { - let degree = 1 << degree_bits; - let rate_bits = config.fri_config.rate_bits; - - let quotient_degree_bits = log2_ceil(stark.quotient_degree_factor()); - assert!( - quotient_degree_bits <= rate_bits, - "Having constraints of degree higher than the rate is not supported yet." - ); - let step = 1 << (rate_bits - quotient_degree_bits); - // When opening the `Z`s polys at the "next" point, need to look at the point - // `next_step` steps away. - let next_step = 1 << quotient_degree_bits; - - // Evaluation of the first Lagrange polynomial on the LDE domain. - let lagrange_first = PolynomialValues::selector(degree, 0).lde_onto_coset(quotient_degree_bits); - // Evaluation of the last Lagrange polynomial on the LDE domain. - let lagrange_last = - PolynomialValues::selector(degree, degree - 1).lde_onto_coset(quotient_degree_bits); - - let z_h_on_coset = ZeroPolyOnCoset::::new(degree_bits, quotient_degree_bits); - - // Retrieve the LDE values at index `i`. - let get_trace_values_packed = - |i_start| -> Vec

{ trace_commitment.get_lde_values_packed(i_start, step) }; - - // Last element of the subgroup. - let last = F::primitive_root_of_unity(degree_bits).inverse(); - let size = degree << quotient_degree_bits; - let coset = F::cyclic_subgroup_coset_known_order( - F::primitive_root_of_unity(degree_bits + quotient_degree_bits), - F::coset_shift(), - size, - ); - - // We will step by `P::WIDTH`, and in each iteration, evaluate the quotient - // polynomial at a batch of `P::WIDTH` points. - let quotient_values = (0..size) - .into_par_iter() - .step_by(P::WIDTH) - .flat_map_iter(|i_start| { - let i_next_start = (i_start + next_step) % size; - let i_range = i_start..i_start + P::WIDTH; - - let x = *P::from_slice(&coset[i_range.clone()]); - let z_last = x - last; - let lagrange_basis_first = *P::from_slice(&lagrange_first.values[i_range.clone()]); - let lagrange_basis_last = *P::from_slice(&lagrange_last.values[i_range]); - - let mut consumer = ConstraintConsumer::new( - alphas.to_vec(), - z_last, - lagrange_basis_first, - lagrange_basis_last, - ); - let vars = StarkEvaluationFrame::from_values( - &get_trace_values_packed(i_start), - &get_trace_values_packed(i_next_start), - public_inputs, - ); - let public_sub_table_data_chain = public_sub_table_data.zs_columns.as_slice(); - let ctl_vars = ctl_data - .zs_columns - .iter() - .chain(public_sub_table_data_chain.iter()) - .enumerate() - .map(|(i, zs_columns)| CtlCheckVars:: { - local_z: ctl_zs_commitment.get_lde_values_packed(i_start, step)[i], - next_z: ctl_zs_commitment.get_lde_values_packed(i_next_start, step)[i], - challenges: zs_columns.challenge, - columns: &zs_columns.columns, - filter_column: &zs_columns.filter_column, - }) - .collect::>(); - eval_vanishing_poly::(stark, &vars, &ctl_vars, &mut consumer); - let mut constraints_evals = consumer.accumulators(); - // We divide the constraints evaluations by `Z_H(x)`. - let denominator_inv: P = z_h_on_coset.eval_inverse_packed(i_start); - for eval in &mut constraints_evals { - *eval *= denominator_inv; - } - - let num_challenges = alphas.len(); - - (0..P::WIDTH).map(move |i| { - (0..num_challenges) - .map(|j| constraints_evals[j].as_slice()[i]) - .collect() - }) - }) - .collect::>(); - - transpose("ient_values) - .into_par_iter() - .map(PolynomialValues::new) - .map(|values| values.coset_ifft(F::coset_shift())) - .collect() -} - -#[allow(clippy::module_name_repetitions)] -pub fn eval_vanishing_poly( - stark: &S, - vars: &S::EvaluationFrame, - ctl_vars: &[CtlCheckVars], - consumer: &mut ConstraintConsumer

, -) where - F: RichField + Extendable, - FE: FieldExtension, - P: PackedField, - S: Stark, { - stark.eval_packed_generic(vars, consumer); - eval_cross_table_lookup_checks::(vars, ctl_vars, consumer); -} - -pub fn eval_vanishing_poly_circuit( - builder: &mut CircuitBuilder, - stark: &S, - vars: &S::EvaluationFrameTarget, - ctl_vars: &[CtlCheckVarsTarget], - consumer: &mut RecursiveConstraintConsumer, -) where - F: RichField + Extendable, - S: Stark, { - stark.eval_ext_circuit(builder, vars, consumer); - eval_cross_table_lookup_checks_circuit::(builder, vars, ctl_vars, consumer); -} diff --git a/circuits/src/stark/proof.rs b/circuits/src/stark/proof.rs index 52a503f96..448298949 100644 --- a/circuits/src/stark/proof.rs +++ b/circuits/src/stark/proof.rs @@ -14,17 +14,16 @@ use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; #[allow(clippy::wildcard_imports)] use plonky2_maybe_rayon::*; +use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use starky::config::StarkConfig; use super::mozak_stark::{all_kind, PublicInputs, TableKindArray}; -use crate::public_sub_table::PublicSubTableValues; -use crate::stark::permutation::challenge::{GrandProductChallengeSet, GrandProductChallengeTrait}; #[allow(clippy::module_name_repetitions)] impl, C: GenericConfig, const D: usize> AllProof { pub fn degree_bits(&self, config: &StarkConfig) -> TableKindArray { - all_kind!(|kind| self.proofs[kind].recover_degree_bits(config)) + all_kind!(|kind| self.proofs[kind].proof.recover_degree_bits(config)) } } @@ -56,52 +55,6 @@ impl, C: GenericConfig, const D: usize> S } pub fn num_ctl_zs(&self) -> usize { self.openings.ctl_zs_last.len() } - - /// Computes all Fiat-Shamir challenges used in the STARK proof. - pub(crate) fn get_challenges( - &self, - challenger: &mut Challenger, - config: &StarkConfig, - ) -> StarkProofChallenges { - let degree_bits = self.recover_degree_bits(config); - - let StarkProof { - ctl_zs_cap, - quotient_polys_cap, - openings, - opening_proof: - FriProof { - commit_phase_merkle_caps, - final_poly, - pow_witness, - .. - }, - .. - } = &self; - - let num_challenges = config.num_challenges; - - challenger.observe_cap(ctl_zs_cap); - - let stark_alphas = challenger.get_n_challenges(num_challenges); - - challenger.observe_cap(quotient_polys_cap); - let stark_zeta = challenger.get_extension_challenge::(); - - challenger.observe_openings(&openings.to_fri_openings()); - - StarkProofChallenges { - stark_alphas, - stark_zeta, - fri_challenges: challenger.fri_challenges::( - commit_phase_merkle_caps, - final_poly, - *pow_witness, - degree_bits, - &config.fri_config, - ), - } - } } #[derive(Clone, Debug, Eq, PartialEq)] @@ -318,17 +271,19 @@ impl StarkOpeningSetTarget { #[allow(clippy::module_name_repetitions)] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(bound = "")] -pub struct AllProof, C: GenericConfig, const D: usize> { - pub proofs: TableKindArray>, +pub struct AllProof, C: GenericConfig, const D: usize> +where + F: DeserializeOwned + Serialize, { + pub proofs: TableKindArray>, + pub ctl_challenges: starky::lookup::GrandProductChallengeSet, pub program_rom_trace_cap: MerkleCap, pub elf_memory_init_trace_cap: MerkleCap, pub public_inputs: PublicInputs, - pub public_sub_table_values: TableKindArray>>, } pub(crate) struct AllProofChallenges, const D: usize> { - pub stark_challenges: TableKindArray>, - pub ctl_challenges: GrandProductChallengeSet, + pub stark_challenges: TableKindArray>, + pub ctl_challenges: starky::lookup::GrandProductChallengeSet, } impl, C: GenericConfig, const D: usize> AllProof { @@ -337,26 +292,29 @@ impl, C: GenericConfig, const D: usize> A let mut challenger = Challenger::::new(); for proof in &self.proofs { - challenger.observe_cap(&proof.trace_cap); + challenger.observe_cap(&proof.proof.trace_cap); } // TODO: Observe public values. - let ctl_challenges = challenger.get_grand_product_challenge_set(config.num_challenges); + let ctl_challenges = + starky::lookup::get_grand_product_challenge_set(&mut challenger, config.num_challenges); + // TODO(Matthias): consider moving to observing all ctl caps at once, so we can + // use the same `alphas` for the whole set of starks. That would need + // changes in plonky2. + challenger.compact(); AllProofChallenges { stark_challenges: all_kind!(|kind| { - challenger.compact(); - self.proofs[kind].get_challenges(&mut challenger, config) + let mut challenger = challenger.clone(); + self.proofs[kind].proof.get_challenges( + &mut challenger, + Some(&ctl_challenges), + true, + config, + ) }), ctl_challenges, } } - - /// Returns the ordered openings of cross-table lookups `Z` polynomials at - /// `g^-1`. The order corresponds to the order declared in - /// [`TableKind`](crate::cross_table_lookup::TableKind). - pub(crate) fn all_ctl_zs_last(self) -> TableKindArray> { - self.proofs.map(|p| p.openings.ctl_zs_last) - } } diff --git a/circuits/src/stark/prover.rs b/circuits/src/stark/prover.rs index 5dc017636..20bc7bc2b 100644 --- a/circuits/src/stark/prover.rs +++ b/circuits/src/stark/prover.rs @@ -2,16 +2,13 @@ use std::fmt::Display; -use anyhow::{ensure, Result}; -use itertools::Itertools; +use anyhow::Result; use log::Level::Debug; use log::{debug, log_enabled}; use mozak_runner::elf::Program; use mozak_runner::vm::ExecutionRecord; use plonky2::field::extension::Extendable; -use plonky2::field::packable::Packable; use plonky2::field::polynomial::PolynomialValues; -use plonky2::field::types::Field; use plonky2::fri::oracle::PolynomialBatch; use plonky2::hash::hash_types::RichField; use plonky2::iop::challenger::Challenger; @@ -19,20 +16,14 @@ use plonky2::plonk::config::GenericConfig; use plonky2::timed; use plonky2::util::log2_strict; use plonky2::util::timing::TimingTree; -#[allow(clippy::wildcard_imports)] -use plonky2_maybe_rayon::*; use starky::config::StarkConfig; -use starky::stark::{LookupConfig, Stark}; +use starky::proof::StarkProofWithMetadata; +use starky::stark::Stark; use super::mozak_stark::{MozakStark, TableKind, TableKindArray, TableKindSetBuilder}; -use super::proof::{AllProof, StarkOpeningSet, StarkProof}; -use crate::cross_table_lookup::ctl_utils::debug_ctl; -use crate::cross_table_lookup::{cross_table_lookup_data, CtlData}; +use super::proof::AllProof; use crate::generation::{debug_traces, generate_traces}; -use crate::public_sub_table::public_sub_table_data_and_values; use crate::stark::mozak_stark::{all_starks, PublicInputs}; -use crate::stark::permutation::challenge::GrandProductChallengeTrait; -use crate::stark::poly::compute_quotient_polys; /// Prove the execution of a given [Program] /// @@ -58,7 +49,6 @@ where let traces_poly_values = generate_traces(program, record); if mozak_stark.debug || std::env::var("MOZAK_STARK_DEBUG").is_ok() { debug_traces(&traces_poly_values, mozak_stark, &public_inputs); - debug_ctl(&traces_poly_values, mozak_stark); } prove_with_traces( mozak_stark, @@ -116,38 +106,34 @@ where for cap in &trace_caps { challenger.observe_cap(cap); } - - let ctl_challenges = challenger.get_grand_product_challenge_set(config.num_challenges); - let ctl_data_per_table = timed!( - timing, - "Compute CTL data for each table", - cross_table_lookup_data::( - traces_poly_values, - &mozak_stark.cross_table_lookups, - &ctl_challenges + let starky_cross_table_lookups = mozak_stark + .cross_table_lookups + .clone() + .map(starky::cross_table_lookup::CrossTableLookup::from); + let (starky_ctl_challenges, starky_ctl_datas) = { + starky::cross_table_lookup::get_ctl_data::( + config, + &traces_poly_values.0, + &starky_cross_table_lookups, + &mut challenger, + 3, ) - ); - - let (public_sub_table_data_per_table, public_sub_table_values) = - public_sub_table_data_and_values::( - traces_poly_values, - &mozak_stark.public_sub_tables, - &ctl_challenges, - ); + }; let proofs = timed!( timing, "compute all proofs given commitments", + // TODO: use starky's `prove_with_commitments` prove_with_commitments( mozak_stark, config, &public_inputs, traces_poly_values, &trace_commitments, - &ctl_data_per_table, - &public_sub_table_data_per_table, &mut challenger, - timing + timing, + &starky_ctl_challenges, + &starky_ctl_datas, )? ); @@ -158,10 +144,10 @@ where } Ok(AllProof { proofs, + ctl_challenges: starky_ctl_challenges, program_rom_trace_cap, elf_memory_init_trace_cap, public_inputs, - public_sub_table_values, }) } @@ -177,14 +163,16 @@ pub(crate) fn prove_single_table( config: &StarkConfig, trace_poly_values: &[PolynomialValues], trace_commitment: &PolynomialBatch, - public_inputs: &[F], - ctl_data: &CtlData, - public_sub_table_data: &CtlData, challenger: &mut Challenger, + public_inputs: &[F], timing: &mut TimingTree, -) -> Result> + starky_ctl_challenges: &starky::lookup::GrandProductChallengeSet, + starky_ctl_data: &starky::cross_table_lookup::CtlData<'_, F>, + // Of course, we need to match the output, too. + // Ok, looks doable. +) -> Result> where - F: RichField + Extendable, + F: RichField + Extendable + Copy + Eq + core::fmt::Debug, C: GenericConfig, S: Stark + Display, { let degree = trace_poly_values[0].len(); @@ -197,135 +185,23 @@ where "FRI total reduction arity is too large.", ); - let z_poly_public_sub_table = public_sub_table_data.z_polys(); - - // commit to both z poly of ctl and open public - let z_polys = vec![ctl_data.z_polys(), z_poly_public_sub_table] - .into_iter() - .flatten() - .collect_vec(); - // TODO(Matthias): make the code work with empty z_polys, too. - assert!(!z_polys.is_empty(), "No CTL? {stark}"); - - let ctl_zs_commitment = timed!( - timing, - format!("{stark}: compute Zs commitment").as_str(), - PolynomialBatch::from_values( - z_polys, - rate_bits, - false, - config.fri_config.cap_height, - timing, - None, - ) - ); - let ctl_zs_cap = ctl_zs_commitment.merkle_tree.cap.clone(); - challenger.observe_cap(&ctl_zs_cap); - - let alphas = challenger.get_n_challenges(config.num_challenges); - let quotient_polys = timed!( - timing, - format!("{stark}: compute quotient polynomial").as_str(), - compute_quotient_polys::::Packing, C, S, D>( - stark, - trace_commitment, - &ctl_zs_commitment, - public_inputs, - ctl_data, - public_sub_table_data, - &alphas, - degree_bits, - config, - ) - ); - - let all_quotient_chunks = timed!( - timing, - format!("{stark}: split quotient polynomial").as_str(), - quotient_polys - .into_par_iter() - .flat_map(|mut quotient_poly| { - quotient_poly - .trim_to_len(degree * stark.quotient_degree_factor()) - .expect( - "Quotient has failed, the vanishing polynomial is not divisible by Z_H", - ); - // Split quotient into degree-n chunks. - quotient_poly.chunks(degree) - }) - .collect() - ); - let quotient_commitment = timed!( - timing, - format!("{stark}: compute quotient commitment").as_str(), - PolynomialBatch::from_coeffs( - all_quotient_chunks, - rate_bits, - false, - config.fri_config.cap_height, - timing, - None, - ) - ); - let quotient_polys_cap = quotient_commitment.merkle_tree.cap.clone(); - challenger.observe_cap("ient_polys_cap); - - let zeta = challenger.get_extension_challenge::(); - // To avoid leaking witness data, we want to ensure that our opening locations, - // `zeta` and `g * zeta`, are not in our subgroup `H`. It suffices to check - // `zeta` only, since `(g * zeta)^n = zeta^n`, where `n` is the order of - // `g`. - let g = F::primitive_root_of_unity(degree_bits); - ensure!( - zeta.exp_power_of_2(degree_bits) != F::Extension::ONE, - "Opening point is in the subgroup." - ); + // Clear buffered outputs. + let init_challenger_state = challenger.compact(); - let openings = StarkOpeningSet::new( - zeta, - g, + starky::prover::prove_with_commitment( + stark, + config, + trace_poly_values, trace_commitment, - &ctl_zs_commitment, - "ient_commitment, - degree_bits, - ); - - challenger.observe_openings(&openings.to_fri_openings()); - - let initial_merkle_trees = vec![trace_commitment, &ctl_zs_commitment, "ient_commitment]; - - // Make sure that we do not use Starky's lookups. - assert!(!stark.requires_ctls()); - assert!(!stark.uses_lookups()); - let num_make_rows_public_data = public_sub_table_data.len(); - let opening_proof = timed!( + Some(starky_ctl_data), + Some(starky_ctl_challenges), + challenger, + public_inputs, timing, - format!("{stark}: compute opening proofs").as_str(), - PolynomialBatch::prove_openings( - &stark.fri_instance( - zeta, - g, - 0, - vec![], - config, - Some(&LookupConfig { - degree_bits, - num_zs: ctl_data.len() + num_make_rows_public_data - }) - ), - &initial_merkle_trees, - challenger, - &fri_params, - timing, - ) - ); - - Ok(StarkProof { - trace_cap: trace_commitment.merkle_tree.cap.clone(), - ctl_zs_cap, - quotient_polys_cap, - openings, - opening_proof, + ) + .map(|proof_with_pis| StarkProofWithMetadata { + proof: proof_with_pis.proof, + init_challenger_state, }) } @@ -341,11 +217,11 @@ pub fn prove_with_commitments( public_inputs: &PublicInputs, traces_poly_values: &TableKindArray>>, trace_commitments: &TableKindArray>, - ctl_data_per_table: &TableKindArray>, - public_sub_data_per_table: &TableKindArray>, challenger: &mut Challenger, timing: &mut TimingTree, -) -> Result>> + starky_ctl_challenges: &starky::lookup::GrandProductChallengeSet, + starky_ctl_datas: &[starky::cross_table_lookup::CtlData<'_, F>; TableKind::COUNT], +) -> Result>> where F: RichField + Extendable, C: GenericConfig, { @@ -356,18 +232,22 @@ where } .build(); + // Clear buffered outputs. + challenger.compact(); Ok(all_starks!(mozak_stark, |stark, kind| { + let mut challenger = challenger.clone(); prove_single_table( stark, config, &traces_poly_values[kind], &trace_commitments[kind], + &mut challenger, public_inputs[kind], - &ctl_data_per_table[kind], - &public_sub_data_per_table[kind], - challenger, timing, - )? + starky_ctl_challenges, + &starky_ctl_datas[kind as usize], + ) + .unwrap() })) } diff --git a/circuits/src/stark/recursive_verifier.rs b/circuits/src/stark/recursive_verifier.rs index 8435345b2..fcf9b2ba3 100644 --- a/circuits/src/stark/recursive_verifier.rs +++ b/circuits/src/stark/recursive_verifier.rs @@ -4,43 +4,27 @@ use std::fmt::Debug; use std::marker::PhantomData; use anyhow::Result; -use itertools::{zip_eq, Itertools}; use log::info; use mozak_sdk::core::ecall::COMMITMENT_SIZE; use plonky2::field::extension::Extendable; -use plonky2::field::types::Field; use plonky2::fri::witness_util::set_fri_proof_target; use plonky2::gates::noop::NoopGate; use plonky2::hash::hash_types::{RichField, NUM_HASH_OUT_ELTS}; use plonky2::iop::challenger::RecursiveChallenger; -use plonky2::iop::ext_target::ExtensionTarget; use plonky2::iop::target::Target; use plonky2::iop::witness::{PartialWitness, Witness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, VerifierCircuitTarget}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; -use plonky2::util::reducing::ReducingFactorTarget; -use plonky2::with_context; use starky::config::StarkConfig; -use starky::constraint_consumer::RecursiveConstraintConsumer; -use starky::evaluation_frame::StarkEvaluationFrame; -use starky::stark::{LookupConfig, Stark}; +use starky::stark::Stark; -use super::mozak_stark::{all_kind, all_starks, TableKindArray}; +use super::mozak_stark::{all_starks, TableKindArray}; use crate::columns_view::{columns_view_impl, NumberOfColumns}; -use crate::cross_table_lookup::{ - verify_cross_table_lookups_and_public_sub_table_circuit, CrossTableLookup, CtlCheckVarsTarget, -}; -use crate::public_sub_table::{ - public_sub_table_values_and_reduced_targets, PublicSubTable, PublicSubTableValuesTarget, -}; use crate::stark::mozak_stark::{MozakStark, TableKind}; -use crate::stark::permutation::challenge::get_grand_product_challenge_set_target; -use crate::stark::poly::eval_vanishing_poly_circuit; use crate::stark::proof::{ - AllProof, StarkOpeningSetTarget, StarkProof, StarkProofChallengesTarget, StarkProofTarget, - StarkProofWithPublicInputsTarget, + AllProof, StarkOpeningSetTarget, StarkProof, StarkProofTarget, StarkProofWithPublicInputsTarget, }; /// Plonky2's recursion threshold is 2^12 gates. @@ -78,7 +62,6 @@ where C::Hasher: AlgebraicHasher, { pub circuit: CircuitData, pub targets: TableKindArray>, - pub public_sub_table_values_targets: TableKindArray>, } #[derive(Eq, PartialEq, Debug)] @@ -87,7 +70,7 @@ where F: RichField + Extendable, C: GenericConfig, C::Hasher: AlgebraicHasher, { - pub stark_proof_with_pis_target: StarkProofWithPublicInputsTarget, + pub stark_proof_with_pis_target: starky::proof::StarkProofWithPublicInputsTarget, pub zero_target: Target, pub _f: PhantomData<(F, C)>, } @@ -98,16 +81,21 @@ where C: GenericConfig, C::Hasher: AlgebraicHasher, { - pub fn set_targets(&self, witness: &mut PartialWitness, proof: &StarkProof) { - set_stark_proof_with_pis_target( + pub fn set_targets( + &self, + witness: &mut PartialWitness, + proof: &starky::proof::StarkProofWithPublicInputs, + ) { + starky::recursive_verifier::set_stark_proof_with_pis_target( witness, - &self.stark_proof_with_pis_target.proof, + &self.stark_proof_with_pis_target, proof, self.zero_target, ); } } +// TODO(Matthias): this is equivalent to zk_evm's `StarkWrapperCircuit` impl MozakStarkVerifierCircuit where F: RichField + Extendable, @@ -117,23 +105,30 @@ where pub fn prove(&self, all_proof: &AllProof) -> Result> { let mut inputs = PartialWitness::new(); - all_kind!(|kind| { - self.targets[kind].set_targets(&mut inputs, &all_proof.proofs[kind]); - - // set public_sub_table_values targets - for (public_sub_table_values_target, public_sub_table_values) in zip_eq( - &self.public_sub_table_values_targets[kind], - &all_proof.public_sub_table_values[kind], - ) { - for (row_target, row) in - zip_eq(public_sub_table_values_target, public_sub_table_values) - { - for (&values_target, &values) in zip_eq(row_target, row) { - inputs.set_target(values_target, values); - } - } - } - }); + // all_kind!(|kind| { + // self.targets[kind].set_targets(&mut inputs, &all_proof.proofs[kind]); + + // // set public_sub_table_values targets + // for (public_sub_table_values_target, public_sub_table_values) in zip_eq( + // &self.public_sub_table_values_targets[kind], + // &all_proof.public_sub_table_values[kind], + // ) { + // for (row_target, row) in + // zip_eq(public_sub_table_values_target, public_sub_table_values) + // { + // for (&values_target, &values) in zip_eq(row_target, row) { + // inputs.set_target(values_target, values); + // } + // } + // } + // }); + + // How are zk_evm handling their public inputs? + // // let proof = starky::proof::StarkProof::from(proof); + // // TODO(Matthias): not sure we need this, if we don't have the pub sub + // feature? all_kind!(|kind| { + // self.targets[kind].set_targets(&mut inputs, &all_proof.proofs[kind]); + // }); // Set public inputs let cpu_target = &self.targets[TableKind::Cpu].stark_proof_with_pis_target; @@ -146,6 +141,7 @@ where } } +// TODO(Matthias): learn from zk_evm `recursive_stark_circuit` #[must_use] #[allow(clippy::too_many_lines)] pub fn recursive_mozak_stark_circuit< @@ -165,22 +161,21 @@ where let mut challenger = RecursiveChallenger::::new(&mut builder); let stark_proof_with_pis_target = all_starks!(mozak_stark, |stark, kind| { - let num_ctl_zs = CrossTableLookup::num_ctl_zs( - &mozak_stark.cross_table_lookups, - kind, - inner_config.num_challenges, - ); - let num_make_row_public_zs = PublicSubTable::num_zs( - &mozak_stark.public_sub_tables, - kind, - inner_config.num_challenges, - ); - add_virtual_stark_proof_with_pis( + let (total_num_helpers, num_ctl_zs, _) = + starky::cross_table_lookup::CrossTableLookup::num_ctl_helpers_zs_all( + &mozak_stark.cross_table_lookups, + kind as usize, + inner_config.num_challenges, + stark.constraint_degree(), + ); + let num_ctl_helper_zs = num_ctl_zs + total_num_helpers; + starky::recursive_verifier::add_virtual_stark_proof_with_pis( &mut builder, stark, inner_config, degree_bits[kind], - num_ctl_zs + num_make_row_public_zs, + num_ctl_helper_zs, + num_ctl_zs, ) }); @@ -188,49 +183,64 @@ where challenger.observe_cap(&pi.proof.trace_cap); } - let ctl_challenges = get_grand_product_challenge_set_target( + let ctl_challenges = starky::lookup::get_grand_product_challenge_set_target( &mut builder, &mut challenger, inner_config.num_challenges, ); + // TODO(Matthias): use verify_stark_proof_with_challenges_circuit from upstream. - let (public_sub_table_values_targets, reduced_public_sub_table_targets) = - public_sub_table_values_and_reduced_targets( - &mut builder, - &mozak_stark.public_sub_tables, - &ctl_challenges, - ); - - verify_cross_table_lookups_and_public_sub_table_circuit( + // starky::recursive_verifier::verify_stark_proof_with_challenges_circuit( + // &mut builder, + // ); + starky::cross_table_lookup::verify_cross_table_lookups_circuit( &mut builder, - &mozak_stark.cross_table_lookups, - &mozak_stark.public_sub_tables, - &reduced_public_sub_table_targets, - &stark_proof_with_pis_target - .clone() - .map(|p| p.proof.openings.ctl_zs_last), + mozak_stark.cross_table_lookups.to_vec(), + stark_proof_with_pis_target + .each_ref() + .map(|p| p.proof.openings.ctl_zs_first.clone().unwrap()) + .0, + None, inner_config, ); let targets = all_starks!(mozak_stark, |stark, kind| { - let ctl_vars = CtlCheckVarsTarget::from_proof( - kind, + // TODO(Matthias): we are already doing this above? + let num_lookup_columns = stark.num_lookup_helper_columns(inner_config); + let (total_num_helpers, _num_ctl_zs, num_helpers_by_ctl) = + starky::cross_table_lookup::CrossTableLookup::num_ctl_helpers_zs_all( + &mozak_stark.cross_table_lookups, + kind as usize, + inner_config.num_challenges, + stark.constraint_degree(), + ); + let ctl_vars = starky::cross_table_lookup::CtlCheckVarsTarget::from_proof( + kind as usize, &stark_proof_with_pis_target[kind].proof, &mozak_stark.cross_table_lookups, - &mozak_stark.public_sub_tables, &ctl_challenges, + num_lookup_columns, + total_num_helpers, + &num_helpers_by_ctl, ); let challenges_target = stark_proof_with_pis_target[kind] .proof - .get_challenges::(&mut builder, &mut challenger, inner_config); - - verify_stark_proof_with_challenges_circuit::( + .get_challenges::( + &mut builder, + &mut challenger, + Some(&ctl_challenges), + true, + inner_config, + ); + + starky::recursive_verifier::verify_stark_proof_with_challenges_circuit::( &mut builder, stark, - &stark_proof_with_pis_target[kind], - &challenges_target, - &ctl_vars, + &stark_proof_with_pis_target[kind].proof, + &stark_proof_with_pis_target[kind].public_inputs, + challenges_target, + Some(&ctl_vars), inner_config, ); @@ -254,147 +264,9 @@ where .collect::>(), ); } - all_kind!(|kind| { - builder.register_public_inputs( - &public_sub_table_values_targets[kind] - .clone() - .into_iter() - .flatten() - .flatten() - .collect_vec(), - ); - }); let circuit = builder.build(); - MozakStarkVerifierCircuit { - circuit, - targets, - public_sub_table_values_targets, - } -} - -/// Recursively verifies an inner proof. -fn verify_stark_proof_with_challenges_circuit< - F: RichField + Extendable, - C: GenericConfig, - S: Stark, - const D: usize, ->( - builder: &mut CircuitBuilder, - stark: &S, - proof_with_public_inputs: &StarkProofWithPublicInputsTarget, - challenges: &StarkProofChallengesTarget, - ctl_vars: &[CtlCheckVarsTarget], - inner_config: &StarkConfig, -) where - C::Hasher: AlgebraicHasher, { - let zero = builder.zero(); - let one = builder.one_extension(); - - let StarkOpeningSetTarget { - local_values, - next_values, - ctl_zs: _, - ctl_zs_next: _, - ctl_zs_last, - quotient_polys, - } = &proof_with_public_inputs.proof.openings; - - let converted_public_inputs: Vec> = proof_with_public_inputs - .public_inputs - .iter() - .map(|target| builder.convert_to_ext(*target)) // replace with actual conversion function/method - .collect(); - - let vars = - S::EvaluationFrameTarget::from_values(local_values, next_values, &converted_public_inputs); - - let degree_bits = proof_with_public_inputs - .proof - .recover_degree_bits(inner_config); - let zeta_pow_deg = builder.exp_power_of_2_extension(challenges.stark_zeta, degree_bits); - let z_h_zeta = builder.sub_extension(zeta_pow_deg, one); - let (l_0, l_last) = - eval_l_0_and_l_last_circuit(builder, degree_bits, challenges.stark_zeta, z_h_zeta); - let last = - builder.constant_extension(F::Extension::primitive_root_of_unity(degree_bits).inverse()); - let z_last = builder.sub_extension(challenges.stark_zeta, last); - - let mut consumer = RecursiveConstraintConsumer::::new( - builder.zero_extension(), - challenges.stark_alphas.clone(), - z_last, - l_0, - l_last, - ); - - with_context!( - builder, - "evaluate vanishing polynomial", - eval_vanishing_poly_circuit::(builder, stark, &vars, ctl_vars, &mut consumer,) - ); - let vanishing_polys_zeta = consumer.accumulators(); - - // Check each polynomial identity, of the form `vanishing(x) = Z_H(x) - // quotient(x)`, at zeta. - let mut scale = ReducingFactorTarget::new(zeta_pow_deg); - for (i, chunk) in quotient_polys - .chunks(stark.quotient_degree_factor()) - .enumerate() - { - let recombined_quotient = scale.reduce(chunk, builder); - let computed_vanishing_poly = builder.mul_extension(z_h_zeta, recombined_quotient); - builder.connect_extension(vanishing_polys_zeta[i], computed_vanishing_poly); - } - - let merkle_caps = vec![ - proof_with_public_inputs.proof.trace_cap.clone(), - proof_with_public_inputs.proof.ctl_zs_cap.clone(), - proof_with_public_inputs.proof.quotient_polys_cap.clone(), - ]; - - let fri_instance = stark.fri_instance_target( - builder, - challenges.stark_zeta, - F::primitive_root_of_unity(degree_bits), - 0, - 0, - inner_config, - Some(&LookupConfig { - degree_bits, - num_zs: ctl_zs_last.len(), - }), - ); - builder.verify_fri_proof::( - &fri_instance, - &proof_with_public_inputs - .proof - .openings - .to_fri_openings(zero), - &challenges.fri_challenges, - &merkle_caps, - &proof_with_public_inputs.proof.opening_proof, - &inner_config.fri_params(degree_bits), - ); -} - -fn eval_l_0_and_l_last_circuit, const D: usize>( - builder: &mut CircuitBuilder, - log_n: usize, - x: ExtensionTarget, - z_x: ExtensionTarget, -) -> (ExtensionTarget, ExtensionTarget) { - let n = builder.constant_extension(F::Extension::from_canonical_usize(1 << log_n)); - let g = builder.constant_extension(F::Extension::primitive_root_of_unity(log_n)); - let one = builder.one_extension(); - let l_0_deno = builder.mul_sub_extension(n, x, n); - let l_last_deno = builder.mul_sub_extension(g, x, one); - let l_last_deno = builder.mul_extension(n, l_last_deno); - - ( - builder.div_extension(z_x, l_0_deno), - builder.div_extension(z_x, l_last_deno), - ) + MozakStarkVerifierCircuit { circuit, targets } } pub fn add_virtual_stark_proof_with_pis< @@ -705,7 +577,7 @@ mod tests { public_inputs, &mut TimingTree::default(), )?; - verify_proof(&stark, mozak_proof.clone(), &config)?; + verify_proof(&stark, &mozak_proof.clone(), &config)?; let circuit_config = CircuitConfig::standard_recursion_config(); let mozak_stark_circuit = recursive_mozak_stark_circuit::( @@ -724,12 +596,14 @@ mod tests { &public_input_slice.into(); assert_eq!( recursive_proof_public_inputs.event_commitment_tape, expected_event_commitment_tape, - "Could not find expected_event_commitment_tape in recursive proof's public inputs" + "Could not find + expected_event_commitment_tape in recursive proof's public inputs" ); assert_eq!( recursive_proof_public_inputs.castlist_commitment_tape, expected_castlist_commitment_tape, - "Could not find expected_castlist_commitment_tape in recursive proof's public inputs" + "Could not find expected_castlist_commitment_tape in recursive + proof's public inputs" ); mozak_stark_circuit.circuit.verify(recursive_proof) @@ -801,9 +675,9 @@ mod tests { ); let recursion_proof1 = recursion_circuit1.prove(&mozak_proof1)?; - recursion_circuit0 - .circuit - .verify(recursion_proof0.clone())?; + // recursion_circuit0 + // .circuit + // .verify(recursion_proof0.clone())?; let public_inputs_size = recursion_proof0.public_inputs.len(); assert_eq!(VM_PUBLIC_INPUT_SIZE, public_inputs_size); diff --git a/circuits/src/stark/verifier.rs b/circuits/src/stark/verifier.rs index 5e70365cc..1d442f368 100644 --- a/circuits/src/stark/verifier.rs +++ b/circuits/src/stark/verifier.rs @@ -1,30 +1,22 @@ use std::borrow::Borrow; use anyhow::{ensure, Result}; -use itertools::Itertools; use log::debug; -use plonky2::field::extension::{Extendable, FieldExtension}; -use plonky2::field::types::Field; -use plonky2::fri::verifier::verify_fri_proof; +use plonky2::field::extension::Extendable; use plonky2::hash::hash_types::RichField; use plonky2::plonk::config::GenericConfig; -use plonky2::plonk::plonk_common::reduce_with_powers; use starky::config::StarkConfig; -use starky::constraint_consumer::ConstraintConsumer; -use starky::evaluation_frame::StarkEvaluationFrame; -use starky::stark::{LookupConfig, Stark}; +use starky::proof::MultiProof; +use starky::stark::Stark; use super::mozak_stark::{all_starks, MozakStark, TableKind, TableKindSetBuilder}; use super::proof::AllProof; -use crate::cross_table_lookup::{verify_cross_table_lookups_and_public_sub_tables, CtlCheckVars}; -use crate::public_sub_table::reduce_public_sub_tables_values; -use crate::stark::poly::eval_vanishing_poly; -use crate::stark::proof::{AllProofChallenges, StarkOpeningSet, StarkProof, StarkProofChallenges}; +use crate::stark::proof::AllProofChallenges; #[allow(clippy::too_many_lines)] pub fn verify_proof( mozak_stark: &MozakStark, - all_proof: AllProof, + all_proof: &AllProof, config: &StarkConfig, ) -> Result<()> where @@ -38,238 +30,65 @@ where } = all_proof.get_challenges(config); ensure!( - all_proof.proofs[TableKind::Program].trace_cap == all_proof.program_rom_trace_cap, + all_proof.proofs[TableKind::Program].proof.trace_cap == all_proof.program_rom_trace_cap, "Mismatch between Program ROM trace caps" ); ensure!( - all_proof.proofs[TableKind::ElfMemoryInit].trace_cap == all_proof.elf_memory_init_trace_cap, + all_proof.proofs[TableKind::ElfMemoryInit].proof.trace_cap + == all_proof.elf_memory_init_trace_cap, "Mismatch between ElfMemoryInit trace caps" ); - let ctl_vars_per_table = CtlCheckVars::from_proofs( - &all_proof.proofs, + let num_lookup_columns = all_starks!(mozak_stark, |stark, _kind| stark + .num_lookup_helper_columns(config)) + .0; + let multi_proof = MultiProof { + // TODO(Matthias): this is also a bit silly. But proofs are small-ish, and we only clone + // once. + stark_proofs: all_proof.proofs.0.clone(), + // TODO(Matthias): we only use the multi_proof once, and that usage doesn't actualyl read + // the ctl-challenges. That's probably a sloppiness in plonky2. + ctl_challenges: ctl_challenges.clone(), + }; + let ctl_vars_per_table = starky::cross_table_lookup::get_ctl_vars_from_proofs( + // &all_proof.proofs, + &multi_proof, &mozak_stark.cross_table_lookups, - &mozak_stark.public_sub_tables, &ctl_challenges, + &num_lookup_columns, + // TODO(Matthias): perhaps don't hardcode this? + 3, ); - let reduced_public_sub_tables_values = - reduce_public_sub_tables_values(&all_proof.public_sub_table_values, &ctl_challenges); - let public_inputs = TableKindSetBuilder::<&[_]> { cpu_stark: all_proof.public_inputs.borrow(), ..Default::default() } .build(); + // TODO(Matthias): we still need to make sure that all the challenges are + // correct, via our own observing etc. all_starks!(mozak_stark, |stark, kind| { - verify_stark_proof_with_challenges( + starky::verifier::verify_stark_proof_with_challenges( stark, - &all_proof.proofs[kind], + &all_proof.proofs.each_ref()[kind].proof, &stark_challenges[kind], + Some(&ctl_vars_per_table[kind as usize]), public_inputs[kind], - &ctl_vars_per_table[kind], config, - )?; + ) + .unwrap_or_else(|e| panic!("Failed to verify stark proof for {kind:?}: {e}")); }); - verify_cross_table_lookups_and_public_sub_tables::( + starky::cross_table_lookup::verify_cross_table_lookups( &mozak_stark.cross_table_lookups, - &mozak_stark.public_sub_tables, - &reduced_public_sub_tables_values, - &all_proof.all_ctl_zs_last(), + all_proof + .proofs + .each_ref() + .map(|p| p.proof.openings.ctl_zs_first.clone().unwrap()) + .0, + // TODO(Matthias): zk_evm uses this to simulate our pub sub mechanism in a different way. + None, config, )?; Ok(()) } - -pub(crate) fn verify_stark_proof_with_challenges< - F: RichField + Extendable, - C: GenericConfig, - S: Stark, - const D: usize, ->( - stark: &S, - proof: &StarkProof, - challenges: &StarkProofChallenges, - public_inputs: &[F], - ctl_vars: &[CtlCheckVars], - config: &StarkConfig, -) -> Result<()> -where -{ - validate_proof_shape(stark, proof, config, ctl_vars.len())?; - let StarkOpeningSet { - local_values, - next_values, - ctl_zs: _, - ctl_zs_next: _, - ctl_zs_last, - quotient_polys, - } = &proof.openings; - - let vars = S::EvaluationFrame::from_values( - local_values, - next_values, - &public_inputs - .iter() - .map(|pi| F::Extension::from_basefield(*pi)) - .collect_vec(), - ); - - let degree_bits = proof.recover_degree_bits(config); - let (l_0, l_last) = eval_l_0_and_l_last(degree_bits, challenges.stark_zeta); - let last = F::primitive_root_of_unity(degree_bits).inverse(); - let z_last = challenges.stark_zeta - last.into(); - let mut consumer = ConstraintConsumer::::new( - challenges - .stark_alphas - .iter() - .map(|&alpha| F::Extension::from_basefield(alpha)) - .collect::>(), - z_last, - l_0, - l_last, - ); - eval_vanishing_poly::( - stark, - &vars, - ctl_vars, - &mut consumer, - ); - let vanishing_polys_zeta = consumer.accumulators(); - - // Check each polynomial identity, of the form `vanishing(x) = Z_H(x) - // quotient(x)`, at zeta. - let zeta_pow_deg = challenges.stark_zeta.exp_power_of_2(degree_bits); - let z_h_zeta = zeta_pow_deg - F::Extension::ONE; - // `quotient_polys_zeta` holds `num_challenges * quotient_degree_factor` - // evaluations. Each chunk of `quotient_degree_factor` holds the evaluations - // of `t_0(zeta),...,t_{quotient_degree_factor-1}(zeta)` where the "real" - // quotient polynomial is `t(X) = t_0(X) + t_1(X)*X^n + t_2(X)*X^{2n} + ...`. - // So to reconstruct `t(zeta)` we can compute `reduce_with_powers(chunk, - // zeta^n)` for each `quotient_degree_factor`-sized chunk of the original - // evaluations. - for (i, chunk) in quotient_polys - .chunks(stark.quotient_degree_factor()) - .enumerate() - { - ensure!( - vanishing_polys_zeta[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg), - "Mismatch between evaluation and opening of quotient polynomial" - ); - } - - let merkle_caps = vec![ - proof.trace_cap.clone(), - proof.ctl_zs_cap.clone(), - proof.quotient_polys_cap.clone(), - ]; - - // Make sure that we do not use Starky's lookups. - assert!(!stark.requires_ctls()); - assert!(!stark.uses_lookups()); - verify_fri_proof::( - &stark.fri_instance( - challenges.stark_zeta, - F::primitive_root_of_unity(degree_bits), - 0, - vec![], - config, - Some(&LookupConfig { - degree_bits, - num_zs: ctl_zs_last.len(), - }), - ), - &proof.openings.to_fri_openings(), - &challenges.fri_challenges, - &merkle_caps, - &proof.opening_proof, - &config.fri_params(degree_bits), - )?; - - Ok(()) -} - -fn validate_proof_shape( - stark: &S, - proof: &StarkProof, - config: &StarkConfig, - num_ctl_zs: usize, -) -> anyhow::Result<()> -where - F: RichField + Extendable, - C: GenericConfig, - S: Stark, { - let StarkProof { - trace_cap, - ctl_zs_cap, - quotient_polys_cap, - openings, - // The shape of the opening proof will be checked in the FRI verifier (see - // validate_fri_proof_shape), so we ignore it here. - opening_proof: _, - } = proof; - - let StarkOpeningSet { - local_values, - next_values, - ctl_zs, - ctl_zs_next, - ctl_zs_last, - quotient_polys, - } = openings; - - let degree_bits = proof.recover_degree_bits(config); - let fri_params = config.fri_params(degree_bits); - let cap_height = fri_params.config.cap_height; - - ensure!(trace_cap.height() == cap_height); - ensure!(ctl_zs_cap.height() == cap_height); - ensure!(quotient_polys_cap.height() == cap_height); - - ensure!(local_values.len() == S::COLUMNS); - ensure!(next_values.len() == S::COLUMNS); - ensure!(ctl_zs.len() == num_ctl_zs); - ensure!(ctl_zs_next.len() == num_ctl_zs); - ensure!(ctl_zs_last.len() == num_ctl_zs); - ensure!(quotient_polys.len() == stark.num_quotient_polys(config)); - - Ok(()) -} - -/// Evaluate the Lagrange polynomials `L_0` and `L_(n-1)` at a point `x`. -/// `L_0(x) = (x^n - 1)/(n * (x - 1))` -/// `L_(n-1)(x) = (x^n - 1)/(n * (g * x - 1))`, with `g` the first element of -/// the subgroup. -fn eval_l_0_and_l_last(log_n: usize, x: F) -> (F, F) { - let n = F::from_canonical_usize(1 << log_n); - let g = F::primitive_root_of_unity(log_n); - let z_x = x.exp_power_of_2(log_n) - F::ONE; - let invs = F::batch_multiplicative_inverse(&[n * (x - F::ONE), n * (g * x - F::ONE)]); - - (z_x * invs[0], z_x * invs[1]) -} - -#[cfg(test)] -mod tests { - use plonky2::field::goldilocks_field::GoldilocksField; - use plonky2::field::polynomial::PolynomialValues; - use plonky2::field::types::Sample; - - use crate::stark::verifier::eval_l_0_and_l_last; - - #[test] - fn test_eval_l_0_and_l_last() { - type F = GoldilocksField; - let log_n = 5; - let n = 1 << log_n; - - let x = F::rand(); // challenge point - let expected_l_first_x = PolynomialValues::selector(n, 0).ifft().eval(x); - let expected_l_last_x = PolynomialValues::selector(n, n - 1).ifft().eval(x); - - let (l_first_x, l_last_x) = eval_l_0_and_l_last(log_n, x); - assert_eq!(l_first_x, expected_l_first_x); - assert_eq!(l_last_x, expected_l_last_x); - } -} diff --git a/circuits/src/tape_commitments/columns.rs b/circuits/src/tape_commitments/columns.rs index 8fde7db4e..2302dd81e 100644 --- a/circuits/src/tape_commitments/columns.rs +++ b/circuits/src/tape_commitments/columns.rs @@ -1,8 +1,5 @@ -use mozak_sdk::core::ecall::COMMITMENT_SIZE; - use crate::columns_view::{columns_view_impl, make_col_map}; use crate::linear_combination::Column; -use crate::public_sub_table::PublicSubTable; use crate::stark::mozak_stark::{TableWithTypedOutput, TapeCommitmentsTable}; make_col_map!(TAPE_COMMITMENTS, TapeCommitments); @@ -61,25 +58,3 @@ pub fn lookup_for_event_tape_commitment() -> TableWithTypedOutput PublicSubTable { - PublicSubTable { - table: TapeCommitmentsTable::new( - vec![TAPE_COMMITMENTS.commitment_byte_row.byte], - TAPE_COMMITMENTS.is_event_commitment_tape_row, - ), - num_rows: COMMITMENT_SIZE, - } -} - -#[must_use] -pub fn make_castlist_commitment_tape_public() -> PublicSubTable { - PublicSubTable { - table: TapeCommitmentsTable::new( - vec![TAPE_COMMITMENTS.commitment_byte_row.byte], - TAPE_COMMITMENTS.is_castlist_commitment_tape_row, - ), - num_rows: COMMITMENT_SIZE, - } -} diff --git a/circuits/src/tape_commitments/stark.rs b/circuits/src/tape_commitments/stark.rs index 08202cfda..6b681f42c 100644 --- a/circuits/src/tape_commitments/stark.rs +++ b/circuits/src/tape_commitments/stark.rs @@ -36,6 +36,7 @@ fn generate_constraints<'a, T: Copy>( #[allow(clippy::module_name_repetitions)] pub struct TapeCommitmentsStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for TapeCommitmentsStark { @@ -54,6 +55,8 @@ impl, const D: usize> Stark for TapeCommitmen type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -89,23 +92,13 @@ mod tests { use mozak_runner::instruction::{Args, Instruction, Op}; use mozak_sdk::core::ecall::{self, COMMITMENT_SIZE}; use mozak_sdk::core::reg_abi::{REG_A0, REG_A1, REG_A2}; - use plonky2::field::types::Field; - use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::plonk::config::{GenericConfig, Poseidon2GoldilocksConfig}; - use plonky2::util::timing::TimingTree; use rand::Rng; - use starky::config::StarkConfig; use starky::stark_testing::test_stark_circuit_constraints; use super::TapeCommitmentsStark; - use crate::stark::mozak_stark::{MozakStark, PublicInputs}; - use crate::stark::prover::prove; - use crate::stark::recursive_verifier::{ - recursive_mozak_stark_circuit, VMRecursiveProofPublicInputs, VM_PUBLIC_INPUT_SIZE, - }; - use crate::stark::verifier::verify_proof; + use crate::stark::mozak_stark::MozakStark; use crate::test_utils::ProveAndVerify; - use crate::utils::from_u32; const D: usize = 2; type C = Poseidon2GoldilocksConfig; @@ -195,63 +188,67 @@ mod tests { #[test] fn test_tape_commitment_recursive_prover() -> Result<(), anyhow::Error> { - let mut rng = rand::thread_rng(); - // generate tapes with random bytes - let cast_list_commitment_tape: [u8; COMMITMENT_SIZE] = rng.gen(); - let events_commitment_tape: [u8; COMMITMENT_SIZE] = rng.gen(); - let code = io_read_tape_commitments_code(); - let (program, record) = - code::execute_code_with_ro_memory(code, &[], &[], &[], RuntimeArguments { - events_commitment_tape, - cast_list_commitment_tape, - ..Default::default() - }); - let stark = MozakStark::::default(); - let config = StarkConfig::standard_fast_config(); - let public_inputs = PublicInputs { - entry_point: from_u32(program.entry_point), - }; - let mozak_proof = prove::( - &program, - &record, - &stark, - &config, - public_inputs, - &mut TimingTree::default(), - )?; - verify_proof(&stark, mozak_proof.clone(), &config)?; + todo!() + // let mut rng = rand::thread_rng(); + // // generate tapes with random bytes + // let cast_list_commitment_tape: [u8; COMMITMENT_SIZE] = rng.gen(); + // let events_commitment_tape: [u8; COMMITMENT_SIZE] = rng.gen(); + // let code = io_read_tape_commitments_code(); + // let (program, record) = + // code::execute_code_with_ro_memory(code, &[], &[], &[], + // RuntimeArguments { events_commitment_tape, + // cast_list_commitment_tape, + // ..Default::default() + // }); + // let stark = MozakStark::::default(); + // let config = StarkConfig::standard_fast_config(); + // let public_inputs = PublicInputs { + // entry_point: from_u32(program.entry_point), + // }; + // let mozak_proof = prove::( + // &program, + // &record, + // &stark, + // &config, + // public_inputs, + // &mut TimingTree::default(), + // )?; + // verify_proof(&stark, mozak_proof.clone(), &config)?; - let circuit_config = CircuitConfig::standard_recursion_config(); - let mozak_stark_circuit = recursive_mozak_stark_circuit::( - &stark, - &mozak_proof.degree_bits(&config), - &circuit_config, - &config, - ); + // let circuit_config = CircuitConfig::standard_recursion_config(); + // let mozak_stark_circuit = recursive_mozak_stark_circuit::( + // &stark, + // &mozak_proof.degree_bits(&config), + // &circuit_config, + // &config, + // ); - let recursive_proof = mozak_stark_circuit.prove(&mozak_proof)?; - let public_input_slice: [F; VM_PUBLIC_INPUT_SIZE] = - recursive_proof.public_inputs.as_slice().try_into().unwrap(); - let recursive_proof_public_inputs: &VMRecursiveProofPublicInputs = - &public_input_slice.into(); + // let recursive_proof = mozak_stark_circuit.prove(&mozak_proof)?; + // let public_input_slice: [F; VM_PUBLIC_INPUT_SIZE] = + // recursive_proof.public_inputs.as_slice().try_into().unwrap(); + // let recursive_proof_public_inputs: &VMRecursiveProofPublicInputs = + // &public_input_slice.into(); - // assert that the commitment tapes match those in pubilc inputs - assert_eq!( - recursive_proof_public_inputs.event_commitment_tape, - events_commitment_tape.map(F::from_canonical_u8), - "Mismatch in events commitment tape in public inputs" - ); - assert_eq!( - recursive_proof_public_inputs.castlist_commitment_tape, - cast_list_commitment_tape.map(F::from_canonical_u8), - "Mismatch in cast list commitment tape in public inputs" - ); - mozak_stark_circuit.circuit.verify(recursive_proof) + // // assert that the commitment tapes match those in pubilc inputs + // assert_eq!( + // recursive_proof_public_inputs.event_commitment_tape, + // events_commitment_tape.map(F::from_canonical_u8), + // "Mismatch in events commitment tape in public inputs" + // ); + // assert_eq!( + // recursive_proof_public_inputs.castlist_commitment_tape, + // cast_list_commitment_tape.map(F::from_canonical_u8), + // "Mismatch in cast list commitment tape in public inputs" + // ); + // mozak_stark_circuit.circuit.verify(recursive_proof) } #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/circuits/src/test_utils.rs b/circuits/src/test_utils.rs index 221c795ea..ebf15dc39 100644 --- a/circuits/src/test_utils.rs +++ b/circuits/src/test_utils.rs @@ -126,7 +126,11 @@ impl ProveAndVerify for CpuStark { let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; + let trace_poly_values = trace_rows_to_poly_values(generate_cpu_trace(record)); let public_inputs: PublicInputs = PublicInputs { entry_point: from_u32(program.entry_point), @@ -149,7 +153,10 @@ impl ProveAndVerify for RangeCheckStark { let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let cpu_trace = generate_cpu_trace(record); let memory_init = generate_memory_init_trace(program); @@ -213,7 +220,10 @@ impl ProveAndVerify for XorStark { let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let cpu_trace = generate_cpu_trace(record); let trace_poly_values = trace_rows_to_poly_values(generate_xor_trace(&cpu_trace)); let proof = prove_table::( @@ -233,7 +243,10 @@ impl ProveAndVerify for MemoryStark { type S = MemoryStark; let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let memory_init = generate_memory_init_trace(program); let memory_zeroinit_rows = generate_memory_zero_init_trace(&record.executed, program); @@ -279,7 +292,10 @@ impl ProveAndVerify for HalfWordMemoryStark { type S = HalfWordMemoryStark; let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let trace_poly_values = trace_rows_to_poly_values(generate_halfword_memory_trace(&record.executed)); let proof = prove_table::( @@ -299,7 +315,10 @@ impl ProveAndVerify for FullWordMemoryStark { type S = FullWordMemoryStark; let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let trace_poly_values = trace_rows_to_poly_values(generate_fullword_memory_trace(&record.executed)); let proof = prove_table::( @@ -319,7 +338,10 @@ impl ProveAndVerify for StorageDeviceStark { type S = StorageDeviceStark; let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let trace_poly_values = trace_rows_to_poly_values(generate_io_memory_private_trace(&record.executed)); let proof = prove_table::( @@ -339,7 +361,10 @@ impl ProveAndVerify for BitshiftStark { type S = BitshiftStark; let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let cpu_rows = generate_cpu_trace::(record); let trace = generate_shift_amount_trace(&cpu_rows); let trace_poly_values = trace_rows_to_poly_values(trace); @@ -360,7 +385,10 @@ impl ProveAndVerify for RegisterInitStark { type S = RegisterInitStark; let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let trace = generate_register_init_trace::(record); let trace_poly_values = trace_rows_to_poly_values(trace); let proof = prove_table::( @@ -380,7 +408,10 @@ impl ProveAndVerify for RegisterStark { type S = RegisterStark; let config = fast_test_config(); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let cpu_trace = generate_cpu_trace(record); let io_memory_private = generate_io_memory_private_trace(&record.executed); let io_memory_public = generate_io_memory_public_trace(&record.executed); @@ -417,7 +448,10 @@ impl ProveAndVerify for RegisterStark { impl ProveAndVerify for TapeCommitmentsStark { fn prove_and_verify(_program: &Program, record: &ExecutionRecord) -> Result<()> { type S = TapeCommitmentsStark; - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let config = fast_test_config(); let trace = generate_tape_commitments_trace(record); let trace_poly_values = trace_rows_to_poly_values(trace); @@ -467,7 +501,7 @@ pub fn prove_and_verify_mozak_stark( public_inputs, &mut TimingTree::default(), )?; - verify_proof(&stark, all_proof, config) + verify_proof(&stark, &all_proof, config) } /// Interpret a u64 as a field element and try to invert it. diff --git a/circuits/src/unstark.rs b/circuits/src/unstark.rs index 3efcc5595..8802fd2e9 100644 --- a/circuits/src/unstark.rs +++ b/circuits/src/unstark.rs @@ -20,6 +20,7 @@ use crate::columns_view::{columns_view_impl, HasNamedColumns, NumberOfColumns}; pub struct Unstark { pub _f: PhantomData, pub _d: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns @@ -45,6 +46,8 @@ impl< type EvaluationFrameTarget = StarkFrame, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, _vars: &Self::EvaluationFrame, diff --git a/circuits/src/utils.rs b/circuits/src/utils.rs index aaf9800f7..302b27715 100644 --- a/circuits/src/utils.rs +++ b/circuits/src/utils.rs @@ -49,7 +49,7 @@ pub fn pad_trace_with_default(trace: Vec) -> Vec } #[must_use] -pub(crate) fn from_u32(x: u32) -> F { Field::from_noncanonical_u64(x.into()) } +pub(crate) fn from_u32(x: u32) -> F { Field::from_canonical_u32(x) } #[must_use] #[allow(clippy::cast_possible_wrap)] diff --git a/circuits/src/xor/stark.rs b/circuits/src/xor/stark.rs index ec0effe44..f65af2a4c 100644 --- a/circuits/src/xor/stark.rs +++ b/circuits/src/xor/stark.rs @@ -21,6 +21,7 @@ use crate::unstark::NoColumns; #[allow(clippy::module_name_repetitions)] pub struct XorStark { pub _f: PhantomData, + pub standalone_proving: bool, } impl HasNamedColumns for XorStark { @@ -67,6 +68,8 @@ impl, const D: usize> Stark for XorStark, ExtensionTarget, COLUMNS, PUBLIC_INPUTS>; + fn requires_ctls(&self) -> bool { !self.standalone_proving } + fn eval_packed_generic( &self, vars: &Self::EvaluationFrame, @@ -113,7 +116,10 @@ mod tests { type S = XorStark; #[test] fn test_degree() -> Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_low_degree(stark) } @@ -158,7 +164,10 @@ mod tests { let cpu_trace = generate_cpu_trace(&record); let trace = timed!(timing, "generate_xor_trace", generate_xor_trace(&cpu_trace)); let trace_poly_values = timed!(timing, "trace to poly", trace_rows_to_poly_values(trace)); - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; let proof = timed!( timing, @@ -190,7 +199,10 @@ mod tests { #[test] fn test_circuit() -> anyhow::Result<()> { - let stark = S::default(); + let stark = S { + standalone_proving: true, + ..S::default() + }; test_stark_circuit_constraints::(stark)?; Ok(()) diff --git a/cli/src/main.rs b/cli/src/main.rs index 314e8d1fd..6715fdea4 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -368,8 +368,11 @@ fn main() -> Result<()> { let mut buffer: Vec = vec![]; proof.read_to_end(&mut buffer)?; let all_proof: AllProof = serde_json::from_slice(&buffer)?; - verify_proof(&stark, all_proof, &config)?; - println!("proof verified successfully!"); + verify_proof(&stark, &all_proof, &config)?; + println!( + "proof verified + successfully!" + ); } Command::VerifyRecursiveProof { mut proof, diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 4da2f39a7..23b78edc7 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -435,8 +435,8 @@ dependencies = [ [[package]] name = "plonky2" -version = "0.2.1" -source = "git+https://github.com/0xmozak/plonky2.git#51f540a0e2a9bd9d6fc6234c6e62d167eaa7c707" +version = "0.2.2" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#b550351ad1a5a61f8ffc4483c3f15bd0645b3cc1" dependencies = [ "ahash", "anyhow", @@ -457,8 +457,8 @@ dependencies = [ [[package]] name = "plonky2_field" -version = "0.2.1" -source = "git+https://github.com/0xmozak/plonky2.git#51f540a0e2a9bd9d6fc6234c6e62d167eaa7c707" +version = "0.2.2" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#b550351ad1a5a61f8ffc4483c3f15bd0645b3cc1" dependencies = [ "anyhow", "itertools", @@ -473,12 +473,12 @@ dependencies = [ [[package]] name = "plonky2_maybe_rayon" version = "0.2.0" -source = "git+https://github.com/0xmozak/plonky2.git#51f540a0e2a9bd9d6fc6234c6e62d167eaa7c707" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#b550351ad1a5a61f8ffc4483c3f15bd0645b3cc1" [[package]] name = "plonky2_util" version = "0.2.0" -source = "git+https://github.com/0xmozak/plonky2.git#51f540a0e2a9bd9d6fc6234c6e62d167eaa7c707" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#b550351ad1a5a61f8ffc4483c3f15bd0645b3cc1" [[package]] name = "ppv-lite86" @@ -723,9 +723,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "2.0.59" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -796,9 +796,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", "serde", diff --git a/sdk/Cargo.lock b/sdk/Cargo.lock index 8847c2bca..f3570df7f 100644 --- a/sdk/Cargo.lock +++ b/sdk/Cargo.lock @@ -308,8 +308,8 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "plonky2" -version = "0.2.1" -source = "git+https://github.com/0xmozak/plonky2.git#51f540a0e2a9bd9d6fc6234c6e62d167eaa7c707" +version = "0.2.2" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#b550351ad1a5a61f8ffc4483c3f15bd0645b3cc1" dependencies = [ "ahash", "anyhow", @@ -330,8 +330,8 @@ dependencies = [ [[package]] name = "plonky2_field" -version = "0.2.1" -source = "git+https://github.com/0xmozak/plonky2.git#51f540a0e2a9bd9d6fc6234c6e62d167eaa7c707" +version = "0.2.2" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#b550351ad1a5a61f8ffc4483c3f15bd0645b3cc1" dependencies = [ "anyhow", "itertools", @@ -346,12 +346,12 @@ dependencies = [ [[package]] name = "plonky2_maybe_rayon" version = "0.2.0" -source = "git+https://github.com/0xmozak/plonky2.git#51f540a0e2a9bd9d6fc6234c6e62d167eaa7c707" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#b550351ad1a5a61f8ffc4483c3f15bd0645b3cc1" [[package]] name = "plonky2_util" version = "0.2.0" -source = "git+https://github.com/0xmozak/plonky2.git#51f540a0e2a9bd9d6fc6234c6e62d167eaa7c707" +source = "git+https://github.com/0xmozak/plonky2.git?branch=matthias/looked-tables#b550351ad1a5a61f8ffc4483c3f15bd0645b3cc1" [[package]] name = "ppv-lite86" @@ -554,9 +554,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "2.0.59" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -616,9 +616,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", "serde", diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 18b1d0f90..a669c7080 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -20,7 +20,8 @@ slice-group-by = { version = "0.3", default-features = false, features = ["night [target.'cfg(not(target_os="mozakvm"))'.dependencies] hex = "0.4" -plonky2 = { git = "https://github.com/0xmozak/plonky2.git", default-features = false } +# plonky2 = { path = "../../plonky2/plonky2" } +plonky2 = { git = "https://github.com/0xmozak/plonky2.git", branch = "matthias/looked-tables", default-features = false } rand = "0.8" rand_chacha = "0.3" serde = { version = "1.0", features = ["derive"] }