From 309c74dcfb9e5e3bbede5e89350b7772679e3e13 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Fri, 10 Jan 2025 16:34:34 +0000 Subject: [PATCH 01/16] Add placeholders for lookup state --- o1vm/src/interpreters/mips/witness.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/o1vm/src/interpreters/mips/witness.rs b/o1vm/src/interpreters/mips/witness.rs index ff328c8802..95ecc0fb9f 100644 --- a/o1vm/src/interpreters/mips/witness.rs +++ b/o1vm/src/interpreters/mips/witness.rs @@ -92,6 +92,8 @@ pub struct Env { pub scratch_state_idx_inverse: usize, pub scratch_state: [Fp; SCRATCH_SIZE], pub scratch_state_inverse: [Fp; SCRATCH_SIZE_INVERSE], + pub lookup_state_idx: usize, + pub lookup_state: Vec, pub halt: bool, pub syscall_env: SyscallEnv, pub selector: usize, @@ -915,6 +917,8 @@ impl Env { scratch_state_idx_inverse: 0, scratch_state: fresh_scratch_state(), scratch_state_inverse: fresh_scratch_state(), + lookup_state_idx: 0, + lookup_state: vec![], halt: state.exited, syscall_env, selector, @@ -947,6 +951,11 @@ impl Env { self.scratch_state_inverse = fresh_scratch_state(); } + pub fn reset_lookup_state(&mut self) { + self.lookup_state_idx = 0; + self.lookup_state = vec![]; + } + pub fn write_column(&mut self, column: Column, value: u64) { self.write_field_column(column, value.into()) } @@ -1190,6 +1199,7 @@ impl Env { ) -> Instruction { self.reset_scratch_state(); self.reset_scratch_state_inverse(); + self.reset_lookup_state(); let (opcode, _instruction) = self.decode_instruction(); self.pp_info(&config.info_at, metadata, start); From dd844cc43a46c81d6d68898032be9fcb5477b029 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 11 Jan 2025 17:29:16 +0000 Subject: [PATCH 02/16] Add type parameter to Column --- ivc/src/expr_eval.rs | 10 +++++----- ivc/src/ivc/columns.rs | 2 +- ivc/src/plonkish_lang.rs | 6 +++--- ivc/src/poseidon_55_0_7_3_2/columns.rs | 2 +- ivc/src/poseidon_55_0_7_3_7/columns.rs | 2 +- ivc/src/poseidon_8_56_5_3_2/columns.rs | 2 +- ivc/src/prover.rs | 4 ++-- ivc/src/verifier.rs | 2 +- msm/src/circuit_design/constraints.rs | 2 +- msm/src/circuit_design/witness.rs | 2 +- msm/src/column_env.rs | 2 +- msm/src/columns.rs | 14 +++++++------- msm/src/expr.rs | 6 +++--- msm/src/fec/columns.rs | 8 ++++---- msm/src/ffa/columns.rs | 2 +- msm/src/logup.rs | 4 ++-- msm/src/proof.rs | 2 +- msm/src/serialization/column.rs | 2 +- msm/src/test/test_circuit/columns.rs | 2 +- o1vm/src/interpreters/keccak/column.rs | 4 ++-- o1vm/src/interpreters/mips/column.rs | 4 ++-- o1vm/src/lib.rs | 2 +- o1vm/src/pickles/column_env.rs | 11 ++++++----- o1vm/src/pickles/verifier.rs | 2 +- 24 files changed, 50 insertions(+), 49 deletions(-) diff --git a/ivc/src/expr_eval.rs b/ivc/src/expr_eval.rs index 7fffa1af36..3e15ded8af 100644 --- a/ivc/src/expr_eval.rs +++ b/ivc/src/expr_eval.rs @@ -23,10 +23,10 @@ use strum::EnumCount; /// Generic structure containing column vectors. pub struct GenericVecStructure(pub Vec>); -impl Index for GenericVecStructure { +impl Index> for GenericVecStructure { type Output = [G::ScalarField]; - fn index(&self, index: GenericColumn) -> &Self::Output { + fn index(&self, index: GenericColumn) -> &Self::Output { match index { GenericColumn::FixedSelector(i) => &self.0[i], _ => panic!("should not happen"), @@ -73,7 +73,7 @@ impl< } pub fn process_extended_folding_column< - FC: FoldingConfig, + FC: FoldingConfig, Curve = Curve, Challenge = PlonkishChallenge>, >( &self, col: &ExtendedFoldingColumn, @@ -105,7 +105,7 @@ impl< /// Evaluates the expression in the provided side pub fn eval_naive_fexpr< 'a, - FC: FoldingConfig, + FC: FoldingConfig, Curve = Curve, Challenge = PlonkishChallenge>, >( &'a self, exp: &FoldingExp, @@ -136,7 +136,7 @@ impl< /// For FoldingCompatibleExp pub fn eval_naive_fcompat< 'a, - FC: FoldingConfig, + FC: FoldingConfig, Curve = Curve, Challenge = PlonkishChallenge>, >( &'a self, exp: &FoldingCompatibleExpr, diff --git a/ivc/src/ivc/columns.rs b/ivc/src/ivc/columns.rs index 4a3311a2ea..2d0c1ef948 100644 --- a/ivc/src/ivc/columns.rs +++ b/ivc/src/ivc/columns.rs @@ -391,7 +391,7 @@ impl ColumnIndexer for IVCColumn { // We also add 1 for the FoldIteration column. const N_COL: usize = IVCPoseidonColumn::N_COL + 1 + N_BLOCKS; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { // We keep a column that will be used for the folding iteration. // Question: do we need it for all the rows or does it appear only diff --git a/ivc/src/plonkish_lang.rs b/ivc/src/plonkish_lang.rs index 4cfcc8cd0a..2a71b1df7e 100644 --- a/ivc/src/plonkish_lang.rs +++ b/ivc/src/plonkish_lang.rs @@ -75,13 +75,13 @@ impl< { } -impl> Index - for PlonkishWitnessGeneric +impl> + Index> for PlonkishWitnessGeneric { type Output = [F]; /// Map a column alias to the corresponding witness column. - fn index(&self, index: Column) -> &Self::Output { + fn index(&self, index: Column) -> &Self::Output { match index { Column::Relation(i) => self.witness.cols[i].e_as_slice(), Column::FixedSelector(i) => self.fixed_selectors[i].e_as_slice(), diff --git a/ivc/src/poseidon_55_0_7_3_2/columns.rs b/ivc/src/poseidon_55_0_7_3_2/columns.rs index c9a6791422..69a0d7078d 100644 --- a/ivc/src/poseidon_55_0_7_3_2/columns.rs +++ b/ivc/src/poseidon_55_0_7_3_2/columns.rs @@ -42,7 +42,7 @@ impl ColumnIndexer // - STATE_SIZE * NB_FULL_ROUND constants const N_COL: usize = STATE_SIZE + 5 * NB_FULL_ROUND * STATE_SIZE; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { PoseidonColumn::Input(i) => { assert!(i < STATE_SIZE); diff --git a/ivc/src/poseidon_55_0_7_3_7/columns.rs b/ivc/src/poseidon_55_0_7_3_7/columns.rs index cf62625369..2631f85f59 100644 --- a/ivc/src/poseidon_55_0_7_3_7/columns.rs +++ b/ivc/src/poseidon_55_0_7_3_7/columns.rs @@ -25,7 +25,7 @@ impl ColumnIndexer { const N_COL: usize = STATE_SIZE + NB_FULL_ROUND * STATE_SIZE; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { PoseidonColumn::Input(i) => { assert!(i < STATE_SIZE); diff --git a/ivc/src/poseidon_8_56_5_3_2/columns.rs b/ivc/src/poseidon_8_56_5_3_2/columns.rs index c5893aab51..c60e3f9d69 100644 --- a/ivc/src/poseidon_8_56_5_3_2/columns.rs +++ b/ivc/src/poseidon_8_56_5_3_2/columns.rs @@ -54,7 +54,7 @@ impl Column { + fn to_column(self) -> Column { // number of reductions for // x -> x^2 -> x^4 -> x^5 -> x^5 * MDS let nb_red = 4; diff --git a/ivc/src/prover.rs b/ivc/src/prover.rs index 8e318ad7a7..f9c2eefaaa 100644 --- a/ivc/src/prover.rs +++ b/ivc/src/prover.rs @@ -91,7 +91,7 @@ impl< F: Clone, > ColumnEvaluations for ProofEvaluations { - type Column = kimchi_msm::columns::Column; + type Column = kimchi_msm::columns::Column; fn evaluate(&self, col: Self::Column) -> Result, ExprError> { // TODO: substitute when non-literal generic constants are available @@ -147,7 +147,7 @@ pub struct Proof< pub fn prove< EFqSponge: Clone + FqSponge, EFrSponge: FrSponge, - FC: FoldingConfig, + FC: FoldingConfig, Curve = G, Challenge = PlonkishChallenge>, RNG, const N_WIT: usize, const N_WIT_QUAD: usize, // witness columns + quad columns diff --git a/ivc/src/verifier.rs b/ivc/src/verifier.rs index acec3e5f6f..9ccc5a3ad3 100644 --- a/ivc/src/verifier.rs +++ b/ivc/src/verifier.rs @@ -40,7 +40,7 @@ pub type Fq = ark_bn254::Fq; pub fn verify< EFqSponge: Clone + FqSponge, EFrSponge: FrSponge, - FC: FoldingConfig, + FC: FoldingConfig, Curve = G, Challenge = PlonkishChallenge>, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, diff --git a/msm/src/circuit_design/constraints.rs b/msm/src/circuit_design/constraints.rs index d9bd7396af..cca3c6d7cf 100644 --- a/msm/src/circuit_design/constraints.rs +++ b/msm/src/circuit_design/constraints.rs @@ -15,7 +15,7 @@ use crate::{ pub struct ConstraintBuilderEnv { /// An indexed set of constraints. - pub constraints: Vec, Column>>, + pub constraints: Vec, Column>>, /// Aggregated lookups or "reads". pub lookup_reads: BTreeMap>>>, /// Aggregated "write" lookups, for runtime tables. diff --git a/msm/src/circuit_design/witness.rs b/msm/src/circuit_design/witness.rs index 7266594f6b..43136ba786 100644 --- a/msm/src/circuit_design/witness.rs +++ b/msm/src/circuit_design/witness.rs @@ -284,7 +284,7 @@ impl< LT: LookupTableID, > WitnessBuilderEnv { - pub fn write_column_raw(&mut self, position: Column, value: F) { + pub fn write_column_raw(&mut self, position: Column, value: F) { match position { Column::Relation(i) => self.witness.last_mut().unwrap().cols[i] = value, Column::FixedSelector(_) => { diff --git a/msm/src/column_env.rs b/msm/src/column_env.rs index 808ac598ba..0aead85667 100644 --- a/msm/src/column_env.rs +++ b/msm/src/column_env.rs @@ -54,7 +54,7 @@ impl< > TColumnEnvironment<'a, F, BerkeleyChallengeTerm, BerkeleyChallenges> for ColumnEnvironment<'a, N_WIT, N_REL, N_DSEL, N_FSEL, F, ID> { - type Column = crate::columns::Column; + type Column = crate::columns::Column; fn get_column( &self, diff --git a/msm/src/columns.rs b/msm/src/columns.rs index eef53a5035..f221eb8ec0 100644 --- a/msm/src/columns.rs +++ b/msm/src/columns.rs @@ -5,9 +5,9 @@ use kimchi::circuits::expr::{CacheId, FormattedOutput}; /// Describe a generic indexed variable X_{i}. #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] -pub enum Column { +pub enum Column { /// Columns related to the relation encoded in the circuit - Relation(usize), + Relation(T), /// Columns related to dynamic selectors to indicate gate type DynamicSelector(usize), /// Constant column that is /always/ fixed for a given circuit. @@ -25,9 +25,9 @@ pub enum Column { LookupFixedTable(u32), } -impl Column { +impl Column { /// Adds offset if the column is `Relation`. Fails otherwise. - pub fn add_rel_offset(self, offset: usize) -> Column { + pub fn add_rel_offset(self, offset: usize) -> Column { let Column::Relation(i) = self else { todo!("add_rel_offset is only implemented for the relation columns") }; @@ -35,7 +35,7 @@ impl Column { } } -impl FormattedOutput for Column { +impl FormattedOutput for Column { fn latex(&self, _cache: &mut HashMap) -> String { match self { Column::Relation(i) => format!("x_{{{i}}}"), @@ -78,12 +78,12 @@ pub trait ColumnIndexer: core::fmt::Debug + Copy + Eq + Ord { const N_COL: usize; /// Flatten the column "alias" into the integer-like column. - fn to_column(self) -> Column; + fn to_column(self) -> Column; } // Implementation to be compatible with folding if we use generic column // constraints -impl FoldingColumnTrait for Column { +impl FoldingColumnTrait for Column { fn is_witness(&self) -> bool { match self { // Witness diff --git a/msm/src/expr.rs b/msm/src/expr.rs index 48f0d6e4d9..6b352981e4 100644 --- a/msm/src/expr.rs +++ b/msm/src/expr.rs @@ -48,16 +48,16 @@ use crate::columns::Column; /// ``` /// A list of such constraints is used to represent the entire circuit and will /// be used to build the quotient polynomial. -pub type E = Expr, Column>; +pub type E = Expr, Column>; -pub fn curr_cell(col: Column) -> E { +pub fn curr_cell(col: Column) -> E { E::Atom(ExprInner::Cell(Variable { col, row: CurrOrNext::Curr, })) } -pub fn next_cell(col: Column) -> E { +pub fn next_cell(col: Column) -> E { E::Atom(ExprInner::Cell(Variable { col, row: CurrOrNext::Next, diff --git a/msm/src/fec/columns.rs b/msm/src/fec/columns.rs index 1d6c0d2267..30331a0d5e 100644 --- a/msm/src/fec/columns.rs +++ b/msm/src/fec/columns.rs @@ -53,7 +53,7 @@ pub enum FECColumn { impl ColumnIndexer for FECColumnInput { const N_COL: usize = 4 * N_LIMBS_LARGE; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { FECColumnInput::XP(i) => { assert!(i < N_LIMBS_LARGE); @@ -77,7 +77,7 @@ impl ColumnIndexer for FECColumnInput { impl ColumnIndexer for FECColumnOutput { const N_COL: usize = 2 * N_LIMBS_SMALL; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { FECColumnOutput::XR(i) => { assert!(i < N_LIMBS_SMALL); @@ -93,7 +93,7 @@ impl ColumnIndexer for FECColumnOutput { impl ColumnIndexer for FECColumnInter { const N_COL: usize = 4 * N_LIMBS_LARGE + 10 * N_LIMBS_SMALL + 9; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { FECColumnInter::F(i) => { assert!(i < N_LIMBS_LARGE); @@ -148,7 +148,7 @@ impl ColumnIndexer for FECColumnInter { impl ColumnIndexer for FECColumn { const N_COL: usize = FEC_N_COLUMNS; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { FECColumn::Input(input) => input.to_column(), FECColumn::Inter(inter) => inter.to_column().add_rel_offset(FECColumnInput::N_COL), diff --git a/msm/src/ffa/columns.rs b/msm/src/ffa/columns.rs index 9d06b45ef6..a2583b505c 100644 --- a/msm/src/ffa/columns.rs +++ b/msm/src/ffa/columns.rs @@ -22,7 +22,7 @@ pub enum FFAColumn { impl ColumnIndexer for FFAColumn { const N_COL: usize = FFA_N_COLUMNS; - fn to_column(self) -> Column { + fn to_column(self) -> Column { let to_column_inner = |offset, i| { assert!(i < N_LIMBS); Column::Relation(N_LIMBS * offset + i) diff --git a/msm/src/logup.rs b/msm/src/logup.rs index f38c2ff171..a953dd1ad6 100644 --- a/msm/src/logup.rs +++ b/msm/src/logup.rs @@ -349,7 +349,7 @@ impl<'lt, G, ID: LookupTableID> IntoIterator for &'lt LookupProof { /// h(X) * (β + t(X)) * (β + f(X)) = (β + t(X)) + m(X) * (β + f(X)) /// ``` pub fn combine_lookups( - column: Column, + column: Column, lookups: Vec, ID>>, ) -> E { let joint_combiner = { @@ -419,7 +419,7 @@ pub fn constraint_lookups( lookup_writes: &BTreeMap>>>, ) -> Vec> { let mut constraints: Vec> = vec![]; - let mut lookup_terms_cols: Vec = vec![]; + let mut lookup_terms_cols: Vec> = vec![]; lookup_reads.iter().for_each(|(table_id, reads)| { let mut idx_partial_sum = 0; let table_id_u32 = table_id.to_u32(); diff --git a/msm/src/proof.rs b/msm/src/proof.rs index 4700450cf5..6fcd03e08c 100644 --- a/msm/src/proof.rs +++ b/msm/src/proof.rs @@ -95,7 +95,7 @@ impl< ID: LookupTableID, > ColumnEvaluations for ProofEvaluations { - type Column = crate::columns::Column; + type Column = crate::columns::Column; fn evaluate(&self, col: Self::Column) -> Result, ExprError> { // TODO: substitute when non-literal generic constants are available diff --git a/msm/src/serialization/column.rs b/msm/src/serialization/column.rs index fb30bb1c66..c983c0f5d4 100644 --- a/msm/src/serialization/column.rs +++ b/msm/src/serialization/column.rs @@ -42,7 +42,7 @@ pub enum SerializationColumn { impl ColumnIndexer for SerializationColumn { const N_COL: usize = N_COL_SER; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { Self::CurrentRow => Column::FixedSelector(0), Self::PreviousCoeffRow => Column::FixedSelector(1), diff --git a/msm/src/test/test_circuit/columns.rs b/msm/src/test/test_circuit/columns.rs index a417dba1e5..4e6d34cad6 100644 --- a/msm/src/test/test_circuit/columns.rs +++ b/msm/src/test/test_circuit/columns.rs @@ -23,7 +23,7 @@ pub enum TestColumn { impl ColumnIndexer for TestColumn { const N_COL: usize = N_COL_TEST; - fn to_column(self) -> Column { + fn to_column(self) -> Column { let to_column_inner = |offset, i| { assert!(i < N_LIMBS); Column::Relation(N_LIMBS * offset + i) diff --git a/o1vm/src/interpreters/keccak/column.rs b/o1vm/src/interpreters/keccak/column.rs index 708349b2fe..44afb830b8 100644 --- a/o1vm/src/interpreters/keccak/column.rs +++ b/o1vm/src/interpreters/keccak/column.rs @@ -375,7 +375,7 @@ impl IndexMut for KeccakWitness { impl ColumnIndexer for ColumnAlias { const N_COL: usize = N_ZKVM_KECCAK_REL_COLS + N_ZKVM_KECCAK_SEL_COLS; - fn to_column(self) -> Column { + fn to_column(self) -> Column { Column::Relation(usize::from(self)) } } @@ -403,7 +403,7 @@ impl IndexMut for KeccakWitness { impl ColumnIndexer for Steps { const N_COL: usize = N_ZKVM_KECCAK_REL_COLS + N_ZKVM_KECCAK_SEL_COLS; - fn to_column(self) -> Column { + fn to_column(self) -> Column { Column::DynamicSelector(usize::from(self) - N_ZKVM_KECCAK_REL_COLS) } } diff --git a/o1vm/src/interpreters/mips/column.rs b/o1vm/src/interpreters/mips/column.rs index d780171715..554a0e1501 100644 --- a/o1vm/src/interpreters/mips/column.rs +++ b/o1vm/src/interpreters/mips/column.rs @@ -146,7 +146,7 @@ impl IndexMut for MIPSWitness { impl ColumnIndexer for ColumnAlias { const N_COL: usize = N_MIPS_COLS; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { Self::ScratchState(ss) => { assert!( @@ -200,7 +200,7 @@ impl IndexMut for MIPSWitness { impl ColumnIndexer for Instruction { const N_COL: usize = N_MIPS_REL_COLS + N_MIPS_SEL_COLS; - fn to_column(self) -> Column { + fn to_column(self) -> Column { Column::DynamicSelector(usize::from(self) - N_MIPS_REL_COLS) } } diff --git a/o1vm/src/lib.rs b/o1vm/src/lib.rs index e5ddbe84a8..b0c2e36c08 100644 --- a/o1vm/src/lib.rs +++ b/o1vm/src/lib.rs @@ -43,4 +43,4 @@ pub use ramlookup::{LookupMode as RAMLookupMode, RAMLookup}; /// `P(X, Y, Z) = q_x X + q_y Y + q_m X Y + q_o Z + q_c` /// To represent this multi-variate polynomial using the expression framework, /// we would use 3 different columns. -pub(crate) type E = Expr, Column>; +pub(crate) type E = Expr, Column>; diff --git a/o1vm/src/pickles/column_env.rs b/o1vm/src/pickles/column_env.rs index 61f72d05e1..5119646b2c 100644 --- a/o1vm/src/pickles/column_env.rs +++ b/o1vm/src/pickles/column_env.rs @@ -35,9 +35,10 @@ pub struct ColumnEnvironment<'a, F: FftField> { pub domain: EvaluationDomains, } -pub fn get_all_columns() -> Vec { - let mut cols = - Vec::::with_capacity(SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 2 + N_MIPS_SEL_COLS); +pub fn get_all_columns() -> Vec> { + let mut cols = Vec::>::with_capacity( + SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 2 + N_MIPS_SEL_COLS, + ); for i in 0..SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 2 { cols.push(Column::Relation(i)); } @@ -48,7 +49,7 @@ pub fn get_all_columns() -> Vec { } impl WitnessColumns { - pub fn get_column(&self, col: &Column) -> Option<&G> { + pub fn get_column(&self, col: &Column) -> Option<&G> { match *col { Column::Relation(i) => { if i < SCRATCH_SIZE { @@ -92,7 +93,7 @@ impl<'a, F: FftField> TColumnEnvironment<'a, F, BerkeleyChallengeTerm, BerkeleyC { // FIXME: do we change to the MIPS column type? // We do not want to keep kimchi_msm/generic prover - type Column = Column; + type Column = Column; fn get_column(&self, col: &Self::Column) -> Option<&'a Evals> { self.witness.get_column(col) diff --git a/o1vm/src/pickles/verifier.rs b/o1vm/src/pickles/verifier.rs index fbbaa912eb..a4defb44d2 100644 --- a/o1vm/src/pickles/verifier.rs +++ b/o1vm/src/pickles/verifier.rs @@ -40,7 +40,7 @@ struct ColumnEval<'a, G: AffineRepr> { } impl ColumnEvaluations for ColumnEval<'_, G> { - type Column = Column; + type Column = Column; fn evaluate( &self, col: Self::Column, From dad3c0eb465dc0e0072703ce94f3767525278b29 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 11 Jan 2025 18:05:35 +0000 Subject: [PATCH 03/16] Add a parameter to ColumnIndexer --- ivc/src/ivc/columns.rs | 2 +- ivc/src/ivc/helpers.rs | 12 ++++- ivc/src/poseidon_55_0_7_3_2/columns.rs | 2 +- ivc/src/poseidon_55_0_7_3_7/columns.rs | 2 +- ivc/src/poseidon_8_56_5_3_2/columns.rs | 2 +- msm/src/circuit_design/capabilities.rs | 20 +++---- msm/src/circuit_design/composition.rs | 74 ++++++++++++++------------ msm/src/circuit_design/constraints.rs | 6 +-- msm/src/circuit_design/witness.rs | 18 +++---- msm/src/columns.rs | 4 +- msm/src/fec/columns.rs | 8 +-- msm/src/ffa/columns.rs | 2 +- msm/src/serialization/column.rs | 2 +- msm/src/serialization/interpreter.rs | 18 ++++--- msm/src/test/test_circuit/columns.rs | 2 +- o1vm/src/interpreters/keccak/column.rs | 4 +- o1vm/src/interpreters/mips/column.rs | 4 +- 17 files changed, 101 insertions(+), 81 deletions(-) diff --git a/ivc/src/ivc/columns.rs b/ivc/src/ivc/columns.rs index 2d0c1ef948..552f9a2a4d 100644 --- a/ivc/src/ivc/columns.rs +++ b/ivc/src/ivc/columns.rs @@ -378,7 +378,7 @@ pub enum IVCColumn { Block6UOutput, } -impl ColumnIndexer for IVCColumn { +impl ColumnIndexer for IVCColumn { /// Number of columns used by the IVC circuit /// It contains at least the columns used for Poseidon. /// It does not include the additional columns that might be required diff --git a/ivc/src/ivc/helpers.rs b/ivc/src/ivc/helpers.rs index 4507833bb7..11932c671f 100644 --- a/ivc/src/ivc/helpers.rs +++ b/ivc/src/ivc/helpers.rs @@ -10,7 +10,11 @@ use kimchi_msm::{ use super::{LIMB_BITSIZE_XLARGE, N_LIMBS_XLARGE}; /// Helper. Combines small limbs into big limbs. -pub fn combine_large_to_xlarge>( +pub fn combine_large_to_xlarge< + F: PrimeField, + CIx: ColumnIndexer, + Env: ColAccessCap, +>( x: [Env::Variable; N_LIMBS_LARGE], ) -> [Env::Variable; N_LIMBS_XLARGE] { combine_limbs_m_to_n::< @@ -25,7 +29,11 @@ pub fn combine_large_to_xlarge>( +pub fn combine_small_to_full< + F: PrimeField, + CIx: ColumnIndexer, + Env: ColAccessCap, +>( x: [Env::Variable; N_LIMBS_SMALL], ) -> Env::Variable { let [res] = diff --git a/ivc/src/poseidon_55_0_7_3_2/columns.rs b/ivc/src/poseidon_55_0_7_3_2/columns.rs index 69a0d7078d..e676630db4 100644 --- a/ivc/src/poseidon_55_0_7_3_2/columns.rs +++ b/ivc/src/poseidon_55_0_7_3_2/columns.rs @@ -29,7 +29,7 @@ pub enum PoseidonColumn { RoundConstant(usize, usize), } -impl ColumnIndexer +impl ColumnIndexer for PoseidonColumn { // - STATE_SIZE input columns diff --git a/ivc/src/poseidon_55_0_7_3_7/columns.rs b/ivc/src/poseidon_55_0_7_3_7/columns.rs index 2631f85f59..8e7ee91876 100644 --- a/ivc/src/poseidon_55_0_7_3_7/columns.rs +++ b/ivc/src/poseidon_55_0_7_3_7/columns.rs @@ -20,7 +20,7 @@ pub enum PoseidonColumn { RoundConstant(usize, usize), } -impl ColumnIndexer +impl ColumnIndexer for PoseidonColumn { const N_COL: usize = STATE_SIZE + NB_FULL_ROUND * STATE_SIZE; diff --git a/ivc/src/poseidon_8_56_5_3_2/columns.rs b/ivc/src/poseidon_8_56_5_3_2/columns.rs index c60e3f9d69..c48814a7a8 100644 --- a/ivc/src/poseidon_8_56_5_3_2/columns.rs +++ b/ivc/src/poseidon_8_56_5_3_2/columns.rs @@ -30,7 +30,7 @@ pub enum PoseidonColumn< } impl - ColumnIndexer for PoseidonColumn + ColumnIndexer for PoseidonColumn { // - STATE_SIZE input columns // - for each partial round: diff --git a/msm/src/circuit_design/capabilities.rs b/msm/src/circuit_design/capabilities.rs index 5e7780b343..22943529ed 100644 --- a/msm/src/circuit_design/capabilities.rs +++ b/msm/src/circuit_design/capabilities.rs @@ -10,7 +10,7 @@ use ark_ff::PrimeField; /// Environment capability for accessing and reading columns. This is necessary for /// building constraints. -pub trait ColAccessCap { +pub trait ColAccessCap> { // NB: 'static here means that `Variable` does not contain any // references with a lifetime less than 'static. Which is true in // our case. Necessary for `set_assert_mapper` @@ -39,7 +39,7 @@ pub trait ColAccessCap { /// Environment capability similar to `ColAccessCap` but for /also /// writing/ columns. Used on the witness side. -pub trait ColWriteCap +pub trait ColWriteCap> where Self: ColAccessCap, { @@ -47,7 +47,7 @@ where } /// Capability for invoking table lookups. -pub trait LookupCap +pub trait LookupCap, LT: LookupTableID> where Self: ColAccessCap, { @@ -62,7 +62,7 @@ where /// Holds a "current" row that can be moved forward with `next_row`. /// The `ColWriteCap` and `ColAccessCap` reason in terms of current /// row. The two other methods can be used to read/write previous. -pub trait MultiRowReadCap +pub trait MultiRowReadCap> where Self: ColWriteCap, { @@ -84,7 +84,7 @@ where // F-typed inputs to a function. /// A direct field access capability modelling an abstract witness /// builder. Not for constraint building. -pub trait DirectWitnessCap +pub trait DirectWitnessCap> where Self: MultiRowReadCap, { @@ -106,7 +106,7 @@ where /// partially) in the constraint builder case. For example, "hcopy", /// despite its name, does not do any "write", so hcopy !=> /// write_column. -pub trait HybridCopyCap +pub trait HybridCopyCap> where Self: ColAccessCap, { @@ -120,7 +120,7 @@ where //////////////////////////////////////////////////////////////////////////// /// Write an array of values simultaneously. -pub fn read_column_array( +pub fn read_column_array, ColMap>( env: &mut Env, column_map: ColMap, ) -> [Env::Variable; ARR_N] @@ -133,7 +133,7 @@ where } /// Write a field element directly as a constant. -pub fn write_column_const(env: &mut Env, col: CIx, var: &F) +pub fn write_column_const>(env: &mut Env, col: CIx, var: &F) where F: PrimeField, Env: ColWriteCap, @@ -142,7 +142,7 @@ where } /// Write an array of values simultaneously. -pub fn write_column_array( +pub fn write_column_array, ColMap>( env: &mut Env, input: [Env::Variable; ARR_N], column_map: ColMap, @@ -157,7 +157,7 @@ pub fn write_column_array( +pub fn write_column_array_const, ColMap>( env: &mut Env, input: &[F; ARR_N], column_map: ColMap, diff --git a/msm/src/circuit_design/composition.rs b/msm/src/circuit_design/composition.rs index 15028c4f44..c32d7dabf0 100644 --- a/msm/src/circuit_design/composition.rs +++ b/msm/src/circuit_design/composition.rs @@ -151,27 +151,35 @@ where /// impossible to instantiate `SubEnv` with two /completely/ different /// lenses and then write proper trait implementations. Rust complains /// about conflicting trait implementations. -struct SubEnv<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> { +struct SubEnv<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> { env: &'a mut Env1, lens: L, phantom: PhantomData<(F, CIx1)>, } /// Sub environment with a lens that is mapping columns. -pub struct SubEnvColumn<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L>( - SubEnv<'a, F, CIx1, Env1, L>, -); +pub struct SubEnvColumn< + 'a, + F: PrimeField, + CIx1: ColumnIndexer, + Env1: ColAccessCap, + L, +>(SubEnv<'a, F, CIx1, Env1, L>); /// Sub environment with a lens that is mapping lookup tables. -pub struct SubEnvLookup<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L>( - SubEnv<'a, F, CIx1, Env1, L>, -); +pub struct SubEnvLookup< + 'a, + F: PrimeField, + CIx1: ColumnIndexer, + Env1: ColAccessCap, + L, +>(SubEnv<'a, F, CIx1, Env1, L>); //////////////////////////////////////////////////////////////////////////// // Trait implementations //////////////////////////////////////////////////////////////////////////// -impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> +impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> SubEnv<'a, F, CIx1, Env1, L> { pub fn new(env: &'a mut Env1, lens: L) -> Self { @@ -183,7 +191,7 @@ impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> } } -impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> +impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> SubEnvColumn<'a, F, CIx1, Env1, L> { pub fn new(env: &'a mut Env1, lens: L) -> Self { @@ -191,7 +199,7 @@ impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> } } -impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> +impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> SubEnvLookup<'a, F, CIx1, Env1, L> { pub fn new(env: &'a mut Env1, lens: L) -> Self { @@ -202,8 +210,8 @@ impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> impl< 'a, F: PrimeField, - CIx1: ColumnIndexer, - CIx2: ColumnIndexer, + CIx1: ColumnIndexer, + CIx2: ColumnIndexer, Env1: ColAccessCap, L: MPrism, > ColAccessCap for SubEnv<'a, F, CIx1, Env1, L> @@ -230,8 +238,8 @@ impl< impl< 'a, F: PrimeField, - CIx1: ColumnIndexer, - CIx2: ColumnIndexer, + CIx1: ColumnIndexer, + CIx2: ColumnIndexer, Env1: ColWriteCap, L: MPrism, > ColWriteCap for SubEnv<'a, F, CIx1, Env1, L> @@ -244,8 +252,8 @@ impl< impl< 'a, F: PrimeField, - CIx1: ColumnIndexer, - CIx2: ColumnIndexer, + CIx1: ColumnIndexer, + CIx2: ColumnIndexer, Env1: HybridCopyCap, L: MPrism, > HybridCopyCap for SubEnv<'a, F, CIx1, Env1, L> @@ -258,8 +266,8 @@ impl< impl< 'a, F: PrimeField, - CIx1: ColumnIndexer, - CIx2: ColumnIndexer, + CIx1: ColumnIndexer, + CIx2: ColumnIndexer, Env1: ColAccessCap, L: MPrism, > ColAccessCap for SubEnvColumn<'a, F, CIx1, Env1, L> @@ -286,8 +294,8 @@ impl< impl< 'a, F: PrimeField, - CIx1: ColumnIndexer, - CIx2: ColumnIndexer, + CIx1: ColumnIndexer, + CIx2: ColumnIndexer, Env1: ColWriteCap, L: MPrism, > ColWriteCap for SubEnvColumn<'a, F, CIx1, Env1, L> @@ -300,8 +308,8 @@ impl< impl< 'a, F: PrimeField, - CIx1: ColumnIndexer, - CIx2: ColumnIndexer, + CIx1: ColumnIndexer, + CIx2: ColumnIndexer, Env1: HybridCopyCap, L: MPrism, > HybridCopyCap for SubEnvColumn<'a, F, CIx1, Env1, L> @@ -311,8 +319,8 @@ impl< } } -impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> ColAccessCap - for SubEnvLookup<'a, F, CIx1, Env1, L> +impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> + ColAccessCap for SubEnvLookup<'a, F, CIx1, Env1, L> { type Variable = Env1::Variable; @@ -333,16 +341,16 @@ impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColAccessCap, L> Col } } -impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColWriteCap, L> ColWriteCap - for SubEnvLookup<'a, F, CIx1, Env1, L> +impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: ColWriteCap, L> + ColWriteCap for SubEnvLookup<'a, F, CIx1, Env1, L> { fn write_column(&mut self, ix: CIx1, value: &Self::Variable) { self.0.env.write_column(ix, value); } } -impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: HybridCopyCap, L> HybridCopyCap - for SubEnvLookup<'a, F, CIx1, Env1, L> +impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: HybridCopyCap, L> + HybridCopyCap for SubEnvLookup<'a, F, CIx1, Env1, L> { fn hcopy(&mut self, x: &Self::Variable, ix: CIx1) -> Self::Variable { self.0.env.hcopy(x, ix) @@ -352,7 +360,7 @@ impl<'a, F: PrimeField, CIx1: ColumnIndexer, Env1: HybridCopyCap, L> Hy impl< 'a, F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, LT1: LookupTableID, LT2: LookupTableID, Env1: LookupCap, @@ -373,8 +381,8 @@ impl< impl< 'a, F: PrimeField, - CIx1: ColumnIndexer, - CIx2: ColumnIndexer, + CIx1: ColumnIndexer, + CIx2: ColumnIndexer, LT: LookupTableID, Env1: LookupCap, L: MPrism, @@ -389,7 +397,7 @@ impl< } } -impl<'a, F: PrimeField, CIx: ColumnIndexer, Env1: MultiRowReadCap, L> +impl<'a, F: PrimeField, CIx: ColumnIndexer, Env1: MultiRowReadCap, L> MultiRowReadCap for SubEnvLookup<'a, F, CIx, Env1, L> { /// Read value from a (row,column) position. @@ -408,7 +416,7 @@ impl<'a, F: PrimeField, CIx: ColumnIndexer, Env1: MultiRowReadCap, L> } } -impl<'a, F: PrimeField, CIx: ColumnIndexer, Env1: DirectWitnessCap, L> +impl<'a, F: PrimeField, CIx: ColumnIndexer, Env1: DirectWitnessCap, L> DirectWitnessCap for SubEnvLookup<'a, F, CIx, Env1, L> { fn variable_to_field(value: Self::Variable) -> F { diff --git a/msm/src/circuit_design/constraints.rs b/msm/src/circuit_design/constraints.rs index cca3c6d7cf..611a2c5d51 100644 --- a/msm/src/circuit_design/constraints.rs +++ b/msm/src/circuit_design/constraints.rs @@ -35,7 +35,7 @@ impl ConstraintBuilderEnv { } } -impl ColAccessCap +impl, LT: LookupTableID> ColAccessCap for ConstraintBuilderEnv { type Variable = E; @@ -61,7 +61,7 @@ impl ColAccessCap } } -impl HybridCopyCap +impl, LT: LookupTableID> HybridCopyCap for ConstraintBuilderEnv { fn hcopy(&mut self, x: &Self::Variable, position: CIx) -> Self::Variable { @@ -77,7 +77,7 @@ impl HybridCopyCap } } -impl LookupCap +impl, LT: LookupTableID> LookupCap for ConstraintBuilderEnv { fn lookup(&mut self, table_id: LT, value: Vec<>::Variable>) { diff --git a/msm/src/circuit_design/witness.rs b/msm/src/circuit_design/witness.rs index 43136ba786..6246b16ee6 100644 --- a/msm/src/circuit_design/witness.rs +++ b/msm/src/circuit_design/witness.rs @@ -16,7 +16,7 @@ use std::{collections::BTreeMap, iter, marker::PhantomData}; /// separately is due to a rust limitation. pub struct WitnessBuilderEnv< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, @@ -68,7 +68,7 @@ pub struct WitnessBuilderEnv< impl< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, @@ -103,7 +103,7 @@ impl< impl< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, @@ -124,7 +124,7 @@ impl< /// for every `T: ColWriteCap`. impl< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, @@ -142,7 +142,7 @@ impl< impl< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, @@ -171,7 +171,7 @@ impl< impl< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, @@ -187,7 +187,7 @@ impl< impl< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, @@ -276,7 +276,7 @@ impl< impl< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, @@ -421,7 +421,7 @@ impl< impl< F: PrimeField, - CIx: ColumnIndexer, + CIx: ColumnIndexer, const N_WIT: usize, const N_REL: usize, const N_DSEL: usize, diff --git a/msm/src/columns.rs b/msm/src/columns.rs index f221eb8ec0..faa817cd79 100644 --- a/msm/src/columns.rs +++ b/msm/src/columns.rs @@ -73,12 +73,12 @@ impl FormattedOutput for Column { /// A datatype expressing a generalized column, but with potentially /// more convenient interface than a bare column. -pub trait ColumnIndexer: core::fmt::Debug + Copy + Eq + Ord { +pub trait ColumnIndexer: core::fmt::Debug + Copy + Eq + Ord { /// Total number of columns in this index. const N_COL: usize; /// Flatten the column "alias" into the integer-like column. - fn to_column(self) -> Column; + fn to_column(self) -> Column; } // Implementation to be compatible with folding if we use generic column diff --git a/msm/src/fec/columns.rs b/msm/src/fec/columns.rs index 30331a0d5e..4d38404389 100644 --- a/msm/src/fec/columns.rs +++ b/msm/src/fec/columns.rs @@ -51,7 +51,7 @@ pub enum FECColumn { Inter(FECColumnInter), } -impl ColumnIndexer for FECColumnInput { +impl ColumnIndexer for FECColumnInput { const N_COL: usize = 4 * N_LIMBS_LARGE; fn to_column(self) -> Column { match self { @@ -75,7 +75,7 @@ impl ColumnIndexer for FECColumnInput { } } -impl ColumnIndexer for FECColumnOutput { +impl ColumnIndexer for FECColumnOutput { const N_COL: usize = 2 * N_LIMBS_SMALL; fn to_column(self) -> Column { match self { @@ -91,7 +91,7 @@ impl ColumnIndexer for FECColumnOutput { } } -impl ColumnIndexer for FECColumnInter { +impl ColumnIndexer for FECColumnInter { const N_COL: usize = 4 * N_LIMBS_LARGE + 10 * N_LIMBS_SMALL + 9; fn to_column(self) -> Column { match self { @@ -146,7 +146,7 @@ impl ColumnIndexer for FECColumnInter { } } -impl ColumnIndexer for FECColumn { +impl ColumnIndexer for FECColumn { const N_COL: usize = FEC_N_COLUMNS; fn to_column(self) -> Column { match self { diff --git a/msm/src/ffa/columns.rs b/msm/src/ffa/columns.rs index a2583b505c..17506b7147 100644 --- a/msm/src/ffa/columns.rs +++ b/msm/src/ffa/columns.rs @@ -20,7 +20,7 @@ pub enum FFAColumn { Quotient, } -impl ColumnIndexer for FFAColumn { +impl ColumnIndexer for FFAColumn { const N_COL: usize = FFA_N_COLUMNS; fn to_column(self) -> Column { let to_column_inner = |offset, i| { diff --git a/msm/src/serialization/column.rs b/msm/src/serialization/column.rs index c983c0f5d4..62b0e957c1 100644 --- a/msm/src/serialization/column.rs +++ b/msm/src/serialization/column.rs @@ -40,7 +40,7 @@ pub enum SerializationColumn { CoeffResult(usize), } -impl ColumnIndexer for SerializationColumn { +impl ColumnIndexer for SerializationColumn { const N_COL: usize = N_COL_SER; fn to_column(self) -> Column { match self { diff --git a/msm/src/serialization/interpreter.rs b/msm/src/serialization/interpreter.rs index 7ad0637f30..a24d1d83b9 100644 --- a/msm/src/serialization/interpreter.rs +++ b/msm/src/serialization/interpreter.rs @@ -26,7 +26,7 @@ use o1_utils::{field_helpers::FieldHelpers, foreign_field::ForeignElement}; // Such "helpers" defeat the whole purpose of the interpreter. // TODO remove -pub trait HybridSerHelpers { +pub trait HybridSerHelpers, LT: LookupTableID> { /// Returns the bits between [highest_bit, lowest_bit] of the variable `x`, /// and copy the result in the column `position`. /// The value `x` is expected to be encoded in big-endian @@ -41,7 +41,7 @@ pub trait HybridSerHelpers Self: ColAccessCap; } -impl HybridSerHelpers +impl, LT: LookupTableID> HybridSerHelpers for crate::circuit_design::ConstraintBuilderEnv { fn bitmask_be( @@ -62,7 +62,7 @@ impl HybridSerHelpers, const N_COL: usize, const N_REL: usize, const N_DSEL: usize, @@ -350,7 +350,11 @@ pub fn combine_limbs_m_to_n< /// Helper function for limb recombination. /// /// Combines small limbs into big limbs. -pub fn combine_small_to_large>( +pub fn combine_small_to_large< + F: PrimeField, + CIx: ColumnIndexer, + Env: ColAccessCap, +>( x: [Env::Variable; N_LIMBS_SMALL], ) -> [Env::Variable; N_LIMBS_LARGE] { combine_limbs_m_to_n::< @@ -367,7 +371,7 @@ pub fn combine_small_to_large>( +pub fn combine_carry, Env: ColAccessCap>( x: [Env::Variable; 2 * N_LIMBS_SMALL + 2], ) -> [Env::Variable; 2 * N_LIMBS_LARGE - 2] { let constant_u128 = |x: u128| Env::constant(From::from(x)); @@ -816,8 +820,8 @@ mod tests { type SerializationWitnessBuilderEnv = WitnessBuilderEnv< Fp, SerializationColumn, - { ::N_COL }, - { ::N_COL }, + { >::N_COL }, + { >::N_COL }, 0, 0, LookupTable, diff --git a/msm/src/test/test_circuit/columns.rs b/msm/src/test/test_circuit/columns.rs index 4e6d34cad6..bdd9fb38e3 100644 --- a/msm/src/test/test_circuit/columns.rs +++ b/msm/src/test/test_circuit/columns.rs @@ -21,7 +21,7 @@ pub enum TestColumn { FixedSel3, } -impl ColumnIndexer for TestColumn { +impl ColumnIndexer for TestColumn { const N_COL: usize = N_COL_TEST; fn to_column(self) -> Column { let to_column_inner = |offset, i| { diff --git a/o1vm/src/interpreters/keccak/column.rs b/o1vm/src/interpreters/keccak/column.rs index 44afb830b8..0767b229b4 100644 --- a/o1vm/src/interpreters/keccak/column.rs +++ b/o1vm/src/interpreters/keccak/column.rs @@ -373,7 +373,7 @@ impl IndexMut for KeccakWitness { } } -impl ColumnIndexer for ColumnAlias { +impl ColumnIndexer for ColumnAlias { const N_COL: usize = N_ZKVM_KECCAK_REL_COLS + N_ZKVM_KECCAK_SEL_COLS; fn to_column(self) -> Column { Column::Relation(usize::from(self)) @@ -401,7 +401,7 @@ impl IndexMut for KeccakWitness { } } -impl ColumnIndexer for Steps { +impl ColumnIndexer for Steps { const N_COL: usize = N_ZKVM_KECCAK_REL_COLS + N_ZKVM_KECCAK_SEL_COLS; fn to_column(self) -> Column { Column::DynamicSelector(usize::from(self) - N_ZKVM_KECCAK_REL_COLS) diff --git a/o1vm/src/interpreters/mips/column.rs b/o1vm/src/interpreters/mips/column.rs index 554a0e1501..75effebb28 100644 --- a/o1vm/src/interpreters/mips/column.rs +++ b/o1vm/src/interpreters/mips/column.rs @@ -143,7 +143,7 @@ impl IndexMut for MIPSWitness { } } -impl ColumnIndexer for ColumnAlias { +impl ColumnIndexer for ColumnAlias { const N_COL: usize = N_MIPS_COLS; fn to_column(self) -> Column { @@ -198,7 +198,7 @@ impl IndexMut for MIPSWitness { } } -impl ColumnIndexer for Instruction { +impl ColumnIndexer for Instruction { const N_COL: usize = N_MIPS_REL_COLS + N_MIPS_SEL_COLS; fn to_column(self) -> Column { Column::DynamicSelector(usize::from(self) - N_MIPS_REL_COLS) From 76073e884d8a6d31efd271e09b84c763f873f113 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 11 Jan 2025 18:07:17 +0000 Subject: [PATCH 04/16] Use a sane type for Relation in the MIPS constraints --- o1vm/src/interpreters/keccak/column.rs | 11 +++--- o1vm/src/interpreters/mips/column.rs | 15 ++++---- o1vm/src/lib.rs | 3 +- o1vm/src/pickles/column_env.rs | 50 +++++++++++++------------- o1vm/src/pickles/verifier.rs | 4 +-- 5 files changed, 45 insertions(+), 38 deletions(-) diff --git a/o1vm/src/interpreters/keccak/column.rs b/o1vm/src/interpreters/keccak/column.rs index 0767b229b4..d283039cb8 100644 --- a/o1vm/src/interpreters/keccak/column.rs +++ b/o1vm/src/interpreters/keccak/column.rs @@ -1,7 +1,10 @@ //! This module defines the custom columns used in the Keccak witness, which //! are aliases for the actual Keccak witness columns also defined here. use self::{Absorbs::*, Sponges::*, Steps::*}; -use crate::interpreters::keccak::{ZKVM_KECCAK_COLS_CURR, ZKVM_KECCAK_COLS_NEXT}; +use crate::{ + interpreters::keccak::{ZKVM_KECCAK_COLS_CURR, ZKVM_KECCAK_COLS_NEXT}, + RelationColumnType, +}; use kimchi::circuits::polynomials::keccak::constants::{ CHI_SHIFTS_B_LEN, CHI_SHIFTS_B_OFF, CHI_SHIFTS_SUM_LEN, CHI_SHIFTS_SUM_OFF, PIRHO_DENSE_E_LEN, PIRHO_DENSE_E_OFF, PIRHO_DENSE_ROT_E_LEN, PIRHO_DENSE_ROT_E_OFF, PIRHO_EXPAND_ROT_E_LEN, @@ -373,10 +376,10 @@ impl IndexMut for KeccakWitness { } } -impl ColumnIndexer for ColumnAlias { +impl ColumnIndexer for ColumnAlias { const N_COL: usize = N_ZKVM_KECCAK_REL_COLS + N_ZKVM_KECCAK_SEL_COLS; - fn to_column(self) -> Column { - Column::Relation(usize::from(self)) + fn to_column(self) -> Column { + Column::Relation(RelationColumnType::Scratch(usize::from(self))) } } diff --git a/o1vm/src/interpreters/mips/column.rs b/o1vm/src/interpreters/mips/column.rs index 75effebb28..781f997493 100644 --- a/o1vm/src/interpreters/mips/column.rs +++ b/o1vm/src/interpreters/mips/column.rs @@ -1,4 +1,7 @@ -use crate::interpreters::mips::Instruction::{self, IType, JType, RType}; +use crate::{ + interpreters::mips::Instruction::{self, IType, JType, RType}, + RelationColumnType, +}; use kimchi_msm::{ columns::{Column, ColumnIndexer}, witness::Witness, @@ -143,10 +146,10 @@ impl IndexMut for MIPSWitness { } } -impl ColumnIndexer for ColumnAlias { +impl ColumnIndexer for ColumnAlias { const N_COL: usize = N_MIPS_COLS; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { Self::ScratchState(ss) => { assert!( @@ -155,7 +158,7 @@ impl ColumnIndexer for ColumnAlias { SCRATCH_SIZE, ss ); - Column::Relation(ss) + Column::Relation(RelationColumnType::Scratch(ss)) } Self::ScratchStateInverse(ss) => { assert!( @@ -164,9 +167,9 @@ impl ColumnIndexer for ColumnAlias { SCRATCH_SIZE_INVERSE, ss ); - Column::Relation(SCRATCH_SIZE + ss) + Column::Relation(RelationColumnType::ScratchInverse(ss)) } - Self::InstructionCounter => Column::Relation(SCRATCH_SIZE + SCRATCH_SIZE_INVERSE), + Self::InstructionCounter => Column::Relation(RelationColumnType::InstructionCounter), // TODO: what happens with error? It does not have a corresponding alias Self::Selector(s) => { assert!( diff --git a/o1vm/src/lib.rs b/o1vm/src/lib.rs index b0c2e36c08..218d567240 100644 --- a/o1vm/src/lib.rs +++ b/o1vm/src/lib.rs @@ -24,6 +24,7 @@ pub mod utils; pub mod test_preimage_read; +use crate::pickles::column_env::RelationColumnType; use kimchi::circuits::{ berkeley_columns::BerkeleyChallengeTerm, expr::{ConstantExpr, Expr}, @@ -43,4 +44,4 @@ pub use ramlookup::{LookupMode as RAMLookupMode, RAMLookup}; /// `P(X, Y, Z) = q_x X + q_y Y + q_m X Y + q_o Z + q_c` /// To represent this multi-variate polynomial using the expression framework, /// we would use 3 different columns. -pub(crate) type E = Expr, Column>; +pub(crate) type E = Expr, Column>; diff --git a/o1vm/src/pickles/column_env.rs b/o1vm/src/pickles/column_env.rs index 5119646b2c..4cb0661654 100644 --- a/o1vm/src/pickles/column_env.rs +++ b/o1vm/src/pickles/column_env.rs @@ -14,6 +14,14 @@ use kimchi::circuits::{ type Evals = Evaluations>; +#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] +pub enum RelationColumnType { + Scratch(usize), + ScratchInverse(usize), + InstructionCounter, + Error, +} + /// The collection of polynomials (all in evaluation form) and constants /// required to evaluate an expression as a polynomial. /// @@ -35,13 +43,18 @@ pub struct ColumnEnvironment<'a, F: FftField> { pub domain: EvaluationDomains, } -pub fn get_all_columns() -> Vec> { - let mut cols = Vec::>::with_capacity( +pub fn get_all_columns() -> Vec> { + let mut cols = Vec::>::with_capacity( SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 2 + N_MIPS_SEL_COLS, ); - for i in 0..SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 2 { - cols.push(Column::Relation(i)); + for i in 0..SCRATCH_SIZE { + cols.push(Column::Relation(RelationColumnType::Scratch(i))); } + for i in 0..SCRATCH_SIZE_INVERSE { + cols.push(Column::Relation(RelationColumnType::ScratchInverse(i))); + } + cols.push(Column::Relation(RelationColumnType::InstructionCounter)); + cols.push(Column::Relation(RelationColumnType::Error)); for i in 0..N_MIPS_SEL_COLS { cols.push(Column::DynamicSelector(i)); } @@ -49,25 +62,14 @@ pub fn get_all_columns() -> Vec> { } impl WitnessColumns { - pub fn get_column(&self, col: &Column) -> Option<&G> { + pub fn get_column(&self, col: &Column) -> Option<&G> { match *col { - Column::Relation(i) => { - if i < SCRATCH_SIZE { - let res = &self.scratch[i]; - Some(res) - } else if i < SCRATCH_SIZE + SCRATCH_SIZE_INVERSE { - let res = &self.scratch_inverse[i - SCRATCH_SIZE]; - Some(res) - } else if i == SCRATCH_SIZE + SCRATCH_SIZE_INVERSE { - let res = &self.instruction_counter; - Some(res) - } else if i == SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 1 { - let res = &self.error; - Some(res) - } else { - panic!("We should not have that many relation columns. We have {} columns and index {} was given", SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 2, i); - } - } + Column::Relation(i) => match i { + RelationColumnType::Scratch(i) => Some(&self.scratch[i]), + RelationColumnType::ScratchInverse(i) => Some(&self.scratch_inverse[i]), + RelationColumnType::InstructionCounter => Some(&self.instruction_counter), + RelationColumnType::Error => Some(&self.error), + }, Column::DynamicSelector(i) => { assert!( i < N_MIPS_SEL_COLS, @@ -91,9 +93,7 @@ impl WitnessColumns { impl<'a, F: FftField> TColumnEnvironment<'a, F, BerkeleyChallengeTerm, BerkeleyChallenges> for ColumnEnvironment<'a, F> { - // FIXME: do we change to the MIPS column type? - // We do not want to keep kimchi_msm/generic prover - type Column = Column; + type Column = Column; fn get_column(&self, col: &Self::Column) -> Option<&'a Evals> { self.witness.get_column(col) diff --git a/o1vm/src/pickles/verifier.rs b/o1vm/src/pickles/verifier.rs index a4defb44d2..76ecd7e67b 100644 --- a/o1vm/src/pickles/verifier.rs +++ b/o1vm/src/pickles/verifier.rs @@ -24,7 +24,7 @@ use poly_commitment::{ }; use super::{ - column_env::get_all_columns, + column_env::{get_all_columns, RelationColumnType}, proof::{Proof, WitnessColumns}, }; use crate::{interpreters::mips::column::N_MIPS_SEL_COLS, E}; @@ -40,7 +40,7 @@ struct ColumnEval<'a, G: AffineRepr> { } impl ColumnEvaluations for ColumnEval<'_, G> { - type Column = Column; + type Column = Column; fn evaluate( &self, col: Self::Column, From 5fa8b43984a4e4c7bab9bf16d45c68354ceaffa3 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 11 Jan 2025 18:16:46 +0000 Subject: [PATCH 05/16] Add LookupState variant --- o1vm/src/pickles/column_env.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/o1vm/src/pickles/column_env.rs b/o1vm/src/pickles/column_env.rs index 4cb0661654..ab54c11d02 100644 --- a/o1vm/src/pickles/column_env.rs +++ b/o1vm/src/pickles/column_env.rs @@ -18,6 +18,7 @@ type Evals = Evaluations>; pub enum RelationColumnType { Scratch(usize), ScratchInverse(usize), + LookupState(usize), InstructionCounter, Error, } @@ -66,7 +67,10 @@ impl WitnessColumns { match *col { Column::Relation(i) => match i { RelationColumnType::Scratch(i) => Some(&self.scratch[i]), - RelationColumnType::ScratchInverse(i) => Some(&self.scratch_inverse[i]), + RelationColumnType::ScratchInverse(i) => { + Some(&self.scratch_inverse[i - SCRATCH_SIZE]) + } + RelationColumnType::LookupState(_) => todo!(), RelationColumnType::InstructionCounter => Some(&self.instruction_counter), RelationColumnType::Error => Some(&self.error), }, From 41ac3c548733a3fd766bd9ec0dc0d93edd6f9e3f Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 11 Jan 2025 18:24:18 +0000 Subject: [PATCH 06/16] Propagate lookup state through to prover --- o1vm/src/pickles/column_env.rs | 7 +++++-- o1vm/src/pickles/main.rs | 25 ++++++++++++++++++++++++- o1vm/src/pickles/proof.rs | 2 ++ o1vm/src/pickles/prover.rs | 31 +++++++++++++++++++++++++++++++ o1vm/src/pickles/verifier.rs | 13 ++++++++++++- 5 files changed, 74 insertions(+), 4 deletions(-) diff --git a/o1vm/src/pickles/column_env.rs b/o1vm/src/pickles/column_env.rs index ab54c11d02..c3b5db78fa 100644 --- a/o1vm/src/pickles/column_env.rs +++ b/o1vm/src/pickles/column_env.rs @@ -44,9 +44,9 @@ pub struct ColumnEnvironment<'a, F: FftField> { pub domain: EvaluationDomains, } -pub fn get_all_columns() -> Vec> { +pub fn get_all_columns(num_lookup_columns: usize) -> Vec> { let mut cols = Vec::>::with_capacity( - SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 2 + N_MIPS_SEL_COLS, + SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + num_lookup_columns + 2 + N_MIPS_SEL_COLS, ); for i in 0..SCRATCH_SIZE { cols.push(Column::Relation(RelationColumnType::Scratch(i))); @@ -54,6 +54,9 @@ pub fn get_all_columns() -> Vec> { for i in 0..SCRATCH_SIZE_INVERSE { cols.push(Column::Relation(RelationColumnType::ScratchInverse(i))); } + for i in 0..num_lookup_columns { + cols.push(Column::Relation(RelationColumnType::LookupState(i))); + } cols.push(Column::Relation(RelationColumnType::InstructionCounter)); cols.push(Column::Relation(RelationColumnType::Error)); for i in 0..N_MIPS_SEL_COLS { diff --git a/o1vm/src/pickles/main.rs b/o1vm/src/pickles/main.rs index da9c858bce..9765a5988a 100644 --- a/o1vm/src/pickles/main.rs +++ b/o1vm/src/pickles/main.rs @@ -1,4 +1,4 @@ -use ark_ff::UniformRand; +use ark_ff::{UniformRand, Zero}; use clap::Parser; use kimchi::circuits::domains::EvaluationDomains; use log::debug; @@ -95,6 +95,29 @@ pub fn cannon_main(args: cli::cannon::RunArgs) { { scratch_chunk.push(*scratch); } + // Lookup state + { + let lookup_state_size = std::cmp::max( + curr_proof_inputs.evaluations.lookup_state.len(), + mips_wit_env.lookup_state.len(), + ); + for idx in 0..lookup_state_size { + if idx < mips_wit_env.lookup_state.len() { + // We pad with 0s for dummy lookups. + curr_proof_inputs.evaluations.lookup_state[idx].push(Fp::zero()); + } else if idx < curr_proof_inputs.evaluations.lookup_state.len() { + // We create a new column filled with 0s. + let mut new_vec = + vec![Fp::zero(); curr_proof_inputs.evaluations.instruction_counter.len()]; + new_vec.push(Fp::from(mips_wit_env.lookup_state[idx])); + curr_proof_inputs.evaluations.lookup_state[idx] = new_vec; + } else { + // Push the value to the column. + curr_proof_inputs.evaluations.lookup_state[idx] + .push(Fp::from(mips_wit_env.lookup_state[idx])); + } + } + } curr_proof_inputs .evaluations .instruction_counter diff --git a/o1vm/src/pickles/proof.rs b/o1vm/src/pickles/proof.rs index 40529a3409..c1644903bc 100644 --- a/o1vm/src/pickles/proof.rs +++ b/o1vm/src/pickles/proof.rs @@ -6,6 +6,7 @@ use crate::interpreters::mips::column::{N_MIPS_SEL_COLS, SCRATCH_SIZE, SCRATCH_S pub struct WitnessColumns { pub scratch: [G; SCRATCH_SIZE], pub scratch_inverse: [G; SCRATCH_SIZE_INVERSE], + pub lookup_state: Vec, pub instruction_counter: G, pub error: G, pub selector: S, @@ -21,6 +22,7 @@ impl ProofInputs { evaluations: WitnessColumns { scratch: std::array::from_fn(|_| Vec::with_capacity(domain_size)), scratch_inverse: std::array::from_fn(|_| Vec::with_capacity(domain_size)), + lookup_state: vec![], instruction_counter: Vec::with_capacity(domain_size), error: Vec::with_capacity(domain_size), selector: Vec::with_capacity(domain_size), diff --git a/o1vm/src/pickles/prover.rs b/o1vm/src/pickles/prover.rs index d9aa9416cf..5310bfa093 100644 --- a/o1vm/src/pickles/prover.rs +++ b/o1vm/src/pickles/prover.rs @@ -86,6 +86,7 @@ where let WitnessColumns { scratch, scratch_inverse, + lookup_state, instruction_counter, error, selector, @@ -119,10 +120,15 @@ where eval_col(evals) }) .collect::>(); + let lookup_state = lookup_state + .into_par_iter() + .map(eval_col) + .collect::>(); let selector = selector.into_par_iter().map(eval_col).collect::>(); WitnessColumns { scratch: scratch.try_into().unwrap(), scratch_inverse: scratch_inverse.try_into().unwrap(), + lookup_state: lookup_state, instruction_counter: eval_col(instruction_counter), error: eval_col(error.clone()), selector: selector.try_into().unwrap(), @@ -134,6 +140,7 @@ where let WitnessColumns { scratch, scratch_inverse, + lookup_state, instruction_counter, error, selector, @@ -151,10 +158,12 @@ where // Doing in parallel let scratch = scratch.par_iter().map(comm).collect::>(); let scratch_inverse = scratch_inverse.par_iter().map(comm).collect::>(); + let lookup_state = lookup_state.par_iter().map(comm).collect::>(); let selector = selector.par_iter().map(comm).collect::>(); WitnessColumns { scratch: scratch.try_into().unwrap(), scratch_inverse: scratch_inverse.try_into().unwrap(), + lookup_state, instruction_counter: comm(instruction_counter), error: comm(error), selector: selector.try_into().unwrap(), @@ -170,6 +179,7 @@ where let WitnessColumns { scratch, scratch_inverse, + lookup_state, instruction_counter, error, selector, @@ -182,10 +192,15 @@ where .into_par_iter() .map(eval_d8) .collect::>(); + let lookup_state = lookup_state + .into_par_iter() + .map(eval_d8) + .collect::>(); let selector = selector.into_par_iter().map(eval_d8).collect::>(); WitnessColumns { scratch: scratch.try_into().unwrap(), scratch_inverse: scratch_inverse.try_into().unwrap(), + lookup_state, instruction_counter: eval_d8(instruction_counter), error: eval_d8(error), selector: selector.try_into().unwrap(), @@ -200,6 +215,9 @@ where for comm in commitments.scratch_inverse.iter() { absorb_commitment(&mut fq_sponge, comm) } + for comm in commitments.lookup_state.iter() { + absorb_commitment(&mut fq_sponge, comm) + } absorb_commitment(&mut fq_sponge, &commitments.instruction_counter); absorb_commitment(&mut fq_sponge, &commitments.error); for comm in commitments.selector.iter() { @@ -314,6 +332,7 @@ where let WitnessColumns { scratch, scratch_inverse, + lookup_state, instruction_counter, error, selector, @@ -321,10 +340,12 @@ where let eval = |poly: &DensePolynomial| poly.evaluate(point); let scratch = scratch.par_iter().map(eval).collect::>(); let scratch_inverse = scratch_inverse.par_iter().map(eval).collect::>(); + let lookup_state = lookup_state.par_iter().map(eval).collect::>(); let selector = selector.par_iter().map(eval).collect::>(); WitnessColumns { scratch: scratch.try_into().unwrap(), scratch_inverse: scratch_inverse.try_into().unwrap(), + lookup_state, instruction_counter: eval(instruction_counter), error: eval(error), selector: selector.try_into().unwrap(), @@ -375,6 +396,15 @@ where fr_sponge.absorb(zeta_eval); fr_sponge.absorb(zeta_omega_eval); } + + for (zeta_eval, zeta_omega_eval) in zeta_evaluations + .lookup_state + .iter() + .zip(zeta_omega_evaluations.lookup_state.iter()) + { + fr_sponge.absorb(zeta_eval); + fr_sponge.absorb(zeta_omega_eval); + } fr_sponge.absorb(&zeta_evaluations.instruction_counter); fr_sponge.absorb(&zeta_omega_evaluations.instruction_counter); fr_sponge.absorb(&zeta_evaluations.error); @@ -401,6 +431,7 @@ where let mut polynomials: Vec<_> = polys.scratch.into_iter().collect(); polynomials.extend(polys.scratch_inverse); + polynomials.extend(polys.lookup_state); polynomials.push(polys.instruction_counter); polynomials.push(polys.error); polynomials.extend(polys.selector); diff --git a/o1vm/src/pickles/verifier.rs b/o1vm/src/pickles/verifier.rs index 76ecd7e67b..87fe7b8719 100644 --- a/o1vm/src/pickles/verifier.rs +++ b/o1vm/src/pickles/verifier.rs @@ -99,6 +99,9 @@ where for comm in commitments.scratch_inverse.iter() { absorb_commitment(&mut fq_sponge, comm) } + for comm in commitments.lookup_state.iter() { + absorb_commitment(&mut fq_sponge, comm) + } absorb_commitment(&mut fq_sponge, &commitments.instruction_counter); absorb_commitment(&mut fq_sponge, &commitments.error); for comm in commitments.selector.iter() { @@ -148,6 +151,14 @@ where fr_sponge.absorb(zeta_eval); fr_sponge.absorb(zeta_omega_eval); } + for (zeta_eval, zeta_omega_eval) in zeta_evaluations + .lookup_state + .iter() + .zip(zeta_omega_evaluations.lookup_state.iter()) + { + fr_sponge.absorb(zeta_eval); + fr_sponge.absorb(zeta_omega_eval); + } fr_sponge.absorb(&zeta_evaluations.instruction_counter); fr_sponge.absorb(&zeta_omega_evaluations.instruction_counter); fr_sponge.absorb(&zeta_evaluations.error); @@ -204,7 +215,7 @@ where let u_chal = fr_sponge.challenge(); let u = u_chal.to_field(endo_r); - let mut evaluations: Vec<_> = get_all_columns() + let mut evaluations: Vec<_> = get_all_columns(column_eval.commitment.lookup_state.len()) .into_iter() .map(|column| { let commitment = column_eval From 8e3e7703f1ba1ff9acac728713159f4ac2ea58d2 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 11 Jan 2025 18:43:02 +0000 Subject: [PATCH 07/16] Record lookup values in the lookup state as they are generated --- o1vm/src/interpreters/mips/witness.rs | 32 +++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/o1vm/src/interpreters/mips/witness.rs b/o1vm/src/interpreters/mips/witness.rs index 95ecc0fb9f..f9e0d04a5a 100644 --- a/o1vm/src/interpreters/mips/witness.rs +++ b/o1vm/src/interpreters/mips/witness.rs @@ -22,6 +22,7 @@ use crate::{ }, lookups::{Lookup, LookupTableIDs}, preimage_oracle::PreImageOracleT, + ramlookup::LookupMode, utils::memory_size, }; use ark_ff::{Field, PrimeField}; @@ -93,7 +94,7 @@ pub struct Env { pub scratch_state: [Fp; SCRATCH_SIZE], pub scratch_state_inverse: [Fp; SCRATCH_SIZE_INVERSE], pub lookup_state_idx: usize, - pub lookup_state: Vec, + pub lookup_state: Vec, pub halt: bool, pub syscall_env: SyscallEnv, pub selector: usize, @@ -157,9 +158,32 @@ impl InterpreterEnv for Env) { - let values: Vec<_> = lookup.value.iter().map(|x| Fp::from(*x)).collect(); - if let Some(idx) = lookup.table_id.ix_by_value(values.as_slice()) { - match lookup.table_id { + let mut add_value = |x: Fp| { + self.lookup_state_idx += 1; + self.lookup_state.push(x); + }; + let Lookup { + table_id, + magnitude: numerator, + mode, + value: values, + } = lookup; + let values: Vec<_> = values.into_iter().map(|x| Fp::from(x)).collect(); + + // Add lookup numerator + match mode { + LookupMode::Write => add_value(Fp::from(numerator)), + LookupMode::Read => add_value(-Fp::from(numerator)), + }; + // Add lookup table ID + add_value(Fp::from(table_id.to_u32())); + // Add values + for value in values.iter() { + add_value(Fp::from(*value)); + } + + if let Some(idx) = table_id.ix_by_value(values.as_slice()) { + match table_id { LookupTableIDs::PadLookup => self.lookup_multiplicities.pad_lookup[idx] += 1, LookupTableIDs::RoundConstantsLookup => { self.lookup_multiplicities.round_constants_lookup[idx] += 1 From bcd22fe66cf5daac4b80c4efa3548ae1bc3aa33d Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 12 Jan 2025 11:14:17 +0000 Subject: [PATCH 08/16] Fixup msm tests --- msm/src/fec/mod.rs | 4 ++-- msm/src/ffa/mod.rs | 8 ++++---- msm/src/serialization/mod.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/msm/src/fec/mod.rs b/msm/src/fec/mod.rs index 6f0c17642c..5baca36c80 100644 --- a/msm/src/fec/mod.rs +++ b/msm/src/fec/mod.rs @@ -27,8 +27,8 @@ mod tests { type FECWitnessBuilderEnv = WitnessBuilderEnv< Fp, FECColumn, - { ::N_COL }, - { ::N_COL }, + { >::N_COL }, + { >::N_COL }, 0, 0, LookupTable, diff --git a/msm/src/ffa/mod.rs b/msm/src/ffa/mod.rs index 811e1e7dcf..ce2f98c41e 100644 --- a/msm/src/ffa/mod.rs +++ b/msm/src/ffa/mod.rs @@ -23,8 +23,8 @@ mod tests { type FFAWitnessBuilderEnv = WitnessBuilderEnv< Fp, FFAColumn, - { ::N_COL }, - { ::N_COL }, + { >::N_COL }, + { >::N_COL }, 0, 0, LookupTable, @@ -86,8 +86,8 @@ mod tests { let proof_inputs = witness_env.get_proof_inputs(domain_size, lookup_tables_data); crate::test::test_completeness_generic::< - { ::N_COL }, - { ::N_COL }, + { >::N_COL }, + { >::N_COL }, 0, 0, LookupTable, diff --git a/msm/src/serialization/mod.rs b/msm/src/serialization/mod.rs index 2cdabdc9f0..3d24d30e60 100644 --- a/msm/src/serialization/mod.rs +++ b/msm/src/serialization/mod.rs @@ -28,8 +28,8 @@ mod tests { type SerializationWitnessBuilderEnv = WitnessBuilderEnv< Fp, SerializationColumn, - { ::N_COL - N_FSEL_SER }, - { ::N_COL - N_FSEL_SER }, + { >::N_COL - N_FSEL_SER }, + { >::N_COL - N_FSEL_SER }, 0, N_FSEL_SER, LookupTable, From 16e617f439784730d59fa8adb112ab759c72bdaa Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 12 Jan 2025 11:18:03 +0000 Subject: [PATCH 09/16] Fixup compilation of IVC tests --- ivc/src/ivc/mod.rs | 4 ++-- ivc/src/poseidon_55_0_7_3_2/mod.rs | 4 ++-- ivc/src/poseidon_55_0_7_3_7/mod.rs | 4 ++-- ivc/src/poseidon_8_56_5_3_2/mod.rs | 4 ++-- ivc/tests/folding_ivc.rs | 6 +++--- ivc/tests/simple.rs | 8 ++++---- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ivc/src/ivc/mod.rs b/ivc/src/ivc/mod.rs index 95e0f805d3..4ba1025889 100644 --- a/ivc/src/ivc/mod.rs +++ b/ivc/src/ivc/mod.rs @@ -74,8 +74,8 @@ mod tests { type IVCWitnessBuilderEnvRaw = WitnessBuilderEnv< Fp, IVCColumn, - { ::N_COL - N_BLOCKS }, - { ::N_COL - N_BLOCKS }, + { >::N_COL - N_BLOCKS }, + { >::N_COL - N_BLOCKS }, 0, N_FSEL_IVC, LT, diff --git a/ivc/src/poseidon_55_0_7_3_2/mod.rs b/ivc/src/poseidon_55_0_7_3_2/mod.rs index 11e8d81b57..a2eb54521e 100644 --- a/ivc/src/poseidon_55_0_7_3_2/mod.rs +++ b/ivc/src/poseidon_55_0_7_3_2/mod.rs @@ -43,8 +43,8 @@ mod tests { type PoseidonWitnessBuilderEnv = WitnessBuilderEnv< Fp, TestPoseidonColumn, - { ::N_COL }, - { ::N_COL }, + { >::N_COL }, + { >::N_COL }, N_DSEL, N_FSEL, DummyLookupTable, diff --git a/ivc/src/poseidon_55_0_7_3_7/mod.rs b/ivc/src/poseidon_55_0_7_3_7/mod.rs index bfebe16ba6..bf16b3cc95 100644 --- a/ivc/src/poseidon_55_0_7_3_7/mod.rs +++ b/ivc/src/poseidon_55_0_7_3_7/mod.rs @@ -41,8 +41,8 @@ mod tests { type PoseidonWitnessBuilderEnv = WitnessBuilderEnv< Fp, TestPoseidonColumn, - { ::N_COL }, - { ::N_COL }, + { >::N_COL }, + { >::N_COL }, N_DSEL, N_FSEL, DummyLookupTable, diff --git a/ivc/src/poseidon_8_56_5_3_2/mod.rs b/ivc/src/poseidon_8_56_5_3_2/mod.rs index 66d7f6be84..5469693e06 100644 --- a/ivc/src/poseidon_8_56_5_3_2/mod.rs +++ b/ivc/src/poseidon_8_56_5_3_2/mod.rs @@ -32,8 +32,8 @@ mod tests { type PoseidonWitnessBuilderEnv = WitnessBuilderEnv< Fp, Column, - { ::N_COL }, - { ::N_COL }, + { >::N_COL }, + { >::N_COL }, N_DSEL, N_FSEL, DummyLookupTable, diff --git a/ivc/tests/folding_ivc.rs b/ivc/tests/folding_ivc.rs index 78e1b485c6..8382d41d40 100644 --- a/ivc/tests/folding_ivc.rs +++ b/ivc/tests/folding_ivc.rs @@ -71,7 +71,7 @@ fn test_regression_additional_columns_reduction_to_degree_2() { impl Witness for TestWitness {} impl FoldingConfig for TestConfig { - type Column = Column; + type Column = Column; type Selector = (); @@ -92,7 +92,7 @@ fn test_regression_additional_columns_reduction_to_degree_2() { struct Env; - impl FoldingEnv for Env { + impl FoldingEnv, Challenge, ()> for Env { type Structure = (); fn new( @@ -103,7 +103,7 @@ fn test_regression_additional_columns_reduction_to_degree_2() { todo!() } - fn col(&self, _col: Column, _curr_or_next: CurrOrNext, _side: Side) -> &[Fp] { + fn col(&self, _col: Column, _curr_or_next: CurrOrNext, _side: Side) -> &[Fp] { todo!() } diff --git a/ivc/tests/simple.rs b/ivc/tests/simple.rs index c43a9941d9..221c56ae95 100644 --- a/ivc/tests/simple.rs +++ b/ivc/tests/simple.rs @@ -67,10 +67,10 @@ pub enum AdditionColumn { C, } -impl ColumnIndexer for AdditionColumn { +impl ColumnIndexer for AdditionColumn { const N_COL: usize = 3; - fn to_column(self) -> Column { + fn to_column(self) -> Column { match self { AdditionColumn::A => Column::Relation(0), AdditionColumn::B => Column::Relation(1), @@ -119,7 +119,7 @@ pub fn heavy_test_simple_add() { const N_FSEL_TOTAL: usize = N_FSEL_IVC; // Total number of witness columns in IVC. The blocks are public selectors. - const N_WIT_IVC: usize = ::N_COL - N_FSEL_IVC; + const N_WIT_IVC: usize = >::N_COL - N_FSEL_IVC; // Number of witness columns in the circuit. // It consists of the columns of the inner circuit and the columns for the @@ -189,7 +189,7 @@ pub fn heavy_test_simple_add() { const N_ALPHAS: usize, > = StandardConfig< Curve, - Column, + Column, PlonkishChallenge, PlonkishInstance, // TODO check if it's quad or not PlonkishWitness, From 40ef225584857a42480dbb8cda741046e6d3db68 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 12 Jan 2025 11:25:10 +0000 Subject: [PATCH 10/16] Fixup compilation of pickles tests --- o1vm/src/interpreters/mips/tests_helpers.rs | 2 ++ o1vm/src/pickles/tests.rs | 30 ++++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/o1vm/src/interpreters/mips/tests_helpers.rs b/o1vm/src/interpreters/mips/tests_helpers.rs index bd1a29d1de..e42640bf1c 100644 --- a/o1vm/src/interpreters/mips/tests_helpers.rs +++ b/o1vm/src/interpreters/mips/tests_helpers.rs @@ -92,6 +92,8 @@ where scratch_state_idx_inverse: 0, scratch_state: [Fp::from(0); SCRATCH_SIZE], scratch_state_inverse: [Fp::from(0); SCRATCH_SIZE_INVERSE], + lookup_state_idx: 0, + lookup_state: vec![], lookup_multiplicities: LookupMultiplicities::new(), selector: crate::interpreters::mips::column::N_MIPS_SEL_COLS, halt: false, diff --git a/o1vm/src/pickles/tests.rs b/o1vm/src/pickles/tests.rs index b4bb102dc7..56afee502e 100644 --- a/o1vm/src/pickles/tests.rs +++ b/o1vm/src/pickles/tests.rs @@ -12,11 +12,15 @@ use crate::{ interpreter::{self, InterpreterEnv}, Instruction, }, - pickles::{verifier::verify, MAXIMUM_DEGREE_CONSTRAINTS, TOTAL_NUMBER_OF_CONSTRAINTS}, + pickles::{ + column_env::RelationColumnType, verifier::verify, MAXIMUM_DEGREE_CONSTRAINTS, + TOTAL_NUMBER_OF_CONSTRAINTS, + }, + E, }; use ark_ff::{Field, One, UniformRand, Zero}; use kimchi::circuits::{domains::EvaluationDomains, expr::Expr, gate::CurrOrNext}; -use kimchi_msm::{columns::Column, expr::E}; +use kimchi_msm::columns::Column; use log::debug; use mina_curves::pasta::{Fp, Fq, Pallas, PallasParameters}; use mina_poseidon::{ @@ -67,6 +71,7 @@ fn test_small_circuit() { evaluations: WitnessColumns { scratch: std::array::from_fn(|_| zero_to_n_minus_one(8)), scratch_inverse: std::array::from_fn(|_| (0..8).map(|_| Fq::zero()).collect()), + lookup_state: vec![], instruction_counter: zero_to_n_minus_one(8) .into_iter() .map(|x| x + Fq::one()) @@ -78,9 +83,26 @@ fn test_small_circuit() { }, }; let mut expr = Expr::zero(); - for i in 0..SCRATCH_SIZE + SCRATCH_SIZE_INVERSE + 2 { - expr += Expr::cell(Column::Relation(i), CurrOrNext::Curr); + for i in 0..SCRATCH_SIZE { + expr += Expr::cell( + Column::Relation(RelationColumnType::Scratch(i)), + CurrOrNext::Curr, + ); + } + for i in 0..SCRATCH_SIZE_INVERSE { + expr += Expr::cell( + Column::Relation(RelationColumnType::ScratchInverse(i)), + CurrOrNext::Curr, + ); } + expr += Expr::cell( + Column::Relation(RelationColumnType::InstructionCounter), + CurrOrNext::Curr, + ); + expr += Expr::cell( + Column::Relation(RelationColumnType::Error), + CurrOrNext::Curr, + ); let mut rng = make_test_rng(None); type BaseSponge = DefaultFqSponge; From 55b002ff1fe9a635391b60d9683c995c7115f732 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 12 Jan 2025 11:27:45 +0000 Subject: [PATCH 11/16] Fixup invered comparison, with clearer names and comments --- o1vm/src/pickles/main.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/o1vm/src/pickles/main.rs b/o1vm/src/pickles/main.rs index 9765a5988a..dd485c6099 100644 --- a/o1vm/src/pickles/main.rs +++ b/o1vm/src/pickles/main.rs @@ -97,16 +97,15 @@ pub fn cannon_main(args: cli::cannon::RunArgs) { } // Lookup state { - let lookup_state_size = std::cmp::max( - curr_proof_inputs.evaluations.lookup_state.len(), - mips_wit_env.lookup_state.len(), - ); + let proof_inputs_length = curr_proof_inputs.evaluations.lookup_state.len(); + let environment_length = mips_wit_env.lookup_state.len(); + let lookup_state_size = std::cmp::max(proof_inputs_length, environment_length); for idx in 0..lookup_state_size { - if idx < mips_wit_env.lookup_state.len() { - // We pad with 0s for dummy lookups. + if idx >= environment_length { + // We pad with 0s for dummy lookups missing from the environment. curr_proof_inputs.evaluations.lookup_state[idx].push(Fp::zero()); - } else if idx < curr_proof_inputs.evaluations.lookup_state.len() { - // We create a new column filled with 0s. + } else if idx >= proof_inputs_length { + // We create a new column filled with 0s in the proof inputs. let mut new_vec = vec![Fp::zero(); curr_proof_inputs.evaluations.instruction_counter.len()]; new_vec.push(Fp::from(mips_wit_env.lookup_state[idx])); From be2d89f9fe920771d46f69ee699a8ed32f28c8b1 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 12 Jan 2025 11:33:21 +0000 Subject: [PATCH 12/16] Why be productive when we can waste time with clippy :) --- o1vm/src/interpreters/mips/witness.rs | 2 +- o1vm/src/pickles/prover.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/o1vm/src/interpreters/mips/witness.rs b/o1vm/src/interpreters/mips/witness.rs index 254fb04764..f65c0ffc56 100644 --- a/o1vm/src/interpreters/mips/witness.rs +++ b/o1vm/src/interpreters/mips/witness.rs @@ -199,7 +199,7 @@ impl InterpreterEnv for Env Date: Sun, 12 Jan 2025 12:02:36 +0000 Subject: [PATCH 13/16] Push new_vec instead of writing to non-existent index --- o1vm/src/pickles/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/o1vm/src/pickles/main.rs b/o1vm/src/pickles/main.rs index dd485c6099..5087cd27ff 100644 --- a/o1vm/src/pickles/main.rs +++ b/o1vm/src/pickles/main.rs @@ -109,7 +109,7 @@ pub fn cannon_main(args: cli::cannon::RunArgs) { let mut new_vec = vec![Fp::zero(); curr_proof_inputs.evaluations.instruction_counter.len()]; new_vec.push(Fp::from(mips_wit_env.lookup_state[idx])); - curr_proof_inputs.evaluations.lookup_state[idx] = new_vec; + curr_proof_inputs.evaluations.lookup_state.push(new_vec); } else { // Push the value to the column. curr_proof_inputs.evaluations.lookup_state[idx] From adf572796a4fbdb6fbd23affa01bb80492ae3c78 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 12 Jan 2025 11:59:22 +0000 Subject: [PATCH 14/16] Fixup expr doc-test --- msm/src/expr.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/msm/src/expr.rs b/msm/src/expr.rs index 6b352981e4..5c21c6d62b 100644 --- a/msm/src/expr.rs +++ b/msm/src/expr.rs @@ -23,9 +23,10 @@ use crate::columns::Column; /// use kimchi::circuits::expr::{ConstantExprInner, ExprInner, Operations, Variable}; /// use kimchi::circuits::gate::CurrOrNext; /// use kimchi::circuits::berkeley_columns::BerkeleyChallengeTerm; -/// use kimchi_msm::columns::Column; +/// use kimchi_msm::columns::{Column as GenericColumn}; /// use kimchi_msm::expr::E; /// pub type Fp = ark_bn254::Fr; +/// pub type Column = GenericColumn; /// let x1 = E::::Atom( /// ExprInner::>, Column>::Cell(Variable { /// col: Column::Relation(1), From 487e282b384353d9112f33d1cece90a9a32eb519 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 12 Jan 2025 12:19:27 +0000 Subject: [PATCH 15/16] Fix copy-paste typo --- o1vm/src/pickles/column_env.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/o1vm/src/pickles/column_env.rs b/o1vm/src/pickles/column_env.rs index c3b5db78fa..e30d309117 100644 --- a/o1vm/src/pickles/column_env.rs +++ b/o1vm/src/pickles/column_env.rs @@ -70,9 +70,7 @@ impl WitnessColumns { match *col { Column::Relation(i) => match i { RelationColumnType::Scratch(i) => Some(&self.scratch[i]), - RelationColumnType::ScratchInverse(i) => { - Some(&self.scratch_inverse[i - SCRATCH_SIZE]) - } + RelationColumnType::ScratchInverse(i) => Some(&self.scratch_inverse[i]), RelationColumnType::LookupState(_) => todo!(), RelationColumnType::InstructionCounter => Some(&self.instruction_counter), RelationColumnType::Error => Some(&self.error), From 90eb0e511db6f2831c48df6971c6bf41c448f629 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Mon, 13 Jan 2025 17:18:58 +0000 Subject: [PATCH 16/16] Do TODO --- o1vm/src/pickles/column_env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/o1vm/src/pickles/column_env.rs b/o1vm/src/pickles/column_env.rs index e30d309117..f8eb37f5e0 100644 --- a/o1vm/src/pickles/column_env.rs +++ b/o1vm/src/pickles/column_env.rs @@ -71,7 +71,7 @@ impl WitnessColumns { Column::Relation(i) => match i { RelationColumnType::Scratch(i) => Some(&self.scratch[i]), RelationColumnType::ScratchInverse(i) => Some(&self.scratch_inverse[i]), - RelationColumnType::LookupState(_) => todo!(), + RelationColumnType::LookupState(i) => Some(&self.lookup_state[i]), RelationColumnType::InstructionCounter => Some(&self.instruction_counter), RelationColumnType::Error => Some(&self.error), },