diff --git a/kimchi/src/bench.rs b/kimchi/src/bench.rs index 57cd64ff80..97cb026a2e 100644 --- a/kimchi/src/bench.rs +++ b/kimchi/src/bench.rs @@ -77,12 +77,7 @@ impl BenchmarkCtx { } /// Produces a proof - pub fn create_proof( - &self, - ) -> ( - ProverProof, KIMCHI_COLS>, - Vec, - ) { + pub fn create_proof(&self) -> (ProverProof>, Vec) { // create witness let witness: [Vec; KIMCHI_COLS] = array::from_fn(|_| vec![1u32.into(); self.num_gates]); @@ -102,13 +97,7 @@ impl BenchmarkCtx { } #[allow(clippy::type_complexity)] - pub fn batch_verification( - &self, - batch: &[( - ProverProof, KIMCHI_COLS>, - Vec, - )], - ) { + pub fn batch_verification(&self, batch: &[(ProverProof>, Vec)]) { // verify the proof let batch: Vec<_> = batch .iter() diff --git a/kimchi/src/circuits/argument.rs b/kimchi/src/circuits/argument.rs index 2f862bf1d7..d4bde64d82 100644 --- a/kimchi/src/circuits/argument.rs +++ b/kimchi/src/circuits/argument.rs @@ -13,6 +13,7 @@ use serde::{Deserialize, Serialize}; use super::{ expr::{constraints::ExprOps, Cache, ConstantExpr, Constants}, gate::{CurrOrNext, GateType}, + wires::KIMCHI_COLS, }; use CurrOrNext::{Curr, Next}; @@ -36,8 +37,8 @@ pub enum ArgumentType { /// created with ArgumentData and F = Field or F = PrimeField, then the constraints /// are built as expressions of real field elements and can be evaluated directly on /// the witness without using the prover. -pub struct ArgumentEnv { - data: Option>, +pub struct ArgumentEnv { + data: Option>, phantom_data: PhantomData, } @@ -51,10 +52,14 @@ impl Default for ArgumentEnv { } } -impl> ArgumentEnv { +impl, const COLUMNS: usize> ArgumentEnv { /// Initialize the environment for creating constraints of real field elements that can be /// evaluated directly over the witness without the prover/verifier - pub fn create(witness: ArgumentWitness, coeffs: Vec, constants: Constants) -> Self { + pub fn create( + witness: ArgumentWitness, + coeffs: Vec, + constants: Constants, + ) -> Self { ArgumentEnv { data: Some(ArgumentData { witness, @@ -129,9 +134,9 @@ impl> ArgumentEnv { } /// Argument environment data for constraints of field elements -pub struct ArgumentData { +pub struct ArgumentData { /// Witness rows - pub witness: ArgumentWitness, + pub witness: ArgumentWitness, /// Gate coefficients pub coeffs: Vec, /// Constants @@ -139,14 +144,14 @@ pub struct ArgumentData { } /// Witness data for a argument -pub struct ArgumentWitness { +pub struct ArgumentWitness { /// Witness for current row - pub curr: Vec, + pub curr: [T; COLUMNS], /// Witness for next row - pub next: Vec, + pub next: [T; COLUMNS], } -impl std::ops::Index<(CurrOrNext, usize)> for ArgumentWitness { +impl std::ops::Index<(CurrOrNext, usize)> for ArgumentWitness { type Output = T; fn index(&self, idx: (CurrOrNext, usize)) -> &T { @@ -168,7 +173,10 @@ pub trait Argument { const CONSTRAINTS: u32; /// Constraints for this argument - fn constraint_checks>(env: &ArgumentEnv, cache: &mut Cache) -> Vec; + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + cache: &mut Cache, + ) -> Vec; /// Returns the set of constraints required to prove this argument. fn constraints(cache: &mut Cache) -> Vec> { diff --git a/kimchi/src/circuits/expr.rs b/kimchi/src/circuits/expr.rs index 393a69f728..3f153895ea 100644 --- a/kimchi/src/circuits/expr.rs +++ b/kimchi/src/circuits/expr.rs @@ -2660,13 +2660,20 @@ pub mod constraints { fn literal(x: F) -> Self; // Witness variable - fn witness(row: CurrOrNext, col: usize, env: Option<&ArgumentData>) -> Self; + fn witness( + row: CurrOrNext, + col: usize, + env: Option<&ArgumentData>, + ) -> Self; /// Coefficient - fn coeff(col: usize, env: Option<&ArgumentData>) -> Self; + fn coeff(col: usize, env: Option<&ArgumentData>) -> Self; /// Create a constant - fn constant(expr: ConstantExpr, env: Option<&ArgumentData>) -> Self; + fn constant( + expr: ConstantExpr, + env: Option<&ArgumentData>, + ) -> Self; /// Cache item fn cache(&self, cache: &mut Cache) -> Self; @@ -2726,15 +2733,22 @@ pub mod constraints { Expr::Constant(ConstantExpr::Literal(x)) } - fn witness(row: CurrOrNext, col: usize, _: Option<&ArgumentData>) -> Self { + fn witness( + row: CurrOrNext, + col: usize, + _: Option<&ArgumentData>, + ) -> Self { witness(col, row) } - fn coeff(col: usize, _: Option<&ArgumentData>) -> Self { + fn coeff(col: usize, _: Option<&ArgumentData>) -> Self { coeff(col) } - fn constant(expr: ConstantExpr, _: Option<&ArgumentData>) -> Self { + fn constant( + expr: ConstantExpr, + _: Option<&ArgumentData>, + ) -> Self { Expr::Constant(expr) } @@ -2784,21 +2798,28 @@ pub mod constraints { x } - fn witness(row: CurrOrNext, col: usize, env: Option<&ArgumentData>) -> Self { + fn witness( + row: CurrOrNext, + col: usize, + env: Option<&ArgumentData>, + ) -> Self { match env { Some(data) => data.witness[(row, col)], None => panic!("Missing witness"), } } - fn coeff(col: usize, env: Option<&ArgumentData>) -> Self { + fn coeff(col: usize, env: Option<&ArgumentData>) -> Self { match env { Some(data) => data.coeffs[col], None => panic!("Missing coefficients"), } } - fn constant(expr: ConstantExpr, env: Option<&ArgumentData>) -> Self { + fn constant( + expr: ConstantExpr, + env: Option<&ArgumentData>, + ) -> Self { match env { Some(data) => expr.value(&data.constants), None => panic!("Missing constants"), diff --git a/kimchi/src/circuits/gate.rs b/kimchi/src/circuits/gate.rs index 3163eeee5b..cdbd44a6a5 100644 --- a/kimchi/src/circuits/gate.rs +++ b/kimchi/src/circuits/gate.rs @@ -264,7 +264,8 @@ impl CircuitGate { zk_rows: cs.zk_rows, }; // Create the argument environment for the constraints over field elements - let env = ArgumentEnv::::create(argument_witness, self.coeffs.clone(), constants); + let env = + ArgumentEnv::::create(argument_witness, self.coeffs.clone(), constants); // Check the wiring (i.e. copy constraints) for this gate // Note: Gates can operated on row Curr or Curr and Next. @@ -299,7 +300,9 @@ impl CircuitGate { // TODO: implement the verification for the generic gate vec![] } - GateType::Poseidon => poseidon::Poseidon::constraint_checks(&env, &mut cache), + GateType::Poseidon => { + poseidon::Poseidon::constraint_checks::(&env, &mut cache) + } GateType::CompleteAdd => complete_add::CompleteAdd::constraint_checks(&env, &mut cache), GateType::VarBaseMul => varbasemul::VarbaseMul::constraint_checks(&env, &mut cache), GateType::EndoMul => endosclmul::EndosclMul::constraint_checks(&env, &mut cache), @@ -358,7 +361,7 @@ impl CircuitGate { &self, row: usize, witness: &[Vec; COLUMNS], - ) -> CircuitGateResult> { + ) -> CircuitGateResult> { // Get the part of the witness relevant to this gate let witness_curr: [F; COLUMNS] = (0..witness.len()) .map(|col| witness[col][row]) @@ -375,9 +378,9 @@ impl CircuitGate { [F::zero(); COLUMNS] }; - Ok(ArgumentWitness:: { - curr: witness_curr.to_vec(), - next: witness_next.to_vec(), + Ok(ArgumentWitness:: { + curr: witness_curr, + next: witness_next, }) } } diff --git a/kimchi/src/circuits/polynomials/complete_add.rs b/kimchi/src/circuits/polynomials/complete_add.rs index 578af66046..3b39b9d711 100644 --- a/kimchi/src/circuits/polynomials/complete_add.rs +++ b/kimchi/src/circuits/polynomials/complete_add.rs @@ -97,7 +97,10 @@ where const ARGUMENT_TYPE: ArgumentType = ArgumentType::Gate(GateType::CompleteAdd); const CONSTRAINTS: u32 = 7; - fn constraint_checks>(env: &ArgumentEnv, cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + cache: &mut Cache, + ) -> Vec { // This function makes 2 + 1 + 1 + 1 + 2 = 7 constraints let x1 = env.witness_curr(0); let y1 = env.witness_curr(1); diff --git a/kimchi/src/circuits/polynomials/endomul_scalar.rs b/kimchi/src/circuits/polynomials/endomul_scalar.rs index 731d7841e1..5e46d74432 100644 --- a/kimchi/src/circuits/polynomials/endomul_scalar.rs +++ b/kimchi/src/circuits/polynomials/endomul_scalar.rs @@ -167,7 +167,10 @@ where const ARGUMENT_TYPE: ArgumentType = ArgumentType::Gate(GateType::EndoMulScalar); const CONSTRAINTS: u32 = 11; - fn constraint_checks>(env: &ArgumentEnv, cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + cache: &mut Cache, + ) -> Vec { let n0 = env.witness_curr(0); let n8 = env.witness_curr(1); let a0 = env.witness_curr(2); diff --git a/kimchi/src/circuits/polynomials/endosclmul.rs b/kimchi/src/circuits/polynomials/endosclmul.rs index 8bbcb2e0b4..63156559c8 100644 --- a/kimchi/src/circuits/polynomials/endosclmul.rs +++ b/kimchi/src/circuits/polynomials/endosclmul.rs @@ -186,7 +186,10 @@ where const ARGUMENT_TYPE: ArgumentType = ArgumentType::Gate(GateType::EndoMul); const CONSTRAINTS: u32 = 11; - fn constraint_checks>(env: &ArgumentEnv, cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + cache: &mut Cache, + ) -> Vec { let b1 = env.witness_curr(11); let b2 = env.witness_curr(12); let b3 = env.witness_curr(13); diff --git a/kimchi/src/circuits/polynomials/foreign_field_add/circuitgates.rs b/kimchi/src/circuits/polynomials/foreign_field_add/circuitgates.rs index cc25e60565..289d31a6bf 100644 --- a/kimchi/src/circuits/polynomials/foreign_field_add/circuitgates.rs +++ b/kimchi/src/circuits/polynomials/foreign_field_add/circuitgates.rs @@ -142,7 +142,10 @@ where const ARGUMENT_TYPE: ArgumentType = ArgumentType::Gate(GateType::ForeignFieldAdd); const CONSTRAINTS: u32 = 4; - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { let foreign_modulus: [T; LIMB_COUNT] = array::from_fn(|i| env.coeff(i)); // stored as coefficient for better correspondance with the relation being proved diff --git a/kimchi/src/circuits/polynomials/foreign_field_mul/circuitgates.rs b/kimchi/src/circuits/polynomials/foreign_field_mul/circuitgates.rs index 4baa6a9eb9..b4e390ccd8 100644 --- a/kimchi/src/circuits/polynomials/foreign_field_mul/circuitgates.rs +++ b/kimchi/src/circuits/polynomials/foreign_field_mul/circuitgates.rs @@ -193,7 +193,10 @@ where const CONSTRAINTS: u32 = 11; // DEGREE is 4 - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { let mut constraints = vec![]; // diff --git a/kimchi/src/circuits/polynomials/generic.rs b/kimchi/src/circuits/polynomials/generic.rs index 77a985ad45..29bd71b825 100644 --- a/kimchi/src/circuits/polynomials/generic.rs +++ b/kimchi/src/circuits/polynomials/generic.rs @@ -74,7 +74,10 @@ where const ARGUMENT_TYPE: ArgumentType = ArgumentType::Gate(GateType::Generic); const CONSTRAINTS: u32 = 2; - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { // First generic gate let left_coeff1 = env.coeff(0); let right_coeff1 = env.coeff(1); diff --git a/kimchi/src/circuits/polynomials/poseidon.rs b/kimchi/src/circuits/polynomials/poseidon.rs index a636570d5b..b690ce45fd 100644 --- a/kimchi/src/circuits/polynomials/poseidon.rs +++ b/kimchi/src/circuits/polynomials/poseidon.rs @@ -337,7 +337,10 @@ where const ARGUMENT_TYPE: ArgumentType = ArgumentType::Gate(GateType::Poseidon); const CONSTRAINTS: u32 = 15; - fn constraint_checks>(env: &ArgumentEnv, cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + cache: &mut Cache, + ) -> Vec { let mut res = vec![]; let mut idx = 0; diff --git a/kimchi/src/circuits/polynomials/range_check/circuitgates.rs b/kimchi/src/circuits/polynomials/range_check/circuitgates.rs index f543aae001..6e4b3def8e 100644 --- a/kimchi/src/circuits/polynomials/range_check/circuitgates.rs +++ b/kimchi/src/circuits/polynomials/range_check/circuitgates.rs @@ -178,7 +178,10 @@ where // * Operates on Curr row // * Range constrain all limbs except vp0 and vp1 (barring plookup constraints, which are done elsewhere) // * Constrain that combining all limbs equals the limb stored in column 0 - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { // 1) Apply range constraints on the limbs // * Columns 1-2 are 12-bit copy constraints // * They are copied 3 rows ahead (to the final row) and are constrained by lookups @@ -279,7 +282,10 @@ where // * Operates on Curr and Next row // * Range constrain all limbs (barring plookup constraints, which are done elsewhere) // * Constrain that combining all limbs equals the value v2 stored in row Curr, column 0 - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { // 1) Apply range constraints on limbs for Curr row // * Column 2 is a 2-bit crumb let mut constraints = vec![crumb(&env.witness_curr(2))]; diff --git a/kimchi/src/circuits/polynomials/rot.rs b/kimchi/src/circuits/polynomials/rot.rs index 71bcdef994..e1ef1e4acb 100644 --- a/kimchi/src/circuits/polynomials/rot.rs +++ b/kimchi/src/circuits/polynomials/rot.rs @@ -213,7 +213,10 @@ where // (stored in coefficient as a power-of-two form) // * Operates on Curr row // * Shifts the words by `rot` bits and then adds the excess to obtain the rotated word. - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { // Check that the last 8 columns are 2-bit crumbs // C1..C8: x * (x - 1) * (x - 2) * (x - 3) = 0 let mut constraints = (7..KIMCHI_COLS) diff --git a/kimchi/src/circuits/polynomials/turshi.rs b/kimchi/src/circuits/polynomials/turshi.rs index 7a40b318ff..6a8a76fd85 100644 --- a/kimchi/src/circuits/polynomials/turshi.rs +++ b/kimchi/src/circuits/polynomials/turshi.rs @@ -772,7 +772,10 @@ where /// Generates the constraints for the Cairo initial claim and first memory checks /// Accesses Curr and Next rows - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { let pc_ini = env.witness_curr(0); // copy from public input let ap_ini = env.witness_curr(1); // copy from public input let pc_fin = env.witness_curr(2); // copy from public input @@ -809,7 +812,10 @@ where /// Generates the constraints for the Cairo instruction /// Accesses Curr and Next rows - fn constraint_checks>(env: &ArgumentEnv, cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + cache: &mut Cache, + ) -> Vec { // load all variables of the witness corresponding to Cairoinstruction gates let pc = env.witness_curr(0); let ap = env.witness_curr(1); @@ -955,7 +961,10 @@ where /// Generates the constraints for the Cairo flags /// Accesses Curr and Next rows - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { // Load current row let f_pc_abs = env.witness_curr(7); let f_pc_rel = env.witness_curr(8); @@ -1022,7 +1031,10 @@ where /// Generates the constraints for the Cairo transition /// Accesses Curr and Next rows (Next only first 3 entries) - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { // load computed updated registers let pcup = env.witness_curr(7); let apup = env.witness_curr(8); diff --git a/kimchi/src/circuits/polynomials/varbasemul.rs b/kimchi/src/circuits/polynomials/varbasemul.rs index a21f7305ab..9f9e524c0b 100644 --- a/kimchi/src/circuits/polynomials/varbasemul.rs +++ b/kimchi/src/circuits/polynomials/varbasemul.rs @@ -176,7 +176,10 @@ impl Point { } impl Point { - pub fn new_from_env>(&self, env: &ArgumentEnv) -> Point { + pub fn new_from_env, const COLUMNS: usize>( + &self, + env: &ArgumentEnv, + ) -> Point { Point::create(self.x.new_from_env(env), self.y.new_from_env(env)) } } @@ -287,7 +290,7 @@ trait FromWitness where F: PrimeField, { - fn new_from_env(&self, env: &ArgumentEnv) -> T; + fn new_from_env(&self, env: &ArgumentEnv) -> T; } impl FromWitness for Variable @@ -295,7 +298,7 @@ where F: PrimeField, T: ExprOps, { - fn new_from_env(&self, env: &ArgumentEnv) -> T { + fn new_from_env(&self, env: &ArgumentEnv) -> T { let column_to_index = |_| match self.col { Column::Witness(i) => i, _ => panic!("Can't get index from witness columns"), @@ -331,7 +334,10 @@ impl Layout { } } - fn new_from_env>(&self, env: &ArgumentEnv) -> Layout { + fn new_from_env, const COLUMNS: usize>( + &self, + env: &ArgumentEnv, + ) -> Layout { Layout { accs: self.accs.map(|point| point.new_from_env(env)), bits: self.bits.map(|var| var.new_from_env(env)), @@ -414,7 +420,10 @@ where const ARGUMENT_TYPE: ArgumentType = ArgumentType::Gate(GateType::VarBaseMul); const CONSTRAINTS: u32 = 21; - fn constraint_checks>(env: &ArgumentEnv, cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + cache: &mut Cache, + ) -> Vec { let Layout { base, accs, @@ -422,7 +431,7 @@ where ss, n_prev, n_next, - } = Layout::create().new_from_env::(env); + } = Layout::create().new_from_env::(env); // n' // = 2^5 * n + 2^4 b0 + 2^3 b1 + 2^2 b2 + 2^1 b3 + b4 diff --git a/kimchi/src/circuits/polynomials/xor.rs b/kimchi/src/circuits/polynomials/xor.rs index 431734926a..630df1d2c9 100644 --- a/kimchi/src/circuits/polynomials/xor.rs +++ b/kimchi/src/circuits/polynomials/xor.rs @@ -149,7 +149,10 @@ where // * Operates on Curr and Next rows // * Constrain the decomposition of `in1`, `in2` and `out` of multiples of 16 bits // * The actual XOR is performed thanks to the plookups of 4-bit XORs. - fn constraint_checks>(env: &ArgumentEnv, _cache: &mut Cache) -> Vec { + fn constraint_checks, const COLUMNS: usize>( + env: &ArgumentEnv, + _cache: &mut Cache, + ) -> Vec { let two = T::from(2u64); // in1 = in1_0 + in1_1 * 2^4 + in1_2 * 2^8 + in1_3 * 2^12 + next_in1 * 2^16 // in2 = in2_0 + in2_1 * 2^4 + in2_2 * 2^8 + in2_3 * 2^12 + next_in2 * 2^16