From 80dfd60052e503eb1e250e31aaf9ed276d5bbeb0 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 23 Apr 2024 22:31:23 +0200 Subject: [PATCH 001/121] add initial doc --- halo2_gadgets/src/ecc.rs | 80 +- halo2_gadgets/src/ecc/chip.rs | 117 ++- halo2_gadgets/src/ecc/chip/mul.rs | 23 +- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 10 +- halo2_gadgets/src/ecc/chip/mul_fixed.rs | 6 +- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 44 +- .../src/ecc/chip/mul_fixed/full_width.rs | 17 +- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 327 +------- halo2_gadgets/src/ecc/chip/witness_point.rs | 41 +- halo2_gadgets/src/ecc_opt.rs | 419 ++++++++++ halo2_gadgets/src/ecc_opt/chip.rs | 61 ++ halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs | 1 + .../src/ecc_opt/chip/mul_fixed/short.rs | 744 ++++++++++++++++++ .../src/ecc_opt/chip/witness_point.rs | 50 ++ halo2_gadgets/src/lib.rs | 3 + halo2_gadgets/src/sinsemilla.rs | 194 ++--- halo2_gadgets/src/sinsemilla/chip.rs | 263 +++++-- .../src/sinsemilla/chip/generator_table.rs | 123 +-- .../src/sinsemilla/chip/hash_to_point.rs | 224 ++---- halo2_gadgets/src/sinsemilla/merkle.rs | 55 +- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 198 +++-- halo2_gadgets/src/sinsemilla/primitives.rs | 66 +- halo2_gadgets/src/sinsemilla_opt.rs | 478 +++++++++++ halo2_gadgets/src/sinsemilla_opt/chip.rs | 56 ++ .../sinsemilla_opt/chip/generator_table.rs | 136 ++++ .../src/sinsemilla_opt/chip/hash_to_point.rs | 146 ++++ halo2_gadgets/src/sinsemilla_opt/merkle.rs | 3 + .../src/sinsemilla_opt/merkle/chip.rs | 75 ++ .../src/sinsemilla_opt/primitives.rs | 74 ++ halo2_gadgets/src/utilities/cond_swap.rs | 346 +------- .../src/utilities/lookup_range_check.rs | 712 +++++------------ halo2_gadgets/src/utilities_opt.rs | 4 + halo2_gadgets/src/utilities_opt/cond_swap.rs | 448 +++++++++++ .../src/utilities_opt/lookup_range_check.rs | 570 ++++++++++++++ 34 files changed, 4149 insertions(+), 1965 deletions(-) create mode 100644 halo2_gadgets/src/ecc_opt.rs create mode 100644 halo2_gadgets/src/ecc_opt/chip.rs create mode 100644 halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs create mode 100644 halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs create mode 100644 halo2_gadgets/src/ecc_opt/chip/witness_point.rs create mode 100644 halo2_gadgets/src/sinsemilla_opt.rs create mode 100644 halo2_gadgets/src/sinsemilla_opt/chip.rs create mode 100644 halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs create mode 100644 halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs create mode 100644 halo2_gadgets/src/sinsemilla_opt/merkle.rs create mode 100644 halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs create mode 100644 halo2_gadgets/src/sinsemilla_opt/primitives.rs create mode 100644 halo2_gadgets/src/utilities_opt.rs create mode 100644 halo2_gadgets/src/utilities_opt/cond_swap.rs create mode 100644 halo2_gadgets/src/utilities_opt/lookup_range_check.rs diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 4861a20e52..2bd1491565 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use halo2_proofs::{ arithmetic::CurveAffine, - circuit::{AssignedCell, Chip, Layouter, Value}, + circuit::{Chip, Layouter, Value}, plonk::Error, }; @@ -60,15 +60,6 @@ pub trait EccInstructions: value: Value, ) -> Result; - /// Witnesses the given constant point as a private input to the circuit. - /// This allows the point to be the identity, mapped to (0, 0) in - /// affine coordinates. - fn witness_point_from_constant( - &self, - layouter: &mut impl Layouter, - value: C, - ) -> Result; - /// Witnesses the given point as a private input to the circuit. /// This returns an error if the point is the identity. fn witness_point_non_id( @@ -120,15 +111,6 @@ pub trait EccInstructions: b: &B, ) -> Result; - /// Performs variable-base sign-scalar multiplication, returning `[sign] point` - /// `sign` must be in {-1, 1}. - fn mul_sign( - &self, - layouter: &mut impl Layouter, - sign: &AssignedCell, - point: &Self::Point, - ) -> Result; - /// Performs variable-base scalar multiplication, returning `[scalar] base`. fn mul( &self, @@ -249,7 +231,7 @@ impl> ScalarFixed { #[derive(Debug)] pub struct ScalarFixedShort> { chip: EccChip, - inner: EccChip::ScalarFixedShort, + pub(crate) inner: EccChip::ScalarFixedShort, } impl> ScalarFixedShort { @@ -393,8 +375,8 @@ impl + Clone + Debug + Eq> /// A point on a specific elliptic curve. #[derive(Copy, Clone, Debug)] pub struct Point + Clone + Debug + Eq> { - chip: EccChip, - inner: EccChip::Point, + pub(crate) chip: EccChip, + pub(crate) inner: EccChip::Point, } impl + Clone + Debug + Eq> Point { @@ -408,16 +390,6 @@ impl + Clone + Debug + Eq> Point, - value: C, - ) -> Result { - let point = chip.witness_point_from_constant(&mut layouter, value); - point.map(|inner| Point { chip, inner }) - } - /// Constrains this point to be equal in value to another point. pub fn constrain_equal> + Clone>( &self, @@ -460,21 +432,6 @@ impl + Clone + Debug + Eq> Point, - sign: &AssignedCell, - ) -> Result, Error> { - self.chip - .mul_sign(&mut layouter, sign, &self.inner) - .map(|point| Point { - chip: self.chip.clone(), - inner: point, - }) - } } /// The affine short Weierstrass x-coordinate of a point on a specific elliptic curve. @@ -617,7 +574,6 @@ impl> FixedPointShort { Self { chip, inner } } } - #[cfg(test)] pub(crate) mod tests { use ff::PrimeField; @@ -638,7 +594,7 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::utilities::lookup_range_check::LookupRangeCheckConfig; + use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -772,7 +728,10 @@ pub(crate) mod tests { #[allow(non_snake_case)] impl Circuit for MyCircuit { - type Config = EccConfig; + type Config = EccConfig< + TestFixedBases, + LookupRangeCheckConfig, + >; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -793,7 +752,6 @@ pub(crate) mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -808,13 +766,11 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = LookupRangeCheckConfig::configure( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); - EccChip::::configure(meta, advices, lagrange_coeffs, range_check) + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup_table); + EccChip::< + TestFixedBases, + LookupRangeCheckConfig, + >::configure(meta, advices, lagrange_coeffs, range_check) } fn synthesize( @@ -914,14 +870,6 @@ pub(crate) mod tests { )?; } - // Test variable-base sign-scalar multiplication - { - super::chip::mul_fixed::short::tests::test_mul_sign( - chip.clone(), - layouter.namespace(|| "variable-base sign-scalar mul"), - )?; - } - // Test full-width fixed-base scalar multiplication { super::chip::mul_fixed::full_width::tests::test_mul_fixed( diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 402020384b..f581e625c6 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -1,10 +1,7 @@ //! Chip implementations for the ECC gadgets. use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; -use crate::{ - sinsemilla::primitives as sinsemilla, - utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, -}; +use crate::utilities::{lookup_range_check::DefaultLookupRangeCheck, UtilitiesInstructions}; use arrayvec::ArrayVec; use ff::PrimeField; @@ -17,12 +14,12 @@ use pasta_curves::{arithmetic::CurveAffine, pallas}; use std::convert::TryInto; -pub(super) mod add; -pub(super) mod add_incomplete; +pub(crate) mod add; +pub(crate) mod add_incomplete; pub mod constants; -pub(super) mod mul; -pub(super) mod mul_fixed; -pub(super) mod witness_point; +pub(crate) mod mul; +pub(crate) mod mul_fixed; +pub(crate) mod witness_point; pub use constants::*; @@ -37,11 +34,11 @@ pub struct EccPoint { /// x-coordinate /// /// Stored as an `Assigned` to enable batching inversions. - x: AssignedCell, pallas::Base>, + pub(crate) x: AssignedCell, pallas::Base>, /// y-coordinate /// /// Stored as an `Assigned` to enable batching inversions. - y: AssignedCell, pallas::Base>, + pub(crate) y: AssignedCell, pallas::Base>, } impl EccPoint { @@ -77,7 +74,7 @@ impl EccPoint { } #[cfg(test)] - fn is_identity(&self) -> Value { + pub(crate) fn is_identity(&self) -> Value { self.x.value().map(|x| x.is_zero_vartime()) } } @@ -137,7 +134,10 @@ impl From for EccPoint { /// Configuration for [`EccChip`]. #[derive(Clone, Debug, Eq, PartialEq)] #[allow(non_snake_case)] -pub struct EccConfig> { +pub struct EccConfig< + FixedPoints: super::FixedPoints, + LookupRangeCheckConfig: DefaultLookupRangeCheck, +> { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], @@ -148,20 +148,20 @@ pub struct EccConfig> { add: add::Config, /// Variable-base scalar multiplication - mul: mul::Config, + mul: mul::Config, /// Fixed-base full-width scalar multiplication mul_fixed_full: mul_fixed::full_width::Config, /// Fixed-base signed short scalar multiplication - mul_fixed_short: mul_fixed::short::Config, + pub(crate) mul_fixed_short: mul_fixed::short::Config, /// Fixed-base mul using a base field element as a scalar - mul_fixed_base_field: mul_fixed::base_field_elem::Config, + mul_fixed_base_field: mul_fixed::base_field_elem::Config, /// Witness point - witness_point: witness_point::Config, + pub(crate) witness_point: witness_point::Config, /// Lookup range check using 10-bit lookup table - pub lookup_config: LookupRangeCheckConfig, + pub lookup_config: LookupRangeCheckConfig, } /// A trait representing the kind of scalar used with a particular `FixedPoint`. @@ -227,12 +227,19 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { /// An [`EccInstructions`] chip that uses 10 advice columns. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct EccChip> { - config: EccConfig, +pub struct EccChip< + FixedPoints: super::FixedPoints, + LookupRangeCheckConfig: DefaultLookupRangeCheck, +> { + config: EccConfig, } -impl> Chip for EccChip { - type Config = EccConfig; +impl< + FixedPoints: super::FixedPoints, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + > Chip for EccChip +{ + type Config = EccConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -244,13 +251,19 @@ impl> Chip for Ecc } } -impl> UtilitiesInstructions - for EccChip +impl< + Fixed: super::FixedPoints, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + > UtilitiesInstructions for EccChip { type Var = AssignedCell; } -impl> EccChip { +impl< + FixedPoints: super::FixedPoints, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + > EccChip +{ /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { Self { config } @@ -264,7 +277,7 @@ impl> EccChip { meta: &mut ConstraintSystem, advices: [Column; 10], lagrange_coeffs: [Column; 8], - range_check: LookupRangeCheckConfig, + range_check: LookupRangeCheckConfig, ) -> >::Config { // Create witness point gate let witness_point = witness_point::Config::configure(meta, advices[0], advices[1]); @@ -301,12 +314,13 @@ impl> EccChip { mul_fixed::short::Config::::configure(meta, mul_fixed.clone()); // Create gate that is only used in fixed-base mul using a base field element. - let mul_fixed_base_field = mul_fixed::base_field_elem::Config::::configure( - meta, - advices[6..9].try_into().unwrap(), - range_check, - mul_fixed, - ); + let mul_fixed_base_field = + mul_fixed::base_field_elem::Config::::configure( + meta, + advices[6..9].try_into().unwrap(), + range_check, + mul_fixed, + ); EccConfig { advices, @@ -339,7 +353,7 @@ pub struct EccScalarFixed { type MagnitudeCell = AssignedCell; // TODO: Make V an enum Sign { Positive, Negative } type SignCell = AssignedCell; -type MagnitudeSign = (MagnitudeCell, SignCell); +pub(crate) type MagnitudeSign = (MagnitudeCell, SignCell); /// A signed short scalar used for fixed-base scalar multiplication. /// A short scalar must have magnitude in the range [0..2^64), with @@ -407,7 +421,8 @@ pub enum ScalarVar { FullWidth, } -impl> EccInstructions for EccChip +impl, LookupRangeCheckConfig: DefaultLookupRangeCheck> + EccInstructions for EccChip where >::Base: FixedPoint, @@ -453,18 +468,6 @@ where ) } - fn witness_point_from_constant( - &self, - layouter: &mut impl Layouter, - value: pallas::Affine, - ) -> Result { - let config = self.config().witness_point; - layouter.assign_region( - || "witness point (constant)", - |mut region| config.constant_point(value, 0, &mut region), - ) - } - fn witness_point_non_id( &self, layouter: &mut impl Layouter, @@ -544,24 +547,6 @@ where ) } - /// Performs variable-base sign-scalar multiplication, returning `[sign] point` - /// `sign` must be in {-1, 1}. - fn mul_sign( - &self, - layouter: &mut impl Layouter, - sign: &AssignedCell, - point: &Self::Point, - ) -> Result { - // Multiply point by sign, using the same gate as mul_fixed::short. - // This also constrains sign to be in {-1, 1}. - let config_short = self.config().mul_fixed_short.clone(); - config_short.assign_scalar_sign( - layouter.namespace(|| "variable-base sign-scalar mul"), - sign, - point, - ) - } - fn mul( &self, layouter: &mut impl Layouter, @@ -624,8 +609,8 @@ where } } -impl> BaseFitsInScalarInstructions - for EccChip +impl, LookupRangeCheckConfig: DefaultLookupRangeCheck> + BaseFitsInScalarInstructions for EccChip where >::Base: FixedPoint, diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 8e857ae442..85677da520 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -1,7 +1,7 @@ use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q}; -use crate::{ - sinsemilla::primitives as sinsemilla, - utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig, ternary}, +use crate::utilities::{ + lookup_range_check::DefaultLookupRangeCheck, + {bool_check, ternary}, }; use std::{ convert::TryInto, @@ -46,7 +46,7 @@ const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, // Configuration used in complete addition @@ -58,14 +58,14 @@ pub struct Config { // Configuration used for complete addition part of double-and-add algorithm complete_config: complete::Config, // Configuration used to check for overflow - overflow_config: overflow::Config, + overflow_config: overflow::Config, } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, add_config: add::Config, - lookup_config: LookupRangeCheckConfig, + lookup_config: LookupRangeCheckConfig, advices: [Column; 10], ) -> Self { let hi_config = incomplete::Config::configure( @@ -467,6 +467,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; + use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; use crate::{ ecc::{ chip::{EccChip, EccPoint}, @@ -476,13 +477,13 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul( - chip: EccChip, + pub(crate) fn test_mul( + chip: EccChip, mut layouter: impl Layouter, - p: &NonIdentityPoint>, + p: &NonIdentityPoint>, p_val: pallas::Affine, ) -> Result<(), Error> { - let column = chip.config().advices[0]; + let column = chip.config.advices[0]; fn constrain_equal_non_id< EccChip: EccInstructions + Clone + Eq + std::fmt::Debug, diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index 12101ae82e..8adaefa311 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -1,6 +1,6 @@ use super::{T_Q, Z}; use crate::{ - sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::LookupRangeCheckConfig, + sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::DefaultLookupRangeCheck, }; use group::ff::PrimeField; @@ -15,19 +15,19 @@ use pasta_curves::pallas; use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, // 10-bit lookup table - lookup_config: LookupRangeCheckConfig, + lookup_config: LookupRangeCheckConfig, // Advice columns advices: [Column; 3], } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, - lookup_config: LookupRangeCheckConfig, + lookup_config: LookupRangeCheckConfig, advices: [Column; 3], ) -> Self { for advice in advices.iter() { diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed.rs b/halo2_gadgets/src/ecc/chip/mul_fixed.rs index d0781056b8..686cb6203e 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed.rs @@ -41,11 +41,11 @@ pub struct Config> { fixed_z: Column, // Decomposition of an `n-1`-bit scalar into `k`-bit windows: // a = a_0 + 2^k(a_1) + 2^{2k}(a_2) + ... + 2^{(n-1)k}(a_{n-1}) - window: Column, + pub(crate) window: Column, // y-coordinate of accumulator (only used in the final row). - u: Column, + pub(crate) u: Column, // Configuration for `add` - add_config: add::Config, + pub(crate) add_config: add::Config, // Configuration for `add_incomplete` add_incomplete_config: add_incomplete::Config, _marker: PhantomData, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 9a2b0c76ce..254ba6804c 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -1,10 +1,8 @@ use super::super::{EccBaseFieldElemFixed, EccPoint, FixedPoints, NUM_WINDOWS, T_P}; use super::H_BASE; -use crate::utilities::bool_check; -use crate::{ - sinsemilla::primitives as sinsemilla, - utilities::{bitrange_subset, lookup_range_check::LookupRangeCheckConfig, range_check}, +use crate::utilities::{ + bitrange_subset, bool_check, lookup_range_check::DefaultLookupRangeCheck, range_check, }; use group::ff::PrimeField; @@ -18,18 +16,23 @@ use pasta_curves::pallas; use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Config> { +pub struct Config< + Fixed: FixedPoints, + LookupRangeCheckConfig: DefaultLookupRangeCheck, +> { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], - lookup_config: LookupRangeCheckConfig, + lookup_config: LookupRangeCheckConfig, super_config: super::Config, } -impl> Config { +impl, LookupRangeCheckConfig: DefaultLookupRangeCheck> + Config +{ pub(crate) fn configure( meta: &mut ConstraintSystem, canon_advices: [Column; 3], - lookup_config: LookupRangeCheckConfig, + lookup_config: LookupRangeCheckConfig, super_config: super::Config, ) -> Self { for advice in canon_advices.iter() { @@ -388,6 +391,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; + use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; use crate::{ ecc::{ chip::{EccChip, FixedPoint, H}, @@ -397,8 +401,8 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul_fixed_base_field( - chip: EccChip, + pub(crate) fn test_mul_fixed_base_field( + chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { test_single_base( @@ -410,22 +414,22 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( - chip: EccChip, + fn test_single_base( + chip: EccChip, mut layouter: impl Layouter, - base: FixedPointBaseField>, + base: FixedPointBaseField>, base_val: pallas::Affine, ) -> Result<(), Error> { let rng = OsRng; let column = chip.config().advices[0]; - fn constrain_equal_non_id( - chip: EccChip, + fn constrain_equal_non_id( + chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, scalar_val: pallas::Base, - result: Point>, + result: Point>, ) -> Result<(), Error> { // Move scalar from base field into scalar field (which always fits for Pallas). let scalar = pallas::Scalar::from_repr(scalar_val.to_repr()).unwrap(); @@ -464,10 +468,10 @@ pub mod tests { { let h = pallas::Base::from(H as u64); let scalar_fixed = "1333333333333333333333333333333333333333333333333333333333333333333333333333333333334" - .chars() - .fold(pallas::Base::zero(), |acc, c| { - acc * &h + &pallas::Base::from(c.to_digit(8).unwrap() as u64) - }); + .chars() + .fold(pallas::Base::zero(), |acc, c| { + acc * &h + &pallas::Base::from(c.to_digit(8).unwrap() as u64) + }); let result = { let scalar_fixed = chip.load_private( layouter.namespace(|| "mul with double"), diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs index 886f86bbba..a06b1b9394 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs @@ -192,9 +192,10 @@ pub mod tests { tests::{FullWidth, TestFixedBases}, FixedPoint, NonIdentityPoint, Point, ScalarFixed, }; + use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; - pub(crate) fn test_mul_fixed( - chip: EccChip, + pub(crate) fn test_mul_fixed( + chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { let test_base = FullWidth::from_pallas_generator(); @@ -209,18 +210,18 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( - chip: EccChip, + fn test_single_base( + chip: EccChip, mut layouter: impl Layouter, - base: FixedPoint>, + base: FixedPoint>, base_val: pallas::Affine, ) -> Result<(), Error> { - fn constrain_equal_non_id( - chip: EccChip, + fn constrain_equal_non_id( + chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, scalar_val: pallas::Scalar, - result: Point>, + result: Point>, ) -> Result<(), Error> { let expected = NonIdentityPoint::new( chip, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index a10c54c1ed..8ce73ca3c6 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -4,7 +4,7 @@ use super::super::{EccPoint, EccScalarFixedShort, FixedPoints, L_SCALAR_SHORT, N use crate::{ecc::chip::MagnitudeSign, utilities::bool_check}; use halo2_proofs::{ - circuit::{AssignedCell, Layouter, Region}, + circuit::{Layouter, Region}, plonk::{ConstraintSystem, Constraints, Error, Expression, Selector}, poly::Rotation, }; @@ -13,8 +13,8 @@ use pasta_curves::pallas; #[derive(Clone, Debug, Eq, PartialEq)] pub struct Config> { // Selector used for fixed-base scalar mul with short signed exponent. - q_mul_fixed_short: Selector, - super_config: super::Config, + pub(crate) q_mul_fixed_short: Selector, + pub(crate) super_config: super::Config, } impl> Config { @@ -241,80 +241,20 @@ impl> Config { Ok((result, scalar)) } - - /// Multiply the point by sign, using the q_mul_fixed_short gate. - /// Constraints `sign` in {-1, 1} - pub fn assign_scalar_sign( - &self, - mut layouter: impl Layouter, - sign: &AssignedCell, - point: &EccPoint, - ) -> Result { - let signed_point = layouter.assign_region( - || "Signed point", - |mut region| { - let offset = 0; - - // Enable mul_fixed_short selector to check the sign logic. - self.q_mul_fixed_short.enable(&mut region, offset)?; - - // Set "last window" to 0 (this field is irrelevant here). - region.assign_advice_from_constant( - || "u=0", - self.super_config.u, - offset, - pallas::Base::zero(), - )?; - - // Copy sign to `window` column - sign.copy_advice(|| "sign", &mut region, self.super_config.window, offset)?; - - // Assign the input y-coordinate. - point.y.copy_advice( - || "unsigned y", - &mut region, - self.super_config.add_config.y_qr, - offset, - )?; - - // Conditionally negate y-coordinate according to the value of sign - let signed_y_val = sign.value().and_then(|sign| { - if sign == &-pallas::Base::one() { - -point.y.value() - } else { - point.y.value().cloned() - } - }); - - // Assign the output signed y-coordinate. - let signed_y = region.assign_advice( - || "signed y", - self.super_config.add_config.y_p, - offset, - || signed_y_val, - )?; - - Ok(EccPoint { - x: point.x.clone(), - y: signed_y, - }) - }, - )?; - - Ok(signed_point) - } } #[cfg(test)] pub mod tests { - use group::{ff::PrimeField, Curve, Group}; + use group::{ff::PrimeField, Curve}; use halo2_proofs::{ arithmetic::CurveAffine, circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{Any, Error}, }; use pasta_curves::pallas; + use std::marker::PhantomData; + use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheck}; use crate::{ ecc::{ chip::{EccChip, FixedPoint, MagnitudeSign}, @@ -325,16 +265,16 @@ pub mod tests { }; #[allow(clippy::op_ref)] - pub(crate) fn test_mul_fixed_short( - chip: EccChip, + pub(crate) fn test_mul_fixed_short( + chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { // test_short let base_val = Short.generator(); let test_short = FixedPointShort::from_inner(chip.clone(), Short); - fn load_magnitude_sign( - chip: EccChip, + fn load_magnitude_sign( + chip: EccChip, mut layouter: impl Layouter, magnitude: pallas::Base, sign: pallas::Base, @@ -351,12 +291,12 @@ pub mod tests { Ok((magnitude, sign)) } - fn constrain_equal_non_id( - chip: EccChip, + fn constrain_equal_non_id( + chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, scalar_val: pallas::Scalar, - result: Point>, + result: Point>, ) -> Result<(), Error> { let expected = NonIdentityPoint::new( chip, @@ -462,6 +402,8 @@ pub mod tests { Ok(()) } + // todo: fixit + #[test] fn invalid_magnitude_sign() { use crate::{ @@ -487,7 +429,10 @@ pub mod tests { } impl Circuit for MyCircuit { - type Config = EccConfig; + type Config = EccConfig< + TestFixedBases, + LookupRangeCheckConfig, + >; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -508,7 +453,6 @@ pub mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -524,13 +468,11 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = LookupRangeCheckConfig::configure( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); - EccChip::::configure(meta, advices, lagrange_coeffs, range_check) + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup_table); + EccChip::< + TestFixedBases, + LookupRangeCheckConfig, + >::configure(meta, advices, lagrange_coeffs, range_check) } fn synthesize( @@ -650,7 +592,7 @@ pub mod tests { )], }, VerifyFailure::Permutation { - column: (Any::Fixed, 10).into(), + column: (Any::Fixed, 9).into(), location: FailureLocation::OutsideRegion { row: 0 }, }, VerifyFailure::Permutation { @@ -725,223 +667,4 @@ pub mod tests { ); } } - - pub(crate) fn test_mul_sign( - chip: EccChip, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Generate a random non-identity point P - let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); - let p = Point::new( - chip.clone(), - layouter.namespace(|| "P"), - Value::known(p_val), - )?; - - // Create -P - let p_neg_val = -p_val; - let p_neg = Point::new( - chip.clone(), - layouter.namespace(|| "-P"), - Value::known(p_neg_val), - )?; - - // Create the identity point - let identity = Point::new( - chip.clone(), - layouter.namespace(|| "identity"), - Value::known(pallas::Point::identity().to_affine()), - )?; - - // Create -1 and 1 scalars - let pos_sign = chip.load_private( - layouter.namespace(|| "positive sign"), - chip.config().advices[0], - Value::known(pallas::Base::one()), - )?; - let neg_sign = chip.load_private( - layouter.namespace(|| "negative sign"), - chip.config().advices[1], - Value::known(-pallas::Base::one()), - )?; - - // [1] P == P - { - let result = p.mul_sign(layouter.namespace(|| "[1] P"), &pos_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p)?; - } - - // [-1] P == -P - { - let result = p.mul_sign(layouter.namespace(|| "[1] P"), &neg_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p_neg)?; - } - - // [1] 0 == 0 - { - let result = identity.mul_sign(layouter.namespace(|| "[1] O"), &pos_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; - } - - // [-1] 0 == 0 - { - let result = identity.mul_sign(layouter.namespace(|| "[-1] O"), &neg_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; - } - - Ok(()) - } - - #[test] - fn invalid_sign_in_mul_sign() { - use crate::{ecc::chip::EccConfig, utilities::UtilitiesInstructions}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::{FailureLocation, MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - - #[derive(Default)] - struct MyCircuit { - base: Value, - sign: Value, - } - - impl UtilitiesInstructions for MyCircuit { - type Var = AssignedCell; - } - - impl Circuit for MyCircuit { - type Config = EccConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let range_check = LookupRangeCheckConfig::configure( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); - EccChip::::configure(meta, advices, lagrange_coeffs, range_check) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let chip = EccChip::construct(config.clone()); - - let column = config.advices[0]; - - //let short_config = config.mul_fixed_short.clone(); - let base = Point::new(chip, layouter.namespace(|| "load base"), self.base)?; - - let sign = - self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; - - base.mul_sign(layouter.namespace(|| "[sign] base"), &sign)?; - - Ok(()) - } - } - - // Copied from halo2_proofs::dev::util - fn format_value(v: pallas::Base) -> String { - use ff::Field; - if v.is_zero_vartime() { - "0".into() - } else if v == pallas::Base::one() { - "1".into() - } else if v == -pallas::Base::one() { - "-1".into() - } else { - // Format value as hex. - let s = format!("{:?}", v); - // Remove leading zeroes. - let s = s.strip_prefix("0x").unwrap(); - let s = s.trim_start_matches('0'); - format!("0x{}", s) - } - } - - // Sign that is not +/- 1 should fail - // Generate a random non-identity point - let point = pallas::Point::random(rand::rngs::OsRng); - let circuit = MyCircuit { - base: Value::known(point.to_affine()), - sign: Value::known(pallas::Base::zero()), - }; - - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check").into(), - location: FailureLocation::InRegion { - region: (2, "Signed point").into(), - offset: 0, - }, - cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], - }, - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 3, - "negation_check" - ) - .into(), - location: FailureLocation::InRegion { - region: (2, "Signed point").into(), - offset: 0, - }, - cell_values: vec![ - ( - ((Any::Advice, 1).into(), 0).into(), - format_value(*point.to_affine().coordinates().unwrap().y()), - ), - ( - ((Any::Advice, 3).into(), 0).into(), - format_value(*point.to_affine().coordinates().unwrap().y()), - ), - (((Any::Advice, 4).into(), 0).into(), "0".to_string()), - ], - } - ]) - ); - } } diff --git a/halo2_gadgets/src/ecc/chip/witness_point.rs b/halo2_gadgets/src/ecc/chip/witness_point.rs index 98f865a6dc..580a07ca1d 100644 --- a/halo2_gadgets/src/ecc/chip/witness_point.rs +++ b/halo2_gadgets/src/ecc/chip/witness_point.rs @@ -12,14 +12,14 @@ use halo2_proofs::{ }; use pasta_curves::{arithmetic::CurveAffine, pallas}; -type Coordinates = ( +pub(crate) type Coordinates = ( AssignedCell, pallas::Base>, AssignedCell, pallas::Base>, ); #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { - q_point: Selector, + pub(crate) q_point: Selector, q_point_non_id: Selector, // x-coordinate pub x: Column, @@ -102,21 +102,6 @@ impl Config { Ok((x_var, y_var)) } - fn assign_xy_from_constant( - &self, - value: (Assigned, Assigned), - offset: usize, - region: &mut Region<'_, pallas::Base>, - ) -> Result { - // Assign `x` value - let x_var = region.assign_advice_from_constant(|| "x", self.x, offset, value.0)?; - - // Assign `y` value - let y_var = region.assign_advice_from_constant(|| "y", self.y, offset, value.1)?; - - Ok((x_var, y_var)) - } - /// Assigns a point that can be the identity. pub(super) fn point( &self, @@ -141,28 +126,6 @@ impl Config { .map(|(x, y)| EccPoint::from_coordinates_unchecked(x, y)) } - /// Assigns a constant point that can be the identity. - pub(super) fn constant_point( - &self, - value: pallas::Affine, - offset: usize, - region: &mut Region<'_, pallas::Base>, - ) -> Result { - // Enable `q_point` selector - self.q_point.enable(region, offset)?; - - let value = if value == pallas::Affine::identity() { - // Map the identity to (0, 0). - (Assigned::Zero, Assigned::Zero) - } else { - let value = value.coordinates().unwrap(); - (value.x().into(), value.y().into()) - }; - - self.assign_xy_from_constant(value, offset, region) - .map(|(x, y)| EccPoint::from_coordinates_unchecked(x, y)) - } - /// Assigns a non-identity point. pub(super) fn point_non_id( &self, diff --git a/halo2_gadgets/src/ecc_opt.rs b/halo2_gadgets/src/ecc_opt.rs new file mode 100644 index 0000000000..a8ed313c10 --- /dev/null +++ b/halo2_gadgets/src/ecc_opt.rs @@ -0,0 +1,419 @@ +//! Elliptic curve operations. + +use std::fmt::Debug; + +use halo2_proofs::{ + arithmetic::CurveAffine, + circuit::{AssignedCell, Layouter}, + plonk::Error, +}; + +use crate::ecc::{EccInstructions, Point}; + +pub(crate) mod chip; + +/// The set of circuit instructions required to use the ECC gadgets. +pub trait EccInstructionsOptimized: EccInstructions { + /// Witnesses the given constant point as a private input to the circuit. + /// This allows the point to be the identity, mapped to (0, 0) in + /// affine coordinates. + fn witness_point_from_constant( + &self, + layouter: &mut impl Layouter, + value: C, + ) -> Result; + + /// Performs variable-base sign-scalar multiplication, returning `[sign] point` + /// `sign` must be in {-1, 1}. + fn mul_sign( + &self, + layouter: &mut impl Layouter, + sign: &AssignedCell, + point: &Self::Point, + ) -> Result; +} + +impl + Clone + Debug + Eq> Point { + /// Constructs a new point with the given fixed value. + pub fn new_from_constant( + chip: EccChip, + mut layouter: impl Layouter, + value: C, + ) -> Result { + let point = chip.witness_point_from_constant(&mut layouter, value); + point.map(|inner| Point { chip, inner }) + } + + /// Returns `[sign] self`. + /// `sign` must be in {-1, 1}. + pub fn mul_sign( + &self, + mut layouter: impl Layouter, + sign: &AssignedCell, + ) -> Result, Error> { + self.chip + .mul_sign(&mut layouter, sign, &self.inner) + .map(|point| Point { + chip: self.chip.clone(), + inner: point, + }) + } +} + +#[cfg(test)] +pub(crate) mod tests { + use ff::PrimeField; + use group::{prime::PrimeCurveAffine, Curve, Group}; + + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use lazy_static::lazy_static; + use pasta_curves::pallas; + + use crate::ecc::{ + chip::{ + find_zs_and_us, BaseFieldElem, EccChip, EccConfig, FixedPoint, FullScalar, ShortScalar, + H, NUM_WINDOWS, NUM_WINDOWS_SHORT, + }, + FixedPoints, + }; + use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; + use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; + + #[derive(Debug, Eq, PartialEq, Clone)] + pub(crate) struct TestFixedBases; + #[derive(Debug, Eq, PartialEq, Clone)] + pub(crate) struct FullWidth(pallas::Affine, &'static [(u64, [pallas::Base; H])]); + #[derive(Debug, Eq, PartialEq, Clone)] + pub(crate) struct BaseField; + #[derive(Debug, Eq, PartialEq, Clone)] + pub(crate) struct Short; + + lazy_static! { + static ref BASE: pallas::Affine = pallas::Point::generator().to_affine(); + static ref ZS_AND_US: Vec<(u64, [pallas::Base; H])> = + find_zs_and_us(*BASE, NUM_WINDOWS).unwrap(); + static ref ZS_AND_US_SHORT: Vec<(u64, [pallas::Base; H])> = + find_zs_and_us(*BASE, NUM_WINDOWS_SHORT).unwrap(); + } + + impl FullWidth { + pub(crate) fn from_pallas_generator() -> Self { + FullWidth(*BASE, &ZS_AND_US) + } + + pub(crate) fn from_parts( + base: pallas::Affine, + zs_and_us: &'static [(u64, [pallas::Base; H])], + ) -> Self { + FullWidth(base, zs_and_us) + } + } + + impl FixedPoint for FullWidth { + type FixedScalarKind = FullScalar; + + fn generator(&self) -> pallas::Affine { + self.0 + } + + fn u(&self) -> Vec<[[u8; 32]; H]> { + self.1 + .iter() + .map(|(_, us)| { + [ + us[0].to_repr(), + us[1].to_repr(), + us[2].to_repr(), + us[3].to_repr(), + us[4].to_repr(), + us[5].to_repr(), + us[6].to_repr(), + us[7].to_repr(), + ] + }) + .collect() + } + + fn z(&self) -> Vec { + self.1.iter().map(|(z, _)| *z).collect() + } + } + + impl FixedPoint for BaseField { + type FixedScalarKind = BaseFieldElem; + + fn generator(&self) -> pallas::Affine { + *BASE + } + + fn u(&self) -> Vec<[[u8; 32]; H]> { + ZS_AND_US + .iter() + .map(|(_, us)| { + [ + us[0].to_repr(), + us[1].to_repr(), + us[2].to_repr(), + us[3].to_repr(), + us[4].to_repr(), + us[5].to_repr(), + us[6].to_repr(), + us[7].to_repr(), + ] + }) + .collect() + } + + fn z(&self) -> Vec { + ZS_AND_US.iter().map(|(z, _)| *z).collect() + } + } + + impl FixedPoint for Short { + type FixedScalarKind = ShortScalar; + + fn generator(&self) -> pallas::Affine { + *BASE + } + + fn u(&self) -> Vec<[[u8; 32]; H]> { + ZS_AND_US_SHORT + .iter() + .map(|(_, us)| { + [ + us[0].to_repr(), + us[1].to_repr(), + us[2].to_repr(), + us[3].to_repr(), + us[4].to_repr(), + us[5].to_repr(), + us[6].to_repr(), + us[7].to_repr(), + ] + }) + .collect() + } + + fn z(&self) -> Vec { + ZS_AND_US_SHORT.iter().map(|(z, _)| *z).collect() + } + } + + impl FixedPoints for TestFixedBases { + type FullScalar = FullWidth; + type ShortScalar = Short; + type Base = BaseField; + } + + struct MyCircuit { + test_errors: bool, + } + + #[allow(non_snake_case)] + impl Circuit for MyCircuit { + type Config = EccConfig< + crate::ecc::tests::TestFixedBases, + LookupRangeCheckConfigOptimized, + >; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + MyCircuit { test_errors: false } + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let lookup_table = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + EccChip::< + crate::ecc::tests::TestFixedBases, + LookupRangeCheckConfigOptimized, + >::configure(meta, advices, lagrange_coeffs, range_check) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = EccChip::construct(config.clone()); + + // Load 10-bit lookup table. In the Action circuit, this will be + // provided by the Sinsemilla chip. + config.lookup_config.load(&mut layouter)?; + + // Generate a random non-identity point P + let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P + let p = crate::ecc::NonIdentityPoint::new( + chip.clone(), + layouter.namespace(|| "P"), + Value::known(p_val), + )?; + let p_neg = -p_val; + let p_neg = crate::ecc::NonIdentityPoint::new( + chip.clone(), + layouter.namespace(|| "-P"), + Value::known(p_neg), + )?; + + // Generate a random non-identity point Q + let q_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // Q + let q = crate::ecc::NonIdentityPoint::new( + chip.clone(), + layouter.namespace(|| "Q"), + Value::known(q_val), + )?; + + // Make sure P and Q are not the same point. + assert_ne!(p_val, q_val); + + // Test that we can witness the identity as a point, but not as a non-identity point. + { + let _ = super::Point::new( + chip.clone(), + layouter.namespace(|| "identity"), + Value::known(pallas::Affine::identity()), + )?; + + crate::ecc::NonIdentityPoint::new( + chip.clone(), + layouter.namespace(|| "identity"), + Value::known(pallas::Affine::identity()), + ) + .expect_err("Trying to witness the identity should return an error"); + } + + // Test witness non-identity point + { + crate::ecc::chip::witness_point::tests::test_witness_non_id( + chip.clone(), + layouter.namespace(|| "witness non-identity point"), + ) + } + + // Test complete addition + { + crate::ecc::chip::add::tests::test_add( + chip.clone(), + layouter.namespace(|| "complete addition"), + p_val, + &p, + q_val, + &q, + &p_neg, + )?; + } + + // Test incomplete addition + { + crate::ecc::chip::add_incomplete::tests::test_add_incomplete( + chip.clone(), + layouter.namespace(|| "incomplete addition"), + p_val, + &p, + q_val, + &q, + &p_neg, + self.test_errors, + )?; + } + + // Test variable-base scalar multiplication + { + crate::ecc::chip::mul::tests::test_mul( + chip.clone(), + layouter.namespace(|| "variable-base scalar mul"), + &p, + p_val, + )?; + } + + // Test variable-base sign-scalar multiplication + { + super::chip::mul_fixed::short::tests::test_mul_sign( + chip.clone(), + layouter.namespace(|| "variable-base sign-scalar mul"), + )?; + } + + // Test full-width fixed-base scalar multiplication + { + crate::ecc::chip::mul_fixed::full_width::tests::test_mul_fixed( + chip.clone(), + layouter.namespace(|| "full-width fixed-base scalar mul"), + )?; + } + + // Test signed short fixed-base scalar multiplication + { + crate::ecc::chip::mul_fixed::short::tests::test_mul_fixed_short( + chip.clone(), + layouter.namespace(|| "signed short fixed-base scalar mul"), + )?; + } + + // Test fixed-base scalar multiplication with a base field element + { + crate::ecc::chip::mul_fixed::base_field_elem::tests::test_mul_fixed_base_field( + chip, + layouter.namespace(|| "fixed-base scalar mul with base field element"), + )?; + } + + Ok(()) + } + } + + #[test] + fn ecc_chip() { + let k = 13; + let circuit = MyCircuit { test_errors: true }; + let prover = MockProver::run(k, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())) + } + + #[cfg(feature = "test-dev-graph")] + #[test] + fn print_ecc_chip() { + use plotters::prelude::*; + + let root = BitMapBackend::new("ecc-chip-layout.png", (1024, 7680)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); + + let circuit = MyCircuit { test_errors: false }; + halo2_proofs::dev::CircuitLayout::default() + .render(13, &circuit, &root) + .unwrap(); + } +} diff --git a/halo2_gadgets/src/ecc_opt/chip.rs b/halo2_gadgets/src/ecc_opt/chip.rs new file mode 100644 index 0000000000..ed391881b3 --- /dev/null +++ b/halo2_gadgets/src/ecc_opt/chip.rs @@ -0,0 +1,61 @@ +//! Chip implementations for the ECC gadgets. + +use halo2_proofs::{ + circuit::{AssignedCell, Chip, Layouter}, + plonk::Error, +}; +use pasta_curves::pallas; + +use crate::{ + ecc::{ + chip::{BaseFieldElem, EccChip, FixedPoint, FullScalar, ShortScalar}, + FixedPoints, + }, + utilities::lookup_range_check::DefaultLookupRangeCheck, +}; + +use super::EccInstructionsOptimized; + +pub(crate) mod mul_fixed; +pub(super) mod witness_point; + +impl, LookupRangeCheckConfig: DefaultLookupRangeCheck> + EccInstructionsOptimized for EccChip +where + >::Base: + FixedPoint, + >::FullScalar: + FixedPoint, + >::ShortScalar: + FixedPoint, +{ + fn witness_point_from_constant( + &self, + layouter: &mut impl Layouter, + value: pallas::Affine, + ) -> Result { + let config = self.config().witness_point; + layouter.assign_region( + || "witness point (constant)", + |mut region| config.constant_point(value, 0, &mut region), + ) + } + + /// Performs variable-base sign-scalar multiplication, returning `[sign] point` + /// `sign` must be in {-1, 1}. + fn mul_sign( + &self, + layouter: &mut impl Layouter, + sign: &AssignedCell, + point: &Self::Point, + ) -> Result { + // Multiply point by sign, using the same gate as mul_fixed::short. + // This also constrains sign to be in {-1, 1}. + let config_short = self.config().mul_fixed_short.clone(); + config_short.assign_scalar_sign( + layouter.namespace(|| "variable-base sign-scalar mul"), + sign, + point, + ) + } +} diff --git a/halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs b/halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs new file mode 100644 index 0000000000..d1dea74e22 --- /dev/null +++ b/halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs @@ -0,0 +1 @@ +pub mod short; diff --git a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs new file mode 100644 index 0000000000..679bd5d2be --- /dev/null +++ b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs @@ -0,0 +1,744 @@ +use crate::ecc::chip::EccPoint; + +use super::super::FixedPoints; + +use halo2_proofs::{ + circuit::{AssignedCell, Layouter}, + plonk::Error, +}; +use pasta_curves::pallas; + +use crate::ecc::chip::mul_fixed::short::Config; + +impl> Config { + /// Multiply the point by sign, using the q_mul_fixed_short gate. + /// Constraints `sign` in {-1, 1} + pub fn assign_scalar_sign( + &self, + mut layouter: impl Layouter, + sign: &AssignedCell, + point: &EccPoint, + ) -> Result { + let signed_point = layouter.assign_region( + || "Signed point", + |mut region| { + let offset = 0; + + // Enable mul_fixed_short selector to check the sign logic. + self.q_mul_fixed_short.enable(&mut region, offset)?; + + // Set "last window" to 0 (this field is irrelevant here). + region.assign_advice_from_constant( + || "u=0", + self.super_config.u, + offset, + pallas::Base::zero(), + )?; + + // Copy sign to `window` column + sign.copy_advice(|| "sign", &mut region, self.super_config.window, offset)?; + + // Assign the input y-coordinate. + point.y.copy_advice( + || "unsigned y", + &mut region, + self.super_config.add_config.y_qr, + offset, + )?; + + // Conditionally negate y-coordinate according to the value of sign + let signed_y_val = sign.value().and_then(|sign| { + if sign == &-pallas::Base::one() { + -point.y.value() + } else { + point.y.value().cloned() + } + }); + + // Assign the output signed y-coordinate. + let signed_y = region.assign_advice( + || "signed y", + self.super_config.add_config.y_p, + offset, + || signed_y_val, + )?; + + Ok(EccPoint { + x: point.x.clone(), + y: signed_y, + }) + }, + )?; + + Ok(signed_point) + } +} + +#[cfg(test)] +pub mod tests { + use group::{ff::PrimeField, Curve, Group}; + use halo2_proofs::{ + arithmetic::CurveAffine, + circuit::{AssignedCell, Chip, Layouter, Value}, + plonk::{Any, Error}, + }; + use pasta_curves::pallas; + + use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheck}; + use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; + use crate::{ + ecc::{ + chip::{EccChip, FixedPoint, MagnitudeSign}, + tests::{Short, TestFixedBases}, + FixedPointShort, NonIdentityPoint, Point, ScalarFixedShort, + }, + utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, + }; + + #[allow(clippy::op_ref)] + pub(crate) fn test_mul_fixed_short( + chip: EccChip< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // test_short + let base_val = Short.generator(); + let test_short = FixedPointShort::from_inner(chip.clone(), Short); + + fn load_magnitude_sign( + chip: EccChip< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + mut layouter: impl Layouter, + magnitude: pallas::Base, + sign: pallas::Base, + ) -> Result { + let column = chip.config().advices[0]; + let magnitude = chip.load_private( + layouter.namespace(|| "magnitude"), + column, + Value::known(magnitude), + )?; + let sign = + chip.load_private(layouter.namespace(|| "sign"), column, Value::known(sign))?; + + Ok((magnitude, sign)) + } + + fn constrain_equal_non_id( + chip: EccChip< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + mut layouter: impl Layouter, + base_val: pallas::Affine, + scalar_val: pallas::Scalar, + result: Point< + pallas::Affine, + EccChip< + TestFixedBases, + LookupRangeCheckConfigOptimized< + pallas::Base, + { crate::sinsemilla::primitives::K }, + >, + >, + >, + ) -> Result<(), Error> { + let expected = NonIdentityPoint::new( + chip, + layouter.namespace(|| "expected point"), + Value::known((base_val * scalar_val).to_affine()), + )?; + result.constrain_equal(layouter.namespace(|| "constrain result"), &expected) + } + + let magnitude_signs = [ + ("random [a]B", pallas::Base::from(rand::random::()), { + let mut random_sign = pallas::Base::one(); + if rand::random::() { + random_sign = -random_sign; + } + random_sign + }), + ( + "[2^64 - 1]B", + pallas::Base::from(0xFFFF_FFFF_FFFF_FFFFu64), + pallas::Base::one(), + ), + ( + "-[2^64 - 1]B", + pallas::Base::from(0xFFFF_FFFF_FFFF_FFFFu64), + -pallas::Base::one(), + ), + // There is a single canonical sequence of window values for which a doubling occurs on the last step: + // 1333333333333333333334 in octal. + // [0xB6DB_6DB6_DB6D_B6DC] B + ( + "mul_with_double", + pallas::Base::from(0xB6DB_6DB6_DB6D_B6DCu64), + pallas::Base::one(), + ), + ( + "mul_with_double negative", + pallas::Base::from(0xB6DB_6DB6_DB6D_B6DCu64), + -pallas::Base::one(), + ), + ]; + + for (name, magnitude, sign) in magnitude_signs.iter() { + let (result, _) = { + let magnitude_sign = load_magnitude_sign( + chip.clone(), + layouter.namespace(|| *name), + *magnitude, + *sign, + )?; + let by = ScalarFixedShort::new( + chip.clone(), + layouter.namespace(|| "signed short scalar"), + magnitude_sign, + )?; + test_short.mul(layouter.namespace(|| *name), by)? + }; + // Move from base field into scalar field + let scalar = { + let magnitude = pallas::Scalar::from_repr(magnitude.to_repr()).unwrap(); + let sign = if *sign == pallas::Base::one() { + pallas::Scalar::one() + } else { + -pallas::Scalar::one() + }; + magnitude * sign + }; + constrain_equal_non_id( + chip.clone(), + layouter.namespace(|| *name), + base_val, + scalar, + result, + )?; + } + + let zero_magnitude_signs = [ + ("mul by +zero", pallas::Base::zero(), pallas::Base::one()), + ("mul by -zero", pallas::Base::zero(), -pallas::Base::one()), + ]; + + for (name, magnitude, sign) in zero_magnitude_signs.iter() { + let (result, _) = { + let magnitude_sign = load_magnitude_sign( + chip.clone(), + layouter.namespace(|| *name), + *magnitude, + *sign, + )?; + let by = ScalarFixedShort::new( + chip.clone(), + layouter.namespace(|| "signed short scalar"), + magnitude_sign, + )?; + test_short.mul(layouter.namespace(|| *name), by)? + }; + result + .inner() + .is_identity() + .assert_if_known(|is_identity| *is_identity); + } + + Ok(()) + } + + #[test] + fn invalid_magnitude_sign() { + use crate::{ + ecc::chip::{EccConfig, FixedPoint}, + utilities::UtilitiesInstructions, + }; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner}, + dev::{FailureLocation, MockProver, VerifyFailure}, + plonk::{Circuit, ConstraintSystem, Error}, + }; + + #[derive(Default)] + struct MyCircuit { + magnitude: Value, + sign: Value, + // For test checking + magnitude_error: Value, + } + + impl UtilitiesInstructions for MyCircuit { + type Var = AssignedCell; + } + + impl Circuit for MyCircuit { + type Config = EccConfig< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let lookup_table = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + EccChip::< + TestFixedBases, + LookupRangeCheckConfigOptimized< + pallas::Base, + { crate::sinsemilla::primitives::K }, + >, + >::configure(meta, advices, lagrange_coeffs, range_check) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let column = config.advices[0]; + + let short_config = config.mul_fixed_short.clone(); + let magnitude_sign = { + let magnitude = self.load_private( + layouter.namespace(|| "load magnitude"), + column, + self.magnitude, + )?; + let sign = + self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; + ScalarFixedShort::new( + EccChip::construct(config), + layouter.namespace(|| "signed short scalar"), + (magnitude, sign), + )? + }; + + short_config.assign(layouter, &magnitude_sign.inner, &Short)?; + + Ok(()) + } + } + + // Copied from halo2_proofs::dev::util + fn format_value(v: pallas::Base) -> String { + use ff::Field; + if v.is_zero_vartime() { + "0".into() + } else if v == pallas::Base::one() { + "1".into() + } else if v == -pallas::Base::one() { + "-1".into() + } else { + // Format value as hex. + let s = format!("{:?}", v); + // Remove leading zeroes. + let s = s.strip_prefix("0x").unwrap(); + let s = s.trim_start_matches('0'); + format!("0x{}", s) + } + } + + // Magnitude larger than 64 bits should fail + { + let circuits = [ + // 2^64 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 64)), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 1)), + }, + // -2^64 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 64)), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 1)), + }, + // 2^66 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 66)), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 3)), + }, + // -2^66 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 66)), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 3)), + }, + // 2^254 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known( + pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), + ), + }, + // -2^254 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known( + pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), + ), + }, + ]; + + for circuit in circuits.iter() { + let prover = MockProver::::run(11, circuit, vec![]).unwrap(); + circuit.magnitude_error.assert_if_known(|magnitude_error| { + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 0, + "last_window_check", + ) + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)") + .into(), + offset: 1, + }, + cell_values: vec![( + ((Any::Advice, 5).into(), 0).into(), + format_value(*magnitude_error), + )], + }, + VerifyFailure::Permutation { + column: (Any::Fixed, 10).into(), + location: FailureLocation::OutsideRegion { row: 0 }, + }, + VerifyFailure::Permutation { + column: (Any::Advice, 4).into(), + location: FailureLocation::InRegion { + region: (2, "Short fixed-base mul (incomplete addition)") + .into(), + offset: 22, + }, + }, + ]) + ); + true + }); + } + } + + // Sign that is not +/- 1 should fail + { + let magnitude_u64 = rand::random::(); + let circuit = MyCircuit { + magnitude: Value::known(pallas::Base::from(magnitude_u64)), + sign: Value::known(pallas::Base::zero()), + magnitude_error: Value::unknown(), + }; + + let negation_check_y = { + *(Short.generator() * pallas::Scalar::from(magnitude_u64)) + .to_affine() + .coordinates() + .unwrap() + .y() + }; + + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check") + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)").into(), + offset: 1, + }, + cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], + }, + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 3, + "negation_check" + ) + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)").into(), + offset: 1, + }, + cell_values: vec![ + ( + ((Any::Advice, 1).into(), 0).into(), + format_value(negation_check_y), + ), + ( + ((Any::Advice, 3).into(), 0).into(), + format_value(negation_check_y), + ), + (((Any::Advice, 4).into(), 0).into(), "0".to_string()), + ], + } + ]) + ); + } + } + + pub(crate) fn test_mul_sign( + chip: EccChip, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Generate a random non-identity point P + let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); + let p = Point::new( + chip.clone(), + layouter.namespace(|| "P"), + Value::known(p_val), + )?; + + // Create -P + let p_neg_val = -p_val; + let p_neg = Point::new( + chip.clone(), + layouter.namespace(|| "-P"), + Value::known(p_neg_val), + )?; + + // Create the identity point + let identity = Point::new( + chip.clone(), + layouter.namespace(|| "identity"), + Value::known(pallas::Point::identity().to_affine()), + )?; + + // Create -1 and 1 scalars + let pos_sign = chip.load_private( + layouter.namespace(|| "positive sign"), + chip.config().advices[0], + Value::known(pallas::Base::one()), + )?; + let neg_sign = chip.load_private( + layouter.namespace(|| "negative sign"), + chip.config().advices[1], + Value::known(-pallas::Base::one()), + )?; + + // [1] P == P + { + let result = p.mul_sign(layouter.namespace(|| "[1] P"), &pos_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p)?; + } + + // [-1] P == -P + { + let result = p.mul_sign(layouter.namespace(|| "[1] P"), &neg_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p_neg)?; + } + + // [1] 0 == 0 + { + let result = identity.mul_sign(layouter.namespace(|| "[1] O"), &pos_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; + } + + // [-1] 0 == 0 + { + let result = identity.mul_sign(layouter.namespace(|| "[-1] O"), &neg_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; + } + + Ok(()) + } + + #[test] + fn invalid_sign_in_mul_sign() { + use crate::{ecc::chip::EccConfig, utilities::UtilitiesInstructions}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner}, + dev::{FailureLocation, MockProver, VerifyFailure}, + plonk::{Circuit, ConstraintSystem, Error}, + }; + + #[derive(Default)] + struct MyCircuit { + base: Value, + sign: Value, + } + + impl UtilitiesInstructions for MyCircuit { + type Var = AssignedCell; + } + + impl Circuit for MyCircuit { + type Config = EccConfig< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let lookup_table = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + EccChip::< + TestFixedBases, + LookupRangeCheckConfigOptimized< + pallas::Base, + { crate::sinsemilla::primitives::K }, + >, + >::configure(meta, advices, lagrange_coeffs, range_check) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = EccChip::construct(config.clone()); + + let column = config.advices[0]; + + //let short_config = config.mul_fixed_short.clone(); + let base = Point::new(chip, layouter.namespace(|| "load base"), self.base)?; + + let sign = + self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; + + base.mul_sign(layouter.namespace(|| "[sign] base"), &sign)?; + + Ok(()) + } + } + + // Copied from halo2_proofs::dev::util + fn format_value(v: pallas::Base) -> String { + use ff::Field; + if v.is_zero_vartime() { + "0".into() + } else if v == pallas::Base::one() { + "1".into() + } else if v == -pallas::Base::one() { + "-1".into() + } else { + // Format value as hex. + let s = format!("{:?}", v); + // Remove leading zeroes. + let s = s.strip_prefix("0x").unwrap(); + let s = s.trim_start_matches('0'); + format!("0x{}", s) + } + } + + // Sign that is not +/- 1 should fail + // Generate a random non-identity point + let point = pallas::Point::random(rand::rngs::OsRng); + let circuit = MyCircuit { + base: Value::known(point.to_affine()), + sign: Value::known(pallas::Base::zero()), + }; + + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check").into(), + location: FailureLocation::InRegion { + region: (2, "Signed point").into(), + offset: 0, + }, + cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], + }, + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 3, + "negation_check" + ) + .into(), + location: FailureLocation::InRegion { + region: (2, "Signed point").into(), + offset: 0, + }, + cell_values: vec![ + ( + ((Any::Advice, 1).into(), 0).into(), + format_value(*point.to_affine().coordinates().unwrap().y()), + ), + ( + ((Any::Advice, 3).into(), 0).into(), + format_value(*point.to_affine().coordinates().unwrap().y()), + ), + (((Any::Advice, 4).into(), 0).into(), "0".to_string()), + ], + } + ]) + ); + } +} diff --git a/halo2_gadgets/src/ecc_opt/chip/witness_point.rs b/halo2_gadgets/src/ecc_opt/chip/witness_point.rs new file mode 100644 index 0000000000..9e1bfeae6d --- /dev/null +++ b/halo2_gadgets/src/ecc_opt/chip/witness_point.rs @@ -0,0 +1,50 @@ +use crate::ecc::chip::EccPoint; + +use group::prime::PrimeCurveAffine; + +use halo2_proofs::{ + circuit::Region, + plonk::{Assigned, Error}, +}; +use pasta_curves::{arithmetic::CurveAffine, pallas}; + +use crate::ecc::chip::witness_point::{Config, Coordinates}; + +impl Config { + fn assign_xy_from_constant( + &self, + value: (Assigned, Assigned), + offset: usize, + region: &mut Region<'_, pallas::Base>, + ) -> Result { + // Assign `x` value + let x_var = region.assign_advice_from_constant(|| "x", self.x, offset, value.0)?; + + // Assign `y` value + let y_var = region.assign_advice_from_constant(|| "y", self.y, offset, value.1)?; + + Ok((x_var, y_var)) + } + + /// Assigns a constant point that can be the identity. + pub(crate) fn constant_point( + &self, + value: pallas::Affine, + offset: usize, + region: &mut Region<'_, pallas::Base>, + ) -> Result { + // Enable `q_point` selector + self.q_point.enable(region, offset)?; + + let value = if value == pallas::Affine::identity() { + // Map the identity to (0, 0). + (Assigned::Zero, Assigned::Zero) + } else { + let value = value.coordinates().unwrap(); + (value.x().into(), value.y().into()) + }; + + self.assign_xy_from_constant(value, offset, region) + .map(|(x, y)| EccPoint::from_coordinates_unchecked(x, y)) + } +} diff --git a/halo2_gadgets/src/lib.rs b/halo2_gadgets/src/lib.rs index 2ac2623a99..33ffcfa6b8 100644 --- a/halo2_gadgets/src/lib.rs +++ b/halo2_gadgets/src/lib.rs @@ -22,9 +22,12 @@ #![deny(unsafe_code)] pub mod ecc; +pub mod ecc_opt; pub mod poseidon; #[cfg(feature = "unstable-sha256-gadget")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable-sha256-gadget")))] pub mod sha256; pub mod sinsemilla; +pub mod sinsemilla_opt; pub mod utilities; +pub mod utilities_opt; diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index e57c0a2129..d518c341cc 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -15,7 +15,7 @@ use std::fmt::Debug; pub mod chip; pub mod merkle; -mod message; +pub(crate) mod message; pub mod primitives; /// The set of circuit instructions required to use the [`Sinsemilla`](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html) gadget. @@ -78,30 +78,17 @@ pub trait SinsemillaInstructions, + is_Q_public: bool, Q: C, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec), Error>; - /// Hashes a message to an ECC curve point. - /// This returns both the resulting point, as well as the message - /// decomposition in the form of intermediate values in a cumulative - /// sum. - /// The initial point `Q` is a private point. - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( - &self, - layouter: impl Layouter, - Q: &Self::NonIdentityPoint, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec), Error>; - /// Extracts the x-coordinate of the output of a Sinsemilla hash. fn extract(point: &Self::NonIdentityPoint) -> Self::X; } @@ -116,8 +103,8 @@ pub struct Message + Clone + Debug + Eq, { - chip: SinsemillaChip, - inner: SinsemillaChip::Message, + pub(crate) chip: SinsemillaChip, + pub(crate) inner: SinsemillaChip::Message, } impl @@ -126,7 +113,7 @@ where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, { #![allow(dead_code)] - fn from_bitstring( + pub(crate) fn from_bitstring( chip: SinsemillaChip, mut layouter: impl Layouter, bitstring: Vec>, @@ -200,7 +187,7 @@ where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, { #![allow(dead_code)] - fn from_bitstring( + pub(crate) fn from_bitstring( chip: SinsemillaChip, layouter: impl Layouter, bitstring: &[Value], @@ -297,9 +284,9 @@ pub struct HashDomain< + Debug + Eq, { - sinsemilla_chip: SinsemillaChip, - ecc_chip: EccChip, - Q: C, + pub(crate) sinsemilla_chip: SinsemillaChip, + pub(crate) ecc_chip: EccChip, + pub(crate) Q: C, } impl @@ -335,26 +322,12 @@ where pub fn hash_to_point( &self, layouter: impl Layouter, + is_Q_public: bool, message: Message, ) -> Result<(ecc::NonIdentityPoint, Vec), Error> { assert_eq!(self.sinsemilla_chip, message.chip); self.sinsemilla_chip - .hash_to_point(layouter, self.Q, message.inner) - .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) - } - - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - /// Evaluate the Sinsemilla hash of `message` from the private initial point `Q`. - pub fn hash_to_point_with_private_init( - &self, - layouter: impl Layouter, - Q: &>::NonIdentityPoint, - message: Message, - ) -> Result<(ecc::NonIdentityPoint, Vec), Error> { - assert_eq!(self.sinsemilla_chip, message.chip); - self.sinsemilla_chip - .hash_to_point_with_private_init(layouter, Q, message.inner) + .hash_to_point(layouter, is_Q_public, self.Q, message.inner) .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) } @@ -365,10 +338,11 @@ where pub fn hash( &self, layouter: impl Layouter, + is_Q_public: bool, message: Message, ) -> Result<(ecc::X, Vec), Error> { assert_eq!(self.sinsemilla_chip, message.chip); - let (p, zs) = self.hash_to_point(layouter, message)?; + let (p, zs) = self.hash_to_point(layouter, is_Q_public, message)?; Ok((p.extract_p(), zs)) } } @@ -412,8 +386,8 @@ pub struct CommitDomain< + Debug + Eq, { - M: HashDomain, - R: ecc::FixedPoint, + pub(crate) M: HashDomain, + pub(crate) R: ecc::FixedPoint, } impl @@ -441,63 +415,6 @@ where } } - #[allow(clippy::type_complexity)] - /// Evaluates the Sinsemilla hash of `message` from the public initial point `Q` stored - /// into `CommitDomain`. - pub fn hash( - &self, - layouter: impl Layouter, - message: Message, - ) -> Result< - ( - ecc::NonIdentityPoint, - Vec, - ), - Error, - > { - assert_eq!(self.M.sinsemilla_chip, message.chip); - self.M.hash_to_point(layouter, message) - } - - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - /// Evaluates the Sinsemilla hash of `message` from the private initial point `Q`. - pub fn hash_with_private_init( - &self, - layouter: impl Layouter, - Q: &>::NonIdentityPoint, - message: Message, - ) -> Result< - ( - ecc::NonIdentityPoint, - Vec, - ), - Error, - > { - assert_eq!(self.M.sinsemilla_chip, message.chip); - self.M.hash_to_point_with_private_init(layouter, Q, message) - } - - #[allow(clippy::type_complexity)] - /// Returns the public initial point `Q` stored into `CommitDomain`. - pub fn q_init(&self) -> C { - self.M.Q - } - - #[allow(clippy::type_complexity)] - /// Evaluates the blinding factor equal to $\[r\] R$ where `r` is stored in the `CommitDomain`. - pub fn blinding_factor( - &self, - mut layouter: impl Layouter, - r: ecc::ScalarFixed, - ) -> Result< - ecc::Point, - Error, - > { - let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; - Ok(blind) - } - #[allow(clippy::type_complexity)] /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// @@ -505,6 +422,7 @@ where pub fn commit( &self, mut layouter: impl Layouter, + is_Q_public: bool, message: Message, r: ecc::ScalarFixed, ) -> Result< @@ -515,8 +433,15 @@ where Error, > { assert_eq!(self.M.sinsemilla_chip, message.chip); - let blind = self.blinding_factor(layouter.namespace(|| "[r] R"), r)?; - let (p, zs) = self.hash(layouter.namespace(|| "M"), message)?; + + // FIXME: consider returning ZSA version of the following lines. + // It's not a breaking change because `blinding_factor` simply wraps `R.mul` + // and `hash` simply wraps `M.hash_to_point` - are those wrapper really needed? + //let blind = self.blinding_factor(layouter.namespace(|| "[r] R"), r)?; + //let (p, zs) = self.hash(layouter.namespace(|| "M"), message)?; + let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; + let (p, zs) = self.M.hash_to_point(layouter.namespace(|| "M"), is_Q_public, message)?; + let commitment = p.add(layouter.namespace(|| "M + [r] R"), &blind)?; Ok((commitment, zs)) } @@ -528,11 +453,12 @@ where pub fn short_commit( &self, mut layouter: impl Layouter, + is_Q_public: bool, message: Message, r: ecc::ScalarFixed, ) -> Result<(ecc::X, Vec), Error> { assert_eq!(self.M.sinsemilla_chip, message.chip); - let (p, zs) = self.commit(layouter.namespace(|| "commit"), message, r)?; + let (p, zs) = self.commit(layouter.namespace(|| "commit"), is_Q_public, message, r)?; Ok((p.extract_p(), zs)) } } @@ -568,6 +494,8 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; + use crate::sinsemilla::chip::generator_table::GeneratorTableConfig; + use crate::utilities::lookup_range_check::LookupRangeCheck; use std::convert::TryInto; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; @@ -607,9 +535,24 @@ pub(crate) mod tests { impl Circuit for MyCircuit { #[allow(clippy::type_complexity)] type Config = ( - EccConfig, - SinsemillaConfig, - SinsemillaConfig, + EccConfig< + TestFixedBases, + LookupRangeCheckConfig, + >, + SinsemillaConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfig, + GeneratorTableConfig, + >, + SinsemillaConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfig, + GeneratorTableConfig, + >, ); type FloorPlanner = SimpleFloorPlanner; @@ -637,7 +580,6 @@ pub(crate) mod tests { meta.enable_constant(constants); let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -654,33 +596,36 @@ pub(crate) mod tests { table_idx, meta.lookup_table_column(), meta.lookup_table_column(), - table_range_check_tag, ); - let range_check = LookupRangeCheckConfig::configure( - meta, - advices[9], - table_idx, - table_range_check_tag, - ); + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let table = GeneratorTableConfig { + table_idx: lookup.0, + table_x: lookup.1, + table_y: lookup.2, + }; - let ecc_config = - EccChip::::configure(meta, advices, lagrange_coeffs, range_check); + let ecc_config = EccChip::< + TestFixedBases, + LookupRangeCheckConfig, + >::configure(meta, advices, lagrange_coeffs, range_check); let config1 = SinsemillaChip::configure( + true, meta, advices[..5].try_into().unwrap(), advices[2], lagrange_coeffs[0], - lookup, + table, range_check, ); let config2 = SinsemillaChip::configure( + true, meta, advices[5..].try_into().unwrap(), advices[7], lagrange_coeffs[1], - lookup, + table, range_check, ); (ecc_config, config1, config2) @@ -696,10 +641,13 @@ pub(crate) mod tests { let ecc_chip = EccChip::construct(config.0); // The two `SinsemillaChip`s share the same lookup table. - SinsemillaChip::::load( - config.1.clone(), - &mut layouter, - )?; + SinsemillaChip::< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfig, + GeneratorTableConfig, + >::load(config.1.clone(), &mut layouter)?; // This MerkleCRH example is purely for illustrative purposes. // It is not an implementation of the Orchard protocol spec. @@ -766,7 +714,7 @@ pub(crate) mod tests { // Parent let (parent, _) = { let message = Message::from_pieces(chip1, vec![l, left, right]); - merkle_crh.hash_to_point(layouter.namespace(|| "parent"), message)? + merkle_crh.hash_to_point(layouter.namespace(|| "parent"), true, message)? }; parent.constrain_equal( @@ -796,7 +744,7 @@ pub(crate) mod tests { layouter.namespace(|| "witness message"), message.clone(), )?; - test_commit.commit(layouter.namespace(|| "commit"), message, r)? + test_commit.commit(layouter.namespace(|| "commit"), true, message, r)? }; // Witness expected result. diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index c55efd1105..07ad5323f9 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -9,7 +9,7 @@ use crate::{ chip::{DoubleAndAdd, NonIdentityEccPoint}, FixedPoints, }, - utilities::lookup_range_check::LookupRangeCheckConfig, + utilities::lookup_range_check::DefaultLookupRangeCheck, }; use std::marker::PhantomData; @@ -22,51 +22,60 @@ use halo2_proofs::{ poly::Rotation, }; use pasta_curves::pallas; +use pasta_curves::pallas::Base; -mod generator_table; +pub(crate) mod generator_table; +use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable, GeneratorTable}; +use crate::sinsemilla_opt::chip::generator_table::GeneratorTableConfigOptimized; +use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use generator_table::GeneratorTableConfig; -mod hash_to_point; +pub(crate) mod hash_to_point; /// Configuration for the Sinsemilla hash chip #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaConfig +pub struct SinsemillaConfig where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { /// Binary selector used in lookup argument and in the body of the Sinsemilla hash. - q_sinsemilla1: Selector, + pub(crate) q_sinsemilla1: Selector, /// Non-binary selector used in lookup argument and in the body of the Sinsemilla hash. - q_sinsemilla2: Column, + pub(crate) q_sinsemilla2: Column, /// q_sinsemilla2 is used to define a synthetic selector, /// q_sinsemilla3 = (q_sinsemilla2) ⋅ (q_sinsemilla2 - 1) /// Simple selector used to constrain hash initialization to be consistent with /// the y-coordinate of the domain $Q$. - q_sinsemilla4: Selector, + pub(crate) q_sinsemilla4: Selector, /// Fixed column used to load the y-coordinate of the domain $Q$. - fixed_y_q: Column, + pub(crate) fixed_y_q: Column, /// Logic specific to merged double-and-add. - double_and_add: DoubleAndAdd, + pub(crate) double_and_add: DoubleAndAdd, /// Advice column used to load the message. - bits: Column, + pub(crate) bits: Column, /// Advice column used to witness message pieces. This may or may not be the same /// column as `bits`. - witness_pieces: Column, + pub(crate) witness_pieces: Column, /// The lookup table where $(\mathsf{idx}, x_p, y_p)$ are loaded for the $2^K$ /// generators of the Sinsemilla hash. - pub(super) generator_table: GeneratorTableConfig, + pub(crate) generator_table: GeneratorTableConfigType, /// An advice column configured to perform lookup range checks. - lookup_config: LookupRangeCheckConfig, + pub(crate) lookup_config: LookupRangeCheckConfig, _marker: PhantomData<(Hash, Commit, F)>, } -impl SinsemillaConfig +impl + SinsemillaConfig where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { /// Returns an array of all advice columns in this config, in arbitrary order. pub(super) fn advices(&self) -> [Column; 5] { @@ -80,7 +89,7 @@ where } /// Returns the lookup range check config used in this config. - pub fn lookup_config(&self) -> LookupRangeCheckConfig { + pub fn lookup_config(&self) -> LookupRangeCheckConfig { self.lookup_config } @@ -96,22 +105,28 @@ where /// /// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaChip +pub struct SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { - config: SinsemillaConfig, + config: SinsemillaConfig, } -impl Chip for SinsemillaChip +impl Chip + for SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { - type Config = SinsemillaConfig; + type Config = + SinsemillaConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -123,11 +138,14 @@ where } } -impl SinsemillaChip +impl + SinsemillaChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { @@ -136,65 +154,55 @@ where /// Loads the lookup table required by this chip into the circuit. pub fn load( - config: SinsemillaConfig, + config: SinsemillaConfig, layouter: &mut impl Layouter, ) -> Result<>::Loaded, Error> { // Load the lookup table. config.generator_table.load(layouter) } - /// # Side-effects - /// - /// All columns in `advices` and will be equality-enabled. - #[allow(clippy::too_many_arguments)] - #[allow(non_snake_case)] - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - lookup: (TableColumn, TableColumn, TableColumn, TableColumn), - range_check: LookupRangeCheckConfig, - ) -> >::Config { - // Enable equality on all advice columns - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let config = SinsemillaConfig:: { - q_sinsemilla1: meta.complex_selector(), - q_sinsemilla2: meta.fixed_column(), - q_sinsemilla4: meta.selector(), - fixed_y_q, - double_and_add: DoubleAndAdd { - x_a: advices[0], - x_p: advices[1], - lambda_1: advices[3], - lambda_2: advices[4], - }, - bits: advices[2], - witness_pieces, - generator_table: GeneratorTableConfig { - table_idx: lookup.0, - table_x: lookup.1, - table_y: lookup.2, - table_range_check_tag: lookup.3, - }, - lookup_config: range_check, - _marker: PhantomData, - }; + /// Query a fixed value from the circuit's fixed column using the configuration `fixed_y_q`. + fn get_y_q_fixed( + meta: &mut VirtualCells, + config: &SinsemillaConfig< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >, + ) -> Expression { + meta.query_fixed(config.fixed_y_q) + } - // Set up lookup argument - GeneratorTableConfig::configure(meta, config.clone()); + /// Query an advice value 'y_q' from a specific advice column `x_p` at the previous rotation. + fn get_y_q_advice( + meta: &mut VirtualCells, + config: &SinsemillaConfig< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >, + ) -> Expression { + meta.query_advice(config.double_and_add.x_p, Rotation::prev()) + } + #[allow(non_snake_case)] + pub(crate) fn create_initial_y_q_gate( + is_Q_public: bool, + meta: &mut ConstraintSystem, + config: &SinsemillaConfig< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >, + ) { let two = pallas::Base::from(2); - // Closures for expressions that are derived multiple times - // x_r = lambda_1^2 - x_a - x_p - let x_r = |meta: &mut VirtualCells, rotation| { - config.double_and_add.x_r(meta, rotation) - }; - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) let Y_A = |meta: &mut VirtualCells, rotation| { config.double_and_add.Y_A(meta, rotation) @@ -204,7 +212,12 @@ where // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Initial y_Q", |meta| { let q_s4 = meta.query_selector(config.q_sinsemilla4); - let y_q = meta.query_advice(config.double_and_add.x_p, Rotation::prev()); + // fixme: how to change to optimized get_y_q in a simple way? + let y_q = if is_Q_public { + Self::get_y_q_fixed(meta, &config) + } else { + Self::get_y_q_advice(meta, &config) + }; // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) let Y_A_cur = Y_A(meta, Rotation::cur()); @@ -214,6 +227,31 @@ where Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) }); + } + + #[allow(non_snake_case)] + pub(crate) fn create_sinsemilla_gate( + meta: &mut ConstraintSystem, + config: &SinsemillaConfig< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >, + ) { + let two = pallas::Base::from(2); + + // Closures for expressions that are derived multiple times + // x_r = lambda_1^2 - x_a - x_p + let x_r = |meta: &mut VirtualCells, rotation| { + config.double_and_add.x_r(meta, rotation) + }; + + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) + let Y_A = |meta: &mut VirtualCells, rotation| { + config.double_and_add.Y_A(meta, rotation) + }; // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Sinsemilla gate", |meta| { @@ -259,18 +297,82 @@ where Constraints::with_selector(q_s1, [("Secant line", secant_line), ("y check", y_check)]) }); + } + + pub(crate) fn create_config( + meta: &mut ConstraintSystem, + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + table: GeneratorTableConfigType, + range_check: LookupRangeCheckConfig, + ) -> >::Config { + // Enable equality on all advice columns + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let config = + SinsemillaConfig:: { + q_sinsemilla1: meta.complex_selector(), + q_sinsemilla2: meta.fixed_column(), + q_sinsemilla4: meta.selector(), + fixed_y_q, + double_and_add: DoubleAndAdd { + x_a: advices[0], + x_p: advices[1], + lambda_1: advices[3], + lambda_2: advices[4], + }, + bits: advices[2], + witness_pieces, + // todo: check + generator_table: table, + lookup_config: range_check, + _marker: PhantomData, + }; + + // Set up lookup argument + config.generator_table.configure(meta, &config); + + config + } + + /// # Side-effects + /// + /// All columns in `advices` and will be equality-enabled. + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] + pub fn configure( + is_Q_public: bool, + meta: &mut ConstraintSystem, + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + table: GeneratorTableConfigType, + range_check: LookupRangeCheckConfig, + ) -> >::Config { + let config = + Self::create_config(meta, advices, witness_pieces, fixed_y_q, table, range_check); + + Self::create_initial_y_q_gate(is_Q_public, meta, &config); + + Self::create_sinsemilla_gate(meta, &config); config } } // Implement `SinsemillaInstructions` for `SinsemillaChip` -impl SinsemillaInstructions - for SinsemillaChip +impl + SinsemillaInstructions + for SinsemillaChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { type CellValue = AssignedCell; @@ -313,26 +415,13 @@ where fn hash_to_point( &self, mut layouter: impl Layouter, + is_Q_public: bool, Q: pallas::Affine, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec), Error> { layouter.assign_region( || "hash_to_point", - |mut region| self.hash_message(&mut region, Q, &message), - ) - } - - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( - &self, - mut layouter: impl Layouter, - Q: &Self::NonIdentityPoint, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec), Error> { - layouter.assign_region( - || "hash_to_point", - |mut region| self.hash_message_with_private_init(&mut region, Q, &message), + |mut region| self.hash_message(is_Q_public, &mut region, Q, &message), ) } diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index e77928b128..5c09500554 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -1,12 +1,18 @@ +use ff::PrimeFieldBits; use group::ff::PrimeField; use halo2_proofs::{ circuit::{Layouter, Value}, plonk::{ConstraintSystem, Error, Expression, TableColumn}, poly::Rotation, }; +use std::fmt::Debug; use super::{CommitDomains, FixedPoints, HashDomains}; -use crate::sinsemilla::primitives::{self as sinsemilla, K, SINSEMILLA_S}; +use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; +use crate::{ + sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, + utilities::lookup_range_check::DefaultLookupRangeCheck, +}; use pasta_curves::pallas; /// Table containing independent generators S[0..2^k] @@ -15,27 +21,38 @@ pub struct GeneratorTableConfig { pub table_idx: TableColumn, pub table_x: TableColumn, pub table_y: TableColumn, - pub table_range_check_tag: TableColumn, } -impl GeneratorTableConfig { +/// FIXME: add doc +pub trait GeneratorTable { + fn config(&self) -> &GeneratorTableConfig; + #[allow(clippy::too_many_arguments)] #[allow(non_snake_case)] /// Even though the lookup table can be used in other parts of the circuit, /// this specific configuration sets up Sinsemilla-specific constraints /// controlled by `q_sinsemilla`, and would likely not apply to other chips. - pub fn configure( + fn configure( + &self, meta: &mut ConstraintSystem, - config: super::SinsemillaConfig, + config: &super::SinsemillaConfig< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >, ) where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { let (table_idx, table_x, table_y) = ( - config.generator_table.table_idx, - config.generator_table.table_x, - config.generator_table.table_y, + self.config().table_idx, + self.config().table_x, + self.config().table_y, ); // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial @@ -78,23 +95,14 @@ impl GeneratorTableConfig { }); } - /// Load the generator table into the circuit. - /// - /// | table_idx | table_x | table_y | table_range_check_tag | - /// ------------------------------------------------------------------- - /// | 0 | X(S\[0\]) | Y(S\[0\]) | 0 | - /// | 1 | X(S\[1\]) | Y(S\[1\]) | 0 | - /// | ... | ... | ... | 0 | - /// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | 0 | - /// | 0 | X(S\[0\]) | Y(S\[0\]) | 4 | - /// | 1 | X(S\[1\]) | Y(S\[1\]) | 4 | - /// | ... | ... | ... | 4 | - /// | 2^4-1 | X(S\[2^4-1\]) | Y(S\[2^4-1\]) | 4 | - /// | 0 | X(S\[0\]) | Y(S\[0\]) | 5 | - /// | 1 | X(S\[1\]) | Y(S\[1\]) | 5 | - /// | ... | ... | ... | 5 | - /// | 2^5-1 | X(S\[2^5-1\]) | Y(S\[2^5-1\]) | 5 | - pub fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error>; +} +impl GeneratorTable for GeneratorTableConfig { + fn config(&self) -> &GeneratorTableConfig { + self + } + + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { layouter.assign_table( || "generator_table", |mut table| { @@ -107,69 +115,14 @@ impl GeneratorTableConfig { )?; table.assign_cell(|| "table_x", self.table_x, index, || Value::known(*x))?; table.assign_cell(|| "table_y", self.table_y, index, || Value::known(*y))?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - index, - || Value::known(pallas::Base::zero()), - )?; - if index < (1 << 4) { - let new_index = index + (1 << K); - table.assign_cell( - || "table_idx", - self.table_idx, - new_index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell( - || "table_x", - self.table_x, - new_index, - || Value::known(*x), - )?; - table.assign_cell( - || "table_y", - self.table_y, - new_index, - || Value::known(*y), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(pallas::Base::from(4_u64)), - )?; - } - if index < (1 << 5) { - let new_index = index + (1 << 10) + (1 << 4); - table.assign_cell( - || "table_idx", - self.table_idx, - new_index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell( - || "table_x", - self.table_x, - new_index, - || Value::known(*x), - )?; - table.assign_cell( - || "table_y", - self.table_y, - new_index, - || Value::known(*y), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(pallas::Base::from(5_u64)), - )?; - } } Ok(()) }, ) } } + +/// FIXME: add doc +pub trait DefaultGeneratorTable: GeneratorTable + Eq + PartialEq + Clone + Copy + Debug {} + +impl DefaultGeneratorTable for GeneratorTableConfig {} diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 165615efaa..6c0bc392e5 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -3,6 +3,7 @@ use super::{NonIdentityEccPoint, SinsemillaChip}; use crate::{ ecc::FixedPoints, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, + utilities::lookup_range_check::DefaultLookupRangeCheck, }; use ff::Field; @@ -14,19 +15,31 @@ use halo2_proofs::{ use group::ff::{PrimeField, PrimeFieldBits}; use pasta_curves::{arithmetic::CurveAffine, pallas}; +use crate::sinsemilla::chip::generator_table::DefaultGeneratorTable; use std::ops::Deref; -impl SinsemillaChip +/// Define an enum that can hold either type +#[derive(Debug, Clone)] +pub enum EccPointQ<'a> { + PublicPoint(pallas::Affine), + PrivatePoint(&'a NonIdentityEccPoint), +} + +impl + SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] #[allow(clippy::type_complexity)] pub(super) fn hash_message( &self, + is_Q_public: bool, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, message: & { - let (offset, x_a, y_a) = self.public_initialization(region, Q)?; + // todo: add doc about is_Q_public + let (offset, x_a, y_a) = if is_Q_public { + self.public_initialization_vanilla(region, Q)? + } else { + self.public_initialization(region, Q)? + }; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; #[cfg(test)] - #[allow(non_snake_case)] - // Check equivalence to result from primitives::sinsemilla::hash_to_point - { - use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; - - use group::{prime::PrimeCurveAffine, Curve}; - use pasta_curves::arithmetic::CurveExt; - - let field_elems: Value> = message - .iter() - .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) - .collect(); - - field_elems - .zip(x_a.value().zip(y_a.value())) - .assert_if_known(|(field_elems, (x_a, y_a))| { - // Get message as a bitstring. - let bitstring: Vec = field_elems - .iter() - .flat_map(|(elem, num_words)| { - elem.to_le_bits().into_iter().take(K * num_words) - }) - .collect(); - - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - - // We can use complete addition here because it differs from - // incomplete addition with negligible probability. - let expected_point = bitstring - .chunks(K) - .fold(Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); - let actual_point = - pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); - expected_point.to_affine() == actual_point - }); - } - - x_a.value() - .zip(y_a.value()) - .error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?; - Ok(( - NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a), - zs_sum, - )) + self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum) } - /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). + #[cfg(test)] #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(super) fn hash_message_with_private_init( + // Check equivalence to result from primitives::sinsemilla::hash_to_point + pub(crate) fn check_hash_result( &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, + Q: EccPointQ, message: &>::Message, + x_a: X, + y_a: AssignedCell, pallas::Base>, + zs_sum: Vec>>, ) -> Result< ( NonIdentityEccPoint, @@ -112,49 +88,42 @@ where ), Error, > { - let (offset, x_a, y_a) = self.private_initialization(region, Q)?; + use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; - let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; + use group::{prime::PrimeCurveAffine, Curve}; + use pasta_curves::arithmetic::CurveExt; - #[cfg(test)] - #[allow(non_snake_case)] - // Check equivalence to result from primitives::sinsemilla::hash_to_point - { - use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; + let field_elems: Value> = message + .iter() + .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) + .collect(); - use group::{prime::PrimeCurveAffine, Curve}; - use pasta_curves::arithmetic::CurveExt; + let value_Q = match Q { + EccPointQ::PublicPoint(p) => Value::known(p), + EccPointQ::PrivatePoint(p) => p.point(), + }; - let field_elems: Value> = message - .iter() - .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) - .collect(); - - field_elems - .zip(x_a.value().zip(y_a.value())) - .zip(Q.point()) - .assert_if_known(|((field_elems, (x_a, y_a)), Q)| { - // Get message as a bitstring. - let bitstring: Vec = field_elems - .iter() - .flat_map(|(elem, num_words)| { - elem.to_le_bits().into_iter().take(K * num_words) - }) - .collect(); - - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - - // We can use complete addition here because it differs from - // incomplete addition with negligible probability. - let expected_point = bitstring - .chunks(K) - .fold(Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); - let actual_point = - pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); - expected_point.to_affine() == actual_point - }); - } + field_elems + .zip(x_a.value().zip(y_a.value())) + .zip(value_Q) + .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { + // Get message as a bitstring. + let bitstring: Vec = field_elems + .iter() + .flat_map(|(elem, num_words)| elem.to_le_bits().into_iter().take(K * num_words)) + .collect(); + + let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); + let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); + + // We can use complete addition here because it differs from + // incomplete addition with negligible probability. + let expected_point = bitstring + .chunks(K) + .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); + let actual_point = pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); + expected_point.to_affine() == actual_point + }); x_a.value() .zip(y_a.value()) @@ -168,17 +137,16 @@ where #[allow(non_snake_case)] /// Assign the coordinates of the initial public point `Q` /// - /// | offset | x_A | x_P | q_sinsemilla4 | + /// | offset | x_A | q_sinsemilla4 | fixed_y_q | /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn public_initialization( + /// | 0 | x_Q | 1 | y_Q | + pub(crate) fn public_initialization_vanilla( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, ) -> Result<(usize, X, Y), Error> { let config = self.config().clone(); - let mut offset = 0; + let offset = 0; // Get the `x`- and `y`-coordinates of the starting `Q` base. let x_q = *Q.coordinates().unwrap().x(); @@ -187,19 +155,17 @@ where // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 // selector. let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, offset + 1)?; - let y_a: AssignedCell, pallas::Base> = region - .assign_advice_from_constant( - || "fixed y_q", - config.double_and_add.x_p, - offset, - y_q.into(), - )?; + // Enable `q_sinsemilla4` on the first row. + config.q_sinsemilla4.enable(region, offset)?; + region.assign_fixed( + || "fixed y_q", + config.fixed_y_q, + offset, + || Value::known(y_q), + )?; - y_a.value_field().into() + Value::known(y_q.into()).into() }; - offset += 1; // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. let x_a: X = { @@ -216,47 +182,9 @@ where Ok((offset, x_a, y_a)) } - #[allow(non_snake_case)] - /// Assign the coordinates of the initial private point `Q` - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn private_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - let mut offset = 0; - - // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, - // x_p, y_Q using the q_sinsemilla4 selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, offset + 1)?; - let q_y: AssignedCell, pallas::Base> = Q.y().into(); - let y_a: AssignedCell, pallas::Base> = - q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, offset)?; - - y_a.value_field().into() - }; - offset += 1; - - let x_a: X = { - let q_x: AssignedCell, pallas::Base> = Q.x().into(); - let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, offset)?; - - x_a.into() - }; - - Ok((offset, x_a, y_a)) - } - #[allow(clippy::type_complexity)] /// Hash `message` from the initial point `Q`. - fn hash_all_pieces( + pub(crate) fn hash_all_pieces( &self, region: &mut Region<'_, pallas::Base>, mut offset: usize, @@ -534,7 +462,7 @@ where } /// The x-coordinate of the accumulator in a Sinsemilla hash instance. -struct X(AssignedCell, F>); +pub(crate) struct X(pub(crate) AssignedCell, F>); impl From, F>> for X { fn from(cell_value: AssignedCell, F>) -> Self { @@ -555,7 +483,7 @@ impl Deref for X { /// This is never actually witnessed until the last round, since it /// can be derived from other variables. Thus it only exists as a field /// element, not a `CellValue`. -struct Y(Value>); +pub(crate) struct Y(pub(crate) Value>); impl From>> for Y { fn from(value: Value>) -> Self { diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 1eabfaa870..3b85ac807c 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -36,6 +36,7 @@ pub trait MerkleInstructions< fn hash_layer( &self, layouter: impl Layouter, + is_Q_public: bool, Q: C, l: usize, left: Self::Var, @@ -117,6 +118,7 @@ where pub fn calculate_root( &self, mut layouter: impl Layouter, + is_Q_public: bool, leaf: MerkleChip::Var, ) -> Result { // Each chip processes `ceil(PATH_LENGTH / PAR)` layers. @@ -159,6 +161,7 @@ where // M^l_i = MerkleCRH(l, M^{l+1}_{2i}, M^{l+1}_{2i+1}) node = chip.hash_layer( layouter.namespace(|| format!("MerkleCRH({}, left, right)", l)), + is_Q_public, Q, l, pair.0, @@ -184,7 +187,11 @@ pub mod tests { tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, - utilities::{i2lebsp, lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, + utilities::{ + i2lebsp, + lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + UtilitiesInstructions, + }, }; use group::ff::{Field, PrimeField, PrimeFieldBits}; @@ -195,6 +202,7 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; + use crate::sinsemilla::chip::generator_table::GeneratorTableConfig; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; @@ -209,8 +217,20 @@ pub mod tests { impl Circuit for MyCircuit { type Config = ( - MerkleConfig, - MerkleConfig, + MerkleConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfig, + GeneratorTableConfig, + >, + MerkleConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfig, + GeneratorTableConfig, + >, ); type FloorPlanner = SimpleFloorPlanner; @@ -246,28 +266,34 @@ pub mod tests { meta.lookup_table_column(), meta.lookup_table_column(), meta.lookup_table_column(), - meta.lookup_table_column(), ); - let range_check = - LookupRangeCheckConfig::configure(meta, advices[9], lookup.0, lookup.3); + let table = GeneratorTableConfig { + table_idx: lookup.0, + table_x: lookup.1, + table_y: lookup.2, + }; + + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup.0); let sinsemilla_config_1 = SinsemillaChip::configure( + true, meta, advices[5..].try_into().unwrap(), advices[7], fixed_y_q_1, - lookup, + table, range_check, ); let config1 = MerkleChip::configure(meta, sinsemilla_config_1); let sinsemilla_config_2 = SinsemillaChip::configure( + true, meta, advices[..5].try_into().unwrap(), advices[2], fixed_y_q_2, - lookup, + table, range_check, ); let config2 = MerkleChip::configure(meta, sinsemilla_config_2); @@ -281,10 +307,13 @@ pub mod tests { mut layouter: impl Layouter, ) -> Result<(), Error> { // Load generator table (shared across both configs) - SinsemillaChip::::load( - config.0.sinsemilla_config.clone(), - &mut layouter, - )?; + SinsemillaChip::< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfig, + GeneratorTableConfig, + >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. let chip_1 = MerkleChip::construct(config.0.clone()); @@ -304,7 +333,7 @@ pub mod tests { }; let computed_final_root = - path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?; + path.calculate_root(layouter.namespace(|| "calculate root"), true, leaf)?; self.leaf .zip(self.leaf_pos) diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index cb3c5be4cc..ebfe08a701 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -9,9 +9,10 @@ use pasta_curves::pallas; use super::MerkleInstructions; +use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable, GeneratorTableConfig}; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, - utilities::RangeConstrained, + utilities::{lookup_range_check::DefaultLookupRangeCheck, RangeConstrained}, { ecc::FixedPoints, sinsemilla::{ @@ -28,16 +29,19 @@ use group::ff::PrimeField; /// Configuration for the `MerkleChip` implementation. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleConfig +pub struct MerkleConfig where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { advices: [Column; 5], q_decompose: Selector, - pub(super) cond_swap_config: CondSwapConfig, - pub(super) sinsemilla_config: SinsemillaConfig, + pub(crate) cond_swap_config: CondSwapConfig, + pub(crate) sinsemilla_config: + SinsemillaConfig, } /// Chip implementing `MerkleInstructions`. @@ -51,22 +55,28 @@ where /// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of /// `left` and `right`. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleChip +pub struct MerkleChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { - config: MerkleConfig, + config: MerkleConfig, } -impl Chip for MerkleChip +impl Chip + for MerkleChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { - type Config = MerkleConfig; + type Config = + MerkleConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -78,17 +88,26 @@ where } } -impl MerkleChip +impl + MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { /// Configures the [`MerkleChip`]. pub fn configure( meta: &mut ConstraintSystem, - sinsemilla_config: SinsemillaConfig, - ) -> MerkleConfig { + sinsemilla_config: SinsemillaConfig< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >, + ) -> MerkleConfig { // All five advice columns are equality-enabled by SinsemillaConfig. let advices = sinsemilla_config.advices(); let cond_swap_config = CondSwapChip::configure(meta, advices); @@ -191,23 +210,34 @@ where } /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. - pub fn construct(config: MerkleConfig) -> Self { + pub fn construct( + config: MerkleConfig, + ) -> Self { MerkleChip { config } } } -impl - MerkleInstructions - for MerkleChip +impl< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + const MERKLE_DEPTH: usize, + > MerkleInstructions + for MerkleChip where Hash: HashDomains + Eq, F: FixedPoints, Commit: CommitDomains + Eq, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { #[allow(non_snake_case)] fn hash_layer( &self, mut layouter: impl Layouter, + is_Q_public: bool, Q: pallas::Affine, // l = MERKLE_DEPTH - layer - 1 l: usize, @@ -299,6 +329,7 @@ where // https://p.z.cash/proto:merkle-crh-orchard let (point, zs) = self.hash_to_point( layouter.namespace(|| format!("hash at l = {}", l)), + is_Q_public, Q, vec![a.inner(), b.inner(), c.inner()].into(), )?; @@ -415,20 +446,28 @@ where } } -impl UtilitiesInstructions for MerkleChip +impl + UtilitiesInstructions + for MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { type Var = AssignedCell; } -impl CondSwapInstructions for MerkleChip +impl + CondSwapInstructions + for MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { #[allow(clippy::type_complexity)] fn swap( @@ -441,71 +480,106 @@ where let chip = CondSwapChip::::construct(config); chip.swap(layouter, pair, swap) } - - fn mux( - &self, - layouter: &mut impl Layouter, - choice: Self::Var, - left: Self::Var, - right: Self::Var, - ) -> Result { - let config = self.config().cond_swap_config.clone(); - let chip = CondSwapChip::::construct(config); - chip.mux(layouter, choice, left, right) - } } -impl SinsemillaInstructions - for MerkleChip +impl + SinsemillaInstructions + for MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, { - type CellValue = as SinsemillaInstructions< + type CellValue = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::CellValue; - type Message = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::Message; - type MessagePiece = as SinsemillaInstructions< + type Message = as SinsemillaInstructions>::Message; + type MessagePiece = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::MessagePiece; - type RunningSum = as SinsemillaInstructions< + type RunningSum = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::RunningSum; - type X = as SinsemillaInstructions< + type X = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::X; - type NonIdentityPoint = as SinsemillaInstructions< + type NonIdentityPoint = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::NonIdentityPoint; - type FixedPoints = as SinsemillaInstructions< + type FixedPoints = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::FixedPoints; - type HashDomains = as SinsemillaInstructions< + type HashDomains = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::HashDomains; - type CommitDomains = as SinsemillaInstructions< + type CommitDomains = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, @@ -518,7 +592,13 @@ where num_words: usize, ) -> Result { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChip::::construct(config); + let chip = SinsemillaChip::< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >::construct(config); chip.witness_message_piece(layouter, value, num_words) } @@ -527,28 +607,24 @@ where fn hash_to_point( &self, layouter: impl Layouter, + is_Q_public: bool, Q: pallas::Affine, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChip::::construct(config); - chip.hash_to_point(layouter, Q, message) - } - - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( - &self, - layouter: impl Layouter, - Q: &Self::NonIdentityPoint, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { - let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChip::::construct(config); - chip.hash_to_point_with_private_init(layouter, Q, message) + let chip = SinsemillaChip::< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >::construct(config); + chip.hash_to_point(layouter, is_Q_public, Q, message) } fn extract(point: &Self::NonIdentityPoint) -> Self::X { - SinsemillaChip::::extract(point) + SinsemillaChip::::extract( + point, + ) } } diff --git a/halo2_gadgets/src/sinsemilla/primitives.rs b/halo2_gadgets/src/sinsemilla/primitives.rs index ad9e397b5e..2ebde8faf4 100644 --- a/halo2_gadgets/src/sinsemilla/primitives.rs +++ b/halo2_gadgets/src/sinsemilla/primitives.rs @@ -56,7 +56,7 @@ fn extract_p_bottom(point: CtOption) -> CtOption { /// Pads the given iterator (which MUST have length $\leq K * C$) with zero-bits to a /// multiple of $K$ bits. -struct Pad> { +pub(crate) struct Pad> { /// The iterator we are padding. inner: I, /// The measured length of the inner iterator. @@ -184,9 +184,10 @@ impl HashDomain { #[derive(Debug)] #[allow(non_snake_case)] pub struct CommitDomain { + // FIXME: THis comment came from ZSA version /// A domain in which $\mathsf{SinsemillaHashToPoint}$ and $\mathsf{SinsemillaHash}$ can be used - M: HashDomain, - R: pallas::Point, + pub(crate) M: HashDomain, + pub(crate) R: pallas::Point, } impl CommitDomain { @@ -201,17 +202,6 @@ impl CommitDomain { } } - /// Constructs a new `CommitDomain` from different values for `hash_domain` and `blind_domain` - pub fn new_with_personalization(hash_domain: &str, blind_domain: &str) -> Self { - let m_prefix = format!("{}-M", hash_domain); - let r_prefix = format!("{}-r", blind_domain); - let hasher_r = pallas::Point::hash_to_curve(&r_prefix); - CommitDomain { - M: HashDomain::new(&m_prefix), - R: hasher_r(&[]), - } - } - /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit @@ -226,26 +216,6 @@ impl CommitDomain { .map(|p| p + Wnaf::new().scalar(r).base(self.R)) } - /// $\mathsf{SinsemillaHashToPoint}$ from [§ 5.4.1.9][concretesinsemillahash]. - /// - /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash - pub fn hash_to_point(&self, msg: impl Iterator) -> CtOption { - self.M.hash_to_point(msg) - } - - /// Returns `SinsemillaCommit_r(personalization, msg) = hash_point + [r]R` - /// where `SinsemillaHash(personalization, msg) = hash_point` - /// and `R` is derived from the `personalization`. - #[allow(non_snake_case)] - pub fn commit_from_hash_point( - &self, - hash_point: CtOption, - r: &pallas::Scalar, - ) -> CtOption { - // We use complete addition for the blinding factor. - hash_point.map(|p| p + Wnaf::new().scalar(r).base(self.R)) - } - /// $\mathsf{SinsemillaShortCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit @@ -337,32 +307,4 @@ mod tests { assert_eq!(computed, actual); } } - - #[test] - fn commit_in_several_steps() { - use rand::{rngs::OsRng, Rng}; - - use ff::Field; - - use crate::sinsemilla::primitives::CommitDomain; - - let domain = CommitDomain::new("z.cash:ZSA-NoteCommit"); - - let mut os_rng = OsRng::default(); - let msg: Vec = (0..36).map(|_| os_rng.gen::()).collect(); - - let rcm = pallas::Scalar::random(&mut os_rng); - - // Evaluate the commitment with commit function - let commit1 = domain.commit(msg.clone().into_iter(), &rcm); - - // Evaluate the commitment with the following steps - // 1. hash msg - // 2. evaluate the commitment from the hash point - let hash_point = domain.M.hash_to_point(msg.into_iter()); - let commit2 = domain.commit_from_hash_point(hash_point, &rcm); - - // Test equality - assert_eq!(commit1.unwrap(), commit2.unwrap()); - } } diff --git a/halo2_gadgets/src/sinsemilla_opt.rs b/halo2_gadgets/src/sinsemilla_opt.rs new file mode 100644 index 0000000000..1103a73705 --- /dev/null +++ b/halo2_gadgets/src/sinsemilla_opt.rs @@ -0,0 +1,478 @@ +//! The [Sinsemilla] hash function. +//! +//! [Sinsemilla]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash + +use std::fmt::Debug; + +use pasta_curves::arithmetic::CurveAffine; + +use halo2_proofs::{circuit::Layouter, plonk::Error}; + +use crate::{ + ecc::{self, EccInstructions}, + sinsemilla::{CommitDomain, HashDomain, Message, SinsemillaInstructions}, +}; + +pub mod chip; +pub mod merkle; +pub mod primitives; + +/// FIXME: add a doc +pub trait SinsemillaInstructionsOptimized: + SinsemillaInstructions +{ + /// Hashes a message to an ECC curve point. + /// This returns both the resulting point, as well as the message + /// decomposition in the form of intermediate values in a cumulative + /// sum. + /// The initial point `Q` is a private point. + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point_with_private_init( + &self, + layouter: impl Layouter, + Q: &Self::NonIdentityPoint, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec), Error>; +} + +impl + HashDomain +where + SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, + EccChip: EccInstructions< + C, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + /// Evaluate the Sinsemilla hash of `message` from the private initial point `Q`. + pub fn hash_to_point_with_private_init( + &self, + layouter: impl Layouter, + Q: &>::NonIdentityPoint, + message: Message, + ) -> Result<(ecc::NonIdentityPoint, Vec), Error> { + assert_eq!(self.sinsemilla_chip, message.chip); + self.sinsemilla_chip + .hash_to_point_with_private_init(layouter, Q, message.inner) + .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) + } + +} + +impl + CommitDomain +where + SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, + EccChip: EccInstructions< + C, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, +{ + #[allow(clippy::type_complexity)] + /// Evaluates the Sinsemilla hash of `message` from the public initial point `Q` stored + /// into `CommitDomain`. + pub fn hash( + &self, + layouter: impl Layouter, + is_Q_public: bool, + message: Message, + ) -> Result< + ( + ecc::NonIdentityPoint, + Vec, + ), + Error, + > { + assert_eq!(self.M.sinsemilla_chip, message.chip); + self.M.hash_to_point(layouter, is_Q_public, message) + } + + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + /// Evaluates the Sinsemilla hash of `message` from the private initial point `Q`. + pub fn hash_with_private_init( + &self, + layouter: impl Layouter, + Q: &>::NonIdentityPoint, + message: Message, + ) -> Result< + ( + ecc::NonIdentityPoint, + Vec, + ), + Error, + > { + assert_eq!(self.M.sinsemilla_chip, message.chip); + self.M.hash_to_point_with_private_init(layouter, Q, message) + } + + #[allow(clippy::type_complexity)] + /// Returns the public initial point `Q` stored into `CommitDomain`. + pub fn q_init(&self) -> C { + self.M.Q + } + + #[allow(clippy::type_complexity)] + /// Evaluates the blinding factor equal to $\[r\] R$ where `r` is stored in the `CommitDomain`. + pub fn blinding_factor( + &self, + mut layouter: impl Layouter, + r: ecc::ScalarFixed, + ) -> Result< + ecc::Point, + Error, + > { + let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; + Ok(blind) + } +} + +#[cfg(test)] +pub(crate) mod tests { + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use rand::rngs::OsRng; + + use crate::sinsemilla::{ + chip::{SinsemillaChip, SinsemillaConfig}, + CommitDomain, CommitDomains, HashDomain, HashDomains, Message, MessagePiece, + }; + + use crate::{ + ecc::ScalarFixed, + sinsemilla::primitives::{self as sinsemilla, K}, + { + ecc::{ + chip::{find_zs_and_us, EccChip, EccConfig, H, NUM_WINDOWS}, + tests::{FullWidth, TestFixedBases}, + NonIdentityPoint, + }, + utilities::lookup_range_check::LookupRangeCheckConfig, + }, + }; + + use group::{ff::Field, Curve}; + use lazy_static::lazy_static; + use pasta_curves::pallas; + + use crate::sinsemilla::chip::generator_table::GeneratorTableConfig; + use crate::sinsemilla_opt::chip::generator_table::GeneratorTableConfigOptimized; + use crate::utilities::lookup_range_check::LookupRangeCheck; + use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; + use std::convert::TryInto; + + pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; + + lazy_static! { + static ref COMMIT_DOMAIN: sinsemilla::CommitDomain = + sinsemilla::CommitDomain::new(PERSONALIZATION); + static ref Q: pallas::Affine = COMMIT_DOMAIN.Q().to_affine(); + static ref R: pallas::Affine = COMMIT_DOMAIN.R().to_affine(); + static ref R_ZS_AND_US: Vec<(u64, [pallas::Base; H])> = + find_zs_and_us(*R, NUM_WINDOWS).unwrap(); + } + + #[derive(Debug, Clone, Eq, PartialEq)] + pub(crate) struct TestHashDomain; + impl HashDomains for TestHashDomain { + fn Q(&self) -> pallas::Affine { + *Q + } + } + + // This test does not make use of the CommitDomain. + #[derive(Debug, Clone, Eq, PartialEq)] + pub(crate) struct TestCommitDomain; + impl CommitDomains for TestCommitDomain { + fn r(&self) -> FullWidth { + FullWidth::from_parts(*R, &R_ZS_AND_US) + } + + fn hash_domain(&self) -> TestHashDomain { + TestHashDomain + } + } + + struct MyCircuit {} + + impl Circuit for MyCircuit { + #[allow(clippy::type_complexity)] + type Config = ( + EccConfig< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + SinsemillaConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + GeneratorTableConfigOptimized, + >, + SinsemillaConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + GeneratorTableConfigOptimized, + >, + ); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + MyCircuit {} + } + + #[allow(non_snake_case)] + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let table_idx = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + // todo: check the lookup.3 and LookupRangeCheckConfigOptimized::configure, to see if one more column is created + // Fixed columns for the Sinsemilla generator lookup table + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], table_idx); + let table = GeneratorTableConfigOptimized { + base: GeneratorTableConfig { + table_idx: lookup.0, + table_x: lookup.1, + table_y: lookup.2, + }, + table_range_check_tag: lookup.3, + }; + + let ecc_config = EccChip::< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >::configure(meta, advices, lagrange_coeffs, range_check); + + let config1 = SinsemillaChip::configure( + false, + meta, + advices[..5].try_into().unwrap(), + advices[2], + lagrange_coeffs[0], + table, + range_check, + ); + let config2 = SinsemillaChip::configure( + false, + meta, + advices[5..].try_into().unwrap(), + advices[7], + lagrange_coeffs[1], + table, + range_check, + ); + (ecc_config, config1, config2) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let rng = OsRng; + + let ecc_chip = EccChip::construct(config.0); + + // The two `SinsemillaChip`s share the same lookup table. + SinsemillaChip::< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + GeneratorTableConfigOptimized, + >::load(config.1.clone(), &mut layouter)?; + + // This MerkleCRH example is purely for illustrative purposes. + // It is not an implementation of the Orchard protocol spec. + { + let chip1 = SinsemillaChip::construct(config.1); + + let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); + + // Layer 31, l = MERKLE_DEPTH - 1 - layer = 0 + let l_bitstring = vec![Value::known(false); K]; + let l = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "l"), + &l_bitstring, + )?; + + // Left leaf + let left_bitstring: Vec> = (0..250) + .map(|_| Value::known(rand::random::())) + .collect(); + let left = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "left"), + &left_bitstring, + )?; + + // Right leaf + let right_bitstring: Vec> = (0..250) + .map(|_| Value::known(rand::random::())) + .collect(); + let right = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "right"), + &right_bitstring, + )?; + + let l_bitstring: Value> = l_bitstring.into_iter().collect(); + let left_bitstring: Value> = left_bitstring.into_iter().collect(); + let right_bitstring: Value> = right_bitstring.into_iter().collect(); + + // Witness expected parent + let expected_parent = { + let expected_parent = l_bitstring.zip(left_bitstring.zip(right_bitstring)).map( + |(l, (left, right))| { + let merkle_crh = sinsemilla::HashDomain::from_Q((*Q).into()); + let point = merkle_crh + .hash_to_point( + l.into_iter() + .chain(left.into_iter()) + .chain(right.into_iter()), + ) + .unwrap(); + point.to_affine() + }, + ); + + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "Witness expected parent"), + expected_parent, + )? + }; + + // Parent + let (parent, _) = { + let message = Message::from_pieces(chip1, vec![l, left, right]); + merkle_crh.hash_to_point(layouter.namespace(|| "parent"), false, message)? + }; + + parent.constrain_equal( + layouter.namespace(|| "parent == expected parent"), + &expected_parent, + )?; + } + + { + let chip2 = SinsemillaChip::construct(config.2); + + let test_commit = + CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); + let r_val = pallas::Scalar::random(rng); + let message: Vec> = (0..500) + .map(|_| Value::known(rand::random::())) + .collect(); + + let (result, _) = { + let r = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "r"), + Value::known(r_val), + )?; + let message = Message::from_bitstring( + chip2, + layouter.namespace(|| "witness message"), + message.clone(), + )?; + test_commit.commit(layouter.namespace(|| "commit"), false, message, r)? + }; + + // Witness expected result. + let expected_result = { + let message: Value> = message.into_iter().collect(); + let expected_result = message.map(|message| { + let domain = sinsemilla::CommitDomain::new(PERSONALIZATION); + let point = domain.commit(message.into_iter(), &r_val).unwrap(); + point.to_affine() + }); + + NonIdentityPoint::new( + ecc_chip, + layouter.namespace(|| "Witness expected result"), + expected_result, + )? + }; + + result.constrain_equal( + layouter.namespace(|| "result == expected result"), + &expected_result, + ) + } + } + } + + #[test] + fn sinsemilla_chip() { + let k = 11; + let circuit = MyCircuit {}; + let prover = MockProver::run(k, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())) + } + + #[cfg(feature = "test-dev-graph")] + #[test] + fn print_sinsemilla_chip() { + use plotters::prelude::*; + + let root = + BitMapBackend::new("sinsemilla-hash-layout.png", (1024, 7680)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); + + let circuit = MyCircuit {}; + halo2_proofs::dev::CircuitLayout::default() + .render(11, &circuit, &root) + .unwrap(); + } +} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip.rs b/halo2_gadgets/src/sinsemilla_opt/chip.rs new file mode 100644 index 0000000000..790a7c9484 --- /dev/null +++ b/halo2_gadgets/src/sinsemilla_opt/chip.rs @@ -0,0 +1,56 @@ +//! Chip implementations for the Sinsemilla gadgets. + +use super::SinsemillaInstructionsOptimized; +use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable, GeneratorTableConfig}; +use crate::sinsemilla_opt::chip::generator_table::GeneratorTableConfigOptimized; +use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheckConfig}; +use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; +use crate::{ + ecc::{chip::NonIdentityEccPoint, FixedPoints}, + sinsemilla::{ + chip::{SinsemillaChip, SinsemillaConfig}, + message::{Message, MessagePiece}, + primitives as sinsemilla, CommitDomains, HashDomains, SinsemillaInstructions, + }, + utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, +}; +use halo2_proofs::plonk::Expression; +use halo2_proofs::{ + circuit::{AssignedCell, Chip, Layouter, Value}, + plonk::{ + Advice, Column, ConstraintSystem, Constraints, Error, Fixed, TableColumn, VirtualCells, + }, + poly::Rotation, +}; +use pasta_curves::pallas; +use pasta_curves::pallas::Base; + +pub(crate) mod generator_table; + +mod hash_to_point; + +// Implement `SinsemillaInstructionsOptimized` for `SinsemillaChip` +impl + SinsemillaInstructionsOptimized + for SinsemillaChip +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point_with_private_init( + &self, + mut layouter: impl Layouter, + Q: &Self::NonIdentityPoint, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec), Error> { + layouter.assign_region( + || "hash_to_point", + |mut region| self.hash_message_with_private_init(&mut region, Q, &message), + ) + } +} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs new file mode 100644 index 0000000000..d721778427 --- /dev/null +++ b/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs @@ -0,0 +1,136 @@ +use halo2_proofs::{ + circuit::{Layouter, Value}, + plonk::{Error, TableColumn}, +}; +use std::fmt::Debug; + +use pasta_curves::pallas; + +use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable, GeneratorTable}; +use crate::sinsemilla::{ + chip::generator_table::GeneratorTableConfig, + primitives::{K, SINSEMILLA_S}, +}; +use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheckConfig}; +use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; + +/// Table containing independent generators S[0..2^k] +#[derive(Eq, PartialEq, Copy, Clone, Debug)] +pub struct GeneratorTableConfigOptimized { + pub(crate) base: GeneratorTableConfig, + pub(crate) table_range_check_tag: TableColumn, +} +impl GeneratorTable for GeneratorTableConfigOptimized { + fn config(&self) -> &GeneratorTableConfig { + &self.base + } + + /// Load the generator table into the circuit. + /// + /// | table_idx | table_x | table_y | table_range_check_tag | + /// ------------------------------------------------------------------- + /// | 0 | X(S\[0\]) | Y(S\[0\]) | 0 | + /// | 1 | X(S\[1\]) | Y(S\[1\]) | 0 | + /// | ... | ... | ... | 0 | + /// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | 0 | + /// | 0 | X(S\[0\]) | Y(S\[0\]) | 4 | + /// | 1 | X(S\[1\]) | Y(S\[1\]) | 4 | + /// | ... | ... | ... | 4 | + /// | 2^4-1 | X(S\[2^4-1\]) | Y(S\[2^4-1\]) | 4 | + /// | 0 | X(S\[0\]) | Y(S\[0\]) | 5 | + /// | 1 | X(S\[1\]) | Y(S\[1\]) | 5 | + /// | ... | ... | ... | 5 | + /// | 2^5-1 | X(S\[2^5-1\]) | Y(S\[2^5-1\]) | 5 | + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "generator_table", + |mut table| { + for (index, (x, y)) in SINSEMILLA_S.iter().enumerate() { + table.assign_cell( + || "table_idx", + self.config().table_idx, + index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell( + || "table_x", + self.config().table_x, + index, + || Value::known(*x), + )?; + table.assign_cell( + || "table_y", + self.config().table_y, + index, + || Value::known(*y), + )?; + table.assign_cell( + || "table_range_check_tag", + self.table_range_check_tag, + index, + || Value::known(pallas::Base::zero()), + )?; + if index < (1 << 4) { + let new_index = index + (1 << K); + table.assign_cell( + || "table_idx", + self.config().table_idx, + new_index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell( + || "table_x", + self.config().table_x, + new_index, + || Value::known(*x), + )?; + table.assign_cell( + || "table_y", + self.config().table_y, + new_index, + || Value::known(*y), + )?; + table.assign_cell( + || "table_range_check_tag", + self.table_range_check_tag, + new_index, + || Value::known(pallas::Base::from(4_u64)), + )?; + } + if index < (1 << 5) { + let new_index = index + (1 << 10) + (1 << 4); + table.assign_cell( + || "table_idx", + self.config().table_idx, + new_index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell( + || "table_x", + self.config().table_x, + new_index, + || Value::known(*x), + )?; + table.assign_cell( + || "table_y", + self.config().table_y, + new_index, + || Value::known(*y), + )?; + table.assign_cell( + || "table_range_check_tag", + self.table_range_check_tag, + new_index, + || Value::known(pallas::Base::from(5_u64)), + )?; + } + } + Ok(()) + }, + ) + } +} + +pub(crate) type DefaultGeneratorTableConfigOptimized = GeneratorTableConfigOptimized; + +impl DefaultGeneratorTable for DefaultGeneratorTableConfigOptimized {} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs new file mode 100644 index 0000000000..b62a8ae152 --- /dev/null +++ b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs @@ -0,0 +1,146 @@ +use pasta_curves::{arithmetic::CurveAffine, pallas}; + +use halo2_proofs::{ + circuit::{AssignedCell, Chip, Region}, + plonk::{Assigned, Error}, +}; + +use crate::sinsemilla::chip::generator_table::DefaultGeneratorTable; +use crate::sinsemilla::chip::hash_to_point::EccPointQ; +use crate::sinsemilla::chip::SinsemillaChip; +use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; +use crate::{ + ecc::{chip::NonIdentityEccPoint, FixedPoints}, + sinsemilla::{ + chip::hash_to_point::{X, Y}, + primitives::{self as sinsemilla}, + CommitDomains, HashDomains, SinsemillaInstructions, + }, +}; + +impl + SinsemillaChip +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, +{ + /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(crate) fn hash_message_with_private_init( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + let (offset, x_a, y_a) = self.private_initialization(region, Q)?; + + // FIXME: calling construct_base is possibly(!) non-optimal + let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; + + #[cfg(test)] + self.check_hash_result(EccPointQ::PrivatePoint(Q), message, x_a, y_a, zs_sum) + } + + #[allow(non_snake_case)] + /// Assign the coordinates of the initial public point `Q` + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + pub(crate) fn public_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: pallas::Affine, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + let mut offset = 0; + + // Get the `x`- and `y`-coordinates of the starting `Q` base. + let x_q = *Q.coordinates().unwrap().x(); + let y_q = *Q.coordinates().unwrap().y(); + + // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 + // selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, offset + 1)?; + let y_a: AssignedCell, pallas::Base> = region + .assign_advice_from_constant( + || "fixed y_q", + config.double_and_add.x_p, + offset, + y_q.into(), + )?; + + y_a.value_field().into() + }; + offset += 1; + + // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. + let x_a: X = { + let x_a = region.assign_advice_from_constant( + || "fixed x_q", + config.double_and_add.x_a, + offset, + x_q.into(), + )?; + + x_a.into() + }; + + Ok((offset, x_a, y_a)) + } + + #[allow(non_snake_case)] + /// Assign the coordinates of the initial private point `Q` + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + fn private_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + let mut offset = 0; + + // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, + // x_p, y_Q using the q_sinsemilla4 selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, offset + 1)?; + let q_y: AssignedCell, pallas::Base> = Q.y().into(); + let y_a: AssignedCell, pallas::Base> = + q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, offset)?; + + y_a.value_field().into() + }; + offset += 1; + + let x_a: X = { + let q_x: AssignedCell, pallas::Base> = Q.x().into(); + let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, offset)?; + + x_a.into() + }; + + Ok((offset, x_a, y_a)) + } +} diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle.rs b/halo2_gadgets/src/sinsemilla_opt/merkle.rs new file mode 100644 index 0000000000..2927585229 --- /dev/null +++ b/halo2_gadgets/src/sinsemilla_opt/merkle.rs @@ -0,0 +1,3 @@ +//! Gadgets for implementing a Merkle tree with Sinsemilla. + +pub mod chip; diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs new file mode 100644 index 0000000000..48f078cb38 --- /dev/null +++ b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs @@ -0,0 +1,75 @@ +//! Chip implementing a Merkle hash using Sinsemilla as the hash function. + +use halo2_proofs::{ + circuit::{Chip, Layouter}, + plonk::Error, +}; +use pasta_curves::pallas; + +use crate::sinsemilla::chip::generator_table::DefaultGeneratorTable; +use crate::sinsemilla::chip::SinsemillaChip; +use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; +use crate::{ + sinsemilla::{merkle::chip::MerkleChip, primitives as sinsemilla}, + sinsemilla_opt::SinsemillaInstructionsOptimized, + utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, + { + ecc::FixedPoints, + sinsemilla::{CommitDomains, HashDomains}, + utilities::cond_swap::CondSwapChip, + utilities_opt::cond_swap::CondSwapInstructionsOptimized, + }, +}; + +impl + CondSwapInstructionsOptimized + for MerkleChip +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, +{ + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result { + let config = self.config().cond_swap_config.clone(); + let chip = CondSwapChip::::construct(config); + chip.mux(layouter, choice, left, right) + } +} + +impl + SinsemillaInstructionsOptimized + for MerkleChip +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + LookupRangeCheckConfig: DefaultLookupRangeCheck, + GeneratorTableConfigType: DefaultGeneratorTable, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point_with_private_init( + &self, + layouter: impl Layouter, + Q: &Self::NonIdentityPoint, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { + let config = self.config().sinsemilla_config.clone(); + let chip = SinsemillaChip::< + Hash, + Commit, + F, + LookupRangeCheckConfig, + GeneratorTableConfigType, + >::construct(config); + chip.hash_to_point_with_private_init(layouter, Q, message) + } +} diff --git a/halo2_gadgets/src/sinsemilla_opt/primitives.rs b/halo2_gadgets/src/sinsemilla_opt/primitives.rs new file mode 100644 index 0000000000..dd2930d6d2 --- /dev/null +++ b/halo2_gadgets/src/sinsemilla_opt/primitives.rs @@ -0,0 +1,74 @@ +//! Implementation of Sinsemilla outside the circuit. + +use group::Wnaf; +use halo2_proofs::arithmetic::CurveExt; +use pasta_curves::pallas; +use subtle::CtOption; + +use crate::sinsemilla::primitives::{CommitDomain, HashDomain}; + +impl CommitDomain { + /// Constructs a new `CommitDomain` from different values for `hash_domain` and `blind_domain` + pub fn new_with_personalization(hash_domain: &str, blind_domain: &str) -> Self { + let m_prefix = format!("{}-M", hash_domain); + let r_prefix = format!("{}-r", blind_domain); + let hasher_r = pallas::Point::hash_to_curve(&r_prefix); + CommitDomain { + M: HashDomain::new(&m_prefix), + R: hasher_r(&[]), + } + } + + /// $\mathsf{SinsemillaHashToPoint}$ from [§ 5.4.1.9][concretesinsemillahash]. + /// + /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash + pub fn hash_to_point(&self, msg: impl Iterator) -> CtOption { + self.M.hash_to_point(msg) + } + + /// Returns `SinsemillaCommit_r(personalization, msg) = hash_point + [r]R` + /// where `SinsemillaHash(personalization, msg) = hash_point` + /// and `R` is derived from the `personalization`. + #[allow(non_snake_case)] + pub fn commit_from_hash_point( + &self, + hash_point: CtOption, + r: &pallas::Scalar, + ) -> CtOption { + // We use complete addition for the blinding factor. + hash_point.map(|p| p + Wnaf::new().scalar(r).base(self.R)) + } +} + +#[cfg(test)] +mod tests { + use pasta_curves::pallas; + + #[test] + fn commit_in_several_steps() { + use rand::{rngs::OsRng, Rng}; + + use ff::Field; + + use crate::sinsemilla::primitives::CommitDomain; + + let domain = CommitDomain::new("z.cash:ZSA-NoteCommit"); + + let mut os_rng = OsRng::default(); + let msg: Vec = (0..36).map(|_| os_rng.gen::()).collect(); + + let rcm = pallas::Scalar::random(&mut os_rng); + + // Evaluate the commitment with commit function + let commit1 = domain.commit(msg.clone().into_iter(), &rcm); + + // Evaluate the commitment with the following steps + // 1. hash msg + // 2. evaluate the commitment from the hash point + let hash_point = domain.M.hash_to_point(msg.into_iter()); + let commit2 = domain.commit_from_hash_point(hash_point, &rcm); + + // Test equality + assert_eq!(commit1.unwrap(), commit2.unwrap()); + } +} diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 78049e742a..7712c89b2a 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -2,14 +2,12 @@ use super::{bool_check, ternary, UtilitiesInstructions}; -use crate::ecc::chip::{EccPoint, NonIdentityEccPoint}; use group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, - plonk::{self, Advice, Column, ConstraintSystem, Constraints, Error, Selector}, + plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; -use pasta_curves::pallas; use std::marker::PhantomData; /// Instructions for a conditional swap gadget. @@ -26,22 +24,12 @@ pub trait CondSwapInstructions: UtilitiesInstructions { pair: (Self::Var, Value), swap: Value, ) -> Result<(Self::Var, Self::Var), Error>; - - /// Given an input `(choice, left, right)` where `choice` is a boolean flag, - /// returns `left` if `choice` is not set and `right` if `choice` is set. - fn mux( - &self, - layouter: &mut impl Layouter, - choice: Self::Var, - left: Self::Var, - right: Self::Var, - ) -> Result; } /// A chip implementing a conditional swap. #[derive(Clone, Debug)] pub struct CondSwapChip { - config: CondSwapConfig, + pub(crate) config: CondSwapConfig, _marker: PhantomData, } @@ -61,12 +49,12 @@ impl Chip for CondSwapChip { /// Configuration for the [`CondSwapChip`]. #[derive(Clone, Debug, PartialEq, Eq)] pub struct CondSwapConfig { - q_swap: Selector, - a: Column, - b: Column, - a_swapped: Column, - b_swapped: Column, - swap: Column, + pub(crate) q_swap: Selector, + pub(crate) a: Column, + pub(crate) b: Column, + pub(crate) a_swapped: Column, + pub(crate) b_swapped: Column, + pub(crate) swap: Column, } #[cfg(test)] @@ -133,97 +121,6 @@ impl CondSwapInstructions for CondSwapChip { }, ) } - - fn mux( - &self, - layouter: &mut impl Layouter, - choice: Self::Var, - left: Self::Var, - right: Self::Var, - ) -> Result { - let config = self.config(); - - layouter.assign_region( - || "mux", - |mut region| { - // Enable `q_swap` selector - config.q_swap.enable(&mut region, 0)?; - - // Copy in `a` value - let left = left.copy_advice(|| "copy left", &mut region, config.a, 0)?; - - // Copy in `b` value - let right = right.copy_advice(|| "copy right", &mut region, config.b, 0)?; - - // Copy `choice` value - let choice = choice.copy_advice(|| "copy choice", &mut region, config.swap, 0)?; - - let a_swapped = left - .value() - .zip(right.value()) - .zip(choice.value()) - .map(|((left, right), choice)| { - if *choice == F::from(0_u64) { - left - } else { - right - } - }) - .cloned(); - let b_swapped = left - .value() - .zip(right.value()) - .zip(choice.value()) - .map(|((left, right), choice)| { - if *choice == F::from(0_u64) { - right - } else { - left - } - }) - .cloned(); - - region.assign_advice(|| "out b_swap", self.config.b_swapped, 0, || b_swapped)?; - region.assign_advice(|| "out a_swap", self.config.a_swapped, 0, || a_swapped) - }, - ) - } -} - -impl CondSwapChip { - /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are `EccPoint`, - /// returns `left` if `choice` is not set and `right` if `choice` is set. - pub fn mux_on_points( - &self, - mut layouter: impl Layouter, - choice: &AssignedCell, - left: &EccPoint, - right: &EccPoint, - ) -> Result { - let x_cell = self.mux(&mut layouter, choice.clone(), left.x(), right.x())?; - let y_cell = self.mux(&mut layouter, choice.clone(), left.y(), right.y())?; - Ok(EccPoint::from_coordinates_unchecked( - x_cell.into(), - y_cell.into(), - )) - } - - /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are - /// `NonIdentityEccPoint`, returns `left` if `choice` is not set and `right` if `choice` is set. - pub fn mux_on_non_identity_points( - &self, - mut layouter: impl Layouter, - choice: &AssignedCell, - left: &NonIdentityEccPoint, - right: &NonIdentityEccPoint, - ) -> Result { - let x_cell = self.mux(&mut layouter, choice.clone(), left.x(), right.x())?; - let y_cell = self.mux(&mut layouter, choice.clone(), left.y(), right.y())?; - Ok(NonIdentityEccPoint::from_coordinates_unchecked( - x_cell.into(), - y_cell.into(), - )) - } } impl CondSwapChip { @@ -394,231 +291,4 @@ mod tests { assert_eq!(prover.verify(), Ok(())); } } - - #[test] - fn test_mux() { - use crate::{ - ecc::{ - chip::{EccChip, EccConfig}, - tests::TestFixedBases, - NonIdentityPoint, Point, - }, - utilities::lookup_range_check::LookupRangeCheckConfig, - }; - - use group::{cofactor::CofactorCurveAffine, Curve, Group}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, - }; - use pasta_curves::arithmetic::CurveAffine; - use pasta_curves::{pallas, EpAffine}; - - use rand::rngs::OsRng; - - #[derive(Clone, Debug)] - pub struct MyConfig { - primary: Column, - advice: Column, - cond_swap_config: CondSwapConfig, - ecc_config: EccConfig, - } - - #[derive(Default)] - struct MyCircuit { - left_point: Value, - right_point: Value, - choice: Value, - } - - impl Circuit for MyCircuit { - type Config = MyConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - // Instance column used for public inputs - let primary = meta.instance_column(); - meta.enable_equality(primary); - - let cond_swap_config = - CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let range_check = LookupRangeCheckConfig::configure( - meta, - advices[9], - table_idx, - table_range_check_tag, - ); - - let ecc_config = EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ); - - MyConfig { - primary, - advice: advices[0], - cond_swap_config, - ecc_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Construct a CondSwap chip - let cond_swap_chip = CondSwapChip::construct(config.cond_swap_config); - - // Construct an ECC chip - let ecc_chip = EccChip::construct(config.ecc_config); - - // Assign choice - let choice = layouter.assign_region( - || "load private", - |mut region| { - region.assign_advice(|| "load private", config.advice, 0, || self.choice) - }, - )?; - - // Test mux on non identity points - // Assign left point - let left_non_identity_point = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "left point"), - self.left_point.map(|left_point| left_point), - )?; - - // Assign right point - let right_non_identity_point = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "right point"), - self.right_point.map(|right_point| right_point), - )?; - - // Apply mux - let result_non_identity_point = cond_swap_chip.mux_on_non_identity_points( - layouter.namespace(|| "MUX"), - &choice, - left_non_identity_point.inner(), - right_non_identity_point.inner(), - )?; - - // Check equality with instance - layouter.constrain_instance( - result_non_identity_point.x().cell(), - config.primary, - 0, - )?; - layouter.constrain_instance( - result_non_identity_point.y().cell(), - config.primary, - 1, - )?; - - // Test mux on points - // Assign left point - let left_point = Point::new( - ecc_chip.clone(), - layouter.namespace(|| "left point"), - self.left_point.map(|left_point| left_point), - )?; - - // Assign right point - let right_point = Point::new( - ecc_chip, - layouter.namespace(|| "right point"), - self.right_point.map(|right_point| right_point), - )?; - - // Apply mux - let result = cond_swap_chip.mux_on_points( - layouter.namespace(|| "MUX"), - &choice, - left_point.inner(), - right_point.inner(), - )?; - - // Check equality with instance - layouter.constrain_instance(result.x().cell(), config.primary, 0)?; - layouter.constrain_instance(result.y().cell(), config.primary, 1) - } - } - - // Test different circuits - let mut circuits = vec![]; - let mut instances = vec![]; - for choice in [false, true] { - let choice_value = if choice { - pallas::Base::one() - } else { - pallas::Base::zero() - }; - let left_point = pallas::Point::random(OsRng).to_affine(); - let right_point = pallas::Point::random(OsRng).to_affine(); - circuits.push(MyCircuit { - left_point: Value::known(left_point), - right_point: Value::known(right_point), - choice: Value::known(choice_value), - }); - let expected_output = if choice { right_point } else { left_point }; - let (expected_x, expected_y) = if bool::from(expected_output.is_identity()) { - (pallas::Base::zero(), pallas::Base::zero()) - } else { - let coords = expected_output.coordinates().unwrap(); - (*coords.x(), *coords.y()) - }; - instances.push([[expected_x, expected_y]]); - } - - for (circuit, instance) in circuits.iter().zip(instances.iter()) { - let prover = MockProver::::run( - 5, - circuit, - instance.iter().map(|p| p.to_vec()).collect(), - ) - .unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - } } diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 64b4ce4c90..09369c04f1 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -6,10 +6,14 @@ use halo2_proofs::{ plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector, TableColumn}, poly::Rotation, }; -use std::{convert::TryInto, marker::PhantomData}; +use std::{convert::TryInto, fmt::Debug, marker::PhantomData}; use ff::PrimeFieldBits; +use pasta_curves::pallas; + +use crate::sinsemilla::primitives as sinsemilla; + use super::*; /// The running sum $[z_0, ..., z_W]$. If created in strict mode, $z_W = 0$. @@ -30,8 +34,8 @@ impl RangeConstrained> { /// # Panics /// /// Panics if `bitrange.len() >= K`. - pub fn witness_short( - lookup_config: &LookupRangeCheckConfig, + pub fn witness_short>( + lookup_config: &L, layouter: impl Layouter, value: Value<&F>, bitrange: Range, @@ -49,7 +53,7 @@ impl RangeConstrained> { .map(|inner| Self { inner, num_bits, - _phantom: PhantomData::default(), + _phantom: PhantomData, }) } } @@ -57,198 +61,44 @@ impl RangeConstrained> { /// Configuration that provides methods for a lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] pub struct LookupRangeCheckConfig { - q_lookup: Selector, - q_running: Selector, - q_bitshift: Selector, - q_range_check_4: Selector, - q_range_check_5: Selector, - running_sum: Column, - table_idx: TableColumn, - table_range_check_tag: TableColumn, - _marker: PhantomData, + pub(crate) q_lookup: Selector, + pub(crate) q_running: Selector, + pub(crate) q_bitshift: Selector, + pub(crate) running_sum: Column, + pub(crate) table_idx: TableColumn, + pub(crate) _marker: PhantomData, } -impl LookupRangeCheckConfig { - /// The `running_sum` advice column breaks the field element into `K`-bit - /// words. It is used to construct the input expression to the lookup - /// argument. - /// - /// The `table_idx` fixed column contains values from [0..2^K). Looking up - /// a value in `table_idx` constrains it to be within this range. The table - /// can be loaded outside this helper. - /// - /// # Side-effects - /// - /// Both the `running_sum` and `constants` columns will be equality-enabled. - pub fn configure( +/// FIXME: add doc +pub trait LookupRangeCheck { + /// FIXME: add doc + fn config(&self) -> &LookupRangeCheckConfig; + + /// FIXME: add doc + fn configure( meta: &mut ConstraintSystem, running_sum: Column, table_idx: TableColumn, - table_range_check_tag: TableColumn, - ) -> Self { - meta.enable_equality(running_sum); - - let q_lookup = meta.complex_selector(); - let q_running = meta.complex_selector(); - let q_bitshift = meta.selector(); - let q_range_check_4 = meta.complex_selector(); - let q_range_check_5 = meta.complex_selector(); - let config = LookupRangeCheckConfig { - q_lookup, - q_running, - q_bitshift, - q_range_check_4, - q_range_check_5, - running_sum, - table_idx, - table_range_check_tag, - _marker: PhantomData, - }; - - // https://p.z.cash/halo2-0.1:decompose-combined-lookup - meta.lookup(|meta| { - let q_lookup = meta.query_selector(config.q_lookup); - let q_running = meta.query_selector(config.q_running); - let q_range_check_4 = meta.query_selector(config.q_range_check_4); - let q_range_check_5 = meta.query_selector(config.q_range_check_5); - let z_cur = meta.query_advice(config.running_sum, Rotation::cur()); - let one = Expression::Constant(F::ONE); - - // In the case of a running sum decomposition, we recover the word from - // the difference of the running sums: - // z_i = 2^{K}⋅z_{i + 1} + a_i - // => a_i = z_i - 2^{K}⋅z_{i + 1} - let running_sum_lookup = { - let running_sum_word = { - let z_next = meta.query_advice(config.running_sum, Rotation::next()); - z_cur.clone() - z_next * F::from(1 << K) - }; - - q_running.clone() * running_sum_word - }; - - // In the short range check, the word is directly witnessed. - let short_lookup = { - let short_word = z_cur.clone(); - let q_short = one.clone() - q_running; - - q_short * short_word - }; - - // q_range_check is equal to - // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 - // - 0 otherwise - let q_range_check = one.clone() - - (one.clone() - q_range_check_4.clone()) * (one.clone() - q_range_check_5.clone()); - - // num_bits is equal to - // - 5 if q_range_check_5 = 1 - // - 4 if q_range_check_4 = 1 and q_range_check_5 = 0 - // - 0 otherwise - let num_bits = q_range_check_5.clone() * Expression::Constant(F::from(5_u64)) - + (one.clone() - q_range_check_5) - * q_range_check_4 - * Expression::Constant(F::from(4_u64)); - - // Combine the running sum, short lookups and optimized range checks: - vec![ - ( - q_lookup.clone() - * ((one - q_range_check.clone()) * (running_sum_lookup + short_lookup) - + q_range_check.clone() * z_cur), - config.table_idx, - ), - ( - q_lookup * q_range_check * num_bits, - config.table_range_check_tag, - ), - ] - }); - - // For short lookups, check that the word has been shifted by the correct number of bits. - // https://p.z.cash/halo2-0.1:decompose-short-lookup - meta.create_gate("Short lookup bitshift", |meta| { - let q_bitshift = meta.query_selector(config.q_bitshift); - let word = meta.query_advice(config.running_sum, Rotation::prev()); - let shifted_word = meta.query_advice(config.running_sum, Rotation::cur()); - let inv_two_pow_s = meta.query_advice(config.running_sum, Rotation::next()); - - let two_pow_k = F::from(1 << K); - - // shifted_word = word * 2^{K-s} - // = word * 2^K * inv_two_pow_s - Constraints::with_selector( - q_bitshift, - Some(word * two_pow_k * inv_two_pow_s - shifted_word), - ) - }); - - config - } + ) -> Self + where + Self: Sized; #[cfg(test)] - // Fill `table_idx` and `table_range_check_tag`. - // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table - // in the Orchard context. - pub fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { - layouter.assign_table( - || "table_idx", - |mut table| { - // We generate the row values lazily (we only need them during keygen). - for index in 0..(1 << K) { - table.assign_cell( - || "table_idx", - self.table_idx, - index, - || Value::known(F::from(index as u64)), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - index, - || Value::known(F::ZERO), - )?; - } - for index in 0..(1 << 4) { - let new_index = index + (1 << K); - table.assign_cell( - || "table_idx", - self.table_idx, - new_index, - || Value::known(F::from(index as u64)), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(F::from(4_u64)), - )?; - } - for index in 0..(1 << 5) { - let new_index = index + (1 << K) + (1 << 4); - table.assign_cell( - || "table_idx", - self.table_idx, - new_index, - || Value::known(F::from(index as u64)), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(F::from(5_u64)), - )?; - } - Ok(()) - }, - ) - } + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error>; + + /// FIXME: add doc + fn short_range_check( + &self, + region: &mut Region<'_, F>, + element: AssignedCell, + num_bits: usize, + ) -> Result<(), Error>; /// Range check on an existing cell that is copied into this helper. /// /// Returns an error if `element` is not in a column that was passed to /// [`ConstraintSystem::enable_equality`] during circuit configuration. - pub fn copy_check( + fn copy_check( &self, mut layouter: impl Layouter, element: AssignedCell, @@ -259,14 +109,15 @@ impl LookupRangeCheckConfig { || format!("{:?} words range check", num_words), |mut region| { // Copy `element` and initialize running sum `z_0 = element` to decompose it. - let z_0 = element.copy_advice(|| "z_0", &mut region, self.running_sum, 0)?; + let z_0 = + element.copy_advice(|| "z_0", &mut region, self.config().running_sum, 0)?; self.range_check(&mut region, z_0, num_words, strict) }, ) } /// Range check on a value that is witnessed in this helper. - pub fn witness_check( + fn witness_check( &self, mut layouter: impl Layouter, value: Value, @@ -276,8 +127,12 @@ impl LookupRangeCheckConfig { layouter.assign_region( || "Witness element", |mut region| { - let z_0 = - region.assign_advice(|| "Witness element", self.running_sum, 0, || value)?; + let z_0 = region.assign_advice( + || "Witness element", + self.config().running_sum, + 0, + || value, + )?; self.range_check(&mut region, z_0, num_words, strict) }, ) @@ -332,9 +187,9 @@ impl LookupRangeCheckConfig { let inv_two_pow_k = F::from(1u64 << K).invert().unwrap(); for (idx, word) in words.iter().enumerate() { // Enable q_lookup on this row - self.q_lookup.enable(region, idx)?; + self.config().q_lookup.enable(region, idx)?; // Enable q_running on this row - self.q_running.enable(region, idx)?; + self.config().q_running.enable(region, idx)?; // z_next = (z_cur - m_cur) / 2^K z = { @@ -346,7 +201,7 @@ impl LookupRangeCheckConfig { // Assign z_next region.assign_advice( || format!("z_{:?}", idx + 1), - self.running_sum, + self.config().running_sum, idx + 1, || z_val, )? @@ -367,7 +222,7 @@ impl LookupRangeCheckConfig { /// # Panics /// /// Panics if NUM_BITS is equal to or larger than K. - pub fn copy_short_check( + fn copy_short_check( &self, mut layouter: impl Layouter, element: AssignedCell, @@ -379,7 +234,7 @@ impl LookupRangeCheckConfig { |mut region| { // Copy `element` to use in the k-bit lookup. let element = - element.copy_advice(|| "element", &mut region, self.running_sum, 0)?; + element.copy_advice(|| "element", &mut region, self.config().running_sum, 0)?; self.short_range_check(&mut region, element, num_bits) }, @@ -391,7 +246,7 @@ impl LookupRangeCheckConfig { /// # Panics /// /// Panics if num_bits is larger than K. - pub fn witness_short_check( + fn witness_short_check( &self, mut layouter: impl Layouter, element: Value, @@ -402,8 +257,12 @@ impl LookupRangeCheckConfig { || format!("Range check {:?} bits", num_bits), |mut region| { // Witness `element` to use in the k-bit lookup. - let element = - region.assign_advice(|| "Witness element", self.running_sum, 0, || element)?; + let element = region.assign_advice( + || "Witness element", + self.config().running_sum, + 0, + || element, + )?; self.short_range_check(&mut region, element.clone(), num_bits)?; @@ -411,362 +270,159 @@ impl LookupRangeCheckConfig { }, ) } +} - /// Constrain `x` to be a NUM_BITS word. - /// - /// `element` must have been assigned to `self.running_sum` at offset 0. - fn short_range_check( - &self, - region: &mut Region<'_, F>, - element: AssignedCell, - num_bits: usize, - ) -> Result<(), Error> { - // Enable lookup for `element`. - self.q_lookup.enable(region, 0)?; - - match num_bits { - 4 => { - self.q_range_check_4.enable(region, 0)?; - } - 5 => { - self.q_range_check_5.enable(region, 0)?; - } - _ => { - // Enable lookup for shifted element, to constrain it to 10 bits. - self.q_lookup.enable(region, 1)?; +impl LookupRangeCheck for LookupRangeCheckConfig { + fn config(&self) -> &LookupRangeCheckConfig { + self + } - // Check element has been shifted by the correct number of bits. - self.q_bitshift.enable(region, 1)?; + fn configure( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + ) -> Self { + meta.enable_equality(running_sum); - // Assign shifted `element * 2^{K - num_bits}` - let shifted = element.value().into_field() * F::from(1 << (K - num_bits)); + let q_lookup = meta.complex_selector(); + let q_running = meta.complex_selector(); + let q_bitshift = meta.selector(); - region.assign_advice( - || format!("element * 2^({}-{})", K, num_bits), - self.running_sum, - 1, - || shifted, - )?; + // FIXME: q_range_check_4 and q_range_check_5 need to be created here + // if the order of the creation makes a difference + let config = LookupRangeCheckConfig { + q_lookup, + q_running, + q_bitshift, + running_sum, + table_idx, + _marker: PhantomData, + }; - // Assign 2^{-num_bits} from a fixed column. - let inv_two_pow_s = F::from(1 << num_bits).invert().unwrap(); - region.assign_advice_from_constant( - || format!("2^(-{})", num_bits), - self.running_sum, - 2, - inv_two_pow_s, - )?; - } - } + // https://p.z.cash/halo2-0.1:decompose-combined-lookup + meta.lookup(|meta| { + let q_lookup = meta.query_selector(config.q_lookup); + let q_running = meta.query_selector(config.q_running); + // FIXME: q_range_check_4 and q_range_check_5 need to be created here + // if the order of the creation makes a difference + let z_cur = meta.query_advice(config.running_sum, Rotation::cur()); + let one = Expression::Constant(F::ONE); - Ok(()) - } -} + // In the case of a running sum decomposition, we recover the word from + // the difference of the running sums: + // z_i = 2^{K}⋅z_{i + 1} + a_i + // => a_i = z_i - 2^{K}⋅z_{i + 1} + let running_sum_lookup = { + let running_sum_word = { + let z_next = meta.query_advice(config.running_sum, Rotation::next()); + z_cur.clone() - z_next * F::from(1 << K) + }; -#[cfg(test)] -mod tests { - use super::LookupRangeCheckConfig; - - use super::super::lebs2ip; - use crate::sinsemilla::primitives::K; - - use ff::{Field, PrimeFieldBits}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::{FailureLocation, MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use pasta_curves::pallas; - - use std::{convert::TryInto, marker::PhantomData}; - - #[test] - fn lookup_range_check() { - #[derive(Clone, Copy)] - struct MyCircuit { - num_words: usize, - _marker: PhantomData, - } + q_running.clone() * running_sum_word + }; - impl Circuit for MyCircuit { - type Config = LookupRangeCheckConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - *self - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - LookupRangeCheckConfig::::configure( - meta, - running_sum, - table_idx, - table_range_check_tag, - ) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_words * K bits. - let elements_and_expected_final_zs = [ - (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long - (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long - ]; - - fn expected_zs( - element: F, - num_words: usize, - ) -> Vec { - let chunks = { - element - .to_le_bits() - .iter() - .by_vals() - .take(num_words * K) - .collect::>() - .chunks_exact(K) - .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) - .collect::>() - }; - let expected_zs = { - let inv_two_pow_k = F::from(1 << K).invert().unwrap(); - chunks.iter().fold(vec![element], |mut zs, a_i| { - // z_{i + 1} = (z_i - a_i) / 2^{K} - let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; - zs.push(z); - zs - }) - }; - expected_zs - } + // In the short range check, the word is directly witnessed. + let short_lookup = { + let short_word = z_cur.clone(); + let q_short = one.clone() - q_running; - for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { - let expected_zs = expected_zs::(*element, self.num_words); + q_short * short_word + }; - let zs = config.witness_check( - layouter.namespace(|| format!("Lookup {:?}", self.num_words)), - Value::known(*element), - self.num_words, - *strict, - )?; + vec![( + q_lookup * (running_sum_lookup + short_lookup), + config.table_idx, + )] + }); - assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); + // For short lookups, check that the word has been shifted by the correct number of bits. + // https://p.z.cash/halo2-0.1:decompose-short-lookup + meta.create_gate("Short lookup bitshift", |meta| { + let q_bitshift = meta.query_selector(config.q_bitshift); + let word = meta.query_advice(config.running_sum, Rotation::prev()); + let shifted_word = meta.query_advice(config.running_sum, Rotation::cur()); + let inv_two_pow_s = meta.query_advice(config.running_sum, Rotation::next()); - for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { - z.value().assert_if_known(|z| &&expected_z == z); - } - } - Ok(()) - } - } + let two_pow_k = F::from(1 << K); - { - let circuit: MyCircuit = MyCircuit { - num_words: 6, - _marker: PhantomData, - }; + // shifted_word = word * 2^{K-s} + // = word * 2^K * inv_two_pow_s + Constraints::with_selector( + q_bitshift, + Some(word * two_pow_k * inv_two_pow_s - shifted_word), + ) + }); - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + config } - #[test] - fn short_range_check() { - struct MyCircuit { - element: Value, - num_bits: usize, - } - - impl Circuit for MyCircuit { - type Config = LookupRangeCheckConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - MyCircuit { - element: Value::unknown(), - num_bits: self.num_bits, + #[cfg(test)] + // Fill `table_idx` and `table_range_check_tag`. + // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table + // in the Orchard context. + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table_idx", + |mut table| { + // We generate the row values lazily (we only need them during keygen). + for index in 0..(1 << K) { + table.assign_cell( + || "table_idx", + self.table_idx, + index, + || Value::known(F::from(index as u64)), + )?; } - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - LookupRangeCheckConfig::::configure( - meta, - running_sum, - table_idx, - table_range_check_tag, - ) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_bits. - config.witness_short_check( - layouter.namespace(|| format!("Lookup {:?} bits", self.num_bits)), - self.element, - self.num_bits, - )?; - Ok(()) - } - } - - // Edge case: zero bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::ZERO), - num_bits: 0, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + }, + ) + } - // Edge case: K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << K) - 1)), - num_bits: K, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + /// Constrain `x` to be a NUM_BITS word. + /// + /// `element` must have been assigned to `self.running_sum` at offset 0. + fn short_range_check( + &self, + region: &mut Region<'_, F>, + element: AssignedCell, + num_bits: usize, + ) -> Result<(), Error> { + // Enable lookup for `element`. + self.q_lookup.enable(region, 0)?; - // Element within `num_bits` - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << 6) - 1)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + // Enable lookup for shifted element, to constrain it to 10 bits. + self.q_lookup.enable(region, 1)?; - // Element larger than `num_bits` but within K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << 6)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }]) - ); - } + // Check element has been shifted by the correct number of bits. + self.q_bitshift.enable(region, 1)?; - // Element larger than K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << K)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }, - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }, - ]) - ); - } + // Assign shifted `element * 2^{K - num_bits}` + let shifted = element.value().into_field() * F::from(1 << (K - num_bits)); - // Element which is not within `num_bits`, but which has a shifted value within - // num_bits - { - let num_bits = 6; - let shifted = pallas::Base::from((1 << num_bits) - 1); - // Recall that shifted = element * 2^{K-s} - // => element = shifted * 2^{s-K} - let element = shifted - * pallas::Base::from(1 << (K as u64 - num_bits)) - .invert() - .unwrap(); - let circuit: MyCircuit = MyCircuit { - element: Value::known(element), - num_bits: num_bits as usize, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }]) - ); - } + region.assign_advice( + || format!("element * 2^({}-{})", K, num_bits), + self.running_sum, + 1, + || shifted, + )?; - // Element within 4 bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << 4) - 1)), - num_bits: 4, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + // Assign 2^{-num_bits} from a fixed column. + let inv_two_pow_s = F::from(1 << num_bits).invert().unwrap(); + region.assign_advice_from_constant( + || format!("2^(-{})", num_bits), + self.running_sum, + 2, + inv_two_pow_s, + )?; - // Element larger than 5 bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << 5)), - num_bits: 5, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 5 bits").into(), - offset: 0, - }, - }]) - ); - } + Ok(()) } } + +/// FIXME: add doc +pub trait DefaultLookupRangeCheck: + LookupRangeCheck + Eq + PartialEq + Clone + Copy + Debug +{ +} + +impl DefaultLookupRangeCheck for LookupRangeCheckConfig {} diff --git a/halo2_gadgets/src/utilities_opt.rs b/halo2_gadgets/src/utilities_opt.rs new file mode 100644 index 0000000000..ddd75ce739 --- /dev/null +++ b/halo2_gadgets/src/utilities_opt.rs @@ -0,0 +1,4 @@ +//! Utility gadgets. + +pub mod cond_swap; +pub mod lookup_range_check; diff --git a/halo2_gadgets/src/utilities_opt/cond_swap.rs b/halo2_gadgets/src/utilities_opt/cond_swap.rs new file mode 100644 index 0000000000..13b169ec2e --- /dev/null +++ b/halo2_gadgets/src/utilities_opt/cond_swap.rs @@ -0,0 +1,448 @@ +//! Gadget and chip for a conditional swap utility. + +use group::ff::{Field, PrimeField}; +use pasta_curves::pallas; + +use halo2_proofs::{ + circuit::{AssignedCell, Chip, Layouter}, + plonk::{self, Error}, +}; + +use crate::ecc::chip::{EccPoint, NonIdentityEccPoint}; + +use crate::utilities::cond_swap::{CondSwapChip, CondSwapInstructions}; + +/// Instructions for a conditional swap gadget. +pub trait CondSwapInstructionsOptimized: CondSwapInstructions { + /// Given an input `(choice, left, right)` where `choice` is a boolean flag, + /// returns `left` if `choice` is not set and `right` if `choice` is set. + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result; +} + +impl CondSwapInstructionsOptimized for CondSwapChip { + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result { + let config = self.config(); + + layouter.assign_region( + || "mux", + |mut region| { + // Enable `q_swap` selector + config.q_swap.enable(&mut region, 0)?; + + // Copy in `a` value + let left = left.copy_advice(|| "copy left", &mut region, config.a, 0)?; + + // Copy in `b` value + let right = right.copy_advice(|| "copy right", &mut region, config.b, 0)?; + + // Copy `choice` value + let choice = choice.copy_advice(|| "copy choice", &mut region, config.swap, 0)?; + + let a_swapped = left + .value() + .zip(right.value()) + .zip(choice.value()) + .map(|((left, right), choice)| { + if *choice == F::from(0_u64) { + left + } else { + right + } + }) + .cloned(); + let b_swapped = left + .value() + .zip(right.value()) + .zip(choice.value()) + .map(|((left, right), choice)| { + if *choice == F::from(0_u64) { + right + } else { + left + } + }) + .cloned(); + + region.assign_advice(|| "out b_swap", self.config.b_swapped, 0, || b_swapped)?; + region.assign_advice(|| "out a_swap", self.config.a_swapped, 0, || a_swapped) + }, + ) + } +} + +impl CondSwapChip { + /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are `EccPoint`, + /// returns `left` if `choice` is not set and `right` if `choice` is set. + pub fn mux_on_points( + &self, + mut layouter: impl Layouter, + choice: &AssignedCell, + left: &EccPoint, + right: &EccPoint, + ) -> Result { + let x_cell = self.mux(&mut layouter, choice.clone(), left.x(), right.x())?; + let y_cell = self.mux(&mut layouter, choice.clone(), left.y(), right.y())?; + Ok(EccPoint::from_coordinates_unchecked( + x_cell.into(), + y_cell.into(), + )) + } + + /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are + /// `NonIdentityEccPoint`, returns `left` if `choice` is not set and `right` if `choice` is set. + pub fn mux_on_non_identity_points( + &self, + mut layouter: impl Layouter, + choice: &AssignedCell, + left: &NonIdentityEccPoint, + right: &NonIdentityEccPoint, + ) -> Result { + let x_cell = self.mux(&mut layouter, choice.clone(), left.x(), right.x())?; + let y_cell = self.mux(&mut layouter, choice.clone(), left.y(), right.y())?; + Ok(NonIdentityEccPoint::from_coordinates_unchecked( + x_cell.into(), + y_cell.into(), + )) + } +} + +#[cfg(test)] +mod tests { + use super::{CondSwapChip, CondSwapInstructions}; + use crate::utilities::cond_swap::CondSwapConfig; + use crate::utilities::lookup_range_check::LookupRangeCheck; + use crate::utilities::UtilitiesInstructions; + use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; + use group::ff::{Field, PrimeField}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use pasta_curves::pallas::Base; + use rand::rngs::OsRng; + + #[test] + fn cond_swap() { + #[derive(Default)] + struct MyCircuit { + a: Value, + b: Value, + swap: Value, + } + + impl Circuit for MyCircuit { + type Config = CondSwapConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + CondSwapChip::::configure(meta, advices) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = CondSwapChip::::construct(config.clone()); + + // Load the pair and the swap flag into the circuit. + let a = chip.load_private(layouter.namespace(|| "a"), config.a, self.a)?; + // Return the swapped pair. + let swapped_pair = chip.swap( + layouter.namespace(|| "swap"), + (a.clone(), self.b), + self.swap, + )?; + + self.swap + .zip(a.value().zip(self.b.as_ref())) + .zip(swapped_pair.0.value().zip(swapped_pair.1.value())) + .assert_if_known(|((swap, (a, b)), (a_swapped, b_swapped))| { + if *swap { + // Check that `a` and `b` have been swapped + (a_swapped == b) && (b_swapped == a) + } else { + // Check that `a` and `b` have not been swapped + (a_swapped == a) && (b_swapped == b) + } + }); + + Ok(()) + } + } + + let rng = OsRng; + + // Test swap case + { + let circuit: MyCircuit = MyCircuit { + a: Value::known(Base::random(rng)), + b: Value::known(Base::random(rng)), + swap: Value::known(true), + }; + let prover = MockProver::::run(3, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Test non-swap case + { + let circuit: MyCircuit = MyCircuit { + a: Value::known(Base::random(rng)), + b: Value::known(Base::random(rng)), + swap: Value::known(false), + }; + let prover = MockProver::::run(3, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } + + #[test] + fn test_mux() { + use crate::ecc::{ + chip::{EccChip, EccConfig}, + tests::TestFixedBases, + NonIdentityPoint, Point, + }; + + use group::{cofactor::CofactorCurveAffine, Curve, Group}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, + }; + use pasta_curves::arithmetic::CurveAffine; + use pasta_curves::{pallas, EpAffine}; + + use rand::rngs::OsRng; + + #[derive(Clone, Debug)] + pub struct MyConfig { + primary: Column, + advice: Column, + cond_swap_config: CondSwapConfig, + ecc_config: EccConfig< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + } + + #[derive(Default)] + struct MyCircuit { + left_point: Value, + right_point: Value, + choice: Value, + } + + impl Circuit for MyCircuit { + type Config = MyConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + let cond_swap_config = + CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); + + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + meta.enable_constant(lagrange_coeffs[0]); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], table_idx); + + let ecc_config = + EccChip::< + TestFixedBases, + LookupRangeCheckConfigOptimized< + pallas::Base, + { crate::sinsemilla::primitives::K }, + >, + >::configure(meta, advices, lagrange_coeffs, range_check); + + MyConfig { + primary, + advice: advices[0], + cond_swap_config, + ecc_config, + } + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Construct a CondSwap chip + let cond_swap_chip = CondSwapChip::construct(config.cond_swap_config); + + // Construct an ECC chip + let ecc_chip = EccChip::construct(config.ecc_config); + + // Assign choice + let choice = layouter.assign_region( + || "load private", + |mut region| { + region.assign_advice(|| "load private", config.advice, 0, || self.choice) + }, + )?; + + // Test mux on non identity points + // Assign left point + let left_non_identity_point = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "left point"), + self.left_point.map(|left_point| left_point), + )?; + + // Assign right point + let right_non_identity_point = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "right point"), + self.right_point.map(|right_point| right_point), + )?; + + // Apply mux + let result_non_identity_point = cond_swap_chip.mux_on_non_identity_points( + layouter.namespace(|| "MUX"), + &choice, + left_non_identity_point.inner(), + right_non_identity_point.inner(), + )?; + + // Check equality with instance + layouter.constrain_instance( + result_non_identity_point.x().cell(), + config.primary, + 0, + )?; + layouter.constrain_instance( + result_non_identity_point.y().cell(), + config.primary, + 1, + )?; + + // Test mux on points + // Assign left point + let left_point = Point::new( + ecc_chip.clone(), + layouter.namespace(|| "left point"), + self.left_point.map(|left_point| left_point), + )?; + + // Assign right point + let right_point = Point::new( + ecc_chip, + layouter.namespace(|| "right point"), + self.right_point.map(|right_point| right_point), + )?; + + // Apply mux + let result = cond_swap_chip.mux_on_points( + layouter.namespace(|| "MUX"), + &choice, + left_point.inner(), + right_point.inner(), + )?; + + // Check equality with instance + layouter.constrain_instance(result.x().cell(), config.primary, 0)?; + layouter.constrain_instance(result.y().cell(), config.primary, 1) + } + } + + // Test different circuits + let mut circuits = vec![]; + let mut instances = vec![]; + for choice in [false, true] { + let choice_value = if choice { + pallas::Base::one() + } else { + pallas::Base::zero() + }; + let left_point = pallas::Point::random(OsRng).to_affine(); + let right_point = pallas::Point::random(OsRng).to_affine(); + circuits.push(MyCircuit { + left_point: Value::known(left_point), + right_point: Value::known(right_point), + choice: Value::known(choice_value), + }); + let expected_output = if choice { right_point } else { left_point }; + let (expected_x, expected_y) = if bool::from(expected_output.is_identity()) { + (pallas::Base::zero(), pallas::Base::zero()) + } else { + let coords = expected_output.coordinates().unwrap(); + (*coords.x(), *coords.y()) + }; + instances.push([[expected_x, expected_y]]); + } + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + let prover = MockProver::::run( + 5, + circuit, + instance.iter().map(|p| p.to_vec()).collect(), + ) + .unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } +} diff --git a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs new file mode 100644 index 0000000000..13d278f834 --- /dev/null +++ b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs @@ -0,0 +1,570 @@ +//! Make use of a K-bit lookup table to decompose a field element into K-bit +//! words. + +use std::marker::PhantomData; + +use halo2_proofs::{ + circuit::{AssignedCell, Region}, + plonk::{ + Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector, TableColumn, + }, + poly::Rotation, +}; + +#[cfg(test)] +use halo2_proofs::circuit::{Layouter, Value}; + +use ff::PrimeFieldBits; + +use pasta_curves::pallas; + +use crate::{ + sinsemilla::primitives as sinsemilla, + utilities::lookup_range_check::{ + DefaultLookupRangeCheck, LookupRangeCheck, LookupRangeCheckConfig, + }, +}; + +/// Configuration that provides methods for a lookup range check. +#[derive(Eq, PartialEq, Debug, Clone, Copy)] +pub struct LookupRangeCheckConfigOptimized { + base: LookupRangeCheckConfig, + q_range_check_4: Selector, + q_range_check_5: Selector, + // FIXME: Instead of making it pub, add a method in LookupRangeCheckConfig that returns table_range_check_tag + //pub(crate) + table_range_check_tag: TableColumn, +} + +impl LookupRangeCheckConfigOptimized { + /// The `running_sum` advice column breaks the field element into `K`-bit + /// words. It is used to construct the input expression to the lookup + /// argument. + /// + /// The `table_idx` fixed column contains values from [0..2^K). Looking up + /// a value in `table_idx` constrains it to be within this range. The table + /// can be loaded outside this helper. + /// + /// # Side-effects + /// + /// Both the `running_sum` and `constants` columns will be equality-enabled. + fn configure_with_tag( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + table_range_check_tag: TableColumn, + ) -> Self { + meta.enable_equality(running_sum); + + let q_lookup = meta.complex_selector(); + let q_running = meta.complex_selector(); + let q_bitshift = meta.selector(); + + let q_range_check_4 = meta.complex_selector(); + let q_range_check_5 = meta.complex_selector(); + + // FIXME: q_range_check_4 and q_range_check_5 need to be created here + // if the order of the creation makes a difference + let config = LookupRangeCheckConfigOptimized { + base: LookupRangeCheckConfig { + q_lookup, + q_running, + q_bitshift, + running_sum, + table_idx, + _marker: PhantomData, + }, + q_range_check_4, + q_range_check_5, + table_range_check_tag, + }; + + // https://p.z.cash/halo2-0.1:decompose-combined-lookup + meta.lookup(|meta| { + let q_lookup = meta.query_selector(config.base.q_lookup); + let q_running = meta.query_selector(config.base.q_running); + // FIXME: q_range_check_4 and q_range_check_5 need to be created here + // if the order of the creation makes a difference + let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); + let one = Expression::Constant(F::ONE); + + // In the case of a running sum decomposition, we recover the word from + // the difference of the running sums: + // z_i = 2^{K}⋅z_{i + 1} + a_i + // => a_i = z_i - 2^{K}⋅z_{i + 1} + let running_sum_lookup = { + let running_sum_word = { + let z_next = meta.query_advice(config.base.running_sum, Rotation::next()); + z_cur.clone() - z_next * F::from(1 << K) + }; + + q_running.clone() * running_sum_word + }; + + // In the short range check, the word is directly witnessed. + let short_lookup = { + let short_word = z_cur.clone(); + let q_short = one.clone() - q_running; + + q_short * short_word + }; + + let q_range_check_4 = meta.query_selector(config.q_range_check_4); + let q_range_check_5 = meta.query_selector(config.q_range_check_5); + + // q_range_check is equal to + // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 + // - 0 otherwise + let q_range_check = one.clone() + - (one.clone() - q_range_check_4.clone()) * (one.clone() - q_range_check_5.clone()); + + // num_bits is equal to + // - 5 if q_range_check_5 = 1 + // - 4 if q_range_check_4 = 1 and q_range_check_5 = 0 + // - 0 otherwise + let num_bits = q_range_check_5.clone() * Expression::Constant(F::from(5_u64)) + + (one.clone() - q_range_check_5) + * q_range_check_4 + * Expression::Constant(F::from(4_u64)); + + // Combine the running sum, short lookups and optimized range checks: + vec![ + ( + q_lookup.clone() + * ((one - q_range_check.clone()) * (running_sum_lookup + short_lookup) + + q_range_check.clone() * z_cur), + config.base.table_idx, + ), + ( + q_lookup * q_range_check * num_bits, + config.table_range_check_tag, + ), + ] + }); + + // For short lookups, check that the word has been shifted by the correct number of bits. + // https://p.z.cash/halo2-0.1:decompose-short-lookup + meta.create_gate("Short lookup bitshift", |meta| { + let q_bitshift = meta.query_selector(config.base.q_bitshift); + let word = meta.query_advice(config.base.running_sum, Rotation::prev()); + let shifted_word = meta.query_advice(config.base.running_sum, Rotation::cur()); + let inv_two_pow_s = meta.query_advice(config.base.running_sum, Rotation::next()); + + let two_pow_k = F::from(1 << K); + + // shifted_word = word * 2^{K-s} + // = word * 2^K * inv_two_pow_s + Constraints::with_selector( + q_bitshift, + Some(word * two_pow_k * inv_two_pow_s - shifted_word), + ) + }); + + config + } + + pub(crate) fn table_range_check_tag(&self) -> TableColumn { + self.table_range_check_tag + } +} + +impl LookupRangeCheck + for LookupRangeCheckConfigOptimized +{ + fn config(&self) -> &LookupRangeCheckConfig { + &self.base + } + + fn configure( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + ) -> Self { + let table_range_check_tag = meta.lookup_table_column(); + Self::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) + } + + #[cfg(test)] + // Fill `table_idx` and `table_range_check_tag`. + // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table + // in the Orchard context. + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table_idx", + |mut table| { + let mut assign_cells = + |offset: usize, table_size, value: u64| -> Result { + for index in 0..table_size { + let new_index = index + offset; + table.assign_cell( + || "table_idx", + self.base.table_idx, + new_index, + || Value::known(F::from(index as u64)), + )?; + table.assign_cell( + || "table_range_check_tag", + self.table_range_check_tag, + new_index, + || Value::known(F::from(value)), + )?; + } + Ok(offset + table_size) + }; + + // We generate the row values lazily (we only need them during keygen). + let mut offset = 0; + + //annotation: &'v (dyn Fn() -> String + 'v), + //column: TableColumn, + //offset: usize, + //to: &'v mut (dyn FnMut() -> Value> + 'v), + + offset = assign_cells(offset, 1 << K, 0)?; + offset = assign_cells(offset, 1 << 4, 4)?; + assign_cells(offset, 1 << 5, 5)?; + + Ok(()) + }, + ) + } + + /// Constrain `x` to be a NUM_BITS word. + /// + /// `element` must have been assigned to `self.running_sum` at offset 0. + fn short_range_check( + &self, + region: &mut Region<'_, F>, + element: AssignedCell, + num_bits: usize, + ) -> Result<(), Error> { + match num_bits { + 4 => { + self.base.q_lookup.enable(region, 0)?; + self.q_range_check_4.enable(region, 0)?; + Ok(()) + } + + 5 => { + self.base.q_lookup.enable(region, 0)?; + self.q_range_check_5.enable(region, 0)?; + Ok(()) + } + + _ => self.base.short_range_check(region, element, num_bits), + } + } +} + +#[cfg(test)] +mod tests { + use super::{LookupRangeCheck, LookupRangeCheckConfigOptimized}; + + use crate::sinsemilla::primitives::K; + use crate::utilities::lebs2ip; + + use ff::{Field, PrimeFieldBits}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::{FailureLocation, MockProver, VerifyFailure}, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use pasta_curves::pallas; + + use std::{convert::TryInto, marker::PhantomData}; + + #[test] + fn lookup_range_check() { + #[derive(Clone, Copy)] + struct MyCircuit { + num_words: usize, + _marker: PhantomData, + } + + impl Circuit for MyCircuit { + type Config = LookupRangeCheckConfigOptimized; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + *self + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + LookupRangeCheckConfigOptimized::::configure_with_tag( + meta, + running_sum, + table_idx, + table_range_check_tag, + ) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_words * K bits. + let elements_and_expected_final_zs = [ + (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long + (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long + ]; + + fn expected_zs( + element: F, + num_words: usize, + ) -> Vec { + let chunks = { + element + .to_le_bits() + .iter() + .by_vals() + .take(num_words * K) + .collect::>() + .chunks_exact(K) + .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) + .collect::>() + }; + let expected_zs = { + let inv_two_pow_k = F::from(1 << K).invert().unwrap(); + chunks.iter().fold(vec![element], |mut zs, a_i| { + // z_{i + 1} = (z_i - a_i) / 2^{K} + let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; + zs.push(z); + zs + }) + }; + expected_zs + } + + for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { + let expected_zs = expected_zs::(*element, self.num_words); + + let zs = config.witness_check( + layouter.namespace(|| format!("Lookup {:?}", self.num_words)), + Value::known(*element), + self.num_words, + *strict, + )?; + + assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); + + for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { + z.value().assert_if_known(|z| &&expected_z == z); + } + } + Ok(()) + } + } + + { + let circuit: MyCircuit = MyCircuit { + num_words: 6, + _marker: PhantomData, + }; + + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } + + #[test] + fn short_range_check() { + struct MyCircuit { + element: Value, + num_bits: usize, + } + + impl Circuit for MyCircuit { + type Config = LookupRangeCheckConfigOptimized; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + MyCircuit { + element: Value::unknown(), + num_bits: self.num_bits, + } + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + LookupRangeCheckConfigOptimized::::configure_with_tag( + meta, + running_sum, + table_idx, + table_range_check_tag, + ) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_bits. + config.witness_short_check( + layouter.namespace(|| format!("Lookup {:?} bits", self.num_bits)), + self.element, + self.num_bits, + )?; + + Ok(()) + } + } + + // Edge case: zero bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::ZERO), + num_bits: 0, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Edge case: K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from((1 << K) - 1)), + num_bits: K, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Element within `num_bits` + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from((1 << 6) - 1)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Element larger than `num_bits` but within K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from(1 << 6)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }]) + ); + } + + // Element larger than K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from(1 << K)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }, + VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }, + ]) + ); + } + + // Element which is not within `num_bits`, but which has a shifted value within + // num_bits + { + let num_bits = 6; + let shifted = pallas::Base::from((1 << num_bits) - 1); + // Recall that shifted = element * 2^{K-s} + // => element = shifted * 2^{s-K} + let element = shifted + * pallas::Base::from(1 << (K as u64 - num_bits)) + .invert() + .unwrap(); + let circuit: MyCircuit = MyCircuit { + element: Value::known(element), + num_bits: num_bits as usize, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }]) + ); + } + + // Element within 4 bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from((1 << 4) - 1)), + num_bits: 4, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Element larger than 5 bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from(1 << 5)), + num_bits: 5, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 5 bits").into(), + offset: 0, + }, + }]) + ); + } + } +} + +pub(crate) type DefaultLookupRangeCheckConfigOptimized = + LookupRangeCheckConfigOptimized; + +impl DefaultLookupRangeCheck for DefaultLookupRangeCheckConfigOptimized {} From d3a6f4239c21d8c2249664a308d10754186ff2a8 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Wed, 24 Apr 2024 11:29:41 +0200 Subject: [PATCH 002/121] clean up code --- halo2_gadgets/src/ecc/chip/mul.rs | 2 +- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 1 - halo2_gadgets/src/ecc_opt.rs | 15 +- .../src/ecc_opt/chip/mul_fixed/short.rs | 162 +----------------- halo2_gadgets/src/sinsemilla.rs | 6 +- halo2_gadgets/src/sinsemilla/chip.rs | 8 +- .../src/sinsemilla/chip/generator_table.rs | 2 - .../src/sinsemilla/chip/hash_to_point.rs | 70 ++++---- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 2 +- halo2_gadgets/src/sinsemilla_opt.rs | 2 +- halo2_gadgets/src/sinsemilla_opt/chip.rs | 23 +-- .../sinsemilla_opt/chip/generator_table.rs | 2 - .../src/sinsemilla_opt/merkle/chip.rs | 1 - halo2_gadgets/src/utilities_opt/cond_swap.rs | 1 - .../src/utilities_opt/lookup_range_check.rs | 3 - 15 files changed, 58 insertions(+), 242 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 85677da520..6408ae6a44 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -461,7 +461,7 @@ pub mod tests { Curve, }; use halo2_proofs::{ - circuit::{Chip, Layouter, Value}, + circuit::{Layouter, Value}, plonk::Error, }; use pasta_curves::pallas; diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 8ce73ca3c6..c746bd5f97 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -252,7 +252,6 @@ pub mod tests { plonk::{Any, Error}, }; use pasta_curves::pallas; - use std::marker::PhantomData; use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheck}; use crate::{ diff --git a/halo2_gadgets/src/ecc_opt.rs b/halo2_gadgets/src/ecc_opt.rs index a8ed313c10..6f0203c384 100644 --- a/halo2_gadgets/src/ecc_opt.rs +++ b/halo2_gadgets/src/ecc_opt.rs @@ -80,7 +80,7 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; + use crate::utilities::lookup_range_check::LookupRangeCheck; use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; #[derive(Debug, Eq, PartialEq, Clone)] @@ -100,19 +100,6 @@ pub(crate) mod tests { find_zs_and_us(*BASE, NUM_WINDOWS_SHORT).unwrap(); } - impl FullWidth { - pub(crate) fn from_pallas_generator() -> Self { - FullWidth(*BASE, &ZS_AND_US) - } - - pub(crate) fn from_parts( - base: pallas::Affine, - zs_and_us: &'static [(u64, [pallas::Base; H])], - ) -> Self { - FullWidth(base, zs_and_us) - } - } - impl FixedPoint for FullWidth { type FixedScalarKind = FullScalar; diff --git a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs index 679bd5d2be..65abba6291 100644 --- a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs @@ -88,169 +88,13 @@ pub mod tests { use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ ecc::{ - chip::{EccChip, FixedPoint, MagnitudeSign}, + chip::{EccChip}, tests::{Short, TestFixedBases}, - FixedPointShort, NonIdentityPoint, Point, ScalarFixedShort, + Point, ScalarFixedShort, }, - utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, + utilities::UtilitiesInstructions, }; - #[allow(clippy::op_ref)] - pub(crate) fn test_mul_fixed_short( - chip: EccChip< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // test_short - let base_val = Short.generator(); - let test_short = FixedPointShort::from_inner(chip.clone(), Short); - - fn load_magnitude_sign( - chip: EccChip< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - mut layouter: impl Layouter, - magnitude: pallas::Base, - sign: pallas::Base, - ) -> Result { - let column = chip.config().advices[0]; - let magnitude = chip.load_private( - layouter.namespace(|| "magnitude"), - column, - Value::known(magnitude), - )?; - let sign = - chip.load_private(layouter.namespace(|| "sign"), column, Value::known(sign))?; - - Ok((magnitude, sign)) - } - - fn constrain_equal_non_id( - chip: EccChip< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - mut layouter: impl Layouter, - base_val: pallas::Affine, - scalar_val: pallas::Scalar, - result: Point< - pallas::Affine, - EccChip< - TestFixedBases, - LookupRangeCheckConfigOptimized< - pallas::Base, - { crate::sinsemilla::primitives::K }, - >, - >, - >, - ) -> Result<(), Error> { - let expected = NonIdentityPoint::new( - chip, - layouter.namespace(|| "expected point"), - Value::known((base_val * scalar_val).to_affine()), - )?; - result.constrain_equal(layouter.namespace(|| "constrain result"), &expected) - } - - let magnitude_signs = [ - ("random [a]B", pallas::Base::from(rand::random::()), { - let mut random_sign = pallas::Base::one(); - if rand::random::() { - random_sign = -random_sign; - } - random_sign - }), - ( - "[2^64 - 1]B", - pallas::Base::from(0xFFFF_FFFF_FFFF_FFFFu64), - pallas::Base::one(), - ), - ( - "-[2^64 - 1]B", - pallas::Base::from(0xFFFF_FFFF_FFFF_FFFFu64), - -pallas::Base::one(), - ), - // There is a single canonical sequence of window values for which a doubling occurs on the last step: - // 1333333333333333333334 in octal. - // [0xB6DB_6DB6_DB6D_B6DC] B - ( - "mul_with_double", - pallas::Base::from(0xB6DB_6DB6_DB6D_B6DCu64), - pallas::Base::one(), - ), - ( - "mul_with_double negative", - pallas::Base::from(0xB6DB_6DB6_DB6D_B6DCu64), - -pallas::Base::one(), - ), - ]; - - for (name, magnitude, sign) in magnitude_signs.iter() { - let (result, _) = { - let magnitude_sign = load_magnitude_sign( - chip.clone(), - layouter.namespace(|| *name), - *magnitude, - *sign, - )?; - let by = ScalarFixedShort::new( - chip.clone(), - layouter.namespace(|| "signed short scalar"), - magnitude_sign, - )?; - test_short.mul(layouter.namespace(|| *name), by)? - }; - // Move from base field into scalar field - let scalar = { - let magnitude = pallas::Scalar::from_repr(magnitude.to_repr()).unwrap(); - let sign = if *sign == pallas::Base::one() { - pallas::Scalar::one() - } else { - -pallas::Scalar::one() - }; - magnitude * sign - }; - constrain_equal_non_id( - chip.clone(), - layouter.namespace(|| *name), - base_val, - scalar, - result, - )?; - } - - let zero_magnitude_signs = [ - ("mul by +zero", pallas::Base::zero(), pallas::Base::one()), - ("mul by -zero", pallas::Base::zero(), -pallas::Base::one()), - ]; - - for (name, magnitude, sign) in zero_magnitude_signs.iter() { - let (result, _) = { - let magnitude_sign = load_magnitude_sign( - chip.clone(), - layouter.namespace(|| *name), - *magnitude, - *sign, - )?; - let by = ScalarFixedShort::new( - chip.clone(), - layouter.namespace(|| "signed short scalar"), - magnitude_sign, - )?; - test_short.mul(layouter.namespace(|| *name), by)? - }; - result - .inner() - .is_identity() - .assert_if_known(|is_identity| *is_identity); - } - - Ok(()) - } - #[test] fn invalid_magnitude_sign() { use crate::{ diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index d518c341cc..7cbedd7a15 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -78,7 +78,7 @@ pub trait SinsemillaInstructions, @@ -416,6 +418,7 @@ where } #[allow(clippy::type_complexity)] + #[allow(non_snake_case)] /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit @@ -447,6 +450,7 @@ where } #[allow(clippy::type_complexity)] + #[allow(non_snake_case)] /// $\mathsf{SinsemillaShortCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 07ad5323f9..d1e03c044d 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -17,18 +17,14 @@ use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{ Advice, Column, ConstraintSystem, Constraints, Error, Expression, Fixed, Selector, - TableColumn, VirtualCells, + VirtualCells, }, poly::Rotation, }; use pasta_curves::pallas; use pasta_curves::pallas::Base; - pub(crate) mod generator_table; -use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable, GeneratorTable}; -use crate::sinsemilla_opt::chip::generator_table::GeneratorTableConfigOptimized; -use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; -use generator_table::GeneratorTableConfig; +use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable}; pub(crate) mod hash_to_point; diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 5c09500554..463cc4f323 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -1,4 +1,3 @@ -use ff::PrimeFieldBits; use group::ff::PrimeField; use halo2_proofs::{ circuit::{Layouter, Value}, @@ -8,7 +7,6 @@ use halo2_proofs::{ use std::fmt::Debug; use super::{CommitDomains, FixedPoints, HashDomains}; -use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; use crate::{ sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, utilities::lookup_range_check::DefaultLookupRangeCheck, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 6c0bc392e5..c7ca71a4c8 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -63,7 +63,6 @@ where let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; - #[cfg(test)] self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum) } @@ -88,42 +87,47 @@ where ), Error, > { - use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; + #[cfg(test)] + #[allow(non_snake_case)] + { + use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; + + use group::{prime::PrimeCurveAffine, Curve}; + use pasta_curves::arithmetic::CurveExt; - use group::{prime::PrimeCurveAffine, Curve}; - use pasta_curves::arithmetic::CurveExt; + let field_elems: Value> = message + .iter() + .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) + .collect(); - let field_elems: Value> = message - .iter() - .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) - .collect(); + let value_Q = match Q { + EccPointQ::PublicPoint(p) => Value::known(p), + EccPointQ::PrivatePoint(p) => p.point(), + }; - let value_Q = match Q { - EccPointQ::PublicPoint(p) => Value::known(p), - EccPointQ::PrivatePoint(p) => p.point(), - }; + field_elems + .zip(x_a.value().zip(y_a.value())) + .zip(value_Q) + .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { + // Get message as a bitstring. + let bitstring: Vec = field_elems + .iter() + .flat_map(|(elem, num_words)| elem.to_le_bits().into_iter().take(K * num_words)) + .collect(); + + let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); + let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); + + // We can use complete addition here because it differs from + // incomplete addition with negligible probability. + let expected_point = bitstring + .chunks(K) + .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); + let actual_point = pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); + expected_point.to_affine() == actual_point + }); + } - field_elems - .zip(x_a.value().zip(y_a.value())) - .zip(value_Q) - .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { - // Get message as a bitstring. - let bitstring: Vec = field_elems - .iter() - .flat_map(|(elem, num_words)| elem.to_le_bits().into_iter().take(K * num_words)) - .collect(); - - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - - // We can use complete addition here because it differs from - // incomplete addition with negligible probability. - let expected_point = bitstring - .chunks(K) - .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); - let actual_point = pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); - expected_point.to_affine() == actual_point - }); x_a.value() .zip(y_a.value()) diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index ebfe08a701..685d338490 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -9,7 +9,7 @@ use pasta_curves::pallas; use super::MerkleInstructions; -use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable, GeneratorTableConfig}; +use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable}; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, utilities::{lookup_range_check::DefaultLookupRangeCheck, RangeConstrained}, diff --git a/halo2_gadgets/src/sinsemilla_opt.rs b/halo2_gadgets/src/sinsemilla_opt.rs index 1103a73705..8948283c62 100644 --- a/halo2_gadgets/src/sinsemilla_opt.rs +++ b/halo2_gadgets/src/sinsemilla_opt.rs @@ -78,6 +78,7 @@ where + Eq, { #[allow(clippy::type_complexity)] + #[allow(non_snake_case)] /// Evaluates the Sinsemilla hash of `message` from the public initial point `Q` stored /// into `CommitDomain`. pub fn hash( @@ -159,7 +160,6 @@ pub(crate) mod tests { tests::{FullWidth, TestFixedBases}, NonIdentityPoint, }, - utilities::lookup_range_check::LookupRangeCheckConfig, }, }; diff --git a/halo2_gadgets/src/sinsemilla_opt/chip.rs b/halo2_gadgets/src/sinsemilla_opt/chip.rs index 790a7c9484..1fa6bc582f 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip.rs @@ -1,29 +1,20 @@ //! Chip implementations for the Sinsemilla gadgets. use super::SinsemillaInstructionsOptimized; -use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable, GeneratorTableConfig}; -use crate::sinsemilla_opt::chip::generator_table::GeneratorTableConfigOptimized; -use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheckConfig}; -use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; +use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable}; +use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck}; use crate::{ - ecc::{chip::NonIdentityEccPoint, FixedPoints}, + ecc::{FixedPoints}, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, - message::{Message, MessagePiece}, - primitives as sinsemilla, CommitDomains, HashDomains, SinsemillaInstructions, + chip::{SinsemillaChip}, + primitives as sinsemilla, CommitDomains, HashDomains, }, - utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, }; -use halo2_proofs::plonk::Expression; use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter, Value}, - plonk::{ - Advice, Column, ConstraintSystem, Constraints, Error, Fixed, TableColumn, VirtualCells, - }, - poly::Rotation, + circuit::{Layouter}, + plonk::Error, }; use pasta_curves::pallas; -use pasta_curves::pallas::Base; pub(crate) mod generator_table; diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs index d721778427..6a582dddde 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs @@ -11,8 +11,6 @@ use crate::sinsemilla::{ chip::generator_table::GeneratorTableConfig, primitives::{K, SINSEMILLA_S}, }; -use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheckConfig}; -use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; /// Table containing independent generators S[0..2^k] #[derive(Eq, PartialEq, Copy, Clone, Debug)] diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs index 48f078cb38..7b9d160e9c 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs @@ -12,7 +12,6 @@ use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; use crate::{ sinsemilla::{merkle::chip::MerkleChip, primitives as sinsemilla}, sinsemilla_opt::SinsemillaInstructionsOptimized, - utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, { ecc::FixedPoints, sinsemilla::{CommitDomains, HashDomains}, diff --git a/halo2_gadgets/src/utilities_opt/cond_swap.rs b/halo2_gadgets/src/utilities_opt/cond_swap.rs index 13b169ec2e..4ba03e5eea 100644 --- a/halo2_gadgets/src/utilities_opt/cond_swap.rs +++ b/halo2_gadgets/src/utilities_opt/cond_swap.rs @@ -292,7 +292,6 @@ mod tests { CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), diff --git a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs index 13d278f834..115d8ea811 100644 --- a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs @@ -163,9 +163,6 @@ impl LookupRangeCheckConfigOptimized { config } - pub(crate) fn table_range_check_tag(&self) -> TableColumn { - self.table_range_check_tag - } } impl LookupRangeCheck From 86bd33f49d3170620de5038077a5c11860411bdf Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Wed, 24 Apr 2024 11:31:47 +0200 Subject: [PATCH 003/121] remove cfg[test] --- halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs index b62a8ae152..282ef6dc9a 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs @@ -51,7 +51,6 @@ where // FIXME: calling construct_base is possibly(!) non-optimal let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; - #[cfg(test)] self.check_hash_result(EccPointQ::PrivatePoint(Q), message, x_a, y_a, zs_sum) } From 989f29bae96d974e1d3f0de77e95648108ac692f Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Thu, 25 Apr 2024 11:55:31 +0200 Subject: [PATCH 004/121] remove generator table trait, fix hash_to_point --- halo2_gadgets/Cargo.toml | 1 + halo2_gadgets/src/ecc.rs | 6 +- halo2_gadgets/src/ecc/chip.rs | 2 +- halo2_gadgets/src/ecc/chip/mul.rs | 6 +- halo2_gadgets/src/ecc_opt.rs | 23 +- .../src/ecc_opt/chip/mul_fixed/short.rs | 166 ++++++------ halo2_gadgets/src/sinsemilla.rs | 42 +-- halo2_gadgets/src/sinsemilla/chip.rs | 228 ++++++---------- .../src/sinsemilla/chip/generator_table.rs | 39 +-- .../src/sinsemilla/chip/hash_to_point.rs | 31 ++- halo2_gadgets/src/sinsemilla/merkle.rs | 31 +-- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 233 ++++++----------- halo2_gadgets/src/sinsemilla_opt.rs | 53 ++-- halo2_gadgets/src/sinsemilla_opt/chip.rs | 78 +++++- .../sinsemilla_opt/chip/generator_table.rs | 185 ++++++------- .../src/sinsemilla_opt/chip/hash_to_point.rs | 8 +- halo2_gadgets/src/sinsemilla_opt/merkle.rs | 244 ++++++++++++++++++ .../src/sinsemilla_opt/merkle/chip.rs | 21 +- .../src/utilities/lookup_range_check.rs | 7 +- halo2_gadgets/src/utilities_opt/cond_swap.rs | 111 +------- .../src/utilities_opt/lookup_range_check.rs | 9 +- rust-toolchain.toml | 2 +- 22 files changed, 755 insertions(+), 771 deletions(-) diff --git a/halo2_gadgets/Cargo.toml b/halo2_gadgets/Cargo.toml index 09ab4efc84..1aa754264e 100644 --- a/halo2_gadgets/Cargo.toml +++ b/halo2_gadgets/Cargo.toml @@ -49,6 +49,7 @@ pprof = { version = "0.8", features = ["criterion", "flamegraph"] } # MSRV 1.56 bench = false [features] +default = ["test-dev-graph"] test-dev-graph = [ "halo2_proofs/dev-graph", "plotters", diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 2bd1491565..a03eaa141a 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -574,6 +574,7 @@ impl> FixedPointShort { Self { chip, inner } } } + #[cfg(test)] pub(crate) mod tests { use ff::PrimeField; @@ -594,7 +595,10 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; + use crate::{ + sinsemilla::primitives as sinsemilla, + utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + }; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index f581e625c6..df8e1bb124 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -74,7 +74,7 @@ impl EccPoint { } #[cfg(test)] - pub(crate) fn is_identity(&self) -> Value { + fn is_identity(&self) -> Value { self.x.value().map(|x| x.is_zero_vartime()) } } diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 6408ae6a44..b4b6d55518 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -62,7 +62,7 @@ pub struct Config { } impl Config { - pub(super) fn configure( + pub(crate) fn configure( meta: &mut ConstraintSystem, add_config: add::Config, lookup_config: LookupRangeCheckConfig, @@ -461,13 +461,13 @@ pub mod tests { Curve, }; use halo2_proofs::{ - circuit::{Layouter, Value}, + circuit::{Chip, Layouter, Value}, plonk::Error, }; use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; + use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheckConfig}; use crate::{ ecc::{ chip::{EccChip, EccPoint}, diff --git a/halo2_gadgets/src/ecc_opt.rs b/halo2_gadgets/src/ecc_opt.rs index 6f0203c384..253662a7ca 100644 --- a/halo2_gadgets/src/ecc_opt.rs +++ b/halo2_gadgets/src/ecc_opt.rs @@ -59,7 +59,6 @@ impl + Clone + Debug + Eq> }) } } - #[cfg(test)] pub(crate) mod tests { use ff::PrimeField; @@ -100,6 +99,19 @@ pub(crate) mod tests { find_zs_and_us(*BASE, NUM_WINDOWS_SHORT).unwrap(); } + impl FullWidth { + pub(crate) fn from_pallas_generator() -> Self { + FullWidth(*BASE, &ZS_AND_US) + } + + pub(crate) fn from_parts( + base: pallas::Affine, + zs_and_us: &'static [(u64, [pallas::Base; H])], + ) -> Self { + FullWidth(base, zs_and_us) + } + } + impl FixedPoint for FullWidth { type FixedScalarKind = FullScalar; @@ -226,6 +238,7 @@ pub(crate) mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -240,8 +253,12 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup_table, + table_range_check_tag, + ); EccChip::< crate::ecc::tests::TestFixedBases, LookupRangeCheckConfigOptimized, diff --git a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs index 65abba6291..927aea4858 100644 --- a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs @@ -76,7 +76,8 @@ impl> Config { #[cfg(test)] pub mod tests { - use group::{ff::PrimeField, Curve, Group}; + use ff::PrimeField; + use group::{Curve, Group}; use halo2_proofs::{ arithmetic::CurveAffine, circuit::{AssignedCell, Chip, Layouter, Value}, @@ -84,17 +85,84 @@ pub mod tests { }; use pasta_curves::pallas; - use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheck}; + use crate::ecc::tests::Short; + use crate::ecc::ScalarFixedShort; + use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ - ecc::{ - chip::{EccChip}, - tests::{Short, TestFixedBases}, - Point, ScalarFixedShort, + ecc::{chip::EccChip, tests::TestFixedBases, Point}, + utilities::{ + lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + UtilitiesInstructions, }, - utilities::UtilitiesInstructions, }; + pub(crate) fn test_mul_sign( + chip: EccChip, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Generate a random non-identity point P + let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); + let p = Point::new( + chip.clone(), + layouter.namespace(|| "P"), + Value::known(p_val), + )?; + + // Create -P + let p_neg_val = -p_val; + let p_neg = Point::new( + chip.clone(), + layouter.namespace(|| "-P"), + Value::known(p_neg_val), + )?; + + // Create the identity point + let identity = Point::new( + chip.clone(), + layouter.namespace(|| "identity"), + Value::known(pallas::Point::identity().to_affine()), + )?; + + // Create -1 and 1 scalars + let pos_sign = chip.load_private( + layouter.namespace(|| "positive sign"), + chip.config().advices[0], + Value::known(pallas::Base::one()), + )?; + let neg_sign = chip.load_private( + layouter.namespace(|| "negative sign"), + chip.config().advices[1], + Value::known(-pallas::Base::one()), + )?; + + // [1] P == P + { + let result = p.mul_sign(layouter.namespace(|| "[1] P"), &pos_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p)?; + } + + // [-1] P == -P + { + let result = p.mul_sign(layouter.namespace(|| "[1] P"), &neg_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p_neg)?; + } + + // [1] 0 == 0 + { + let result = identity.mul_sign(layouter.namespace(|| "[1] O"), &pos_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; + } + + // [-1] 0 == 0 + { + let result = identity.mul_sign(layouter.namespace(|| "[-1] O"), &neg_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; + } + + Ok(()) + } + #[test] fn invalid_magnitude_sign() { use crate::{ @@ -144,6 +212,7 @@ pub mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -159,8 +228,12 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup_table, + table_range_check_tag, + ); EccChip::< TestFixedBases, LookupRangeCheckConfigOptimized< @@ -363,72 +436,6 @@ pub mod tests { } } - pub(crate) fn test_mul_sign( - chip: EccChip, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Generate a random non-identity point P - let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); - let p = Point::new( - chip.clone(), - layouter.namespace(|| "P"), - Value::known(p_val), - )?; - - // Create -P - let p_neg_val = -p_val; - let p_neg = Point::new( - chip.clone(), - layouter.namespace(|| "-P"), - Value::known(p_neg_val), - )?; - - // Create the identity point - let identity = Point::new( - chip.clone(), - layouter.namespace(|| "identity"), - Value::known(pallas::Point::identity().to_affine()), - )?; - - // Create -1 and 1 scalars - let pos_sign = chip.load_private( - layouter.namespace(|| "positive sign"), - chip.config().advices[0], - Value::known(pallas::Base::one()), - )?; - let neg_sign = chip.load_private( - layouter.namespace(|| "negative sign"), - chip.config().advices[1], - Value::known(-pallas::Base::one()), - )?; - - // [1] P == P - { - let result = p.mul_sign(layouter.namespace(|| "[1] P"), &pos_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p)?; - } - - // [-1] P == -P - { - let result = p.mul_sign(layouter.namespace(|| "[1] P"), &neg_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p_neg)?; - } - - // [1] 0 == 0 - { - let result = identity.mul_sign(layouter.namespace(|| "[1] O"), &pos_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; - } - - // [-1] 0 == 0 - { - let result = identity.mul_sign(layouter.namespace(|| "[-1] O"), &neg_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; - } - - Ok(()) - } - #[test] fn invalid_sign_in_mul_sign() { use crate::{ecc::chip::EccConfig, utilities::UtilitiesInstructions}; @@ -473,6 +480,7 @@ pub mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -488,8 +496,12 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup_table, + table_range_check_tag, + ); EccChip::< TestFixedBases, LookupRangeCheckConfigOptimized< diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 7cbedd7a15..a3e2dc892b 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -78,13 +78,12 @@ pub trait SinsemillaInstructions, - is_Q_public: bool, Q: C, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec), Error>; @@ -316,19 +315,17 @@ where } #[allow(clippy::type_complexity)] - #[allow(non_snake_case)] /// $\mathsf{SinsemillaHashToPoint}$ from [§ 5.4.1.9][concretesinsemillahash]. /// /// [concretesinsemillahash]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash pub fn hash_to_point( &self, layouter: impl Layouter, - is_Q_public: bool, message: Message, ) -> Result<(ecc::NonIdentityPoint, Vec), Error> { assert_eq!(self.sinsemilla_chip, message.chip); self.sinsemilla_chip - .hash_to_point(layouter, is_Q_public, self.Q, message.inner) + .hash_to_point(layouter, self.Q, message.inner) .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) } @@ -336,15 +333,13 @@ where /// /// [concretesinsemillahash]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash #[allow(clippy::type_complexity)] - #[allow(non_snake_case)] pub fn hash( &self, layouter: impl Layouter, - is_Q_public: bool, message: Message, ) -> Result<(ecc::X, Vec), Error> { assert_eq!(self.sinsemilla_chip, message.chip); - let (p, zs) = self.hash_to_point(layouter, is_Q_public, message)?; + let (p, zs) = self.hash_to_point(layouter, message)?; Ok((p.extract_p(), zs)) } } @@ -418,14 +413,12 @@ where } #[allow(clippy::type_complexity)] - #[allow(non_snake_case)] /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit pub fn commit( &self, mut layouter: impl Layouter, - is_Q_public: bool, message: Message, r: ecc::ScalarFixed, ) -> Result< @@ -443,26 +436,23 @@ where //let blind = self.blinding_factor(layouter.namespace(|| "[r] R"), r)?; //let (p, zs) = self.hash(layouter.namespace(|| "M"), message)?; let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; - let (p, zs) = self.M.hash_to_point(layouter.namespace(|| "M"), is_Q_public, message)?; - + let (p, zs) = self.M.hash_to_point(layouter.namespace(|| "M"), message)?; let commitment = p.add(layouter.namespace(|| "M + [r] R"), &blind)?; Ok((commitment, zs)) } #[allow(clippy::type_complexity)] - #[allow(non_snake_case)] /// $\mathsf{SinsemillaShortCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit pub fn short_commit( &self, mut layouter: impl Layouter, - is_Q_public: bool, message: Message, r: ecc::ScalarFixed, ) -> Result<(ecc::X, Vec), Error> { assert_eq!(self.M.sinsemilla_chip, message.chip); - let (p, zs) = self.commit(layouter.namespace(|| "commit"), is_Q_public, message, r)?; + let (p, zs) = self.commit(layouter.namespace(|| "commit"), message, r)?; Ok((p.extract_p(), zs)) } } @@ -490,7 +480,7 @@ pub(crate) mod tests { tests::{FullWidth, TestFixedBases}, NonIdentityPoint, }, - utilities::lookup_range_check::LookupRangeCheckConfig, + utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, }, }; @@ -498,8 +488,6 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::sinsemilla::chip::generator_table::GeneratorTableConfig; - use crate::utilities::lookup_range_check::LookupRangeCheck; use std::convert::TryInto; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; @@ -548,14 +536,12 @@ pub(crate) mod tests { TestCommitDomain, TestFixedBases, LookupRangeCheckConfig, - GeneratorTableConfig, >, SinsemillaConfig< TestHashDomain, TestCommitDomain, TestFixedBases, LookupRangeCheckConfig, - GeneratorTableConfig, >, ); type FloorPlanner = SimpleFloorPlanner; @@ -603,11 +589,6 @@ pub(crate) mod tests { ); let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); - let table = GeneratorTableConfig { - table_idx: lookup.0, - table_x: lookup.1, - table_y: lookup.2, - }; let ecc_config = EccChip::< TestFixedBases, @@ -615,21 +596,19 @@ pub(crate) mod tests { >::configure(meta, advices, lagrange_coeffs, range_check); let config1 = SinsemillaChip::configure( - true, meta, advices[..5].try_into().unwrap(), advices[2], lagrange_coeffs[0], - table, + lookup, range_check, ); let config2 = SinsemillaChip::configure( - true, meta, advices[5..].try_into().unwrap(), advices[7], lagrange_coeffs[1], - table, + lookup, range_check, ); (ecc_config, config1, config2) @@ -650,7 +629,6 @@ pub(crate) mod tests { TestCommitDomain, TestFixedBases, LookupRangeCheckConfig, - GeneratorTableConfig, >::load(config.1.clone(), &mut layouter)?; // This MerkleCRH example is purely for illustrative purposes. @@ -718,7 +696,7 @@ pub(crate) mod tests { // Parent let (parent, _) = { let message = Message::from_pieces(chip1, vec![l, left, right]); - merkle_crh.hash_to_point(layouter.namespace(|| "parent"), true, message)? + merkle_crh.hash_to_point(layouter.namespace(|| "parent"), message)? }; parent.constrain_equal( @@ -748,7 +726,7 @@ pub(crate) mod tests { layouter.namespace(|| "witness message"), message.clone(), )?; - test_commit.commit(layouter.namespace(|| "commit"), true, message, r)? + test_commit.commit(layouter.namespace(|| "commit"), message, r)? }; // Witness expected result. diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index d1e03c044d..4793a99da2 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -17,26 +17,25 @@ use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{ Advice, Column, ConstraintSystem, Constraints, Error, Expression, Fixed, Selector, - VirtualCells, + TableColumn, VirtualCells, }, poly::Rotation, }; use pasta_curves::pallas; -use pasta_curves::pallas::Base; + pub(crate) mod generator_table; -use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable}; +use generator_table::GeneratorTableConfig; pub(crate) mod hash_to_point; /// Configuration for the Sinsemilla hash chip #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaConfig +pub struct SinsemillaConfig where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { /// Binary selector used in lookup argument and in the body of the Sinsemilla hash. pub(crate) q_sinsemilla1: Selector, @@ -58,20 +57,19 @@ where pub(crate) witness_pieces: Column, /// The lookup table where $(\mathsf{idx}, x_p, y_p)$ are loaded for the $2^K$ /// generators of the Sinsemilla hash. - pub(crate) generator_table: GeneratorTableConfigType, + pub(crate) generator_table: GeneratorTableConfig, /// An advice column configured to perform lookup range checks. pub(crate) lookup_config: LookupRangeCheckConfig, - _marker: PhantomData<(Hash, Commit, F)>, + pub(crate) _marker: PhantomData<(Hash, Commit, F)>, } -impl - SinsemillaConfig +impl + SinsemillaConfig where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { /// Returns an array of all advice columns in this config, in arbitrary order. pub(super) fn advices(&self) -> [Column; 5] { @@ -101,28 +99,25 @@ where /// /// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaChip +pub struct SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { - config: SinsemillaConfig, + config: SinsemillaConfig, } -impl Chip - for SinsemillaChip +impl Chip + for SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { - type Config = - SinsemillaConfig; + type Config = SinsemillaConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -134,14 +129,13 @@ where } } -impl - SinsemillaChip +impl + SinsemillaChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { @@ -150,55 +144,67 @@ where /// Loads the lookup table required by this chip into the circuit. pub fn load( - config: SinsemillaConfig, + config: SinsemillaConfig, layouter: &mut impl Layouter, ) -> Result<>::Loaded, Error> { // Load the lookup table. - config.generator_table.load(layouter) - } - /// Query a fixed value from the circuit's fixed column using the configuration `fixed_y_q`. - fn get_y_q_fixed( - meta: &mut VirtualCells, - config: &SinsemillaConfig< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - >, - ) -> Expression { - meta.query_fixed(config.fixed_y_q) - } - - /// Query an advice value 'y_q' from a specific advice column `x_p` at the previous rotation. - fn get_y_q_advice( - meta: &mut VirtualCells, - config: &SinsemillaConfig< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - >, - ) -> Expression { - meta.query_advice(config.double_and_add.x_p, Rotation::prev()) + config.generator_table.load(layouter) } + /// # Side-effects + /// + /// All columns in `advices` and will be equality-enabled. + #[allow(clippy::too_many_arguments)] #[allow(non_snake_case)] - pub(crate) fn create_initial_y_q_gate( - is_Q_public: bool, + pub fn configure( meta: &mut ConstraintSystem, - config: &SinsemillaConfig< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - >, - ) { + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + lookup: (TableColumn, TableColumn, TableColumn), + range_check: LookupRangeCheckConfig, + ) -> >::Config { + // FIXME: add comments + + // Enable equality on all advice columns + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let config = SinsemillaConfig:: { + q_sinsemilla1: meta.complex_selector(), + q_sinsemilla2: meta.fixed_column(), + q_sinsemilla4: meta.selector(), + fixed_y_q, + double_and_add: DoubleAndAdd { + x_a: advices[0], + x_p: advices[1], + lambda_1: advices[3], + lambda_2: advices[4], + }, + bits: advices[2], + witness_pieces, + generator_table: GeneratorTableConfig { + table_idx: lookup.0, + table_x: lookup.1, + table_y: lookup.2, + }, + lookup_config: range_check, + _marker: PhantomData, + }; + + // Set up lookup argument + GeneratorTableConfig::configure(meta, &config); + let two = pallas::Base::from(2); + // Closures for expressions that are derived multiple times + // x_r = lambda_1^2 - x_a - x_p + let x_r = |meta: &mut VirtualCells, rotation| { + config.double_and_add.x_r(meta, rotation) + }; + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) let Y_A = |meta: &mut VirtualCells, rotation| { config.double_and_add.Y_A(meta, rotation) @@ -208,13 +214,11 @@ where // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Initial y_Q", |meta| { let q_s4 = meta.query_selector(config.q_sinsemilla4); - // fixme: how to change to optimized get_y_q in a simple way? - let y_q = if is_Q_public { - Self::get_y_q_fixed(meta, &config) + let y_q = if LookupRangeCheckConfig::is_optimized() { + meta.query_advice(config.double_and_add.x_p, Rotation::prev()) } else { - Self::get_y_q_advice(meta, &config) + meta.query_fixed(config.fixed_y_q) }; - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) let Y_A_cur = Y_A(meta, Rotation::cur()); @@ -223,31 +227,6 @@ where Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) }); - } - - #[allow(non_snake_case)] - pub(crate) fn create_sinsemilla_gate( - meta: &mut ConstraintSystem, - config: &SinsemillaConfig< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - >, - ) { - let two = pallas::Base::from(2); - - // Closures for expressions that are derived multiple times - // x_r = lambda_1^2 - x_a - x_p - let x_r = |meta: &mut VirtualCells, rotation| { - config.double_and_add.x_r(meta, rotation) - }; - - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) - let Y_A = |meta: &mut VirtualCells, rotation| { - config.double_and_add.Y_A(meta, rotation) - }; // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Sinsemilla gate", |meta| { @@ -293,82 +272,20 @@ where Constraints::with_selector(q_s1, [("Secant line", secant_line), ("y check", y_check)]) }); - } - - pub(crate) fn create_config( - meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - table: GeneratorTableConfigType, - range_check: LookupRangeCheckConfig, - ) -> >::Config { - // Enable equality on all advice columns - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let config = - SinsemillaConfig:: { - q_sinsemilla1: meta.complex_selector(), - q_sinsemilla2: meta.fixed_column(), - q_sinsemilla4: meta.selector(), - fixed_y_q, - double_and_add: DoubleAndAdd { - x_a: advices[0], - x_p: advices[1], - lambda_1: advices[3], - lambda_2: advices[4], - }, - bits: advices[2], - witness_pieces, - // todo: check - generator_table: table, - lookup_config: range_check, - _marker: PhantomData, - }; - - // Set up lookup argument - config.generator_table.configure(meta, &config); - - config - } - - /// # Side-effects - /// - /// All columns in `advices` and will be equality-enabled. - #[allow(clippy::too_many_arguments)] - #[allow(non_snake_case)] - pub fn configure( - is_Q_public: bool, - meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - table: GeneratorTableConfigType, - range_check: LookupRangeCheckConfig, - ) -> >::Config { - let config = - Self::create_config(meta, advices, witness_pieces, fixed_y_q, table, range_check); - - Self::create_initial_y_q_gate(is_Q_public, meta, &config); - - Self::create_sinsemilla_gate(meta, &config); config } } // Implement `SinsemillaInstructions` for `SinsemillaChip` -impl +impl SinsemillaInstructions - for SinsemillaChip + for SinsemillaChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { type CellValue = AssignedCell; @@ -411,13 +328,12 @@ where fn hash_to_point( &self, mut layouter: impl Layouter, - is_Q_public: bool, Q: pallas::Affine, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec), Error> { layouter.assign_region( || "hash_to_point", - |mut region| self.hash_message(is_Q_public, &mut region, Q, &message), + |mut region| self.hash_message(&mut region, Q, &message), ) } diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 463cc4f323..ed7cc9e554 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -4,9 +4,9 @@ use halo2_proofs::{ plonk::{ConstraintSystem, Error, Expression, TableColumn}, poly::Rotation, }; -use std::fmt::Debug; use super::{CommitDomains, FixedPoints, HashDomains}; +use crate::utilities::lookup_range_check::LookupRangeCheckConfig; use crate::{ sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, utilities::lookup_range_check::DefaultLookupRangeCheck, @@ -21,36 +21,25 @@ pub struct GeneratorTableConfig { pub table_y: TableColumn, } -/// FIXME: add doc -pub trait GeneratorTable { - fn config(&self) -> &GeneratorTableConfig; - +impl GeneratorTableConfig { #[allow(clippy::too_many_arguments)] #[allow(non_snake_case)] /// Even though the lookup table can be used in other parts of the circuit, /// this specific configuration sets up Sinsemilla-specific constraints /// controlled by `q_sinsemilla`, and would likely not apply to other chips. - fn configure( - &self, + pub fn configure( meta: &mut ConstraintSystem, - config: &super::SinsemillaConfig< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - >, + config: &super::SinsemillaConfig, ) where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { let (table_idx, table_x, table_y) = ( - self.config().table_idx, - self.config().table_x, - self.config().table_y, + config.generator_table.table_idx, + config.generator_table.table_x, + config.generator_table.table_y, ); // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial @@ -93,14 +82,7 @@ pub trait GeneratorTable { }); } - fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error>; -} -impl GeneratorTable for GeneratorTableConfig { - fn config(&self) -> &GeneratorTableConfig { - self - } - - fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + pub fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { layouter.assign_table( || "generator_table", |mut table| { @@ -119,8 +101,3 @@ impl GeneratorTable for GeneratorTableConfig { ) } } - -/// FIXME: add doc -pub trait DefaultGeneratorTable: GeneratorTable + Eq + PartialEq + Clone + Copy + Debug {} - -impl DefaultGeneratorTable for GeneratorTableConfig {} diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index c7ca71a4c8..1bb1ce9ed6 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -1,5 +1,5 @@ use super::super::{CommitDomains, HashDomains, SinsemillaInstructions}; -use super::{NonIdentityEccPoint, SinsemillaChip}; +use super::{NonIdentityEccPoint, SinsemillaChip, SinsemillaConfig}; use crate::{ ecc::FixedPoints, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, @@ -15,7 +15,6 @@ use halo2_proofs::{ use group::ff::{PrimeField, PrimeFieldBits}; use pasta_curves::{arithmetic::CurveAffine, pallas}; -use crate::sinsemilla::chip::generator_table::DefaultGeneratorTable; use std::ops::Deref; /// Define an enum that can hold either type @@ -25,21 +24,19 @@ pub enum EccPointQ<'a> { PrivatePoint(&'a NonIdentityEccPoint), } -impl - SinsemillaChip +impl + SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] #[allow(clippy::type_complexity)] pub(super) fn hash_message( &self, - is_Q_public: bool, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, message: & { - // todo: add doc about is_Q_public - let (offset, x_a, y_a) = if is_Q_public { - self.public_initialization_vanilla(region, Q)? - } else { + // todo: add doc about LookupRangeCheckConfig::is_optimized() + //let (offset, x_a, y_a) = self.public_initialization(region, Q)?; + let (offset, x_a, y_a) = if LookupRangeCheckConfig::is_optimized() { self.public_initialization(region, Q)? + } else { + self.public_initialization_vanilla(region, Q)? }; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; @@ -66,7 +64,6 @@ where self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum) } - #[cfg(test)] #[allow(non_snake_case)] // Check equivalence to result from primitives::sinsemilla::hash_to_point pub(crate) fn check_hash_result( @@ -88,7 +85,6 @@ where Error, > { #[cfg(test)] - #[allow(non_snake_case)] { use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; @@ -112,7 +108,9 @@ where // Get message as a bitstring. let bitstring: Vec = field_elems .iter() - .flat_map(|(elem, num_words)| elem.to_le_bits().into_iter().take(K * num_words)) + .flat_map(|(elem, num_words)| { + elem.to_le_bits().into_iter().take(K * num_words) + }) .collect(); let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); @@ -123,12 +121,12 @@ where let expected_point = bitstring .chunks(K) .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); - let actual_point = pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); + let actual_point = + pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); expected_point.to_affine() == actual_point }); } - x_a.value() .zip(y_a.value()) .error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?; @@ -139,7 +137,8 @@ where } #[allow(non_snake_case)] - /// Assign the coordinates of the initial public point `Q` + /// Assign the coordinates of the initial public point `Q`, + /// y_Q to a fixed column /// /// | offset | x_A | q_sinsemilla4 | fixed_y_q | /// -------------------------------------- diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 3b85ac807c..1485c466f1 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -36,7 +36,6 @@ pub trait MerkleInstructions< fn hash_layer( &self, layouter: impl Layouter, - is_Q_public: bool, Q: C, l: usize, left: Self::Var, @@ -57,11 +56,11 @@ pub struct MerklePath< > where MerkleChip: MerkleInstructions + Clone, { - chips: [MerkleChip; PAR], - domain: MerkleChip::HashDomains, - leaf_pos: Value, + pub(crate) chips: [MerkleChip; PAR], + pub(crate) domain: MerkleChip::HashDomains, + pub(crate) leaf_pos: Value, // The Merkle path is ordered from leaves to root. - path: Value<[C::Base; PATH_LENGTH]>, + pub(crate) path: Value<[C::Base; PATH_LENGTH]>, } impl< @@ -118,7 +117,6 @@ where pub fn calculate_root( &self, mut layouter: impl Layouter, - is_Q_public: bool, leaf: MerkleChip::Var, ) -> Result { // Each chip processes `ceil(PATH_LENGTH / PAR)` layers. @@ -161,7 +159,6 @@ where // M^l_i = MerkleCRH(l, M^{l+1}_{2i}, M^{l+1}_{2i+1}) node = chip.hash_layer( layouter.namespace(|| format!("MerkleCRH({}, left, right)", l)), - is_Q_public, Q, l, pair.0, @@ -202,7 +199,6 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::sinsemilla::chip::generator_table::GeneratorTableConfig; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; @@ -222,14 +218,12 @@ pub mod tests { TestCommitDomain, TestFixedBases, LookupRangeCheckConfig, - GeneratorTableConfig, >, MerkleConfig< TestHashDomain, TestCommitDomain, TestFixedBases, LookupRangeCheckConfig, - GeneratorTableConfig, >, ); type FloorPlanner = SimpleFloorPlanner; @@ -268,32 +262,24 @@ pub mod tests { meta.lookup_table_column(), ); - let table = GeneratorTableConfig { - table_idx: lookup.0, - table_x: lookup.1, - table_y: lookup.2, - }; - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup.0); let sinsemilla_config_1 = SinsemillaChip::configure( - true, meta, advices[5..].try_into().unwrap(), advices[7], fixed_y_q_1, - table, + lookup, range_check, ); let config1 = MerkleChip::configure(meta, sinsemilla_config_1); let sinsemilla_config_2 = SinsemillaChip::configure( - true, meta, advices[..5].try_into().unwrap(), advices[2], fixed_y_q_2, - table, + lookup, range_check, ); let config2 = MerkleChip::configure(meta, sinsemilla_config_2); @@ -312,7 +298,6 @@ pub mod tests { TestCommitDomain, TestFixedBases, LookupRangeCheckConfig, - GeneratorTableConfig, >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. @@ -333,7 +318,7 @@ pub mod tests { }; let computed_final_root = - path.calculate_root(layouter.namespace(|| "calculate root"), true, leaf)?; + path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?; self.leaf .zip(self.leaf_pos) @@ -422,7 +407,7 @@ pub mod tests { let circuit = MyCircuit::default(); halo2_proofs::dev::CircuitLayout::default() - .show_labels(false) + .show_labels(true) .render(11, &circuit, &root) .unwrap(); } diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 685d338490..dc7fb3f6f8 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -9,7 +9,6 @@ use pasta_curves::pallas; use super::MerkleInstructions; -use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable}; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, utilities::{lookup_range_check::DefaultLookupRangeCheck, RangeConstrained}, @@ -29,19 +28,17 @@ use group::ff::PrimeField; /// Configuration for the `MerkleChip` implementation. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleConfig +pub struct MerkleConfig where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { advices: [Column; 5], q_decompose: Selector, pub(crate) cond_swap_config: CondSwapConfig, - pub(crate) sinsemilla_config: - SinsemillaConfig, + pub(crate) sinsemilla_config: SinsemillaConfig, } /// Chip implementing `MerkleInstructions`. @@ -55,28 +52,25 @@ where /// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of /// `left` and `right`. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleChip +pub struct MerkleChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { - config: MerkleConfig, + config: MerkleConfig, } -impl Chip - for MerkleChip +impl Chip + for MerkleChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { - type Config = - MerkleConfig; + type Config = MerkleConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -88,26 +82,18 @@ where } } -impl - MerkleChip +impl MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { /// Configures the [`MerkleChip`]. pub fn configure( meta: &mut ConstraintSystem, - sinsemilla_config: SinsemillaConfig< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - >, - ) -> MerkleConfig { + sinsemilla_config: SinsemillaConfig, + ) -> MerkleConfig { // All five advice columns are equality-enabled by SinsemillaConfig. let advices = sinsemilla_config.advices(); let cond_swap_config = CondSwapChip::configure(meta, advices); @@ -210,34 +196,24 @@ where } /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. - pub fn construct( - config: MerkleConfig, - ) -> Self { + pub fn construct(config: MerkleConfig) -> Self { MerkleChip { config } } } -impl< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - const MERKLE_DEPTH: usize, - > MerkleInstructions - for MerkleChip +impl + MerkleInstructions + for MerkleChip where Hash: HashDomains + Eq, F: FixedPoints, Commit: CommitDomains + Eq, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { #[allow(non_snake_case)] fn hash_layer( &self, mut layouter: impl Layouter, - is_Q_public: bool, Q: pallas::Affine, // l = MERKLE_DEPTH - layer - 1 l: usize, @@ -329,7 +305,6 @@ where // https://p.z.cash/proto:merkle-crh-orchard let (point, zs) = self.hash_to_point( layouter.namespace(|| format!("hash at l = {}", l)), - is_Q_public, Q, vec![a.inner(), b.inner(), c.inner()].into(), )?; @@ -446,28 +421,24 @@ where } } -impl - UtilitiesInstructions - for MerkleChip +impl UtilitiesInstructions + for MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { type Var = AssignedCell; } -impl - CondSwapInstructions - for MerkleChip +impl CondSwapInstructions + for MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { #[allow(clippy::type_complexity)] fn swap( @@ -482,108 +453,71 @@ where } } -impl +impl SinsemillaInstructions - for MerkleChip + for MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { - type CellValue = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CellValue; - - type Message = as SinsemillaInstructions>::Message; - type MessagePiece = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::MessagePiece; - type RunningSum = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::RunningSum; - - type X = as SinsemillaInstructions< + type CellValue = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CellValue; + + type Message = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::Message; + type MessagePiece = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::MessagePiece; + type RunningSum = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::RunningSum; + + type X = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::X; - type NonIdentityPoint = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::NonIdentityPoint; - type FixedPoints = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::FixedPoints; - - type HashDomains = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::HashDomains; - type CommitDomains = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CommitDomains; + type NonIdentityPoint = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::NonIdentityPoint; + type FixedPoints = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::FixedPoints; + + type HashDomains = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::HashDomains; + type CommitDomains = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CommitDomains; fn witness_message_piece( &self, @@ -592,13 +526,7 @@ where num_words: usize, ) -> Result { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChip::< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - >::construct(config); + let chip = SinsemillaChip::::construct(config); chip.witness_message_piece(layouter, value, num_words) } @@ -607,24 +535,15 @@ where fn hash_to_point( &self, layouter: impl Layouter, - is_Q_public: bool, Q: pallas::Affine, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChip::< - Hash, - Commit, - F, - LookupRangeCheckConfig, - GeneratorTableConfigType, - >::construct(config); - chip.hash_to_point(layouter, is_Q_public, Q, message) + let chip = SinsemillaChip::::construct(config); + chip.hash_to_point(layouter, Q, message) } fn extract(point: &Self::NonIdentityPoint) -> Self::X { - SinsemillaChip::::extract( - point, - ) + SinsemillaChip::::extract(point) } } diff --git a/halo2_gadgets/src/sinsemilla_opt.rs b/halo2_gadgets/src/sinsemilla_opt.rs index 8948283c62..cca2af19f8 100644 --- a/halo2_gadgets/src/sinsemilla_opt.rs +++ b/halo2_gadgets/src/sinsemilla_opt.rs @@ -5,6 +5,7 @@ use std::fmt::Debug; use pasta_curves::arithmetic::CurveAffine; +use pasta_curves::pallas; use halo2_proofs::{circuit::Layouter, plonk::Error}; @@ -78,13 +79,11 @@ where + Eq, { #[allow(clippy::type_complexity)] - #[allow(non_snake_case)] /// Evaluates the Sinsemilla hash of `message` from the public initial point `Q` stored /// into `CommitDomain`. pub fn hash( &self, layouter: impl Layouter, - is_Q_public: bool, message: Message, ) -> Result< ( @@ -94,7 +93,7 @@ where Error, > { assert_eq!(self.M.sinsemilla_chip, message.chip); - self.M.hash_to_point(layouter, is_Q_public, message) + self.M.hash_to_point(layouter, message) } #[allow(non_snake_case)] @@ -160,6 +159,7 @@ pub(crate) mod tests { tests::{FullWidth, TestFixedBases}, NonIdentityPoint, }, + utilities::lookup_range_check::LookupRangeCheckConfig, }, }; @@ -167,9 +167,7 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::sinsemilla::chip::generator_table::GeneratorTableConfig; - use crate::sinsemilla_opt::chip::generator_table::GeneratorTableConfigOptimized; - use crate::utilities::lookup_range_check::LookupRangeCheck; + use crate::sinsemilla_opt::chip::SinsemillaChipOptimized; use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use std::convert::TryInto; @@ -219,14 +217,12 @@ pub(crate) mod tests { TestCommitDomain, TestFixedBases, LookupRangeCheckConfigOptimized, - GeneratorTableConfigOptimized, >, SinsemillaConfig< TestHashDomain, TestCommitDomain, TestFixedBases, LookupRangeCheckConfigOptimized, - GeneratorTableConfigOptimized, >, ); type FloorPlanner = SimpleFloorPlanner; @@ -255,6 +251,7 @@ pub(crate) mod tests { meta.enable_constant(constants); let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -266,25 +263,19 @@ pub(crate) mod tests { meta.fixed_column(), ]; - // todo: check the lookup.3 and LookupRangeCheckConfigOptimized::configure, to see if one more column is created // Fixed columns for the Sinsemilla generator lookup table let lookup = ( table_idx, meta.lookup_table_column(), meta.lookup_table_column(), - meta.lookup_table_column(), ); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], table_idx); - let table = GeneratorTableConfigOptimized { - base: GeneratorTableConfig { - table_idx: lookup.0, - table_x: lookup.1, - table_y: lookup.2, - }, - table_range_check_tag: lookup.3, - }; + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); let ecc_config = EccChip::< TestFixedBases, @@ -292,21 +283,19 @@ pub(crate) mod tests { >::configure(meta, advices, lagrange_coeffs, range_check); let config1 = SinsemillaChip::configure( - false, meta, advices[..5].try_into().unwrap(), advices[2], lagrange_coeffs[0], - table, + lookup, range_check, ); let config2 = SinsemillaChip::configure( - false, meta, advices[5..].try_into().unwrap(), advices[7], lagrange_coeffs[1], - table, + lookup, range_check, ); (ecc_config, config1, config2) @@ -321,14 +310,12 @@ pub(crate) mod tests { let ecc_chip = EccChip::construct(config.0); + // todo: check SinsemillaChipOptimized::load // The two `SinsemillaChip`s share the same lookup table. - SinsemillaChip::< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfigOptimized, - GeneratorTableConfigOptimized, - >::load(config.1.clone(), &mut layouter)?; + SinsemillaChipOptimized::::load( + config.1.clone(), + &mut layouter, + )?; // This MerkleCRH example is purely for illustrative purposes. // It is not an implementation of the Orchard protocol spec. @@ -395,7 +382,7 @@ pub(crate) mod tests { // Parent let (parent, _) = { let message = Message::from_pieces(chip1, vec![l, left, right]); - merkle_crh.hash_to_point(layouter.namespace(|| "parent"), false, message)? + merkle_crh.hash_to_point(layouter.namespace(|| "parent"), message)? }; parent.constrain_equal( @@ -425,7 +412,7 @@ pub(crate) mod tests { layouter.namespace(|| "witness message"), message.clone(), )?; - test_commit.commit(layouter.namespace(|| "commit"), false, message, r)? + test_commit.commit(layouter.namespace(|| "commit"), message, r)? }; // Witness expected result. diff --git a/halo2_gadgets/src/sinsemilla_opt/chip.rs b/halo2_gadgets/src/sinsemilla_opt/chip.rs index 1fa6bc582f..909ad21f7c 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip.rs @@ -1,35 +1,40 @@ //! Chip implementations for the Sinsemilla gadgets. use super::SinsemillaInstructionsOptimized; -use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable}; -use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck}; +use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; use crate::{ - ecc::{FixedPoints}, + ecc::{chip::NonIdentityEccPoint, FixedPoints}, sinsemilla::{ - chip::{SinsemillaChip}, - primitives as sinsemilla, CommitDomains, HashDomains, + chip::{SinsemillaChip, SinsemillaConfig}, + message::{Message, MessagePiece}, + primitives as sinsemilla, CommitDomains, HashDomains, SinsemillaInstructions, }, + utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, }; +use halo2_proofs::plonk::Expression; use halo2_proofs::{ - circuit::{Layouter}, - plonk::Error, + circuit::{AssignedCell, Chip, Layouter, Value}, + plonk::{ + Advice, Column, ConstraintSystem, Constraints, Error, Fixed, TableColumn, VirtualCells, + }, + poly::Rotation, }; use pasta_curves::pallas; +use pasta_curves::pallas::Base; pub(crate) mod generator_table; mod hash_to_point; // Implement `SinsemillaInstructionsOptimized` for `SinsemillaChip` -impl +impl SinsemillaInstructionsOptimized - for SinsemillaChip + for SinsemillaChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { #[allow(non_snake_case)] #[allow(clippy::type_complexity)] @@ -45,3 +50,56 @@ where ) } } + +/// A chip that implements 10-bit Sinsemilla using a lookup table and 5 advice columns. +/// +/// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct SinsemillaChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + inner: SinsemillaChip, +} + +// FIXME: is this needed? +impl Chip for SinsemillaChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + type Config = SinsemillaConfig; + type Loaded = (); + + fn config(&self) -> &Self::Config { + self.inner.config() + } + + fn loaded(&self) -> &Self::Loaded { + &() + } +} + +impl SinsemillaChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + /// Loads the lookup table required by this chip into the circuit. + pub fn load( + config: SinsemillaConfig, + layouter: &mut impl Layouter, + ) -> Result<>::Loaded, Error> { + // Load the lookup table. + generator_table::load_with_tag( + &config.generator_table, + // FIXME: consider to remove Option arount tag + config.lookup_config.table_range_check_tag(), + layouter, + ) + } +} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs index 6a582dddde..fc87e48c07 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs @@ -2,133 +2,110 @@ use halo2_proofs::{ circuit::{Layouter, Value}, plonk::{Error, TableColumn}, }; -use std::fmt::Debug; use pasta_curves::pallas; -use crate::sinsemilla::chip::generator_table::{DefaultGeneratorTable, GeneratorTable}; use crate::sinsemilla::{ chip::generator_table::GeneratorTableConfig, primitives::{K, SINSEMILLA_S}, }; -/// Table containing independent generators S[0..2^k] -#[derive(Eq, PartialEq, Copy, Clone, Debug)] -pub struct GeneratorTableConfigOptimized { - pub(crate) base: GeneratorTableConfig, - pub(crate) table_range_check_tag: TableColumn, -} -impl GeneratorTable for GeneratorTableConfigOptimized { - fn config(&self) -> &GeneratorTableConfig { - &self.base - } +/// Load the generator table into the circuit. +/// +/// | table_idx | table_x | table_y | table_range_check_tag | +/// ------------------------------------------------------------------- +/// | 0 | X(S\[0\]) | Y(S\[0\]) | 0 | +/// | 1 | X(S\[1\]) | Y(S\[1\]) | 0 | +/// | ... | ... | ... | 0 | +/// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | 0 | +/// | 0 | X(S\[0\]) | Y(S\[0\]) | 4 | +/// | 1 | X(S\[1\]) | Y(S\[1\]) | 4 | +/// | ... | ... | ... | 4 | +/// | 2^4-1 | X(S\[2^4-1\]) | Y(S\[2^4-1\]) | 4 | +/// | 0 | X(S\[0\]) | Y(S\[0\]) | 5 | +/// | 1 | X(S\[1\]) | Y(S\[1\]) | 5 | +/// | ... | ... | ... | 5 | +/// | 2^5-1 | X(S\[2^5-1\]) | Y(S\[2^5-1\]) | 5 | +pub fn load_with_tag( + config: &GeneratorTableConfig, + table_range_check_tag: TableColumn, + layouter: &mut impl Layouter, +) -> Result<(), Error> { + layouter.assign_table( + || "generator_table", + |mut table| { + for (index, (x, y)) in SINSEMILLA_S.iter().enumerate() { + table.assign_cell( + || "table_idx", + config.table_idx, + index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell(|| "table_x", config.table_x, index, || Value::known(*x))?; + table.assign_cell(|| "table_y", config.table_y, index, || Value::known(*y))?; - /// Load the generator table into the circuit. - /// - /// | table_idx | table_x | table_y | table_range_check_tag | - /// ------------------------------------------------------------------- - /// | 0 | X(S\[0\]) | Y(S\[0\]) | 0 | - /// | 1 | X(S\[1\]) | Y(S\[1\]) | 0 | - /// | ... | ... | ... | 0 | - /// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | 0 | - /// | 0 | X(S\[0\]) | Y(S\[0\]) | 4 | - /// | 1 | X(S\[1\]) | Y(S\[1\]) | 4 | - /// | ... | ... | ... | 4 | - /// | 2^4-1 | X(S\[2^4-1\]) | Y(S\[2^4-1\]) | 4 | - /// | 0 | X(S\[0\]) | Y(S\[0\]) | 5 | - /// | 1 | X(S\[1\]) | Y(S\[1\]) | 5 | - /// | ... | ... | ... | 5 | - /// | 2^5-1 | X(S\[2^5-1\]) | Y(S\[2^5-1\]) | 5 | - fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { - layouter.assign_table( - || "generator_table", - |mut table| { - for (index, (x, y)) in SINSEMILLA_S.iter().enumerate() { + table.assign_cell( + || "table_range_check_tag", + table_range_check_tag, + index, + || Value::known(pallas::Base::zero()), + )?; + if index < (1 << 4) { + let new_index = index + (1 << K); table.assign_cell( || "table_idx", - self.config().table_idx, - index, + config.table_idx, + new_index, || Value::known(pallas::Base::from(index as u64)), )?; table.assign_cell( || "table_x", - self.config().table_x, - index, + config.table_x, + new_index, || Value::known(*x), )?; table.assign_cell( || "table_y", - self.config().table_y, - index, + config.table_y, + new_index, || Value::known(*y), )?; table.assign_cell( || "table_range_check_tag", - self.table_range_check_tag, - index, - || Value::known(pallas::Base::zero()), + table_range_check_tag, + new_index, + || Value::known(pallas::Base::from(4_u64)), )?; - if index < (1 << 4) { - let new_index = index + (1 << K); - table.assign_cell( - || "table_idx", - self.config().table_idx, - new_index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell( - || "table_x", - self.config().table_x, - new_index, - || Value::known(*x), - )?; - table.assign_cell( - || "table_y", - self.config().table_y, - new_index, - || Value::known(*y), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(pallas::Base::from(4_u64)), - )?; - } - if index < (1 << 5) { - let new_index = index + (1 << 10) + (1 << 4); - table.assign_cell( - || "table_idx", - self.config().table_idx, - new_index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell( - || "table_x", - self.config().table_x, - new_index, - || Value::known(*x), - )?; - table.assign_cell( - || "table_y", - self.config().table_y, - new_index, - || Value::known(*y), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(pallas::Base::from(5_u64)), - )?; - } } - Ok(()) - }, - ) - } + if index < (1 << 5) { + let new_index = index + (1 << 10) + (1 << 4); + table.assign_cell( + || "table_idx", + config.table_idx, + new_index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell( + || "table_x", + config.table_x, + new_index, + || Value::known(*x), + )?; + table.assign_cell( + || "table_y", + config.table_y, + new_index, + || Value::known(*y), + )?; + table.assign_cell( + || "table_range_check_tag", + table_range_check_tag, + new_index, + || Value::known(pallas::Base::from(5_u64)), + )?; + } + } + Ok(()) + }, + ) } - -pub(crate) type DefaultGeneratorTableConfigOptimized = GeneratorTableConfigOptimized; - -impl DefaultGeneratorTable for DefaultGeneratorTableConfigOptimized {} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs index 282ef6dc9a..469a5991e1 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs @@ -5,7 +5,6 @@ use halo2_proofs::{ plonk::{Assigned, Error}, }; -use crate::sinsemilla::chip::generator_table::DefaultGeneratorTable; use crate::sinsemilla::chip::hash_to_point::EccPointQ; use crate::sinsemilla::chip::SinsemillaChip; use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; @@ -18,14 +17,13 @@ use crate::{ }, }; -impl - SinsemillaChip +impl + SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] @@ -55,7 +53,7 @@ where } #[allow(non_snake_case)] - /// Assign the coordinates of the initial public point `Q` + /// Assign the coordinates of the initial public point `Q` to advice columns /// /// | offset | x_A | x_P | q_sinsemilla4 | /// -------------------------------------- diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle.rs b/halo2_gadgets/src/sinsemilla_opt/merkle.rs index 2927585229..69d43a5c6d 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle.rs @@ -1,3 +1,247 @@ //! Gadgets for implementing a Merkle tree with Sinsemilla. pub mod chip; + +#[cfg(test)] +pub mod tests { + + use crate::{ + ecc::tests::TestFixedBases, + sinsemilla::{ + chip::SinsemillaChip, + tests::{TestCommitDomain, TestHashDomain}, + HashDomains, + }, + utilities::{i2lebsp, lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, + }; + + use group::ff::{Field, PrimeField, PrimeFieldBits}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + pasta::pallas, + plonk::{Circuit, ConstraintSystem, Error}, + }; + + use crate::sinsemilla::merkle::chip::{MerkleChip, MerkleConfig}; + use crate::sinsemilla::merkle::MerklePath; + use crate::sinsemilla_opt::chip::SinsemillaChipOptimized; + use crate::utilities::lookup_range_check::LookupRangeCheck; + use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; + use rand::{rngs::OsRng, RngCore}; + use std::{convert::TryInto, iter}; + + const MERKLE_DEPTH: usize = 32; + + #[derive(Default)] + struct MyCircuit { + leaf: Value, + leaf_pos: Value, + merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, + } + + impl Circuit for MyCircuit { + type Config = ( + MerkleConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + MerkleConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + ); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + // NB: In the actual Action circuit, these fixed columns will be reused + // by other chips. For this test, we are creating new fixed columns. + let fixed_y_q_1 = meta.fixed_column(); + let fixed_y_q_2 = meta.fixed_column(); + + // Fixed columns for the Sinsemilla generator lookup table + let lookup = ( + meta.lookup_table_column(), + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + let table_range_check_tag = meta.lookup_table_column(); + + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup.0, + table_range_check_tag, + ); + + let sinsemilla_config_1 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + fixed_y_q_1, + lookup, + range_check, + ); + let config1 = MerkleChip::configure(meta, sinsemilla_config_1); + + let sinsemilla_config_2 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + fixed_y_q_2, + lookup, + range_check, + ); + let config2 = MerkleChip::configure(meta, sinsemilla_config_2); + + (config1, config2) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load generator table (shared across both configs) for SinsemillaChipOptimized + SinsemillaChipOptimized::::load( + config.0.sinsemilla_config.clone(), + &mut layouter, + )?; + + // Construct Merkle chips which will be placed side-by-side in the circuit. + let chip_1 = MerkleChip::construct(config.0.clone()); + let chip_2 = MerkleChip::construct(config.1.clone()); + + let leaf = chip_1.load_private( + layouter.namespace(|| ""), + config.0.cond_swap_config.a(), + self.leaf, + )?; + + let path = MerklePath { + chips: [chip_1, chip_2], + domain: TestHashDomain, + leaf_pos: self.leaf_pos, + path: self.merkle_path, + }; + + let computed_final_root = + path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?; + + self.leaf + .zip(self.leaf_pos) + .zip(self.merkle_path) + .zip(computed_final_root.value()) + .assert_if_known(|(((leaf, leaf_pos), merkle_path), computed_final_root)| { + // The expected final root + let final_root = + merkle_path + .iter() + .enumerate() + .fold(*leaf, |node, (l, sibling)| { + let l = l as u8; + let (left, right) = if leaf_pos & (1 << l) == 0 { + (&node, sibling) + } else { + (sibling, &node) + }; + + use crate::sinsemilla::primitives as sinsemilla; + let merkle_crh = + sinsemilla::HashDomain::from_Q(TestHashDomain.Q().into()); + + merkle_crh + .hash( + iter::empty() + .chain(i2lebsp::<10>(l as u64).iter().copied()) + .chain( + left.to_le_bits() + .iter() + .by_vals() + .take(pallas::Base::NUM_BITS as usize), + ) + .chain( + right + .to_le_bits() + .iter() + .by_vals() + .take(pallas::Base::NUM_BITS as usize), + ), + ) + .unwrap_or(pallas::Base::zero()) + }); + + // Check the computed final root against the expected final root. + computed_final_root == &&final_root + }); + + Ok(()) + } + } + + #[test] + fn merkle_chip() { + let mut rng = OsRng; + + // Choose a random leaf and position + let leaf = pallas::Base::random(rng); + let pos = rng.next_u32(); + + // Choose a path of random inner nodes + let path: Vec<_> = (0..(MERKLE_DEPTH)) + .map(|_| pallas::Base::random(rng)) + .collect(); + + // The root is provided as a public input in the Orchard circuit. + + let circuit = MyCircuit { + leaf: Value::known(leaf), + leaf_pos: Value::known(pos), + merkle_path: Value::known(path.try_into().unwrap()), + }; + + let prover = MockProver::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())) + } + + #[cfg(feature = "test-dev-graph")] + #[test] + fn print_merkle_chip() { + use plotters::prelude::*; + + let root = BitMapBackend::new("merkle-path-layout.png", (1024, 7680)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); + + let circuit = MyCircuit::default(); + halo2_proofs::dev::CircuitLayout::default() + .show_labels(true) + .render(11, &circuit, &root) + .unwrap(); + } +} diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs index 7b9d160e9c..1eaf2c0853 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs @@ -6,12 +6,13 @@ use halo2_proofs::{ }; use pasta_curves::pallas; -use crate::sinsemilla::chip::generator_table::DefaultGeneratorTable; use crate::sinsemilla::chip::SinsemillaChip; -use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; +use crate::sinsemilla::SinsemillaInstructions; +use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ sinsemilla::{merkle::chip::MerkleChip, primitives as sinsemilla}, sinsemilla_opt::SinsemillaInstructionsOptimized, + utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, { ecc::FixedPoints, sinsemilla::{CommitDomains, HashDomains}, @@ -20,15 +21,12 @@ use crate::{ }, }; -impl - CondSwapInstructionsOptimized - for MerkleChip +impl CondSwapInstructionsOptimized + for MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { fn mux( &self, @@ -43,15 +41,13 @@ where } } -impl +impl SinsemillaInstructionsOptimized - for MerkleChip + for MerkleChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, - GeneratorTableConfigType: DefaultGeneratorTable, { #[allow(non_snake_case)] #[allow(clippy::type_complexity)] @@ -66,8 +62,7 @@ where Hash, Commit, F, - LookupRangeCheckConfig, - GeneratorTableConfigType, + LookupRangeCheckConfigOptimized, >::construct(config); chip.hash_to_point_with_private_init(layouter, Q, message) } diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 09369c04f1..f553920036 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -71,6 +71,8 @@ pub struct LookupRangeCheckConfig { /// FIXME: add doc pub trait LookupRangeCheck { + /// FIXME: add doc + fn is_optimized() -> bool; /// FIXME: add doc fn config(&self) -> &LookupRangeCheckConfig; @@ -235,7 +237,6 @@ pub trait LookupRangeCheck { // Copy `element` to use in the k-bit lookup. let element = element.copy_advice(|| "element", &mut region, self.config().running_sum, 0)?; - self.short_range_check(&mut region, element, num_bits) }, ) @@ -273,6 +274,10 @@ pub trait LookupRangeCheck { } impl LookupRangeCheck for LookupRangeCheckConfig { + fn is_optimized() -> bool { + false + } + fn config(&self) -> &LookupRangeCheckConfig { self } diff --git a/halo2_gadgets/src/utilities_opt/cond_swap.rs b/halo2_gadgets/src/utilities_opt/cond_swap.rs index 4ba03e5eea..d14e5407ba 100644 --- a/halo2_gadgets/src/utilities_opt/cond_swap.rs +++ b/halo2_gadgets/src/utilities_opt/cond_swap.rs @@ -120,113 +120,18 @@ impl CondSwapChip { #[cfg(test)] mod tests { - use super::{CondSwapChip, CondSwapInstructions}; - use crate::utilities::cond_swap::CondSwapConfig; - use crate::utilities::lookup_range_check::LookupRangeCheck; - use crate::utilities::UtilitiesInstructions; + use crate::utilities::cond_swap::{CondSwapChip, CondSwapConfig}; use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; - use group::ff::{Field, PrimeField}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use pasta_curves::pallas::Base; - use rand::rngs::OsRng; - - #[test] - fn cond_swap() { - #[derive(Default)] - struct MyCircuit { - a: Value, - b: Value, - swap: Value, - } - - impl Circuit for MyCircuit { - type Config = CondSwapConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - CondSwapChip::::configure(meta, advices) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let chip = CondSwapChip::::construct(config.clone()); - - // Load the pair and the swap flag into the circuit. - let a = chip.load_private(layouter.namespace(|| "a"), config.a, self.a)?; - // Return the swapped pair. - let swapped_pair = chip.swap( - layouter.namespace(|| "swap"), - (a.clone(), self.b), - self.swap, - )?; - - self.swap - .zip(a.value().zip(self.b.as_ref())) - .zip(swapped_pair.0.value().zip(swapped_pair.1.value())) - .assert_if_known(|((swap, (a, b)), (a_swapped, b_swapped))| { - if *swap { - // Check that `a` and `b` have been swapped - (a_swapped == b) && (b_swapped == a) - } else { - // Check that `a` and `b` have not been swapped - (a_swapped == a) && (b_swapped == b) - } - }); - - Ok(()) - } - } - - let rng = OsRng; - - // Test swap case - { - let circuit: MyCircuit = MyCircuit { - a: Value::known(Base::random(rng)), - b: Value::known(Base::random(rng)), - swap: Value::known(true), - }; - let prover = MockProver::::run(3, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - - // Test non-swap case - { - let circuit: MyCircuit = MyCircuit { - a: Value::known(Base::random(rng)), - b: Value::known(Base::random(rng)), - swap: Value::known(false), - }; - let prover = MockProver::::run(3, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - } #[test] fn test_mux() { - use crate::ecc::{ - chip::{EccChip, EccConfig}, - tests::TestFixedBases, - NonIdentityPoint, Point, + use crate::{ + ecc::{ + chip::{EccChip, EccConfig}, + tests::TestFixedBases, + NonIdentityPoint, Point, + }, + utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, }; use group::{cofactor::CofactorCurveAffine, Curve, Group}; diff --git a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs index 115d8ea811..6306e25bfb 100644 --- a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs @@ -48,7 +48,7 @@ impl LookupRangeCheckConfigOptimized { /// # Side-effects /// /// Both the `running_sum` and `constants` columns will be equality-enabled. - fn configure_with_tag( + pub(crate) fn configure_with_tag( meta: &mut ConstraintSystem, running_sum: Column, table_idx: TableColumn, @@ -163,11 +163,18 @@ impl LookupRangeCheckConfigOptimized { config } + pub(crate) fn table_range_check_tag(&self) -> TableColumn { + self.table_range_check_tag + } } impl LookupRangeCheck for LookupRangeCheckConfigOptimized { + fn is_optimized() -> bool { + true + } + fn config(&self) -> &LookupRangeCheckConfig { &self.base } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 948d27daa4..f8c2abbb3d 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.60.0" +channel = "1.65.0" From 507a53ce73afd79365516f7479f4196cb7810d4e Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 29 Apr 2024 15:31:41 +0200 Subject: [PATCH 005/121] update code for hash --- halo2_gadgets/src/ecc.rs | 1 - halo2_gadgets/src/ecc/chip.rs | 38 +- halo2_gadgets/src/ecc/chip/mul.rs | 18 +- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 8 +- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 26 +- .../src/ecc/chip/mul_fixed/full_width.rs | 16 +- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 14 +- halo2_gadgets/src/ecc_opt.rs | 13 - halo2_gadgets/src/ecc_opt/chip.rs | 4 +- .../src/ecc_opt/chip/mul_fixed/short.rs | 5 +- halo2_gadgets/src/sinsemilla/chip.rs | 189 +++++--- .../src/sinsemilla/chip/generator_table.rs | 7 +- .../src/sinsemilla/chip/hash_to_point.rs | 19 +- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 216 ++++----- halo2_gadgets/src/sinsemilla_opt.rs | 12 +- halo2_gadgets/src/sinsemilla_opt/chip.rs | 198 ++++++-- .../src/sinsemilla_opt/chip/hash_to_point.rs | 32 +- halo2_gadgets/src/sinsemilla_opt/merkle.rs | 19 +- .../src/sinsemilla_opt/merkle/chip.rs | 437 ++++++++++++++++-- .../src/utilities/lookup_range_check.rs | 35 +- halo2_gadgets/src/utilities_opt/cond_swap.rs | 2 +- .../src/utilities_opt/lookup_range_check.rs | 4 - 22 files changed, 918 insertions(+), 395 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index a03eaa141a..1d1a4a48e3 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -596,7 +596,6 @@ pub(crate) mod tests { FixedPoints, }; use crate::{ - sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, }; diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index df8e1bb124..76d5a019a7 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -136,7 +136,7 @@ impl From for EccPoint { #[allow(non_snake_case)] pub struct EccConfig< FixedPoints: super::FixedPoints, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, > { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], @@ -148,20 +148,20 @@ pub struct EccConfig< add: add::Config, /// Variable-base scalar multiplication - mul: mul::Config, + mul: mul::Config, /// Fixed-base full-width scalar multiplication mul_fixed_full: mul_fixed::full_width::Config, /// Fixed-base signed short scalar multiplication pub(crate) mul_fixed_short: mul_fixed::short::Config, /// Fixed-base mul using a base field element as a scalar - mul_fixed_base_field: mul_fixed::base_field_elem::Config, + mul_fixed_base_field: mul_fixed::base_field_elem::Config, /// Witness point pub(crate) witness_point: witness_point::Config, /// Lookup range check using 10-bit lookup table - pub lookup_config: LookupRangeCheckConfig, + pub lookup_config: Lookup, } /// A trait representing the kind of scalar used with a particular `FixedPoint`. @@ -229,17 +229,17 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { #[derive(Clone, Debug, Eq, PartialEq)] pub struct EccChip< FixedPoints: super::FixedPoints, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, > { - config: EccConfig, + config: EccConfig, } impl< FixedPoints: super::FixedPoints, - LookupRangeCheckConfig: DefaultLookupRangeCheck, - > Chip for EccChip + Lookup: DefaultLookupRangeCheck, + > Chip for EccChip { - type Config = EccConfig; + type Config = EccConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -253,16 +253,16 @@ impl< impl< Fixed: super::FixedPoints, - LookupRangeCheckConfig: DefaultLookupRangeCheck, - > UtilitiesInstructions for EccChip + Lookup: DefaultLookupRangeCheck, + > UtilitiesInstructions for EccChip { type Var = AssignedCell; } impl< FixedPoints: super::FixedPoints, - LookupRangeCheckConfig: DefaultLookupRangeCheck, - > EccChip + Lookup: DefaultLookupRangeCheck, + > EccChip { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { @@ -277,7 +277,7 @@ impl< meta: &mut ConstraintSystem, advices: [Column; 10], lagrange_coeffs: [Column; 8], - range_check: LookupRangeCheckConfig, + range_check: Lookup, ) -> >::Config { // Create witness point gate let witness_point = witness_point::Config::configure(meta, advices[0], advices[1]); @@ -315,7 +315,7 @@ impl< // Create gate that is only used in fixed-base mul using a base field element. let mul_fixed_base_field = - mul_fixed::base_field_elem::Config::::configure( + mul_fixed::base_field_elem::Config::::configure( meta, advices[6..9].try_into().unwrap(), range_check, @@ -421,8 +421,8 @@ pub enum ScalarVar { FullWidth, } -impl, LookupRangeCheckConfig: DefaultLookupRangeCheck> - EccInstructions for EccChip +impl, Lookup: DefaultLookupRangeCheck> + EccInstructions for EccChip where >::Base: FixedPoint, @@ -609,8 +609,8 @@ where } } -impl, LookupRangeCheckConfig: DefaultLookupRangeCheck> - BaseFitsInScalarInstructions for EccChip +impl, Lookup: DefaultLookupRangeCheck> + BaseFitsInScalarInstructions for EccChip where >::Base: FixedPoint, diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index b4b6d55518..61f36f88e9 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -46,7 +46,7 @@ const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, // Configuration used in complete addition @@ -58,14 +58,14 @@ pub struct Config { // Configuration used for complete addition part of double-and-add algorithm complete_config: complete::Config, // Configuration used to check for overflow - overflow_config: overflow::Config, + overflow_config: overflow::Config, } -impl Config { +impl Config { pub(crate) fn configure( meta: &mut ConstraintSystem, add_config: add::Config, - lookup_config: LookupRangeCheckConfig, + lookup_config: Lookup, advices: [Column; 10], ) -> Self { let hi_config = incomplete::Config::configure( @@ -461,13 +461,13 @@ pub mod tests { Curve, }; use halo2_proofs::{ - circuit::{Chip, Layouter, Value}, + circuit::{Layouter, Value}, plonk::Error, }; use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheckConfig}; + use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck}; use crate::{ ecc::{ chip::{EccChip, EccPoint}, @@ -477,10 +477,10 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul( - chip: EccChip, + pub(crate) fn test_mul( + chip: EccChip, mut layouter: impl Layouter, - p: &NonIdentityPoint>, + p: &NonIdentityPoint>, p_val: pallas::Affine, ) -> Result<(), Error> { let column = chip.config.advices[0]; diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index 8adaefa311..0912bd3a39 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -15,19 +15,19 @@ use pasta_curves::pallas; use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, // 10-bit lookup table - lookup_config: LookupRangeCheckConfig, + lookup_config: Lookup, // Advice columns advices: [Column; 3], } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, - lookup_config: LookupRangeCheckConfig, + lookup_config: Lookup, advices: [Column; 3], ) -> Self { for advice in advices.iter() { diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 254ba6804c..1298140e43 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -18,21 +18,21 @@ use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] pub struct Config< Fixed: FixedPoints, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, > { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], - lookup_config: LookupRangeCheckConfig, + lookup_config: Lookup, super_config: super::Config, } -impl, LookupRangeCheckConfig: DefaultLookupRangeCheck> - Config +impl, Lookup: DefaultLookupRangeCheck> + Config { pub(crate) fn configure( meta: &mut ConstraintSystem, canon_advices: [Column; 3], - lookup_config: LookupRangeCheckConfig, + lookup_config: Lookup, super_config: super::Config, ) -> Self { for advice in canon_advices.iter() { @@ -401,8 +401,8 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul_fixed_base_field( - chip: EccChip, + pub(crate) fn test_mul_fixed_base_field( + chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { test_single_base( @@ -414,22 +414,22 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( - chip: EccChip, + fn test_single_base( + chip: EccChip, mut layouter: impl Layouter, - base: FixedPointBaseField>, + base: FixedPointBaseField>, base_val: pallas::Affine, ) -> Result<(), Error> { let rng = OsRng; let column = chip.config().advices[0]; - fn constrain_equal_non_id( - chip: EccChip, + fn constrain_equal_non_id( + chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, scalar_val: pallas::Base, - result: Point>, + result: Point>, ) -> Result<(), Error> { // Move scalar from base field into scalar field (which always fits for Pallas). let scalar = pallas::Scalar::from_repr(scalar_val.to_repr()).unwrap(); diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs index a06b1b9394..fe2cc22094 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs @@ -194,8 +194,8 @@ pub mod tests { }; use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; - pub(crate) fn test_mul_fixed( - chip: EccChip, + pub(crate) fn test_mul_fixed( + chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { let test_base = FullWidth::from_pallas_generator(); @@ -210,18 +210,18 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( - chip: EccChip, + fn test_single_base( + chip: EccChip, mut layouter: impl Layouter, - base: FixedPoint>, + base: FixedPoint>, base_val: pallas::Affine, ) -> Result<(), Error> { - fn constrain_equal_non_id( - chip: EccChip, + fn constrain_equal_non_id( + chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, scalar_val: pallas::Scalar, - result: Point>, + result: Point>, ) -> Result<(), Error> { let expected = NonIdentityPoint::new( chip, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index c746bd5f97..48a1cbf88a 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -264,16 +264,16 @@ pub mod tests { }; #[allow(clippy::op_ref)] - pub(crate) fn test_mul_fixed_short( - chip: EccChip, + pub(crate) fn test_mul_fixed_short( + chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { // test_short let base_val = Short.generator(); let test_short = FixedPointShort::from_inner(chip.clone(), Short); - fn load_magnitude_sign( - chip: EccChip, + fn load_magnitude_sign( + chip: EccChip, mut layouter: impl Layouter, magnitude: pallas::Base, sign: pallas::Base, @@ -290,12 +290,12 @@ pub mod tests { Ok((magnitude, sign)) } - fn constrain_equal_non_id( - chip: EccChip, + fn constrain_equal_non_id( + chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, scalar_val: pallas::Scalar, - result: Point>, + result: Point>, ) -> Result<(), Error> { let expected = NonIdentityPoint::new( chip, diff --git a/halo2_gadgets/src/ecc_opt.rs b/halo2_gadgets/src/ecc_opt.rs index 253662a7ca..b7a7dca5a4 100644 --- a/halo2_gadgets/src/ecc_opt.rs +++ b/halo2_gadgets/src/ecc_opt.rs @@ -99,19 +99,6 @@ pub(crate) mod tests { find_zs_and_us(*BASE, NUM_WINDOWS_SHORT).unwrap(); } - impl FullWidth { - pub(crate) fn from_pallas_generator() -> Self { - FullWidth(*BASE, &ZS_AND_US) - } - - pub(crate) fn from_parts( - base: pallas::Affine, - zs_and_us: &'static [(u64, [pallas::Base; H])], - ) -> Self { - FullWidth(base, zs_and_us) - } - } - impl FixedPoint for FullWidth { type FixedScalarKind = FullScalar; diff --git a/halo2_gadgets/src/ecc_opt/chip.rs b/halo2_gadgets/src/ecc_opt/chip.rs index ed391881b3..c2c70bc17f 100644 --- a/halo2_gadgets/src/ecc_opt/chip.rs +++ b/halo2_gadgets/src/ecc_opt/chip.rs @@ -19,8 +19,8 @@ use super::EccInstructionsOptimized; pub(crate) mod mul_fixed; pub(super) mod witness_point; -impl, LookupRangeCheckConfig: DefaultLookupRangeCheck> - EccInstructionsOptimized for EccChip +impl, Lookup: DefaultLookupRangeCheck> + EccInstructionsOptimized for EccChip where >::Base: FixedPoint, diff --git a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs index 927aea4858..b0487b5d73 100644 --- a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs @@ -92,13 +92,12 @@ pub mod tests { use crate::{ ecc::{chip::EccChip, tests::TestFixedBases, Point}, utilities::{ - lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, UtilitiesInstructions, }, }; - pub(crate) fn test_mul_sign( - chip: EccChip, + pub(crate) fn test_mul_sign( + chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { // Generate a random non-identity point P diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 4793a99da2..fa64deedfe 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -30,12 +30,12 @@ pub(crate) mod hash_to_point; /// Configuration for the Sinsemilla hash chip #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaConfig +pub struct SinsemillaConfig where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { /// Binary selector used in lookup argument and in the body of the Sinsemilla hash. pub(crate) q_sinsemilla1: Selector, @@ -59,17 +59,17 @@ where /// generators of the Sinsemilla hash. pub(crate) generator_table: GeneratorTableConfig, /// An advice column configured to perform lookup range checks. - pub(crate) lookup_config: LookupRangeCheckConfig, + pub(crate) lookup_config: Lookup, pub(crate) _marker: PhantomData<(Hash, Commit, F)>, } -impl - SinsemillaConfig +impl + SinsemillaConfig where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { /// Returns an array of all advice columns in this config, in arbitrary order. pub(super) fn advices(&self) -> [Column; 5] { @@ -83,7 +83,7 @@ where } /// Returns the lookup range check config used in this config. - pub fn lookup_config(&self) -> LookupRangeCheckConfig { + pub fn lookup_config(&self) -> Lookup { self.lookup_config } @@ -99,25 +99,25 @@ where /// /// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaChip +pub struct SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { - config: SinsemillaConfig, + config: SinsemillaConfig, } -impl Chip - for SinsemillaChip +impl Chip + for SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { - type Config = SinsemillaConfig; + type Config = SinsemillaConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -129,13 +129,13 @@ where } } -impl - SinsemillaChip +impl + SinsemillaChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { @@ -144,7 +144,7 @@ where /// Loads the lookup table required by this chip into the circuit. pub fn load( - config: SinsemillaConfig, + config: SinsemillaConfig, layouter: &mut impl Layouter, ) -> Result<>::Loaded, Error> { // Load the lookup table. @@ -152,59 +152,13 @@ where config.generator_table.load(layouter) } - /// # Side-effects - /// - /// All columns in `advices` and will be equality-enabled. - #[allow(clippy::too_many_arguments)] #[allow(non_snake_case)] - pub fn configure( + pub(crate) fn create_initial_y_q_gate( meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - lookup: (TableColumn, TableColumn, TableColumn), - range_check: LookupRangeCheckConfig, - ) -> >::Config { - // FIXME: add comments - - // Enable equality on all advice columns - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let config = SinsemillaConfig:: { - q_sinsemilla1: meta.complex_selector(), - q_sinsemilla2: meta.fixed_column(), - q_sinsemilla4: meta.selector(), - fixed_y_q, - double_and_add: DoubleAndAdd { - x_a: advices[0], - x_p: advices[1], - lambda_1: advices[3], - lambda_2: advices[4], - }, - bits: advices[2], - witness_pieces, - generator_table: GeneratorTableConfig { - table_idx: lookup.0, - table_x: lookup.1, - table_y: lookup.2, - }, - lookup_config: range_check, - _marker: PhantomData, - }; - - // Set up lookup argument - GeneratorTableConfig::configure(meta, &config); - + config: &SinsemillaConfig, + ) { let two = pallas::Base::from(2); - // Closures for expressions that are derived multiple times - // x_r = lambda_1^2 - x_a - x_p - let x_r = |meta: &mut VirtualCells, rotation| { - config.double_and_add.x_r(meta, rotation) - }; - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) let Y_A = |meta: &mut VirtualCells, rotation| { config.double_and_add.Y_A(meta, rotation) @@ -214,11 +168,8 @@ where // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Initial y_Q", |meta| { let q_s4 = meta.query_selector(config.q_sinsemilla4); - let y_q = if LookupRangeCheckConfig::is_optimized() { - meta.query_advice(config.double_and_add.x_p, Rotation::prev()) - } else { - meta.query_fixed(config.fixed_y_q) - }; + let y_q = meta.query_fixed(config.fixed_y_q); + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) let Y_A_cur = Y_A(meta, Rotation::cur()); @@ -227,6 +178,25 @@ where Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) }); + } + + #[allow(non_snake_case)] + pub(crate) fn create_sinsemilla_gate( + meta: &mut ConstraintSystem, + config: &SinsemillaConfig, + ) { + let two = pallas::Base::from(2); + + // Closures for expressions that are derived multiple times + // x_r = lambda_1^2 - x_a - x_p + let x_r = |meta: &mut VirtualCells, rotation| { + config.double_and_add.x_r(meta, rotation) + }; + + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) + let Y_A = |meta: &mut VirtualCells, rotation| { + config.double_and_add.Y_A(meta, rotation) + }; // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Sinsemilla gate", |meta| { @@ -272,20 +242,89 @@ where Constraints::with_selector(q_s1, [("Secant line", secant_line), ("y check", y_check)]) }); + } + + pub(crate) fn create_config( + meta: &mut ConstraintSystem, + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + lookup: (TableColumn, TableColumn, TableColumn), + range_check: Lookup, + ) -> >::Config { + // Enable equality on all advice columns + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let config = SinsemillaConfig:: { + q_sinsemilla1: meta.complex_selector(), + q_sinsemilla2: meta.fixed_column(), + q_sinsemilla4: meta.selector(), + fixed_y_q, + double_and_add: DoubleAndAdd { + x_a: advices[0], + x_p: advices[1], + lambda_1: advices[3], + lambda_2: advices[4], + }, + bits: advices[2], + witness_pieces, + generator_table: GeneratorTableConfig { + table_idx: lookup.0, + table_x: lookup.1, + table_y: lookup.2, + }, + lookup_config: range_check, + _marker: PhantomData, + }; + + // Set up lookup argument + GeneratorTableConfig::configure(meta, &config); + + config + } + + /// # Side-effects + /// + /// All columns in `advices` and will be equality-enabled. + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] + pub fn configure( + meta: &mut ConstraintSystem, + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + lookup: (TableColumn, TableColumn, TableColumn), + range_check: Lookup, + ) -> >::Config { + // create SinsemillaConfig + let config = Self::create_config( + meta, + advices, + witness_pieces, + fixed_y_q, + lookup, + range_check, + ); + + Self::create_initial_y_q_gate(meta, &config); + + Self::create_sinsemilla_gate(meta, &config); config } } // Implement `SinsemillaInstructions` for `SinsemillaChip` -impl +impl SinsemillaInstructions - for SinsemillaChip + for SinsemillaChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { type CellValue = AssignedCell; diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index ed7cc9e554..80551a6c91 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -6,7 +6,6 @@ use halo2_proofs::{ }; use super::{CommitDomains, FixedPoints, HashDomains}; -use crate::utilities::lookup_range_check::LookupRangeCheckConfig; use crate::{ sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, utilities::lookup_range_check::DefaultLookupRangeCheck, @@ -27,14 +26,14 @@ impl GeneratorTableConfig { /// Even though the lookup table can be used in other parts of the circuit, /// this specific configuration sets up Sinsemilla-specific constraints /// controlled by `q_sinsemilla`, and would likely not apply to other chips. - pub fn configure( + pub fn configure( meta: &mut ConstraintSystem, - config: &super::SinsemillaConfig, + config: &super::SinsemillaConfig, ) where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { let (table_idx, table_x, table_y) = ( config.generator_table.table_idx, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 1bb1ce9ed6..0456fc0893 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -1,5 +1,5 @@ use super::super::{CommitDomains, HashDomains, SinsemillaInstructions}; -use super::{NonIdentityEccPoint, SinsemillaChip, SinsemillaConfig}; +use super::{NonIdentityEccPoint, SinsemillaChip}; use crate::{ ecc::FixedPoints, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, @@ -24,18 +24,18 @@ pub enum EccPointQ<'a> { PrivatePoint(&'a NonIdentityEccPoint), } -impl - SinsemillaChip +impl + SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - pub(super) fn hash_message( + pub(crate) fn hash_message( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, @@ -51,13 +51,7 @@ where ), Error, > { - // todo: add doc about LookupRangeCheckConfig::is_optimized() - //let (offset, x_a, y_a) = self.public_initialization(region, Q)?; - let (offset, x_a, y_a) = if LookupRangeCheckConfig::is_optimized() { - self.public_initialization(region, Q)? - } else { - self.public_initialization_vanilla(region, Q)? - }; + let (offset, x_a, y_a) = self.public_initialization_vanilla(region, Q)?; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; @@ -65,6 +59,7 @@ where } #[allow(non_snake_case)] + #[allow(unused_variables)] // Check equivalence to result from primitives::sinsemilla::hash_to_point pub(crate) fn check_hash_result( &self, diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index dc7fb3f6f8..c54133e291 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -28,17 +28,17 @@ use group::ff::PrimeField; /// Configuration for the `MerkleChip` implementation. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleConfig -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, +pub struct MerkleConfig + where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { - advices: [Column; 5], - q_decompose: Selector, + pub(crate) advices: [Column; 5], + pub(crate) q_decompose: Selector, pub(crate) cond_swap_config: CondSwapConfig, - pub(crate) sinsemilla_config: SinsemillaConfig, + pub(crate) sinsemilla_config: SinsemillaConfig, } /// Chip implementing `MerkleInstructions`. @@ -52,25 +52,25 @@ where /// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of /// `left` and `right`. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleChip -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, +pub struct MerkleChip + where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { - config: MerkleConfig, + pub(crate) config: MerkleConfig, } -impl Chip - for MerkleChip -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, +impl Chip +for MerkleChip + where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { - type Config = MerkleConfig; + type Config = MerkleConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -82,18 +82,18 @@ where } } -impl MerkleChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, +impl MerkleChip + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { /// Configures the [`MerkleChip`]. pub fn configure( meta: &mut ConstraintSystem, - sinsemilla_config: SinsemillaConfig, - ) -> MerkleConfig { + sinsemilla_config: SinsemillaConfig, + ) -> MerkleConfig { // All five advice columns are equality-enabled by SinsemillaConfig. let advices = sinsemilla_config.advices(); let cond_swap_config = CondSwapChip::configure(meta, advices); @@ -196,19 +196,19 @@ where } /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. - pub fn construct(config: MerkleConfig) -> Self { + pub fn construct(config: MerkleConfig) -> Self { MerkleChip { config } } } -impl - MerkleInstructions - for MerkleChip -where - Hash: HashDomains + Eq, - F: FixedPoints, - Commit: CommitDomains + Eq, - LookupRangeCheckConfig: DefaultLookupRangeCheck, +impl +MerkleInstructions +for MerkleChip + where + Hash: HashDomains + Eq, + F: FixedPoints, + Commit: CommitDomains + Eq, + Lookup: DefaultLookupRangeCheck, { #[allow(non_snake_case)] fn hash_layer( @@ -421,24 +421,24 @@ where } } -impl UtilitiesInstructions - for MerkleChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, +impl UtilitiesInstructions +for MerkleChip + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { type Var = AssignedCell; } -impl CondSwapInstructions - for MerkleChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, +impl CondSwapInstructions +for MerkleChip + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { #[allow(clippy::type_complexity)] fn swap( @@ -453,71 +453,71 @@ where } } -impl - SinsemillaInstructions - for MerkleChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, +impl +SinsemillaInstructions +for MerkleChip + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { type CellValue = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CellValue; + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CellValue; type Message = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::Message; + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::Message; type MessagePiece = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::MessagePiece; + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::MessagePiece; type RunningSum = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::RunningSum; + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::RunningSum; - type X = as SinsemillaInstructions< + type X = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::X; type NonIdentityPoint = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::NonIdentityPoint; + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::NonIdentityPoint; type FixedPoints = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::FixedPoints; + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::FixedPoints; type HashDomains = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::HashDomains; + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::HashDomains; type CommitDomains = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CommitDomains; + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CommitDomains; fn witness_message_piece( &self, @@ -526,7 +526,7 @@ where num_words: usize, ) -> Result { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChip::::construct(config); + let chip = SinsemillaChip::::construct(config); chip.witness_message_piece(layouter, value, num_words) } @@ -539,11 +539,11 @@ where message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChip::::construct(config); + let chip = SinsemillaChip::::construct(config); chip.hash_to_point(layouter, Q, message) } fn extract(point: &Self::NonIdentityPoint) -> Self::X { - SinsemillaChip::::extract(point) + SinsemillaChip::::extract(point) } -} +} \ No newline at end of file diff --git a/halo2_gadgets/src/sinsemilla_opt.rs b/halo2_gadgets/src/sinsemilla_opt.rs index cca2af19f8..397209e80c 100644 --- a/halo2_gadgets/src/sinsemilla_opt.rs +++ b/halo2_gadgets/src/sinsemilla_opt.rs @@ -5,7 +5,6 @@ use std::fmt::Debug; use pasta_curves::arithmetic::CurveAffine; -use pasta_curves::pallas; use halo2_proofs::{circuit::Layouter, plonk::Error}; @@ -18,10 +17,15 @@ pub mod chip; pub mod merkle; pub mod primitives; -/// FIXME: add a doc +/// `SinsemillaInstructionsOptimized` provides an optimized set of instructions +/// for implementing the Sinsemilla hash function and commitment scheme +/// on elliptic curves. This trait is an extension of the `SinsemillaInstructions` trait, +/// designed to enhance performance in specific cryptographic scenarios.ld + pub trait SinsemillaInstructionsOptimized: - SinsemillaInstructions +SinsemillaInstructions { + /// Hashes a message to an ECC curve point. /// This returns both the resulting point, as well as the message /// decomposition in the form of intermediate values in a cumulative @@ -159,7 +163,6 @@ pub(crate) mod tests { tests::{FullWidth, TestFixedBases}, NonIdentityPoint, }, - utilities::lookup_range_check::LookupRangeCheckConfig, }, }; @@ -310,7 +313,6 @@ pub(crate) mod tests { let ecc_chip = EccChip::construct(config.0); - // todo: check SinsemillaChipOptimized::load // The two `SinsemillaChip`s share the same lookup table. SinsemillaChipOptimized::::load( config.1.clone(), diff --git a/halo2_gadgets/src/sinsemilla_opt/chip.rs b/halo2_gadgets/src/sinsemilla_opt/chip.rs index 909ad21f7c..d08c76153d 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip.rs @@ -1,7 +1,6 @@ //! Chip implementations for the Sinsemilla gadgets. use super::SinsemillaInstructionsOptimized; -use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; use crate::{ ecc::{chip::NonIdentityEccPoint, FixedPoints}, sinsemilla::{ @@ -11,7 +10,6 @@ use crate::{ }, utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, }; -use halo2_proofs::plonk::Expression; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{ @@ -20,56 +18,29 @@ use halo2_proofs::{ poly::Rotation, }; use pasta_curves::pallas; -use pasta_curves::pallas::Base; pub(crate) mod generator_table; mod hash_to_point; -// Implement `SinsemillaInstructionsOptimized` for `SinsemillaChip` -impl - SinsemillaInstructionsOptimized - for SinsemillaChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( - &self, - mut layouter: impl Layouter, - Q: &Self::NonIdentityPoint, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec), Error> { - layouter.assign_region( - || "hash_to_point", - |mut region| self.hash_message_with_private_init(&mut region, Q, &message), - ) - } -} - /// A chip that implements 10-bit Sinsemilla using a lookup table and 5 advice columns. /// /// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). #[derive(Eq, PartialEq, Clone, Debug)] pub struct SinsemillaChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, + where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, { inner: SinsemillaChip, } -// FIXME: is this needed? impl Chip for SinsemillaChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, + where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, { type Config = SinsemillaConfig; type Loaded = (); @@ -84,11 +55,21 @@ where } impl SinsemillaChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { + /// Reconstructs this chip from the given config. + pub fn construct(config: >::Config) -> Self { + Self { + inner: + SinsemillaChip::::construct( + config, + ), + } + } + /// Loads the lookup table required by this chip into the circuit. pub fn load( config: SinsemillaConfig, @@ -97,9 +78,142 @@ where // Load the lookup table. generator_table::load_with_tag( &config.generator_table, - // FIXME: consider to remove Option arount tag config.lookup_config.table_range_check_tag(), layouter, ) } + + #[allow(non_snake_case)] + fn create_initial_y_q_gate( + meta: &mut ConstraintSystem, + config: &SinsemillaConfig, + ) { + let two = pallas::Base::from(2); + + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) + let Y_A = |meta: &mut VirtualCells, rotation| { + config.double_and_add.Y_A(meta, rotation) + }; + + // Check that the initial x_A, x_P, lambda_1, lambda_2 are consistent with y_Q. + // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial + meta.create_gate("Initial y_Q", |meta| { + let q_s4 = meta.query_selector(config.q_sinsemilla4); + let y_q = meta.query_advice(config.double_and_add.x_p, Rotation::prev()); + + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) + let Y_A_cur = Y_A(meta, Rotation::cur()); + + // 2 * y_q - Y_{A,0} = 0 + let init_y_q_check = y_q * two - Y_A_cur; + + Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) + }); + } + + /// # Side-effects + /// + /// All columns in `advices` and will be equality-enabled. + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] + pub fn configure( + meta: &mut ConstraintSystem, + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + lookup: (TableColumn, TableColumn, TableColumn), + range_check: DefaultLookupRangeCheckConfigOptimized, + ) -> >::Config { + let config = SinsemillaChip::::create_config( + meta, + advices, + witness_pieces, + fixed_y_q, + lookup, + range_check, + ); + + Self::create_initial_y_q_gate(meta, &config); + + SinsemillaChip::::create_sinsemilla_gate( + meta, &config, + ); + + config + } +} + +// Implement `SinsemillaInstructions` for `SinsemillaChip` +impl SinsemillaInstructions +for SinsemillaChipOptimized + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + type CellValue = AssignedCell; + + type Message = Message; + type MessagePiece = MessagePiece; + + type RunningSum = Vec; + + type X = AssignedCell; + type NonIdentityPoint = NonIdentityEccPoint; + type FixedPoints = F; + + type HashDomains = Hash; + type CommitDomains = Commit; + + fn witness_message_piece( + &self, + layouter: impl Layouter, + field_elem: Value, + num_words: usize, + ) -> Result { + self.inner + .witness_message_piece(layouter, field_elem, num_words) + } + + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point( + &self, + mut layouter: impl Layouter, + Q: pallas::Affine, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec), Error> { + layouter.assign_region( + || "hash_to_point", + |mut region| self.inner.hash_message_zsa(&mut region, Q, &message), + ) + } + + fn extract(point: &Self::NonIdentityPoint) -> Self::X { + point.x() + } } + +// Implement `SinsemillaInstructions` for `SinsemillaChip` +impl +SinsemillaInstructionsOptimized +for SinsemillaChipOptimized + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point_with_private_init( + &self, + mut layouter: impl Layouter, + Q: &Self::NonIdentityPoint, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec), Error> { + layouter.assign_region( + || "hash_to_point", + |mut region| self.inner.hash_message_with_private_init(&mut region, Q, &message), + ) + } +} \ No newline at end of file diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs index 469a5991e1..5f513ba5df 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs @@ -17,14 +17,39 @@ use crate::{ }, }; -impl - SinsemillaChip +impl + SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - LookupRangeCheckConfig: DefaultLookupRangeCheck, + Lookup: DefaultLookupRangeCheck, { + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(crate) fn hash_message_zsa( + &self, + region: &mut Region<'_, pallas::Base>, + Q: pallas::Affine, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + // Coordinates of the initial point `Q` are assigned to advice columns + let (offset, x_a, y_a) = self.public_initialization(region, Q)?; + + let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; + + self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum) + } /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] #[allow(clippy::type_complexity)] @@ -46,7 +71,6 @@ where > { let (offset, x_a, y_a) = self.private_initialization(region, Q)?; - // FIXME: calling construct_base is possibly(!) non-optimal let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; self.check_hash_result(EccPointQ::PrivatePoint(Q), message, x_a, y_a, zs_sum) diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle.rs b/halo2_gadgets/src/sinsemilla_opt/merkle.rs index 69d43a5c6d..95e4d103cd 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle.rs @@ -8,11 +8,10 @@ pub mod tests { use crate::{ ecc::tests::TestFixedBases, sinsemilla::{ - chip::SinsemillaChip, tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, - utilities::{i2lebsp, lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, + utilities::{i2lebsp, UtilitiesInstructions}, }; use group::ff::{Field, PrimeField, PrimeFieldBits}; @@ -23,13 +22,13 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::sinsemilla::merkle::chip::{MerkleChip, MerkleConfig}; + use crate::sinsemilla::merkle::chip::{MerkleConfig}; use crate::sinsemilla::merkle::MerklePath; use crate::sinsemilla_opt::chip::SinsemillaChipOptimized; - use crate::utilities::lookup_range_check::LookupRangeCheck; use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; + use crate::sinsemilla_opt::merkle::chip::MerkleChipOptimized; const MERKLE_DEPTH: usize = 32; @@ -99,7 +98,7 @@ pub mod tests { table_range_check_tag, ); - let sinsemilla_config_1 = SinsemillaChip::configure( + let sinsemilla_config_1 = SinsemillaChipOptimized::configure( meta, advices[5..].try_into().unwrap(), advices[7], @@ -107,9 +106,9 @@ pub mod tests { lookup, range_check, ); - let config1 = MerkleChip::configure(meta, sinsemilla_config_1); + let config1 = MerkleChipOptimized::configure(meta, sinsemilla_config_1); - let sinsemilla_config_2 = SinsemillaChip::configure( + let sinsemilla_config_2 = SinsemillaChipOptimized::configure( meta, advices[..5].try_into().unwrap(), advices[2], @@ -117,7 +116,7 @@ pub mod tests { lookup, range_check, ); - let config2 = MerkleChip::configure(meta, sinsemilla_config_2); + let config2 = MerkleChipOptimized::configure(meta, sinsemilla_config_2); (config1, config2) } @@ -134,8 +133,8 @@ pub mod tests { )?; // Construct Merkle chips which will be placed side-by-side in the circuit. - let chip_1 = MerkleChip::construct(config.0.clone()); - let chip_2 = MerkleChip::construct(config.1.clone()); + let chip_1 = MerkleChipOptimized::construct(config.0.clone()); + let chip_2 = MerkleChipOptimized::construct(config.1.clone()); let leaf = chip_1.load_private( layouter.namespace(|| ""), diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs index 1eaf2c0853..18240919d4 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs @@ -1,69 +1,428 @@ //! Chip implementing a Merkle hash using Sinsemilla as the hash function. +use ff::PrimeField; use halo2_proofs::{ - circuit::{Chip, Layouter}, - plonk::Error, + circuit::{AssignedCell, Chip, Layouter, Value}, + plonk::{ConstraintSystem, Error}, }; use pasta_curves::pallas; -use crate::sinsemilla::chip::SinsemillaChip; -use crate::sinsemilla::SinsemillaInstructions; -use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ - sinsemilla::{merkle::chip::MerkleChip, primitives as sinsemilla}, - sinsemilla_opt::SinsemillaInstructionsOptimized, + sinsemilla::{ + merkle::{ + chip::{MerkleChip, MerkleConfig}, + MerkleInstructions, + }, + primitives as sinsemilla, + }, + sinsemilla_opt::chip::SinsemillaChipOptimized, utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, { ecc::FixedPoints, - sinsemilla::{CommitDomains, HashDomains}, - utilities::cond_swap::CondSwapChip, - utilities_opt::cond_swap::CondSwapInstructionsOptimized, + sinsemilla::{chip::SinsemillaConfig, CommitDomains, HashDomains, SinsemillaInstructions}, + utilities::{cond_swap::CondSwapInstructions, UtilitiesInstructions}, }, }; +use crate::sinsemilla::MessagePiece; +use crate::utilities::RangeConstrained; + +/// Chip implementing `MerkleInstructions`. +/// +/// This chip specifically implements `MerkleInstructions::hash_layer` as the `MerkleCRH` +/// function `hash = SinsemillaHash(Q, 𝑙⋆ || left⋆ || right⋆)`, where: +/// - `𝑙⋆ = I2LEBSP_10(l)` +/// - `left⋆ = I2LEBSP_255(left)` +/// - `right⋆ = I2LEBSP_255(right)` +/// +/// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of +/// `left` and `right`. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MerkleChipOptimized + where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + base: MerkleChip, +} + +impl Chip for MerkleChipOptimized + where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + type Config = MerkleConfig; + type Loaded = (); + + fn config(&self) -> &Self::Config { + &self.base.config + } + + fn loaded(&self) -> &Self::Loaded { + &() + } +} -impl CondSwapInstructionsOptimized - for MerkleChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, +impl MerkleChipOptimized + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { - fn mux( + /// Configures the [`MerkleChip`]. + pub fn configure( + meta: &mut ConstraintSystem, + sinsemilla_config: SinsemillaConfig< + Hash, + Commit, + F, + DefaultLookupRangeCheckConfigOptimized, + >, + ) -> MerkleConfig { + MerkleChip::configure(meta, sinsemilla_config) + } + + /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. + pub fn construct( + config: MerkleConfig, + ) -> Self { + MerkleChipOptimized { + base: MerkleChip { config }, + } + } +} + +impl +MerkleInstructions +for MerkleChipOptimized + where + Hash: HashDomains + Eq, + F: FixedPoints, + Commit: CommitDomains + Eq, +{ + // Todo: simplify the body? + #[allow(non_snake_case)] + fn hash_layer( &self, - layouter: &mut impl Layouter, - choice: Self::Var, + mut layouter: impl Layouter, + Q: pallas::Affine, + // l = MERKLE_DEPTH - layer - 1 + l: usize, left: Self::Var, right: Self::Var, ) -> Result { - let config = self.config().cond_swap_config.clone(); - let chip = CondSwapChip::::construct(config); - chip.mux(layouter, choice, left, right) + // Todo: simplify the body? copied and pasted from the body of the hash_layer function in halo2_gadgets/src/sinsemilla/merkle/chip.rs + + let config = self.config().clone(); + + // We need to hash `l || left || right`, where `l` is a 10-bit value. + // We allow `left` and `right` to be non-canonical 255-bit encodings. + // + // a = a_0||a_1 = l || (bits 0..=239 of left) + // b = b_0||b_1||b_2 + // = (bits 240..=249 of left) || (bits 250..=254 of left) || (bits 0..=4 of right) + // c = bits 5..=254 of right + // + // We start by witnessing all of the individual pieces, and range-constraining the + // short pieces b_1 and b_2. + // + // https://p.z.cash/halo2-0.1:sinsemilla-merkle-crh-bit-lengths?partial + + // `a = a_0||a_1` = `l` || (bits 0..=239 of `left`) + let a = MessagePiece::from_subpieces( + self.clone(), + layouter.namespace(|| "Witness a = a_0 || a_1"), + [ + RangeConstrained::bitrange_of(Value::known(&pallas::Base::from(l as u64)), 0..10), + RangeConstrained::bitrange_of(left.value(), 0..240), + ], + )?; + + // b = b_0 || b_1 || b_2 + // = (bits 240..=249 of left) || (bits 250..=254 of left) || (bits 0..=4 of right) + let (b_1, b_2, b) = { + // b_0 = (bits 240..=249 of `left`) + let b_0 = RangeConstrained::bitrange_of(left.value(), 240..250); + + // b_1 = (bits 250..=254 of `left`) + // Constrain b_1 to 5 bits. + let b_1 = RangeConstrained::witness_short( + &config.sinsemilla_config.lookup_config(), + layouter.namespace(|| "b_1"), + left.value(), + 250..(pallas::Base::NUM_BITS as usize), + )?; + + // b_2 = (bits 0..=4 of `right`) + // Constrain b_2 to 5 bits. + let b_2 = RangeConstrained::witness_short( + &config.sinsemilla_config.lookup_config(), + layouter.namespace(|| "b_2"), + right.value(), + 0..5, + )?; + + let b = MessagePiece::from_subpieces( + self.clone(), + layouter.namespace(|| "Witness b = b_0 || b_1 || b_2"), + [b_0, b_1.value(), b_2.value()], + )?; + + (b_1, b_2, b) + }; + + // c = bits 5..=254 of `right` + let c = MessagePiece::from_subpieces( + self.clone(), + layouter.namespace(|| "Witness c"), + [RangeConstrained::bitrange_of( + right.value(), + 5..(pallas::Base::NUM_BITS as usize), + )], + )?; + + // hash = SinsemillaHash(Q, 𝑙⋆ || left⋆ || right⋆) + // + // `hash = ⊥` is handled internally to `SinsemillaChip::hash_to_point`: incomplete + // addition constraints allows ⊥ to occur, and then during synthesis it detects + // these edge cases and raises an error (aborting proof creation). + // + // Note that MerkleCRH as-defined maps ⊥ to 0. This is for completeness outside + // the circuit (so that the ⊥ does not propagate into the type system). The chip + // explicitly doesn't map ⊥ to 0; in fact it cannot, as doing so would require + // constraints that amount to using complete addition. The rationale for excluding + // this map is the same as why Sinsemilla uses incomplete addition: this situation + // yields a nontrivial discrete log relation, and by assumption it is hard to find + // these. + // + // https://p.z.cash/proto:merkle-crh-orchard + let (point, zs) = self.hash_to_point( + layouter.namespace(|| format!("hash at l = {}", l)), + Q, + vec![a.inner(), b.inner(), c.inner()].into(), + )?; + let hash = Self::extract(&point); + + // `SinsemillaChip::hash_to_point` returns the running sum for each `MessagePiece`. + // Grab the outputs we need for the decomposition constraints. + let z1_a = zs[0][1].clone(); + let z1_b = zs[1][1].clone(); + + // Check that the pieces have been decomposed properly. + // + // The pieces and subpieces are arranged in the following configuration: + // | A_0 | A_1 | A_2 | A_3 | A_4 | q_decompose | + // ------------------------------------------------------- + // | a | b | c | left | right | 1 | + // | z1_a | z1_b | b_1 | b_2 | l | 0 | + { + layouter.assign_region( + || "Check piece decomposition", + |mut region| { + // Set the fixed column `l` to the current l. + // Recall that l = MERKLE_DEPTH - layer - 1. + // The layer with 2^n nodes is called "layer n". + config.q_decompose.enable(&mut region, 0)?; + region.assign_advice_from_constant( + || format!("l {}", l), + config.advices[4], + 1, + pallas::Base::from(l as u64), + )?; + + // Offset 0 + // Copy and assign `a` at the correct position. + a.inner().cell_value().copy_advice( + || "copy a", + &mut region, + config.advices[0], + 0, + )?; + // Copy and assign `b` at the correct position. + b.inner().cell_value().copy_advice( + || "copy b", + &mut region, + config.advices[1], + 0, + )?; + // Copy and assign `c` at the correct position. + c.inner().cell_value().copy_advice( + || "copy c", + &mut region, + config.advices[2], + 0, + )?; + // Copy and assign the left node at the correct position. + left.copy_advice(|| "left", &mut region, config.advices[3], 0)?; + // Copy and assign the right node at the correct position. + right.copy_advice(|| "right", &mut region, config.advices[4], 0)?; + + // Offset 1 + // Copy and assign z_1 of SinsemillaHash(a) = a_1 + z1_a.copy_advice(|| "z1_a", &mut region, config.advices[0], 1)?; + // Copy and assign z_1 of SinsemillaHash(b) = b_1 + z1_b.copy_advice(|| "z1_b", &mut region, config.advices[1], 1)?; + // Copy `b_1`, which has been constrained to be a 5-bit value + b_1.inner() + .copy_advice(|| "b_1", &mut region, config.advices[2], 1)?; + // Copy `b_2`, which has been constrained to be a 5-bit value + b_2.inner() + .copy_advice(|| "b_2", &mut region, config.advices[3], 1)?; + + Ok(()) + }, + )?; + } + // Check layer hash output against Sinsemilla primitives hash + #[cfg(test)] + { + use crate::{sinsemilla::primitives::HashDomain, utilities::i2lebsp}; + + use group::ff::PrimeFieldBits; + + left.value() + .zip(right.value()) + .zip(hash.value()) + .assert_if_known(|((left, right), hash)| { + let l = i2lebsp::<10>(l as u64); + let left: Vec<_> = left + .to_le_bits() + .iter() + .by_vals() + .take(pallas::Base::NUM_BITS as usize) + .collect(); + let right: Vec<_> = right + .to_le_bits() + .iter() + .by_vals() + .take(pallas::Base::NUM_BITS as usize) + .collect(); + let merkle_crh = HashDomain::from_Q(Q.into()); + + let mut message = l.to_vec(); + message.extend_from_slice(&left); + message.extend_from_slice(&right); + + let expected = merkle_crh.hash(message.into_iter()).unwrap(); + + expected.to_repr() == hash.to_repr() + }); + } + + Ok(hash) + + + } +} + +impl UtilitiesInstructions for MerkleChipOptimized + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + type Var = AssignedCell; +} + +impl CondSwapInstructions for MerkleChipOptimized + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + #[allow(clippy::type_complexity)] + fn swap( + &self, + layouter: impl Layouter, + pair: (Self::Var, Value), + swap: Value, + ) -> Result<(Self::Var, Self::Var), Error> { + self.base.swap(layouter, pair, swap) } } -impl - SinsemillaInstructionsOptimized - for MerkleChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, +impl SinsemillaInstructions +for MerkleChipOptimized + where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { + type CellValue = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CellValue; + + type Message = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::Message; + type MessagePiece = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::MessagePiece; + type RunningSum = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::RunningSum; + + type X = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::X; + type NonIdentityPoint = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::NonIdentityPoint; + type FixedPoints = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::FixedPoints; + + type HashDomains = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::HashDomains; + type CommitDomains = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CommitDomains; + + fn witness_message_piece( + &self, + layouter: impl Layouter, + value: Value, + num_words: usize, + ) -> Result { + let config = self.config().sinsemilla_config.clone(); + let chip = SinsemillaChipOptimized::::construct(config); + chip.witness_message_piece(layouter, value, num_words) + } + #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( + fn hash_to_point( &self, layouter: impl Layouter, - Q: &Self::NonIdentityPoint, + Q: pallas::Affine, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChip::< - Hash, - Commit, - F, - LookupRangeCheckConfigOptimized, - >::construct(config); - chip.hash_to_point_with_private_init(layouter, Q, message) + let chip = SinsemillaChipOptimized::::construct(config); + chip.hash_to_point(layouter, Q, message) } -} + + fn extract(point: &Self::NonIdentityPoint) -> Self::X { + SinsemillaChipOptimized::::extract(point) + } +} \ No newline at end of file diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index f553920036..35dcd6ecf3 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -69,14 +69,22 @@ pub struct LookupRangeCheckConfig { pub(crate) _marker: PhantomData, } -/// FIXME: add doc +/// Trait that provides common methods for a lookup range check. pub trait LookupRangeCheck { - /// FIXME: add doc - fn is_optimized() -> bool; - /// FIXME: add doc + /// Returns a reference to the `LookupRangeCheckConfig` instance. fn config(&self) -> &LookupRangeCheckConfig; - /// FIXME: add doc + /// The `running_sum` advice column breaks the field element into `K`-bit + /// words. It is used to construct the input expression to the lookup + /// argument. + /// + /// The `table_idx` fixed column contains values from [0..2^K). Looking up + /// a value in `table_idx` constrains it to be within this range. The table + /// can be loaded outside this helper. + /// + /// # Side-effects + /// + /// Both the `running_sum` and `constants` columns will be equality-enabled. fn configure( meta: &mut ConstraintSystem, running_sum: Column, @@ -86,9 +94,14 @@ pub trait LookupRangeCheck { Self: Sized; #[cfg(test)] + // Fill `table_idx` and `table_range_check_tag`. + // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table + // in the Orchard context. fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error>; - /// FIXME: add doc + /// Constrain `x` to be a NUM_BITS word. + /// + /// `element` must have been assigned to `self.running_sum` at offset 0. fn short_range_check( &self, region: &mut Region<'_, F>, @@ -274,9 +287,6 @@ pub trait LookupRangeCheck { } impl LookupRangeCheck for LookupRangeCheckConfig { - fn is_optimized() -> bool { - false - } fn config(&self) -> &LookupRangeCheckConfig { self @@ -293,7 +303,6 @@ impl LookupRangeCheck for LookupRangeCh let q_running = meta.complex_selector(); let q_bitshift = meta.selector(); - // FIXME: q_range_check_4 and q_range_check_5 need to be created here // if the order of the creation makes a difference let config = LookupRangeCheckConfig { q_lookup, @@ -308,7 +317,6 @@ impl LookupRangeCheck for LookupRangeCh meta.lookup(|meta| { let q_lookup = meta.query_selector(config.q_lookup); let q_running = meta.query_selector(config.q_running); - // FIXME: q_range_check_4 and q_range_check_5 need to be created here // if the order of the creation makes a difference let z_cur = meta.query_advice(config.running_sum, Rotation::cur()); let one = Expression::Constant(F::ONE); @@ -424,10 +432,13 @@ impl LookupRangeCheck for LookupRangeCh } } -/// FIXME: add doc +/// The `DefaultLookupRangeCheck` trait extends the `LookupRangeCheck` with additional +/// standard traits necessary for effective use in cryptographic contexts. pub trait DefaultLookupRangeCheck: LookupRangeCheck + Eq + PartialEq + Clone + Copy + Debug { } impl DefaultLookupRangeCheck for LookupRangeCheckConfig {} + + diff --git a/halo2_gadgets/src/utilities_opt/cond_swap.rs b/halo2_gadgets/src/utilities_opt/cond_swap.rs index d14e5407ba..ffe9d45838 100644 --- a/halo2_gadgets/src/utilities_opt/cond_swap.rs +++ b/halo2_gadgets/src/utilities_opt/cond_swap.rs @@ -131,7 +131,7 @@ mod tests { tests::TestFixedBases, NonIdentityPoint, Point, }, - utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + utilities::lookup_range_check::{LookupRangeCheck}, }; use group::{cofactor::CofactorCurveAffine, Curve, Group}; diff --git a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs index 6306e25bfb..97ab50c97e 100644 --- a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs @@ -171,10 +171,6 @@ impl LookupRangeCheckConfigOptimized { impl LookupRangeCheck for LookupRangeCheckConfigOptimized { - fn is_optimized() -> bool { - true - } - fn config(&self) -> &LookupRangeCheckConfig { &self.base } From 2e31e97debd7bdb03996a0eb3a9a3dd14a55e41a Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 29 Apr 2024 15:35:31 +0200 Subject: [PATCH 006/121] fmt --- halo2_gadgets/src/ecc.rs | 4 +- halo2_gadgets/src/ecc/chip.rs | 24 ++-- halo2_gadgets/src/ecc/chip/mul.rs | 2 +- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 9 +- .../src/ecc_opt/chip/mul_fixed/short.rs | 4 +- halo2_gadgets/src/sinsemilla/chip.rs | 9 +- .../src/sinsemilla/chip/hash_to_point.rs | 3 +- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 121 ++++++++---------- halo2_gadgets/src/sinsemilla_opt.rs | 15 +-- halo2_gadgets/src/sinsemilla_opt/chip.rs | 59 +++++---- .../src/sinsemilla_opt/chip/hash_to_point.rs | 3 +- halo2_gadgets/src/sinsemilla_opt/merkle.rs | 4 +- .../src/sinsemilla_opt/merkle/chip.rs | 70 +++++----- .../src/utilities/lookup_range_check.rs | 3 - halo2_gadgets/src/utilities_opt/cond_swap.rs | 2 +- 15 files changed, 148 insertions(+), 184 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 1d1a4a48e3..97859c3ddd 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -595,9 +595,7 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::{ - utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, - }; + use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 76d5a019a7..c27a34ca6b 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -227,17 +227,13 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { /// An [`EccInstructions`] chip that uses 10 advice columns. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct EccChip< - FixedPoints: super::FixedPoints, - Lookup: DefaultLookupRangeCheck, -> { +pub struct EccChip, Lookup: DefaultLookupRangeCheck> +{ config: EccConfig, } -impl< - FixedPoints: super::FixedPoints, - Lookup: DefaultLookupRangeCheck, - > Chip for EccChip +impl, Lookup: DefaultLookupRangeCheck> + Chip for EccChip { type Config = EccConfig; type Loaded = (); @@ -251,18 +247,14 @@ impl< } } -impl< - Fixed: super::FixedPoints, - Lookup: DefaultLookupRangeCheck, - > UtilitiesInstructions for EccChip +impl, Lookup: DefaultLookupRangeCheck> + UtilitiesInstructions for EccChip { type Var = AssignedCell; } -impl< - FixedPoints: super::FixedPoints, - Lookup: DefaultLookupRangeCheck, - > EccChip +impl, Lookup: DefaultLookupRangeCheck> + EccChip { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 61f36f88e9..a67b77b0e8 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -467,7 +467,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck}; + use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; use crate::{ ecc::{ chip::{EccChip, EccPoint}, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 1298140e43..5ea0b38eef 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -16,19 +16,14 @@ use pasta_curves::pallas; use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Config< - Fixed: FixedPoints, - Lookup: DefaultLookupRangeCheck, -> { +pub struct Config, Lookup: DefaultLookupRangeCheck> { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], lookup_config: Lookup, super_config: super::Config, } -impl, Lookup: DefaultLookupRangeCheck> - Config -{ +impl, Lookup: DefaultLookupRangeCheck> Config { pub(crate) fn configure( meta: &mut ConstraintSystem, canon_advices: [Column; 3], diff --git a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs index b0487b5d73..830eec83b2 100644 --- a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs @@ -91,9 +91,7 @@ pub mod tests { use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ ecc::{chip::EccChip, tests::TestFixedBases, Point}, - utilities::{ - UtilitiesInstructions, - }, + utilities::UtilitiesInstructions, }; pub(crate) fn test_mul_sign( diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index fa64deedfe..7d96f2c8f3 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -63,8 +63,7 @@ where pub(crate) _marker: PhantomData<(Hash, Commit, F)>, } -impl - SinsemillaConfig +impl SinsemillaConfig where Hash: HashDomains, F: FixedPoints, @@ -109,8 +108,7 @@ where config: SinsemillaConfig, } -impl Chip - for SinsemillaChip +impl Chip for SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, @@ -129,8 +127,7 @@ where } } -impl - SinsemillaChip +impl SinsemillaChip where Hash: HashDomains, F: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 0456fc0893..93b5e29d11 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -24,8 +24,7 @@ pub enum EccPointQ<'a> { PrivatePoint(&'a NonIdentityEccPoint), } -impl - SinsemillaChip +impl SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index c54133e291..d05d9fc8b3 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -29,11 +29,11 @@ use group::ff::PrimeField; /// Configuration for the `MerkleChip` implementation. #[derive(Clone, Debug, PartialEq, Eq)] pub struct MerkleConfig - where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { pub(crate) advices: [Column; 5], pub(crate) q_decompose: Selector, @@ -53,22 +53,21 @@ pub struct MerkleConfig /// `left` and `right`. #[derive(Clone, Debug, PartialEq, Eq)] pub struct MerkleChip - where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { pub(crate) config: MerkleConfig, } -impl Chip -for MerkleChip - where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, +impl Chip for MerkleChip +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { type Config = MerkleConfig; type Loaded = (); @@ -83,11 +82,11 @@ for MerkleChip } impl MerkleChip - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { /// Configures the [`MerkleChip`]. pub fn configure( @@ -202,13 +201,13 @@ impl MerkleChip } impl -MerkleInstructions -for MerkleChip - where - Hash: HashDomains + Eq, - F: FixedPoints, - Commit: CommitDomains + Eq, - Lookup: DefaultLookupRangeCheck, + MerkleInstructions + for MerkleChip +where + Hash: HashDomains + Eq, + F: FixedPoints, + Commit: CommitDomains + Eq, + Lookup: DefaultLookupRangeCheck, { #[allow(non_snake_case)] fn hash_layer( @@ -422,23 +421,23 @@ for MerkleChip } impl UtilitiesInstructions -for MerkleChip - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + for MerkleChip +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { type Var = AssignedCell; } impl CondSwapInstructions -for MerkleChip - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + for MerkleChip +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { #[allow(clippy::type_complexity)] fn swap( @@ -454,35 +453,31 @@ for MerkleChip } impl -SinsemillaInstructions -for MerkleChip - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + SinsemillaInstructions + for MerkleChip +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, { - type CellValue = - as SinsemillaInstructions< + type CellValue = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::CellValue; - type Message = - as SinsemillaInstructions< + type Message = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::Message; - type MessagePiece = - as SinsemillaInstructions< + type MessagePiece = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::MessagePiece; - type RunningSum = - as SinsemillaInstructions< + type RunningSum = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, @@ -493,27 +488,23 @@ for MerkleChip { sinsemilla::K }, { sinsemilla::C }, >>::X; - type NonIdentityPoint = - as SinsemillaInstructions< + type NonIdentityPoint = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::NonIdentityPoint; - type FixedPoints = - as SinsemillaInstructions< + type FixedPoints = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::FixedPoints; - type HashDomains = - as SinsemillaInstructions< + type HashDomains = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::HashDomains; - type CommitDomains = - as SinsemillaInstructions< + type CommitDomains = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, @@ -546,4 +537,4 @@ for MerkleChip fn extract(point: &Self::NonIdentityPoint) -> Self::X { SinsemillaChip::::extract(point) } -} \ No newline at end of file +} diff --git a/halo2_gadgets/src/sinsemilla_opt.rs b/halo2_gadgets/src/sinsemilla_opt.rs index 397209e80c..79e788be06 100644 --- a/halo2_gadgets/src/sinsemilla_opt.rs +++ b/halo2_gadgets/src/sinsemilla_opt.rs @@ -23,9 +23,8 @@ pub mod primitives; /// designed to enhance performance in specific cryptographic scenarios.ld pub trait SinsemillaInstructionsOptimized: -SinsemillaInstructions + SinsemillaInstructions { - /// Hashes a message to an ECC curve point. /// This returns both the resulting point, as well as the message /// decomposition in the form of intermediate values in a cumulative @@ -156,14 +155,12 @@ pub(crate) mod tests { use crate::{ ecc::ScalarFixed, - sinsemilla::primitives::{self as sinsemilla, K}, - { - ecc::{ - chip::{find_zs_and_us, EccChip, EccConfig, H, NUM_WINDOWS}, - tests::{FullWidth, TestFixedBases}, - NonIdentityPoint, - }, + ecc::{ + chip::{find_zs_and_us, EccChip, EccConfig, H, NUM_WINDOWS}, + tests::{FullWidth, TestFixedBases}, + NonIdentityPoint, }, + sinsemilla::primitives::{self as sinsemilla, K}, }; use group::{ff::Field, Curve}; diff --git a/halo2_gadgets/src/sinsemilla_opt/chip.rs b/halo2_gadgets/src/sinsemilla_opt/chip.rs index d08c76153d..a630f27e0c 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip.rs @@ -28,19 +28,19 @@ mod hash_to_point; /// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). #[derive(Eq, PartialEq, Clone, Debug)] pub struct SinsemillaChipOptimized - where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, { inner: SinsemillaChip, } impl Chip for SinsemillaChipOptimized - where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, { type Config = SinsemillaConfig; type Loaded = (); @@ -55,18 +55,18 @@ impl Chip for SinsemillaChipOptimized SinsemillaChipOptimized - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { Self { inner: - SinsemillaChip::::construct( - config, - ), + SinsemillaChip::::construct( + config, + ), } } @@ -145,11 +145,11 @@ impl SinsemillaChipOptimized // Implement `SinsemillaInstructions` for `SinsemillaChip` impl SinsemillaInstructions -for SinsemillaChipOptimized - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, + for SinsemillaChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { type CellValue = AssignedCell; @@ -196,12 +196,12 @@ for SinsemillaChipOptimized // Implement `SinsemillaInstructions` for `SinsemillaChip` impl -SinsemillaInstructionsOptimized -for SinsemillaChipOptimized - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, + SinsemillaInstructionsOptimized + for SinsemillaChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { #[allow(non_snake_case)] #[allow(clippy::type_complexity)] @@ -213,7 +213,10 @@ for SinsemillaChipOptimized ) -> Result<(Self::NonIdentityPoint, Vec), Error> { layouter.assign_region( || "hash_to_point", - |mut region| self.inner.hash_message_with_private_init(&mut region, Q, &message), + |mut region| { + self.inner + .hash_message_with_private_init(&mut region, Q, &message) + }, ) } -} \ No newline at end of file +} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs index 5f513ba5df..956a7cd70f 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs @@ -17,8 +17,7 @@ use crate::{ }, }; -impl - SinsemillaChip +impl SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle.rs b/halo2_gadgets/src/sinsemilla_opt/merkle.rs index 95e4d103cd..d1676765b0 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle.rs @@ -22,13 +22,13 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::sinsemilla::merkle::chip::{MerkleConfig}; + use crate::sinsemilla::merkle::chip::MerkleConfig; use crate::sinsemilla::merkle::MerklePath; use crate::sinsemilla_opt::chip::SinsemillaChipOptimized; + use crate::sinsemilla_opt::merkle::chip::MerkleChipOptimized; use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; - use crate::sinsemilla_opt::merkle::chip::MerkleChipOptimized; const MERKLE_DEPTH: usize = 32; diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs index 18240919d4..f0ab3d5ca1 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs @@ -7,6 +7,8 @@ use halo2_proofs::{ }; use pasta_curves::pallas; +use crate::sinsemilla::MessagePiece; +use crate::utilities::RangeConstrained; use crate::{ sinsemilla::{ merkle::{ @@ -23,8 +25,6 @@ use crate::{ utilities::{cond_swap::CondSwapInstructions, UtilitiesInstructions}, }, }; -use crate::sinsemilla::MessagePiece; -use crate::utilities::RangeConstrained; /// Chip implementing `MerkleInstructions`. /// @@ -38,19 +38,19 @@ use crate::utilities::RangeConstrained; /// `left` and `right`. #[derive(Clone, Debug, PartialEq, Eq)] pub struct MerkleChipOptimized - where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, { base: MerkleChip, } impl Chip for MerkleChipOptimized - where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, { type Config = MerkleConfig; type Loaded = (); @@ -65,10 +65,10 @@ impl Chip for MerkleChipOptimized MerkleChipOptimized - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { /// Configures the [`MerkleChip`]. pub fn configure( @@ -94,12 +94,12 @@ impl MerkleChipOptimized } impl -MerkleInstructions -for MerkleChipOptimized - where - Hash: HashDomains + Eq, - F: FixedPoints, - Commit: CommitDomains + Eq, + MerkleInstructions + for MerkleChipOptimized +where + Hash: HashDomains + Eq, + F: FixedPoints, + Commit: CommitDomains + Eq, { // Todo: simplify the body? #[allow(non_snake_case)] @@ -311,25 +311,23 @@ for MerkleChipOptimized } Ok(hash) - - } } impl UtilitiesInstructions for MerkleChipOptimized - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { type Var = AssignedCell; } impl CondSwapInstructions for MerkleChipOptimized - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { #[allow(clippy::type_complexity)] fn swap( @@ -343,11 +341,11 @@ impl CondSwapInstructions for MerkleChipOptimized } impl SinsemillaInstructions -for MerkleChipOptimized - where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, + for MerkleChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, { type CellValue = as SinsemillaInstructions< pallas::Affine, @@ -425,4 +423,4 @@ for MerkleChipOptimized fn extract(point: &Self::NonIdentityPoint) -> Self::X { SinsemillaChipOptimized::::extract(point) } -} \ No newline at end of file +} diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 35dcd6ecf3..a4ab1ba5ab 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -287,7 +287,6 @@ pub trait LookupRangeCheck { } impl LookupRangeCheck for LookupRangeCheckConfig { - fn config(&self) -> &LookupRangeCheckConfig { self } @@ -440,5 +439,3 @@ pub trait DefaultLookupRangeCheck: } impl DefaultLookupRangeCheck for LookupRangeCheckConfig {} - - diff --git a/halo2_gadgets/src/utilities_opt/cond_swap.rs b/halo2_gadgets/src/utilities_opt/cond_swap.rs index ffe9d45838..eae0b148fd 100644 --- a/halo2_gadgets/src/utilities_opt/cond_swap.rs +++ b/halo2_gadgets/src/utilities_opt/cond_swap.rs @@ -131,7 +131,7 @@ mod tests { tests::TestFixedBases, NonIdentityPoint, Point, }, - utilities::lookup_range_check::{LookupRangeCheck}, + utilities::lookup_range_check::LookupRangeCheck, }; use group::{cofactor::CofactorCurveAffine, Curve, Group}; From b02478a6c6a99f6c33ebc4fbf0b519c1c7e51f7d Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 29 Apr 2024 19:11:40 +0200 Subject: [PATCH 007/121] fix run tests error --- halo2_gadgets/Cargo.toml | 3 +-- rust-toolchain.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/halo2_gadgets/Cargo.toml b/halo2_gadgets/Cargo.toml index 1aa754264e..2021d77e25 100644 --- a/halo2_gadgets/Cargo.toml +++ b/halo2_gadgets/Cargo.toml @@ -49,7 +49,6 @@ pprof = { version = "0.8", features = ["criterion", "flamegraph"] } # MSRV 1.56 bench = false [features] -default = ["test-dev-graph"] test-dev-graph = [ "halo2_proofs/dev-graph", "plotters", @@ -83,4 +82,4 @@ harness = false [[bench]] name = "sha256" harness = false -required-features = ["unstable-sha256-gadget"] +required-features = ["unstable-sha256-gadget"] \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f8c2abbb3d..948d27daa4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.65.0" +channel = "1.60.0" From e6d1dbede6bd422306c499fdb43e0bfe02235701 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 29 Apr 2024 20:17:55 +0200 Subject: [PATCH 008/121] minor update --- halo2_gadgets/src/sinsemilla/merkle.rs | 2 +- halo2_gadgets/src/sinsemilla_opt/merkle.rs | 2 +- halo2_gadgets/src/utilities_opt/lookup_range_check.rs | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 1485c466f1..21561e7316 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -407,7 +407,7 @@ pub mod tests { let circuit = MyCircuit::default(); halo2_proofs::dev::CircuitLayout::default() - .show_labels(true) + .show_labels(false) .render(11, &circuit, &root) .unwrap(); } diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle.rs b/halo2_gadgets/src/sinsemilla_opt/merkle.rs index d1676765b0..3983e42659 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle.rs @@ -239,7 +239,7 @@ pub mod tests { let circuit = MyCircuit::default(); halo2_proofs::dev::CircuitLayout::default() - .show_labels(true) + .show_labels(false) .render(11, &circuit, &root) .unwrap(); } diff --git a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs index 97ab50c97e..e2c1a808a9 100644 --- a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs @@ -31,8 +31,6 @@ pub struct LookupRangeCheckConfigOptimized { base: LookupRangeCheckConfig, q_range_check_4: Selector, q_range_check_5: Selector, - // FIXME: Instead of making it pub, add a method in LookupRangeCheckConfig that returns table_range_check_tag - //pub(crate) table_range_check_tag: TableColumn, } @@ -63,7 +61,6 @@ impl LookupRangeCheckConfigOptimized { let q_range_check_4 = meta.complex_selector(); let q_range_check_5 = meta.complex_selector(); - // FIXME: q_range_check_4 and q_range_check_5 need to be created here // if the order of the creation makes a difference let config = LookupRangeCheckConfigOptimized { base: LookupRangeCheckConfig { @@ -83,7 +80,6 @@ impl LookupRangeCheckConfigOptimized { meta.lookup(|meta| { let q_lookup = meta.query_selector(config.base.q_lookup); let q_running = meta.query_selector(config.base.q_running); - // FIXME: q_range_check_4 and q_range_check_5 need to be created here // if the order of the creation makes a difference let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); let one = Expression::Constant(F::ONE); From 23a295172b6c8cb0b642512109801b5116d79c6a Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 29 Apr 2024 20:22:09 +0200 Subject: [PATCH 009/121] test error --- halo2_gadgets/src/ecc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 38fab0a49a..e703337046 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -1,5 +1,5 @@ //! Elliptic curve operations. - +// test error use std::fmt::Debug; use halo2_proofs::{ From 301e7d82e1cc8dee43389d6602b13e8a7a57f601 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 29 Apr 2024 20:35:32 +0200 Subject: [PATCH 010/121] Revert "test error" This reverts commit 23a295172b6c8cb0b642512109801b5116d79c6a. --- halo2_gadgets/src/ecc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index e703337046..38fab0a49a 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -1,5 +1,5 @@ //! Elliptic curve operations. -// test error + use std::fmt::Debug; use halo2_proofs::{ From c3240066afff7e3690d9080c83ea84ce960ee78a Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 30 Apr 2024 13:18:33 +0200 Subject: [PATCH 011/121] re-naming structs and functions --- .../src/sinsemilla/chip/hash_to_point.rs | 16 ++++----- halo2_gadgets/src/sinsemilla_opt/chip.rs | 11 +++--- .../src/sinsemilla_opt/chip/hash_to_point.rs | 35 +++++++++++++------ .../src/sinsemilla_opt/merkle/chip.rs | 8 ++--- .../src/utilities/lookup_range_check.rs | 4 +-- 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 93b5e29d11..2aefb97233 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -24,6 +24,10 @@ pub enum EccPointQ<'a> { PrivatePoint(&'a NonIdentityEccPoint), } +type HashOutput = NonIdentityEccPoint; +type CellMatrix = Vec>>; +type HashResult = Result<(HashOutput, CellMatrix), Error>; + impl SinsemillaChip where Hash: HashDomains, @@ -43,14 +47,8 @@ where { sinsemilla::K }, { sinsemilla::C }, >>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - let (offset, x_a, y_a) = self.public_initialization_vanilla(region, Q)?; + ) -> HashResult { + let (offset, x_a, y_a) = self.public_initialization(region, Q)?; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; @@ -137,7 +135,7 @@ where /// | offset | x_A | q_sinsemilla4 | fixed_y_q | /// -------------------------------------- /// | 0 | x_Q | 1 | y_Q | - pub(crate) fn public_initialization_vanilla( + pub(crate) fn public_initialization( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, diff --git a/halo2_gadgets/src/sinsemilla_opt/chip.rs b/halo2_gadgets/src/sinsemilla_opt/chip.rs index a630f27e0c..1b544edf75 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip.rs @@ -143,7 +143,7 @@ where } } -// Implement `SinsemillaInstructions` for `SinsemillaChip` +// Implement `SinsemillaInstructions` for `SinsemillaChipOptimized` impl SinsemillaInstructions for SinsemillaChipOptimized where @@ -185,7 +185,7 @@ where ) -> Result<(Self::NonIdentityPoint, Vec), Error> { layouter.assign_region( || "hash_to_point", - |mut region| self.inner.hash_message_zsa(&mut region, Q, &message), + |mut region| self.hash_message(&mut region, Q, &message), ) } @@ -194,7 +194,7 @@ where } } -// Implement `SinsemillaInstructions` for `SinsemillaChip` +// Implement `SinsemillaInstructionsOptimized` for `SinsemillaChipOptimized` impl SinsemillaInstructionsOptimized for SinsemillaChipOptimized @@ -213,10 +213,7 @@ where ) -> Result<(Self::NonIdentityPoint, Vec), Error> { layouter.assign_region( || "hash_to_point", - |mut region| { - self.inner - .hash_message_with_private_init(&mut region, Q, &message) - }, + |mut region| self.hash_message_with_private_init(&mut region, Q, &message), ) } } diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs index 956a7cd70f..8ef33ab4ef 100644 --- a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs @@ -7,7 +7,7 @@ use halo2_proofs::{ use crate::sinsemilla::chip::hash_to_point::EccPointQ; use crate::sinsemilla::chip::SinsemillaChip; -use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; +use crate::sinsemilla_opt::chip::SinsemillaChipOptimized; use crate::{ ecc::{chip::NonIdentityEccPoint, FixedPoints}, sinsemilla::{ @@ -17,16 +17,15 @@ use crate::{ }, }; -impl SinsemillaChip +impl SinsemillaChipOptimized where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, { #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - pub(crate) fn hash_message_zsa( + pub(crate) fn hash_message( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, @@ -45,9 +44,17 @@ where // Coordinates of the initial point `Q` are assigned to advice columns let (offset, x_a, y_a) = self.public_initialization(region, Q)?; - let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; - - self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum) + let (x_a, y_a, zs_sum) = + SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; + + SinsemillaChip::check_hash_result( + &self.inner, + EccPointQ::PublicPoint(Q), + message, + x_a, + y_a, + zs_sum, + ) } /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] @@ -70,9 +77,17 @@ where > { let (offset, x_a, y_a) = self.private_initialization(region, Q)?; - let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; - - self.check_hash_result(EccPointQ::PrivatePoint(Q), message, x_a, y_a, zs_sum) + let (x_a, y_a, zs_sum) = + SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; + + SinsemillaChip::check_hash_result( + &self.inner, + EccPointQ::PrivatePoint(Q), + message, + x_a, + y_a, + zs_sum, + ) } #[allow(non_snake_case)] diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs index f0ab3d5ca1..3445bef41f 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs @@ -114,7 +114,7 @@ where ) -> Result { // Todo: simplify the body? copied and pasted from the body of the hash_layer function in halo2_gadgets/src/sinsemilla/merkle/chip.rs - let config = self.config().clone(); + let config = self.base.config().clone(); // We need to hash `l || left || right`, where `l` is a 10-bit value. // We allow `left` and `right` to be non-canonical 255-bit encodings. @@ -131,7 +131,7 @@ where // `a = a_0||a_1` = `l` || (bits 0..=239 of `left`) let a = MessagePiece::from_subpieces( - self.clone(), + self.base.clone(), layouter.namespace(|| "Witness a = a_0 || a_1"), [ RangeConstrained::bitrange_of(Value::known(&pallas::Base::from(l as u64)), 0..10), @@ -164,7 +164,7 @@ where )?; let b = MessagePiece::from_subpieces( - self.clone(), + self.base.clone(), layouter.namespace(|| "Witness b = b_0 || b_1 || b_2"), [b_0, b_1.value(), b_2.value()], )?; @@ -174,7 +174,7 @@ where // c = bits 5..=254 of `right` let c = MessagePiece::from_subpieces( - self.clone(), + self.base.clone(), layouter.namespace(|| "Witness c"), [RangeConstrained::bitrange_of( right.value(), diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index a4ab1ba5ab..ab28eb860b 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -335,8 +335,8 @@ impl LookupRangeCheck for LookupRangeCh // In the short range check, the word is directly witnessed. let short_lookup = { - let short_word = z_cur.clone(); - let q_short = one.clone() - q_running; + let short_word = z_cur; + let q_short = one - q_running; q_short * short_word }; From af29df443306d97a6f74984af56a8b2c2d720c1c Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 30 Apr 2024 13:46:59 +0200 Subject: [PATCH 012/121] fix complex type --- halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 2aefb97233..8818147f41 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -69,13 +69,7 @@ where x_a: X, y_a: AssignedCell, pallas::Base>, zs_sum: Vec>>, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { + ) -> HashResult { #[cfg(test)] { use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; From 1ea04bb86fe3d493f4d83a0e3595d76562ac020d Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 6 May 2024 09:35:46 +0200 Subject: [PATCH 013/121] add round trip test to verify that the pinned verification key (representing the circuit) is as expected --- halo2_gadgets/src/ecc.rs | 24 + halo2_gadgets/src/sinsemilla.rs | 25 + halo2_gadgets/src/sinsemilla/merkle.rs | 40 +- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 54 +- halo2_gadgets/src/sinsemilla/vk_merkle_chip | 3271 +++++ .../src/sinsemilla_opt/merkle/chip.rs | 227 +- .../src/utilities/lookup_range_check.rs | 333 + .../src/utilities/vk_lookup_range_check | 244 + .../src/utilities/vk_short_range_check | 244 + halo2_gadgets/src/vk_ecc_chip | 9915 +++++++++++++ halo2_gadgets/src/vk_sinsemilla_chip | 11821 ++++++++++++++++ 11 files changed, 25966 insertions(+), 232 deletions(-) create mode 100644 halo2_gadgets/src/sinsemilla/vk_merkle_chip create mode 100644 halo2_gadgets/src/utilities/vk_lookup_range_check create mode 100644 halo2_gadgets/src/utilities/vk_short_range_check create mode 100644 halo2_gadgets/src/vk_ecc_chip create mode 100644 halo2_gadgets/src/vk_sinsemilla_chip diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 97859c3ddd..b835aaf3eb 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -580,13 +580,16 @@ pub(crate) mod tests { use ff::PrimeField; use group::{prime::PrimeCurveAffine, Curve, Group}; + use halo2_proofs::poly::commitment::Params; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, + plonk, plonk::{Circuit, ConstraintSystem, Error}, }; use lazy_static::lazy_static; use pasta_curves::pallas; + use pasta_curves::vesta::Affine; use super::{ chip::{ @@ -595,6 +598,7 @@ pub(crate) mod tests { }, FixedPoints, }; + use crate::utilities::lookup_range_check::tests::test_proof_size; use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; #[derive(Debug, Eq, PartialEq, Clone)] @@ -907,6 +911,26 @@ pub(crate) mod tests { assert_eq!(prover.verify(), Ok(())) } + #[test] + fn round_trip() { + let k = 11; + let circuit = MyCircuit { test_errors: false }; + + // Setup phase: generate parameters, vk for the circuit. + let params: Params = Params::new(k); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. + { + //panic!("{:#?}", vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_ecc_chip").replace("\r\n", "\n") + ); + } + test_proof_size(k, circuit, params, vk) + } #[cfg(feature = "test-dev-graph")] #[test] fn print_ecc_chip() { diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index a3e2dc892b..439dba9fae 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -462,6 +462,7 @@ pub(crate) mod tests { use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, + plonk, plonk::{Circuit, ConstraintSystem, Error}, }; use rand::rngs::OsRng; @@ -488,6 +489,9 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; + use crate::utilities::lookup_range_check::tests::test_proof_size; + use halo2_proofs::poly::commitment::Params; + use pasta_curves::vesta::Affine; use std::convert::TryInto; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; @@ -761,6 +765,27 @@ pub(crate) mod tests { assert_eq!(prover.verify(), Ok(())) } + #[test] + fn round_trip() { + let k = 11; + let circuit = MyCircuit {}; + + // Setup phase: generate parameters, vk for the circuit. + let params: Params = Params::new(k); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. + { + //panic!("{:#?}", vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_sinsemilla_chip").replace("\r\n", "\n") + ); + } + test_proof_size(11, circuit, params, vk) + } + #[cfg(feature = "test-dev-graph")] #[test] fn print_sinsemilla_chip() { diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 21561e7316..58bcff9559 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -196,9 +196,12 @@ pub mod tests { circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, pasta::pallas, + plonk, plonk::{Circuit, ConstraintSystem, Error}, }; + use halo2_proofs::poly::commitment::Params; + use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; @@ -370,9 +373,7 @@ pub mod tests { Ok(()) } } - - #[test] - fn merkle_chip() { + fn generate_circuit() -> MyCircuit { let mut rng = OsRng; // Choose a random leaf and position @@ -385,17 +386,44 @@ pub mod tests { .collect(); // The root is provided as a public input in the Orchard circuit. - - let circuit = MyCircuit { + MyCircuit { leaf: Value::known(leaf), leaf_pos: Value::known(pos), merkle_path: Value::known(path.try_into().unwrap()), - }; + } + } + + #[test] + fn merkle_chip() { + let circuit = generate_circuit(); let prover = MockProver::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } + #[test] + fn round_trip() { + let k = 11; + let circuit = generate_circuit(); + + // Setup phase: generate parameters, vk for the circuit. + let params: Params = Params::new(k); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. Which indicates the layouters are the same. + { + //panic!("{:#?}", vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_merkle_chip").replace("\r\n", "\n") + ); + } + + // Test that the proof size is as expected. + crate::utilities::lookup_range_check::tests::test_proof_size(k, circuit, params, vk) + } + #[cfg(feature = "test-dev-graph")] #[test] fn print_merkle_chip() { diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index d05d9fc8b3..4ce0662e91 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -200,13 +200,59 @@ where } } -impl - MerkleInstructions +pub(crate) trait MerkleSinsemillaInstructions +where + Self: SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + MessagePiece = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::MessagePiece, + RunningSum = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::RunningSum, + X = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::X, + >, + Hash: HashDomains, + Commit: CommitDomains, + F: FixedPoints, + Lookup: DefaultLookupRangeCheck, +{ +} + +impl MerkleSinsemillaInstructions for MerkleChip where - Hash: HashDomains + Eq, + Hash: HashDomains, F: FixedPoints, - Commit: CommitDomains + Eq, + Commit: CommitDomains, + Lookup: DefaultLookupRangeCheck, +{ +} + +impl + MerkleInstructions + for InstructionsChip +where + InstructionsChip: MerkleSinsemillaInstructions + + UtilitiesInstructions> + + CondSwapInstructions + + Chip> + + Eq + + Clone + + std::fmt::Debug, + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, Lookup: DefaultLookupRangeCheck, { #[allow(non_snake_case)] diff --git a/halo2_gadgets/src/sinsemilla/vk_merkle_chip b/halo2_gadgets/src/sinsemilla/vk_merkle_chip new file mode 100644 index 0000000000..229243b02c --- /dev/null +++ b/halo2_gadgets/src/sinsemilla/vk_merkle_chip @@ -0,0 +1,3271 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 14, + num_advice_columns: 10, + num_instance_columns: 0, + num_selectors: 11, + gates: [ + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Fixed { + query_index: 5, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 10, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 9, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 10, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 9, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 2, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 2, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 9, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 9, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 10, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 2, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 2, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 9, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 10, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 5, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 10, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Fixed { + query_index: 7, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 18, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 17, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 17, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 17, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 20, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 17, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 18, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 16, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 17, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 13, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 20, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 16, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 17, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 10, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 11, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 12, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 13, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 0, + column_type: Fixed, + }, + Column { + index: 9, + column_type: Advice, + }, + Column { + index: 5, + column_type: Advice, + }, + Column { + index: 6, + column_type: Advice, + }, + Column { + index: 7, + column_type: Advice, + }, + Column { + index: 8, + column_type: Advice, + }, + Column { + index: 0, + column_type: Advice, + }, + Column { + index: 1, + column_type: Advice, + }, + Column { + index: 2, + column_type: Advice, + }, + Column { + index: 3, + column_type: Advice, + }, + Column { + index: 4, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 10, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 5, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 2, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 2, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 2, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 10, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 10, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 10, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 10, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 3, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 13, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 16, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 15, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 14, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 11, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 3, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 0, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x26b223d8ba8ed483bbbdb8447f9166eb40bd77cc586970213757dceca5b3fe7f, 0x05dd2ed4a2456bd237250d2945d955fb415c841e2545fb0d4a8c937f5f933b61), + (0x129d241edb86e5c96fdd9d7beb75bd9a14e7d8592808036c9cf592cfed690b7a, 0x2b54f489a381e59f402ce34abc683b3cec3df0d01377115dc5a143fc9aa09340), + (0x17924baebd9681321232d8646f280221f34cd2d87cd125eeadaa974ab4d5dfd0, 0x311b6a25f7169fb1713e5539e10e52a1bdf6767a2fbbbc56d1f5d59a15024efa), + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x3e727e8554679f98120355d39d958dbd8755d5a7f8b42ea87f258064c4b3eb57, 0x0c0d5c23f3ee62ac1b2d986dd3033bbcab260d590e1393de3a14a4b31ae091bb), + (0x3748680dd6a91c5dec668b30fb6bf9a450aeb884b81cbc344914f265760e7131, 0x18530eaa5c58b61bd3fc38220ea484c0922524a815a8f752be955c229f9c4164), + (0x03c48d550f56a16644251c9a5dc416e30b29a610010ac7709125782b1607b3e6, 0x3edfa55036455c23093e78530124d2b7778b608a68ab039008e2bd7d438416f0), + (0x24fd2ce32655dc5f11fe8e2f9ab780f71a933b9475da27aed0bc3f7f37e29ca1, 0x0cfbb4dc2d19dc3eeecbc1f987c45defa62c0a2a32b601f6eb6305b0b6e3cffa), + (0x29290c56da02655ce46b785d7af446f84badffca09b4cbd41e523bc5b7a2b40c, 0x0e8bcdd3843da6764954a9360d7dc02f98408c07b20a15e7e592b54086655ef5), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2b63c25913a7c51ed52510e22881c2289379dadf144cfaf17cfbd9849ec2593a, 0x07fdeaac027477b02310fbac9575219384101c8c84e67b7be66ab0160f4bea22), + (0x109ac97c3d9d86563fd9847eee02f6affa4d788acd9697f2f828248fd6c7c595, 0x3ca254a78e74bfb5bd8144e2af8561b1f9f97d04b64965c0b97bd47cc00a1a1e), + (0x159abc8bbb102b81095fe82b2e576d2fd3789725ccad02192867eb6b262a6a8f, 0x1485a4c81a8415340d1571c05b0c99267af41def845f07f7254b87f5f1b056a0), + (0x065fa931d37c658c03dea4ad6a87dc06572639527c15c4631a116fd2f2d67062, 0x27765f16048554d160f8e9f1e8f5e285ee71871279b6a83a3060289572cb8844), + ], + permutation: VerifyingKey { + commitments: [ + (0x12c01814753e91eb23e4606d794078a518c227be4acaff3884f9a9bc9ab40000, 0x3ffeae87fb800669e7a3bda23781a4d16893f0b107382688b56e8f212c84a288), + (0x32383e328758decb242d42f75986c1cd5aef9f1a6d6e39c54a53a17630b8a16d, 0x00ae32219df5287e4c3c64ebf0ef83771fad95d67b2f7f3a444f5ede969d1c0c), + (0x06c29c2bad49d6ff8dd5669fd563dbe126692880bbeb495d15f810e5acfaa14a, 0x2be470a3fa70893026bb0506aadd32844fae950eefa502111b5806e916007d95), + (0x2b32307f41326e8d99a5146ba6aee133ed87d305cd0dd4419e537e2b2028e22a, 0x2334c482571d9f726a0715ae1824965009c5fabd6c3864e996e4ae2020e95c7e), + (0x2ebbf8cdb2a64ea5ce464f9439f328e564a02fde4e4f7a8855edcd9c9ef2b2e4, 0x0e73d4cdbe01bff75617a34ddb6fa10c460e3c5556bf4c86230ef54e10a955cf), + (0x0f6ecf422fad0e4ff83c6aa5812dc5c36c87d145d5c2e7f40ca6f0c332067826, 0x22b7cb6d58f8f249d6c656cdac28cdfe0c720f4ac1e4fb571a7c4dcd4f3c7bd0), + (0x0482e99357c02b25b0e8dd7327b34783dc4459119c0635b5de330d843e277da0, 0x0e30c1696995c9c31d1d179c86b99f2a6f66eaf290765344d2219bfb200f353d), + (0x37aba51a64c17ab63e7d76e11ca84ab0aaf7f208fccfd764d27b8b2531046d53, 0x0822915e6a8916334856d07619c7f8862d1c582d651127e9ad81343d9869c5af), + (0x2f1e036cc7cf77f6e64cdb1e6cb74dfeff998ec7dbd9ca90d3655db915150641, 0x27b2e33fdd6dd2344bd10c03522af2dbf38cd675c1ef4b23786bccdf8a8cc44a), + (0x38a60d928d64f1ef68c137da22be0d1d545c750dc4bb06018f78dbdafe0e32f4, 0x2cdc02d55e4164a17b06994225662703361a6ba56b64c5e5980aae6bd5f18bb1), + (0x03b739f9b5f0a3b6093d9d8c7f53068d7dbb5f9dc43ef1871a7bc36dbb0f01d6, 0x2bb4c2c0e642711d11136a9ecfb7bac1d05b400c3a150aeb84bbdb31d01e8c5e), + ], + }, +} diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs index 3445bef41f..b11cf6b57e 100644 --- a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs @@ -1,20 +1,14 @@ //! Chip implementing a Merkle hash using Sinsemilla as the hash function. -use ff::PrimeField; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, plonk::{ConstraintSystem, Error}, }; use pasta_curves::pallas; -use crate::sinsemilla::MessagePiece; -use crate::utilities::RangeConstrained; use crate::{ sinsemilla::{ - merkle::{ - chip::{MerkleChip, MerkleConfig}, - MerkleInstructions, - }, + merkle::chip::{MerkleChip, MerkleConfig, MerkleSinsemillaInstructions}, primitives as sinsemilla, }, sinsemilla_opt::chip::SinsemillaChipOptimized, @@ -93,225 +87,14 @@ where } } -impl - MerkleInstructions +impl + MerkleSinsemillaInstructions for MerkleChipOptimized where - Hash: HashDomains + Eq, + Hash: HashDomains, F: FixedPoints, - Commit: CommitDomains + Eq, + Commit: CommitDomains, { - // Todo: simplify the body? - #[allow(non_snake_case)] - fn hash_layer( - &self, - mut layouter: impl Layouter, - Q: pallas::Affine, - // l = MERKLE_DEPTH - layer - 1 - l: usize, - left: Self::Var, - right: Self::Var, - ) -> Result { - // Todo: simplify the body? copied and pasted from the body of the hash_layer function in halo2_gadgets/src/sinsemilla/merkle/chip.rs - - let config = self.base.config().clone(); - - // We need to hash `l || left || right`, where `l` is a 10-bit value. - // We allow `left` and `right` to be non-canonical 255-bit encodings. - // - // a = a_0||a_1 = l || (bits 0..=239 of left) - // b = b_0||b_1||b_2 - // = (bits 240..=249 of left) || (bits 250..=254 of left) || (bits 0..=4 of right) - // c = bits 5..=254 of right - // - // We start by witnessing all of the individual pieces, and range-constraining the - // short pieces b_1 and b_2. - // - // https://p.z.cash/halo2-0.1:sinsemilla-merkle-crh-bit-lengths?partial - - // `a = a_0||a_1` = `l` || (bits 0..=239 of `left`) - let a = MessagePiece::from_subpieces( - self.base.clone(), - layouter.namespace(|| "Witness a = a_0 || a_1"), - [ - RangeConstrained::bitrange_of(Value::known(&pallas::Base::from(l as u64)), 0..10), - RangeConstrained::bitrange_of(left.value(), 0..240), - ], - )?; - - // b = b_0 || b_1 || b_2 - // = (bits 240..=249 of left) || (bits 250..=254 of left) || (bits 0..=4 of right) - let (b_1, b_2, b) = { - // b_0 = (bits 240..=249 of `left`) - let b_0 = RangeConstrained::bitrange_of(left.value(), 240..250); - - // b_1 = (bits 250..=254 of `left`) - // Constrain b_1 to 5 bits. - let b_1 = RangeConstrained::witness_short( - &config.sinsemilla_config.lookup_config(), - layouter.namespace(|| "b_1"), - left.value(), - 250..(pallas::Base::NUM_BITS as usize), - )?; - - // b_2 = (bits 0..=4 of `right`) - // Constrain b_2 to 5 bits. - let b_2 = RangeConstrained::witness_short( - &config.sinsemilla_config.lookup_config(), - layouter.namespace(|| "b_2"), - right.value(), - 0..5, - )?; - - let b = MessagePiece::from_subpieces( - self.base.clone(), - layouter.namespace(|| "Witness b = b_0 || b_1 || b_2"), - [b_0, b_1.value(), b_2.value()], - )?; - - (b_1, b_2, b) - }; - - // c = bits 5..=254 of `right` - let c = MessagePiece::from_subpieces( - self.base.clone(), - layouter.namespace(|| "Witness c"), - [RangeConstrained::bitrange_of( - right.value(), - 5..(pallas::Base::NUM_BITS as usize), - )], - )?; - - // hash = SinsemillaHash(Q, 𝑙⋆ || left⋆ || right⋆) - // - // `hash = ⊥` is handled internally to `SinsemillaChip::hash_to_point`: incomplete - // addition constraints allows ⊥ to occur, and then during synthesis it detects - // these edge cases and raises an error (aborting proof creation). - // - // Note that MerkleCRH as-defined maps ⊥ to 0. This is for completeness outside - // the circuit (so that the ⊥ does not propagate into the type system). The chip - // explicitly doesn't map ⊥ to 0; in fact it cannot, as doing so would require - // constraints that amount to using complete addition. The rationale for excluding - // this map is the same as why Sinsemilla uses incomplete addition: this situation - // yields a nontrivial discrete log relation, and by assumption it is hard to find - // these. - // - // https://p.z.cash/proto:merkle-crh-orchard - let (point, zs) = self.hash_to_point( - layouter.namespace(|| format!("hash at l = {}", l)), - Q, - vec![a.inner(), b.inner(), c.inner()].into(), - )?; - let hash = Self::extract(&point); - - // `SinsemillaChip::hash_to_point` returns the running sum for each `MessagePiece`. - // Grab the outputs we need for the decomposition constraints. - let z1_a = zs[0][1].clone(); - let z1_b = zs[1][1].clone(); - - // Check that the pieces have been decomposed properly. - // - // The pieces and subpieces are arranged in the following configuration: - // | A_0 | A_1 | A_2 | A_3 | A_4 | q_decompose | - // ------------------------------------------------------- - // | a | b | c | left | right | 1 | - // | z1_a | z1_b | b_1 | b_2 | l | 0 | - { - layouter.assign_region( - || "Check piece decomposition", - |mut region| { - // Set the fixed column `l` to the current l. - // Recall that l = MERKLE_DEPTH - layer - 1. - // The layer with 2^n nodes is called "layer n". - config.q_decompose.enable(&mut region, 0)?; - region.assign_advice_from_constant( - || format!("l {}", l), - config.advices[4], - 1, - pallas::Base::from(l as u64), - )?; - - // Offset 0 - // Copy and assign `a` at the correct position. - a.inner().cell_value().copy_advice( - || "copy a", - &mut region, - config.advices[0], - 0, - )?; - // Copy and assign `b` at the correct position. - b.inner().cell_value().copy_advice( - || "copy b", - &mut region, - config.advices[1], - 0, - )?; - // Copy and assign `c` at the correct position. - c.inner().cell_value().copy_advice( - || "copy c", - &mut region, - config.advices[2], - 0, - )?; - // Copy and assign the left node at the correct position. - left.copy_advice(|| "left", &mut region, config.advices[3], 0)?; - // Copy and assign the right node at the correct position. - right.copy_advice(|| "right", &mut region, config.advices[4], 0)?; - - // Offset 1 - // Copy and assign z_1 of SinsemillaHash(a) = a_1 - z1_a.copy_advice(|| "z1_a", &mut region, config.advices[0], 1)?; - // Copy and assign z_1 of SinsemillaHash(b) = b_1 - z1_b.copy_advice(|| "z1_b", &mut region, config.advices[1], 1)?; - // Copy `b_1`, which has been constrained to be a 5-bit value - b_1.inner() - .copy_advice(|| "b_1", &mut region, config.advices[2], 1)?; - // Copy `b_2`, which has been constrained to be a 5-bit value - b_2.inner() - .copy_advice(|| "b_2", &mut region, config.advices[3], 1)?; - - Ok(()) - }, - )?; - } - // Check layer hash output against Sinsemilla primitives hash - #[cfg(test)] - { - use crate::{sinsemilla::primitives::HashDomain, utilities::i2lebsp}; - - use group::ff::PrimeFieldBits; - - left.value() - .zip(right.value()) - .zip(hash.value()) - .assert_if_known(|((left, right), hash)| { - let l = i2lebsp::<10>(l as u64); - let left: Vec<_> = left - .to_le_bits() - .iter() - .by_vals() - .take(pallas::Base::NUM_BITS as usize) - .collect(); - let right: Vec<_> = right - .to_le_bits() - .iter() - .by_vals() - .take(pallas::Base::NUM_BITS as usize) - .collect(); - let merkle_crh = HashDomain::from_Q(Q.into()); - - let mut message = l.to_vec(); - message.extend_from_slice(&left); - message.extend_from_slice(&right); - - let expected = merkle_crh.hash(message.into_iter()).unwrap(); - - expected.to_repr() == hash.to_repr() - }); - } - - Ok(hash) - } } impl UtilitiesInstructions for MerkleChipOptimized diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index ab28eb860b..370e3cadf7 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -439,3 +439,336 @@ pub trait DefaultLookupRangeCheck: } impl DefaultLookupRangeCheck for LookupRangeCheckConfig {} + +#[cfg(test)] +pub(crate) mod tests { + use super::{LookupRangeCheck, LookupRangeCheckConfig}; + + use super::super::lebs2ip; + use crate::sinsemilla::primitives::K; + + use ff::{Field, PrimeFieldBits}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::{FailureLocation, MockProver, VerifyFailure}, + plonk, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use pasta_curves::{pallas, vesta}; + + use halo2_proofs::plonk::{SingleVerifier, VerifyingKey}; + use halo2_proofs::poly::commitment::Params; + use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite, Challenge255}; + use pasta_curves::vesta::Affine; + use rand::rngs::OsRng; + use std::{convert::TryInto, marker::PhantomData}; + + pub(crate) fn test_proof_size( + k: u32, + circuit: C, + params: Params, + vk: VerifyingKey, + ) where + C: Circuit, + { + // Test that the proof size is as expected. + let circuit_cost = + halo2_proofs::dev::CircuitCost::::measure(k, &circuit); + let expected_proof_size = usize::from(circuit_cost.proof_size(1)); + + let pk = plonk::keygen_pk(¶ms, vk.clone(), &circuit).unwrap(); + let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]); + plonk::create_proof(¶ms, &pk, &[circuit], &[&[]], OsRng, &mut transcript).unwrap(); + let proof = transcript.finalize(); + + let strategy = SingleVerifier::new(¶ms); + let mut transcript: Blake2bRead<&[u8], vesta::Affine, Challenge255> = + Blake2bRead::init(&proof[..]); + let verify = plonk::verify_proof(¶ms, &vk, strategy, &[&[]], &mut transcript); + // Round-trip assertion: check the proof is valid and matches expected values. + assert!(verify.is_ok()); + assert_eq!(proof.len(), expected_proof_size); + } + #[test] + fn lookup_range_check() { + #[derive(Clone, Copy)] + struct MyCircuit { + num_words: usize, + _marker: PhantomData, + } + + impl Circuit for MyCircuit { + type Config = LookupRangeCheckConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + *self + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + LookupRangeCheckConfig::::configure(meta, running_sum, table_idx) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_words * K bits. + let elements_and_expected_final_zs = [ + (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long + (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long + ]; + + fn expected_zs( + element: F, + num_words: usize, + ) -> Vec { + let chunks = { + element + .to_le_bits() + .iter() + .by_vals() + .take(num_words * K) + .collect::>() + .chunks_exact(K) + .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) + .collect::>() + }; + let expected_zs = { + let inv_two_pow_k = F::from(1 << K).invert().unwrap(); + chunks.iter().fold(vec![element], |mut zs, a_i| { + // z_{i + 1} = (z_i - a_i) / 2^{K} + let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; + zs.push(z); + zs + }) + }; + expected_zs + } + + for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { + let expected_zs = expected_zs::(*element, self.num_words); + + let zs = config.witness_check( + layouter.namespace(|| format!("Lookup {:?}", self.num_words)), + Value::known(*element), + self.num_words, + *strict, + )?; + + assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); + + for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { + z.value().assert_if_known(|z| &&expected_z == z); + } + } + Ok(()) + } + } + + { + let circuit: MyCircuit = MyCircuit { + num_words: 6, + _marker: PhantomData, + }; + + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + + // Setup phase: generate parameters, vk for the circuit. + let params: Params = Params::new(11); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. + { + //panic!("{:#?}", vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_lookup_range_check").replace("\r\n", "\n") + ); + } + + // Test that the proof size is as expected. + test_proof_size(11, circuit, params, vk) + } + } + + #[test] + fn short_range_check() { + struct MyCircuit { + element: Value, + num_bits: usize, + } + + impl Circuit for MyCircuit { + type Config = LookupRangeCheckConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + MyCircuit { + element: Value::unknown(), + num_bits: self.num_bits, + } + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + LookupRangeCheckConfig::::configure(meta, running_sum, table_idx) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_bits. + config.witness_short_check( + layouter.namespace(|| format!("Lookup {:?} bits", self.num_bits)), + self.element, + self.num_bits, + )?; + + Ok(()) + } + } + + // Edge case: zero bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::ZERO), + num_bits: 0, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + + // Setup phase: generate parameters, vk for the circuit. + let params: Params = Params::new(11); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. Which indicates the layouters are the same. + { + //panic!("{:#?}", vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_short_range_check").replace("\r\n", "\n") + ); + } + + // Test that the proof size is as expected. + test_proof_size(11, circuit, params, vk) + } + + // Edge case: K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from((1 << K) - 1)), + num_bits: K, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Element within `num_bits` + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from((1 << 6) - 1)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Element larger than `num_bits` but within K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from(1 << 6)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }]) + ); + } + + // Element larger than K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from(1 << K)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }, + VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }, + ]) + ); + } + + // Element which is not within `num_bits`, but which has a shifted value within + // num_bits + { + let num_bits = 6; + let shifted = pallas::Base::from((1 << num_bits) - 1); + // Recall that shifted = element * 2^{K-s} + // => element = shifted * 2^{s-K} + let element = shifted + * pallas::Base::from(1 << (K as u64 - num_bits)) + .invert() + .unwrap(); + let circuit: MyCircuit = MyCircuit { + element: Value::known(element), + num_bits: num_bits as usize, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }]) + ); + } + } +} diff --git a/halo2_gadgets/src/utilities/vk_lookup_range_check b/halo2_gadgets/src/utilities/vk_lookup_range_check new file mode 100644 index 0000000000..48948bcbc7 --- /dev/null +++ b/halo2_gadgets/src/utilities/vk_lookup_range_check @@ -0,0 +1,244 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 5, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 3, + gates: [ + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 1, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 1, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x1e8ad0c6992851e2d92d368088d79e3326cd63e2a12bb086407dc3dbe0691fb0, 0x0895d1133a5889cf2a52bf5a7ac48502ac399a0088625be4db7aaec534ee8576), + (0x1e8ad0c6992851e2d92d368088d79e3326cd63e2a12bb086407dc3dbe0691fb0, 0x0895d1133a5889cf2a52bf5a7ac48502ac399a0088625be4db7aaec534ee8576), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + ], + permutation: VerifyingKey { + commitments: [ + (0x2477ff33a8671d640d752567c99805c0dda68328ddfff306b085f13be1fd9079, 0x3f7c0fa2ae0b1b7683c39103509711d525eb2dfb73ed21458b77b9d0de222923), + (0x1c85783d2128c72103589576bf9d4ed2a509202944a52b48db13848f9431439f, 0x0c363acac4903e6907846abb10920dcf7a2b8c7462ac37f64d0da5cf7f9a643e), + ], + }, +} diff --git a/halo2_gadgets/src/utilities/vk_short_range_check b/halo2_gadgets/src/utilities/vk_short_range_check new file mode 100644 index 0000000000..6de944cf6c --- /dev/null +++ b/halo2_gadgets/src/utilities/vk_short_range_check @@ -0,0 +1,244 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 5, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 3, + gates: [ + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 1, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 1, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x27c2b8ac34f64d4d18eada2b41dc9d8c30409eb866c7e4d539204fadcb696826, 0x0881a9c2e2e4a577b5a951254bd508dedafa5f1c7be905aaf4fbac60971bc9f7), + (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x28d1c924953bc53f232465943d25fd085f85727ae4e2d26249207da1e59559e2, 0x184d19e00f109c4dacf8026c6e0fc4181178b32a236828047c46d9d61eab90fa), + ], + permutation: VerifyingKey { + commitments: [ + (0x3b7b93d7540327328791a14933d8f3345abd943eb35b67a8a4bd2eb72e2a707a, 0x26fff57a6fa3c01dd0d739fc56479303b4302d6baa6f1da06f4013419c40e10c), + (0x3fdf7a15a0d2378accc11f704f4ba4a487b542ace83c7f5a8551b569a3b9a380, 0x34253920878d15d6fe1b5198c31bdd670d32e81621e9fcd569d582e596ed0af5), + ], + }, +} diff --git a/halo2_gadgets/src/vk_ecc_chip b/halo2_gadgets/src/vk_ecc_chip new file mode 100644 index 0000000000..5eb13f31e1 --- /dev/null +++ b/halo2_gadgets/src/vk_ecc_chip @@ -0,0 +1,9915 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 19, + num_advice_columns: 10, + num_instance_columns: 0, + num_selectors: 20, + gates: [ + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Product( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 3, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 4, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 5, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 6, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 7, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 8, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 9, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 10, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 2, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 3, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 4, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 5, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 6, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 7, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 8, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 9, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 10, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 2, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Constant( + 0x0000000000000000000000000000000001000000000000000000000000000000, + ), + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + 0x1000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 9, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 10, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 11, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 12, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 13, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 14, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 15, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 16, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 17, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 18, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 9, + column_type: Fixed, + }, + Column { + index: 9, + column_type: Advice, + }, + Column { + index: 0, + column_type: Advice, + }, + Column { + index: 1, + column_type: Advice, + }, + Column { + index: 2, + column_type: Advice, + }, + Column { + index: 3, + column_type: Advice, + }, + Column { + index: 4, + column_type: Advice, + }, + Column { + index: 6, + column_type: Advice, + }, + Column { + index: 8, + column_type: Advice, + }, + Column { + index: 7, + column_type: Advice, + }, + Column { + index: 5, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 9, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x15e9797cbf96b3ab5f2a21595a5ede5becc665dbf113ae1bd93c5fdd577b3fdd, 0x2276c102a90057ccaac390724cd3e8032eaa0d5c7630b979e2f86354d46044fe), + (0x0a3757ecd8df677c56dd731a5988940130dc69375d09185120348b4c24f23f9a, 0x209e7e273d9d9254893a220d7329114fa83eda5d483437612cf638275b4d97f2), + (0x337f1898449ead1933c764ae23b48d20f646e528b079ac5cd0743d9ac8e8f063, 0x144e28d47be3a5d90eab8ec65a10b965fd83c7b34f8e4b387154f126efbbf7a7), + (0x1ba31dfd22b785ba6080c0a1378f14d104f571d6ab2ac6e650865b27296773db, 0x3c49108055aa494775123cb379dbee7ae628e193cba15827df962722a9a47367), + (0x0fdf7430975fbf9361ee6a0eef8e811b838cf64cb042d5988c669010329a8e8c, 0x1292f817500e4ef166ccf48483d061b41372ac7e44ed52b04fbf03da5b04fc79), + (0x145d45d803dfd99569e689c02583b2a63f004e25ba23bf9acc17148b42267480, 0x230efff0cad7a66c33eb7462b4b60237619e1287a6c23a122057ef0359d324a6), + (0x0ce14fcd6eef4247d75df3d38a918bd8d8c66362629ca8ca697254bf703f1dc9, 0x3cc92942c824cad0a3f16828a29dd42785485b878e459a289db7c377973f2aee), + (0x0bd58593a2e2657cd0a228b678a4a7ec04492e20768108383cfdae26613da0b9, 0x090c75a86508be75f6f57e33946c5f9170f40d08e058eb33c8370311fed2868c), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x1676bb18498c153055ba927b909ef96c5edf8108be253d7a86663f57cd815cd1, 0x0ca79754ab892586fe9df1ae7a23e527bbae042eb89e96747f3befe88c493446), + (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), + (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), + (0x11ee40a7ae1d9b3bc41a88dd50a69661de280c85222c5567ea3fc06c606558a5, 0x0c6ad5f6fb00347486477aededc92f686f6d079737fd2ca147b7db5ea7381061), + (0x33be67428155b1361122a6eddf7e24a7cbeddcce8166dead5d9d5ec6714b25f2, 0x3ec742ac0f64c3ffc4d47bbdeaba0603c55ef74d40065b84b7d738c95f473c79), + (0x11c136f6ea303c5630240788e7a4db6c3aa321aaeaebecbd473af5ace4d05248, 0x0afe33d04a38bae95c2ec4c4372b2d766369c4c5b10f82dcbd4375a41f838d79), + (0x320eb135936ed226a108ccc06bea1ce3ea57dfc2d708fc2ea868ee90330fe22b, 0x15f1174d43608cb597ad1708d2c15e6fcb399219662c75a476b34d51d7ef8f09), + (0x2157882bf836df0d37c2fe7b4c03c099712bf0f1f70475cf79a47a269cd05d6e, 0x2b21b30255ccaa0152b483916b033c38c54edaf1ae8987df41d4812affd004fa), + (0x0bb1ce75e6be204e3d006a0dd70adbc82e9babae94be0a0fcd0eba958bf78d95, 0x25af91a42e58455509f322ab700f45210e369a79cfc3635db30fa5298d46475b), + ], + permutation: VerifyingKey { + commitments: [ + (0x2dfdfeda0fc01492b0884d17870ef7c30a6a59502ead966bb6c072b216ef7b33, 0x206d9ce95f9c1bfb675cd14130a877aa70650b7d1bb5cbf82f3fbfa517c2a19a), + (0x001deacc3520d2f07b82695befedaee3c62c595d80d0f406f473ab3e8c362213, 0x316bcc3ef777e42b96c36bbb95b41654dc91b4fbf264e3796267716917e0b63f), + (0x142095bd2f3ceed4e0ee7eaae4952488aa314d89f4755b81bc4f4df5e849947a, 0x0e6b8ab5b49069d21ea86f1d320c2959f144a3b1f284231312ea776f337b00b6), + (0x20bdfa7afff8a496620db915f9323e348b0ea52ccb0e5ef2a26cc5edfb4a3490, 0x033516b53f25239682efb9f0b6865a1841a2f80e88c08c9431f08906bf2ece95), + (0x3b3d22054a70b22ab2f4daabb0671df492f8ae365372d34f9ed9cbf053f77560, 0x386d905cc46f526544a620c7251d661cf09ec673efafce3bd36f59295e8c8e10), + (0x23bdd78c87775077ce68d63f15349c6851d18cef963e714fad7c182172539964, 0x36df72f765faa06fdc6e79e9b71557043f1b3c32677cbe852bfb89b9ff2adf73), + (0x1f058e8d0ce9494143e267f9190d4a8a0f4fc18cee14b9cbb00fd4324d028d2f, 0x053c9574cfa8f32a4795152eb742f40752011ad9704a6b7a05fdf2d660948eca), + (0x0c116eea00a8888c4a5917f514f323b993c732ad08d9655cbcfb3ea57645c1d3, 0x1811bf498434bba922e2eb1b1dfc3025bedd7fe7aecb3837a561c1e78ee56b05), + (0x1317f5890e3c536bc205f7ecc9e286414f7abcd160903ba663f33cd37821a1ac, 0x39d386ba96759c162f980de92743c908b4808e252d04309fc5c10fb48c8f5f17), + (0x05aa4e237c2775c8105b736664b7b873a3a0a35cda546e29439fdcd87c844afc, 0x36129c33ee883439d98e23d4fb625a22df4b8b62d41702d82b59eb264c649832), + (0x2e48423c28c290a75feb9d431f59ec36e48d9e88c3ff46a9e1dfb04ed894d88d, 0x00d3bb38bca1ec15ac2e79c8e9c093fb496cca52c58f2947b51537ce718d9060), + ], + }, +} diff --git a/halo2_gadgets/src/vk_sinsemilla_chip b/halo2_gadgets/src/vk_sinsemilla_chip new file mode 100644 index 0000000000..1e5ee09d57 --- /dev/null +++ b/halo2_gadgets/src/vk_sinsemilla_chip @@ -0,0 +1,11821 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 25, + num_advice_columns: 10, + num_instance_columns: 0, + num_selectors: 24, + gates: [ + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Product( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 3, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 4, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 5, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 6, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 7, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 8, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 9, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 10, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 2, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 3, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 4, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 5, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 6, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 7, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 8, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 9, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 10, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 2, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Constant( + 0x0000000000000000000000000000000001000000000000000000000000000000, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + 0x1000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Fixed { + query_index: 3, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Fixed { + query_index: 4, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 12, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 13, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 10, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 11, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 14, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 15, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 16, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 17, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 18, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 19, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 20, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 21, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 22, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 23, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 24, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 0, + column_type: Fixed, + }, + Column { + index: 9, + column_type: Advice, + }, + Column { + index: 0, + column_type: Advice, + }, + Column { + index: 1, + column_type: Advice, + }, + Column { + index: 2, + column_type: Advice, + }, + Column { + index: 3, + column_type: Advice, + }, + Column { + index: 4, + column_type: Advice, + }, + Column { + index: 6, + column_type: Advice, + }, + Column { + index: 8, + column_type: Advice, + }, + Column { + index: 7, + column_type: Advice, + }, + Column { + index: 5, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 12, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 13, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 12, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 13, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 0, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x372e1011c41715c062e0bdb944973af06c5e779e64d2eb64b713ba7a923bd921, 0x0df587dbf80715f2e1a3429e4970dc1ee2b4478ac56fc6308bd1423a96630eff), + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x278ceb78d7e41109f04648e31a17d363250264779a54822b6af849e08394f8c6, 0x38657e78f288108b1eabf5752c294db179397f61b34e3bcce8b9ea64f0414ccf), + (0x02f77b8037894d3be78b9913b56f87a4a11de5b23a2715653c95284f5f4a533a, 0x21f3437bc1226236ea0b87217af56ccca66daa8641dfa562c1bac1c9c97e9ba3), + (0x226cbe263518a231a03864a40070593012418e4adaad26a9657068c92bd99834, 0x30aa25907ea9e3751193ca7a4d1e25c1f085f07e24fa55790d8dde572cbb4b39), + (0x31bb1ac8ad43e9c13b44aec205cedd51ba49044f42b9778a281c8f78499c5844, 0x0d10aa271191e573188ce755174183966f97996f460a32129f409c6e33452859), + (0x3cafd5ce5d34b1e0318cc5b0e655cc0411dd86d2c917c4c776923920ce4b8783, 0x1cec31e481cd980c231475d95ce7595a241d33128f0d0f556fa3e3ce64309182), + (0x17749546b03083d43554511e69f5f2049e78c7893f4c6012a44e51f0e8ed314a, 0x39347f6d9fc4dd61e475a277ce7dfb0e4d1d31e1c0a10d8bbe6b4029cb778964), + (0x31d60c414c7acf6d5941cf201088d51eb81e528ffefa458f2fccea9d81ad274b, 0x3aa09ba345b10e2ff005c50f5d1fb5b86a7145c2f744cadac9567fde1e4e1b17), + (0x1de5f02daa9e1bd92e54a37fd41969e14c89c09b718a791f616c0de7c51eea94, 0x096456cd7e00ab2d318dd5d38ef0b918faff5225d8dc34e1fe3c2db4ef5698bb), + (0x3e727e8554679f98120355d39d958dbd8755d5a7f8b42ea87f258064c4b3eb57, 0x0c0d5c23f3ee62ac1b2d986dd3033bbcab260d590e1393de3a14a4b31ae091bb), + (0x3748680dd6a91c5dec668b30fb6bf9a450aeb884b81cbc344914f265760e7131, 0x18530eaa5c58b61bd3fc38220ea484c0922524a815a8f752be955c229f9c4164), + (0x2fa9bff8025b9eb1fd60c0bec845d6d09c49a03d7020280feae9751acb88bdb6, 0x0958e83ae406bdc3c0704afa316f3717568c74cc4475127443a6c9058444234c), + (0x2f39f6d3b0dd8e900034e38670e853e761825dff78c4060e2ca4832ecb1de86a, 0x13c40f0fe6243ac40fb8abbcf7e62f027362a8e0b65b38f7657dc4db3e471fdc), + (0x0fc9e35a206e0ecd68eb1aa156be11067d48cb853f8b7be8366e693077c05adc, 0x0f2d1e728e41ca4cdf33998fcf2b9ff442523b2d854ea7b800cc79ef381ef053), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x0132c6f79957c48e8e89c8bb06a02b1ab2fa2872c6bbf2a98d24ae2cf286ab65, 0x101570d65833ffd44e4a481f7f2c0b42854b2785beebe0f3e3e7cf0432b0f2a8), + (0x1bb21f71d0d3cf31cc7604e6c80f219a95ad8a2fdda1ba4749038a850cb295e5, 0x21fbf3282559a16f747df709bb6e53ae247bf4aefdef22d1456ceee0069a5a30), + (0x298e4558e567ccac97873d2423022d66ccaf4330fe3a168a283fe38c36ded7cf, 0x2a19cc559c589cd3dce09b37b01d147351e5629d81aa067a92564bbab3264606), + (0x25fdb5e53d333b73513af137b20e1ff8556ba3528f8421dc94fff7993c2825fc, 0x1dd77006ac8a5883fc101e9869119f58702ecd6ba2248d6fe887dec9a9cb7abe), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x1807fc6a973fabd4cfdb43133ab368dc3ec8b3e3c49a33022ceb7a11312994a9, 0x090fa9b27aad0b2466a0fe73bc6e27b071522f808223697e06a97b0067a295d9), + (0x09899c24004863d99205b3e8d12091fb9efc7f869213aabfa755ce8226296ac8, 0x3b9fd993ade2b56baa51cb480372188b2b4a6c029721abd78f882376a2e1066f), + ], + permutation: VerifyingKey { + commitments: [ + (0x19b1e656ecc4bcddac6e6223161f9a676f6dc320323dd923d07b107bd956980f, 0x12b19731c6cf97867694f17f8241ae4f87699babe1f2e0aff0da5843c495687c), + (0x34015e25137a9a8ea4feb8af77f10d27fc6a04e952823f7e2343a749419df2ce, 0x2c6589a5343037dd14d33821800626bba96354283fb05011f27dcda6a6b860fb), + (0x3b99cb11670a52fb09cdb23f99dec85dd61bfee1120cb6cb7f976a027e7fe29d, 0x147c5a63bed5b0a16b5f28c68ccc46bb175a71f093c1a14e71c944ca20d2d5a8), + (0x0447bb1bd9cd21264decdcf1d3d8c51152dde3e2973c289636c5143fee588597, 0x2693688ea58e92c734de32906f8646d3e7eb92df37eab9e95f8e1fa0fb47740c), + (0x139a2e45b57a51ef2b2f091026e534e710f4095a248e029411c83545ffbe980a, 0x3a9f5a5f1778dc3ab162ba7e408f8787deccc79eed79f39ba8e95d30d59bf072), + (0x3bb81950a72eed5a0d778f649dcfdebbc7fd777c40ebbc8423a5359b1657ec69, 0x0827061e9cb496f1de9b65eb40414b801f1cab7ea1451db61b26d8828db12934), + (0x053904bdde8cfead3b517bb4f6ded3e699f8b94ca6156a9dd2f92a2a05a7ec5a, 0x16753ff97c0d82ff586bb7a07bf7f27a92df90b3617fa5e75d4f55c3b0ef8711), + (0x3804548f6816452747a5b542fa5656353fc989db40d69e9e27d6f973b5deebb0, 0x389a44d5037866dd83993af75831a5f90a18ad5244255aa5bd2c922cc5853055), + (0x1364aec73f61f3bbef067b079769ef911ef829c7bc96aad03eb7f67f5267f7a2, 0x2286218435feaff751a5b11ffcad519cce178967d265737fce47b4ce2bbf3855), + (0x0c789966ab89d6e03049ae4d06a58aad553df983f7feaf75568ef95e477d8a48, 0x16786ba48d94e3c7968ea059eb9ce4db1684a7804d886a586bb691dca1646754), + (0x16633696ce5a30d1d301ceaab86aad90ea6ea22adf090e31859b4fb571e9b746, 0x035966e0a73b53474ee433e2f835e1a8b02c29a49f109bdd590a37d2b946dd03), + ], + }, +} From 684c13e3b24d3315276b31f7adcd594c432b180d Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 6 May 2024 12:30:55 +0200 Subject: [PATCH 014/121] update serialized_proof_test_case --- Cargo.lock | 6 +- .../src/circuit_proof_test_case_ecc.bin | Bin 0 -> 3872 bytes .../circuit_proof_test_case_sinsemilla.bin | Bin 0 -> 4576 bytes halo2_gadgets/src/ecc.rs | 37 ++++++- halo2_gadgets/src/sinsemilla.rs | 36 ++++++- .../circuit_proof_test_case_merkle.bin | Bin 0 -> 4160 bytes halo2_gadgets/src/sinsemilla/merkle.rs | 38 ++++++- halo2_gadgets/src/utilities.rs | 1 + .../src/utilities/lookup_range_check.rs | 64 ++++++------ halo2_gadgets/src/utilities/test_circuit.rs | 95 ++++++++++++++++++ 10 files changed, 239 insertions(+), 38 deletions(-) create mode 100644 halo2_gadgets/src/circuit_proof_test_case_ecc.bin create mode 100644 halo2_gadgets/src/circuit_proof_test_case_sinsemilla.bin create mode 100644 halo2_gadgets/src/sinsemilla/circuit_proof_test_case_merkle.bin create mode 100644 halo2_gadgets/src/utilities/test_circuit.rs diff --git a/Cargo.lock b/Cargo.lock index 2f8bc71dfb..c7ceac9436 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -2280,4 +2280,4 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", -] +] \ No newline at end of file diff --git a/halo2_gadgets/src/circuit_proof_test_case_ecc.bin b/halo2_gadgets/src/circuit_proof_test_case_ecc.bin new file mode 100644 index 0000000000000000000000000000000000000000..1565f2935cce5a184ba1b5fff88f3c95b78b319d GIT binary patch literal 3872 zcmajf^&=dP!@%)#hI6{R>on6bZ8+VN6Z^<99AlW7c1)j+VRAYqrn|eDIC0u^jPpGI z!T0^^>-V?q_e8w4C}4ICqTXr}J5QJp_da;Q#I^XElH-0UN|>ruwQzKx(`ZJP8<}@odUSts!Z zt`{UP6O#CamZaWlRM>mFheBT^+ZAw{1I5S^;}Rt{ZaVYB)IF}3f+|X9;wcti^qlCl z7jg<=nx#jxV8(-zQVk8~-1xuYGUd+1uK{2`*U8Xx<{2vZHu9Fr_UEI!-YzTlc?w%A(46cLB74M&_(OvFd*43Fe4mN6XU)Z%1j(IJ#qg zpD9}Cs)DONgSZ^D#VUsXGT(;^i8ES!@*)iM)1`dTlD)7CIKrQ)l*ZPclXH15wVNW z%;&%W6xZxx>vVLam0u~m=nwNVax?uihswcjYdPtY?<5!QWVP4X!>5Ir$iJ;`ARP3# z>I7>GQC|kLx+|vLkQf5ihL6@=yT+OV>|Z>aXQ5&rtxm zhaM)Q_4&E0F8fk*)+tYP}Hyq`bV2s zA5HSCDxpLVQTzBX%jd4Xy$?qZL!xD{veWqF9NysV$2jyC-Ii`XMPqnrrD|1qe5;KZ z8b8+GtxxIl61toDv-R1BEkLALC1UJ{Yg{4xl2O-_) z6b!5S?u~_IN7azd--iR+S_$||)H;2P~;YpK1Ao45* zxOuLeDf<%2$aT2a!(arg?#bx50>Lj^@A;?oS%iCF+biKUt?VvvRz5OBhP|v8&tU?f z&RhX!jMT!-AL;8|{DC|dWQ`fxl@11qWejMykjXFzWOmr+xc46|OZ+@hBOSEYWfmjD zh-#OWro}6^N@nYv60O#&k3rQ%D7n;{{+4-dM>hO$m1@L>BXvdmVvgcF^|?zN9RcAV zCtQrDf%j^s$@G2yp?a}YT22|qYJeU4kiZ&?uNczd_M!xCNs_Y3DKdktHS6q}2%qoa zl=Ku;A_;Lv)i(t+DU6hRIMPH3e<@*Js7v<9WrRsa(Z?vRr4P78GU(>CF$QuN(BI^C z8G`LoN%3V(K^OOCH#MX;P<;$^!h1neWurNHk7Lr=2p=in zY3@xAz0PMg496A-6))SA5@7lAZL+AOY)ttSG^+sU*c>Hxy;AKP2ef?!0W~t9w`Wz~ zc!+wbmlgB{*m3_Vu(?j- zRpAO!em9)aOv=^mO`%5Z9`%WMA#sLJFCVCv-bj1oKt61Zlx4pEYlja;s(m_QX}X~Z z>1?|=j=djZdd$Nu813VXzf`2<%B;&v)cD{Gn8XZF2bh1mw7eLBrTse}m*(JMyeYa- z99WZ5AQqZaI5?)rHX>GHFuSi9R61bE(3Wvx!SG-@)m>@u9Bu!dmfnoB7h+MpYothH&C|;j4WqRMnO^0Uu>QYQWWm{bc6R{AmjMe+ zJ;kDaNUZ;ArR|lr7P?f9Ju^aN8QP2Q1`I_$rY)*bAZTeL?m*%n6hApVcnwc-=4ER% z0_*52{5{+X4=XbuH(L92t=y2pJ!X8Fn%4CMMI2&JP;DbnP$~8io4e&owjVN$C{~T@_gvVO+C)vAH7nWpGe5z1XnE zzaQQcjI2A$rZcl1O#M<^mXu8<23I`0rmGC}n93DTSFx4bS+W3wBW~|1?Qk=>*$ljx zB*Ckx);{WI6Zz=12ZzSVDTBfE>55x1e(9M?EvKwtO6KvS_)mny8@vX;ffD>DlKFa@ z`y(HhaHUqS%PBcnt%)xKMaQu>th|~caEdnu8jy+_{5& z{o;a!nQ_BE&zF0Ia>+yFbklGKEFR?l_k&4ileR@H&e%xvaDN0 zSzL}1Ni+%VE$1Wr3xsBdJ%;eOeV< zS;_UkJcUPaqRV?{VWSO|GCc_~7J@ku1}Z_IFk-wV38J{Qrc-8?H>P`CSZb~=Yhd7v?`IN{K3m4@YRT))!;B#x6gW zo6wQEeR5gdLt{KG2=6)-t;5X~Zr}~lPsk>xZ7W*q6KKYX9xBg+-YG@aue%?4u<{Zn zrC$~AOr|uA>?m}jRVLCNFi#7*`0iJIdV;mOqPcMcn(lnxlxB^2t^sidBt-)h7&UHT z*|WC<#(cCFJ~CdH?yP1Ghgf|Jg_I9Qa6{+qa^Cv2&i+-`SCWR+Gz>+?D4zR&Ri}Q6 zIDvZ(KiE1Wu_VXKb|Jp-+oxWP@4#P`^F8eP``cD+*8B);uBEq%{F0l>!YUUJC;xuF z$tBdv;zID&OKkV;$+KE>@G_c;>6=dygU%8Ck%v1gRd|SgPfx)WO^@9J7fZ6v+c6lC zFN-|x#F)1~?a6=NPx;!^?AYdm7~Go)4J<-#Xg3??y1L z2_#DCku6Yy zkF6+dlMVkmG8GjmA7pb>nD>Wzc~z(1bTNQoL$hLdWvM{rlDGvB?0()9adyTFCXsS; zS-G3Qs?m!JTCrxe+1eu5AmiBJ$n8nwACV>S9;fN)<27JBV#XmV%3Y=Z51CR~O%El` z)9l$doR6gBkqkL;&PGqCLTw8n!yt~RzXLgS;L?`v6w%ZwY9NJ%aK;BVT7r?<&e1Hy7zYXJg-If#%p z3KtQbP>gI{EL9traegG!Q%;w6p#mbD{~Ay+|Nkq%>?9vZtjg==N3LSnlBaN%A9JKq-8q>Z@{(e_7=G6jT~vSO(i%lt45nuR<;6hy zS_ICSWb0BSJtR%z&TJ#R#NP_1nFRul={QqD${ewa)81?Vr{+;oY*khD+%(cgJ7qs|tJM1Ebo zlS`GBnoE|)W!J>t233fb_G5Xh>8~ac0ZL|&S+{a9|CVj#1=s7d8(Cd=WNG^^J4;v9 z^k)8uryXq;3(Vq6BK%;=f&jpf(AS9fB2YzZ!pElbr(Xxxo4PPr0RAFe#`!bU=G3X4 zrin0tf+i3>U@?~~D#TfxPb2Xw>W8WlQKCYA@GI(K$EhT;+mui)!5o-U;~HH@L%s9w z<~UYSHQj(i55#5^OEpJgz_|TJtpZ+@d?{nq-d>Z)M6UmR{iZ!?h@mHKejZyLk?;#% zeNd-E==MCtGcwxj$l20sbaGyd(;D3SiI1jd8dupr0o+;hm7=~0XGhot- zHwd=r6-eaByj-cQ4l#+Jd0RX4dabTD}qxyI|=v zYj01+bff=smrSUcGnl3Xsk4?hQcWB7a&3ycZrIt+jCx*6-Yj^%+x90+xfvwzXurB1 zp4R3~(71!wAXpPsa>?etil*eJ9{htN3VccHKg_+8rN@dt^tB{QVl|>9F|7e_u=7MzBoRsH8b0WyPCd z;u7vY^<7_L#1Zl4aFSMaPqeMzJwali-uqh{Hb5?h0pz|F4uq-OHTv!)YDvTH{3EBv zUW{7!#GcSbSi%yJDvy56zlYHqBwOUhn#Yw}2J?6sob&nwbabKoN3TjP4oC*HH)R;~ znZ|6;60Pwi^)I7Ivmx0P5j>>=9fT!mFzr@eyFo=S8?nLWOSHA)_1mG{28kz5V>gL} z9w8iH&pTuk|I5B;P)7>4LnCTbOH63HRC#IPk z>>MS%YahFJpo^AY4cI(XL}>+#PHsd7ISu@1*FD0oU9^9HRJU33S0jy;G!iI64e^hx zfKxmI?wU_y?1t-(#*6WiK52TjO{_gRTGHDSi(bi?Xs}LTKsQ(3+2VH&6D0%=OfW6AjQ{z^kr1|j23;owuolx!wr0H zn$KC;3B{UJ2-1nl)4wwA3gtKee@@wMWS%>?W3*8@qL-10WJ4Cz5}H>!DNbJ52?u-C zecyiq>_6hPmnFR_UsCz}PZ!qT?X!GB8CieEqJ&-))nVNt$lC?3J8R~5dvQbUh+7Fl zmNP9hkR3^YeuaN77BNT(B^veR^>L|18Qt;WtY!38j`Uu}D-gEV26`d( z_!?IDu)a*63}b8WEe!XqcT1KiGI_FN^|Ez=Tht;FIR8?jv zsC)e~^7uy9*#T$oZSRIXHw?hvR!~9Cds2^IgtaHgr6LRl%fu4?o^h;J^n(RwUZRTd zVLCCCYDo~8Nk%%Rk12|NX66>U&CD@(mWh#IS$R2jdg`7%e&o<64Nc#)n<3*1@_Mib zWSlMB<1wmh07F&k+*~kh4d0FtJ2Y*2ZdP&VrtPJ&nnV#GY|ViC>P=q>B5NoP6T?{v z;6kLkz5oqQe&}iMjK?zL_n>}TuE9i*zdJDrmI%X%f_%9p>#F2}{Ij+nGA3*#$Tk5VHf|he-MCaJ#(MX*BbTo|H zm*jTDH-*(O^fDtmmFGqF}3h zi1TI|VA$P_cGVjh-5_Whcg9;ED@8Wb&!?r>|^I4RfzKt#xx32m_5+1rUp`g0?K}c?$_P|W( zm@sqnIaLYj1$eOkz`twAo?yV#oqp5&qUd^9nM9g(!zkccRBk?d$>&d7t@&w}M(p31 z*-Mh73eCgBwaePMg-?xW@IKvW-*U(5Sd*`TTe)X3$Nc#>GxH2XFJvXd{48edAal#` zFQvTiSPV+=cgRCrac3$c=YT_uhk zX7R3+=dSZB&z{rZ(&et!2hHhJhNrv<>QNH(P4|A(ixMI+rGR4EHKOeUe>~ktlWg(? z!qA_Nh-JXJWCF)iE&OV?_tV&VG#+q+qWE(IrQh!8eA-jb{tw^Ve$HjQcNAG}SmAuy zgX6IHKqQCmQ0|IfNiW}?Z%)oiINfxX4ReSNH0CTQX7Nxcxbei_2#=mu!ZVDzgKx#+ zhf!SJTr6hG7sSuT4-Q*;LB3q=EdWnej1jCRYmKXU3f4aRmDs}MB;Q}!EKf%j(lb;5 z5HB+aUDj?@4RQQ19rC;Z5#K>iIx0D$xDOXl;u8f|d3ld!fJRsMWq2Dsqw}#1i|F*G zsL@C8hx#7l>o7%?k;J)BdS!gm$uWZi+8$mOVW5t>gR79szNp}vJ+d`o(wU3~q%l*J z?j7<~XTPhgL=SPh%GHv+pYzLYE8RN&qSZ`~2NA@}mJ=qvG2UHAN<~ikBmQP5>B=8F zssAlW;7$gkr*BlTIA^SSz%mNmgd=tN>dA8C(>w5D2sB@*7=C8KNDB-At1OsI6=DQd;hiZ5Vp|cNrDh%uk{_+Rxf+-B6^yev>K zeu|%nuc@>qA#iRn+)HQ)#UE`fpqY9*wB5Ai(G^a6Baa((KSO9tk;@|D!SlS_00fL0=wV zi+1r}ZC#!9cG}8p7qK8!OY&+|E4KY2M3ZGYP9551)Yl945kf`g55VI|fw$N%Ab0b8 z8zjbzxeiwO+HsGC#PYBaUxq*GV+eI4$G42}R#(ga-anRVUK-1KS% z(Hq>A=ZG`=zYcD1U_kabj%F!($ukrw8~B$fBE=L>O@$F&G5(5-U5{6cLPk50)pp

|d3_{PK*bWd z;qCX3_|1d@M{I(Ub+E!OPKjtVCI;Oez&WARj%Snh)Jcp7%?$|$q2jW3eTXid?j6jf z8cEpJ4)k0Hgj2AnVp4G9u_?4!QosHc*eH+lEiF?DKTJ$DM^HLM=Ut8Ud69%ojR|~| znwuFbOp0sY5%8n|UG$OGT?hW8_=Wsjd^z!6X?#5psEV$f!y!6c$b|1<${P{NntOku zra)25KBd;dMu^SEf-54zQgjYt(V~TyF!zOSd=hF34HAYUF2jRz2XXi8mxK(*j3r`lGyf!&88_ zSK$DkDF^cw@eY_Q*fAxmC;_VfFXp(kKlAjHcDdy3?$0&~dN8mg*<6o_c3yd3{J(0$ za(=c~Md?pf5w;zg6oA4+Hid5kg&`LQqh)`vBks=zC-gCSM>7C@V zgb0X#$e|@J}(cIm{v}e9mi=Y2-b3MUXd5X&vv_V1J^5iOs!|h^y$A43^GQ`WtD8 zdwu{)rGg`&WspK~?5>$^mqYAYrWi)Ucwd{)O7Tz*ftVfX@N_Q6>B)ezO1aOJFkxk5!?egb#aseDw zbDqJ$*q-hmgX)uqwX7>jw;QJ982u4S%8StDi;$t@jIeDkfD1$rPyX$id=*O=P*u76 zR@5~&GsLcnSDb0WcyeD%LbY}xX=mX+H&)V?Do-m)V*pCWUVc@yDk!zT)hMx`; zG8-R&rv4XpUu+34<@x5cmCh;~OJp1-Oh#sFgvQOW~9&Wk3HuNbBgH?`mjFQ zVwk;`ta82klwfn6FymoJGXx;FM6PeOdXYa)%fn`wLyu!t*`e3rMamXav{O`*3 z+wXC2>)a;!*FJDkew96QoxRI*tE19&y{X(Uw6T_LYay{CG;?+vRO) zT#pTgR(;9fB^h8!Co$Em4E_6Y)m5B>>-n*)7Ri2(XzlfN{^djDDR+QLceC&;3*%K? zh}SyG)g9N-V*Czf`i$q{`i7QXr0dL8w!Co`>>X_kj;3b8UMLCT!VJFM!L7~ekETX1zvXit1!AdB&>UAV9*FT>^uz1$xn z&KCBQEhbaswZ}xqzLp7=q)c>;{aZce9FE437W*5>XH!RuC%D3?Dc!poNZ zqYY2%4qZjALYCidQ!bOeo9l1I5<9ONjTB!8(*erW#*6x>i){VaHdG`(iS0Aal39ZL zN9?Xw-gJY<_%Cx2j^Rq6Q2e`hIYY}+9RM-?VARrOd`?@N#}=bc^^;I1ao4( z12we#*$_$y{Z9@0B_Sdyx&t9y=_WBu%I-YRb+ZAd$;n%zGs&+XEW+3GO zXqltNfEVRL*Nv)QTn7?qEw8atZfe3b_(y-R@LSL*wDR@A!Kn7I)Bfi|k_4A6xB1r_ zSc4c3n(*&ia&3#>vnu|%@mttTQGgLw=ZOVCNse5>C?BN^6Sl$Pu^=IxXOVlk`#I#3 z>WRkCXJJ;~m|irzwHU`BtS1pE{}I))x%YuceJwLDSk50aP-0)~$bKM?Qsr*9w%=8N ze=9CSHl5ca6n(L^gA7+Qxsk!%9I1At!L;agc?%5z0;b;-D|fzu|8<{USzvy>iR8Q5ygka&-295yPOz+Z(aN1&aRHregmC9L;-> literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index b835aaf3eb..66ec826e41 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -598,8 +598,8 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::utilities::lookup_range_check::tests::test_proof_size; use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; + use crate::utilities::test_circuit::{Proof, read_test_case, test_proof_size, write_test_case}; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -931,6 +931,41 @@ pub(crate) mod tests { } test_proof_size(k, circuit, params, vk) } + + #[test] + fn serialized_proof_test_case() { + use std::fs; + + let circuit = MyCircuit { test_errors: false }; + // Setup phase: generate parameters, vk for the circuit. + let params:Params = Params::new(11); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let proof = Proof::create( + &vk, + ¶ms, + circuit, + ).unwrap(); + assert!(proof.verify(&vk, ¶ms).is_ok()); + + let file = std::fs::File::create("src/circuit_proof_test_case_ecc.bin")?; + write_test_case(file, &proof) + }; + create_proof().expect("should be able to write new proof"); + } + + // Parse the hardcoded proof test case. + let proof= { + let test_case_bytes = fs::read("src/circuit_proof_test_case_ecc.bin").unwrap(); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + + // todo: check size + assert_eq!(proof.as_ref().len(), 3872); + assert!(proof.verify(&vk, ¶ms).is_ok()); + } #[cfg(feature = "test-dev-graph")] #[test] fn print_ecc_chip() { diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 439dba9fae..ace786e1fd 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -489,10 +489,10 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::utilities::lookup_range_check::tests::test_proof_size; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::convert::TryInto; + use crate::utilities::test_circuit::{Proof, read_test_case, test_proof_size, write_test_case}; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; @@ -786,6 +786,40 @@ pub(crate) mod tests { test_proof_size(11, circuit, params, vk) } + #[test] + fn serialized_proof_test_case() { + use std::fs; + + let circuit = MyCircuit {}; + // Setup phase: generate parameters, vk for the circuit. + let params:Params = Params::new(11); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let proof = Proof::create( + &vk, + ¶ms, + circuit, + ).unwrap(); + assert!(proof.verify(&vk, ¶ms).is_ok()); + + let file = std::fs::File::create("src/circuit_proof_test_case_sinsemilla.bin")?; + write_test_case(file, &proof) + }; + create_proof().expect("should be able to write new proof"); + } + + // Parse the hardcoded proof test case. + let proof= { + let test_case_bytes = fs::read("src/circuit_proof_test_case_sinsemilla.bin").unwrap(); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + + assert_eq!(proof.as_ref().len(), 4576); + assert!(proof.verify(&vk, ¶ms).is_ok()); + } + #[cfg(feature = "test-dev-graph")] #[test] fn print_sinsemilla_chip() { diff --git a/halo2_gadgets/src/sinsemilla/circuit_proof_test_case_merkle.bin b/halo2_gadgets/src/sinsemilla/circuit_proof_test_case_merkle.bin new file mode 100644 index 0000000000000000000000000000000000000000..df788aebfabd74cf7f76ccb1d5b2a90bec188121 GIT binary patch literal 4160 zcmV-G5Wny4=>7~%D@Lc7iCnR=YbMU7yNI4&6~;@f8m`)O5%{gcATZeKTivT6q2y>p zFNs7p(YX|qdRv-Te;tudO3kpeIK}j9{Y^~}uBbzqj5foa`jN*^x7i=dJgl1Y=YK3H zGPQ!(-*y6kt%_A0Clp4RR9WaZbGfWm)Ox85osc@St)!LA{9FZi za5frlWc>}61UM@VBy61Z2x<0BGceF@ONv_HmXizt_OvB_Ffbrn6m(H_{a-RcSiX+u(f~h>&qW z!#y}%BSoh4C-Rgj7-X=&iGM~nC>q=WfsR5>XI04893Hf=u~0SHeVW?)%sQo1637R5 z1ztJ}!k#y!c>vhTzbU&NgR`1M-JS}UfsechME6?*ET@T=VdhMUgcD_&Nm%6V%03GD zT6Mfs3J+i*qD9Ts zkfW8xO5zO%z8yIDqFgkZEqf;)Uc%QqSy(e2wOaeGz5!`Ki+3JHBG`?wI~XdXBcuyE zPId-&wp|3h#iR4YUt}!Igv&mD>hR>k`>J4sub3`$F(Eb8!%*=6p*oPPDgY86J4Bfy zNQv`i{K-bytck!=U=tx5w0UwexuyJImYs9=bsa;#G0kre6%6Vg^&Ke=7Pa~Mf@DZ2zk3+6_ezr<=7>MB+=)jG4$TXm}&K~PP|wY zXmTJQ>pG~PEm;i`MZ)G#s7?<&^^^%kGEF`|;RkS6z_A-wX#6(vW+Di&1qp2HG&Q~< z%jYsWPBFb(+;rV?PCY!61(nOrHrRJc{cJzmq@3$NbVqxRCL~Z=cp3Y0RAUP$*1i~L z$6jcKEhriVL!pZH6u;XC$I{AZ-di1uy@nzGomzkwnTsN-M%uaw3#sE7pxQgfz`=q$ z-RHdqc7`m_%aIgyuV>F)F$Dt~h342K{7U+8Dt(ENZrt9%ElL!~l-V@+K1r@^gkLil z->*DO1SNcyb*iO~uS^*@uh1`s}5aIA(tNS~{C>tgMT##D;>MR?8)yfHg@eOKXFeRq$v2VMQ~|)qPyC z&$F>lq6Oebza=#<;vFRQEg16esR)q3*6&jd*!+pAK$UTP*B5F@$q^PD9TwSH#bkEH9Co{IsMj{db00000000000000000000000000000000000 z0001+toi0)73lruYG|V&+zej(`1X7iE26b zl?)g3k4Lj6yCgm0+_ z=s1>pc}O>IiR&2bqli{vKj zfP?Kk4O(w+FTbAN`>tNylnv+4zz9sxurR5T=7I?n$ZY(kmd7#NbO2MpqJlQaEntV+SCrI#0j2Z}D6G*+&)Tzw(Zp(2(#o z`8C_|Th+{kx1ghe4E6Q81dNFTJJl|_r9<-}bS@DgL$WJ7mWYFw3x(>;@}Vuqg+0S+ z#1<5m>>#tQ*n1QCoRvJ1dP#NL~T5Md)cCwgH`_7Qw@B0E)iG zHo~kdaGBAE72G1T&1wk1W03BN>CaCi$fgJJYF_Y9ZnNAS)|Ew}Fi>PFWQH1)?O(qw zA-pz-dV{h-%$qD~+Ix)fykj7t)b;c2n;k4~9}Q45Ol}^GXR2BhvC~Dv$2MxO2NZOv zW1Z4pWtu<#5 z`+iP+iC1l=p3R$=mxz_t8pl-e zAb)O^8*Zq_FYyRSU+!VT9e47U)uiS+iDay`W6`3JPqlt{F>1v3?JsX%#9vHw6S_Hsfi?K+BUwY9^v z0W=Z%azi?do>PUo&jp9rbWKxtFGdDTgu0OQMUumH`_C1~SyvxfrZxMLGvXtnis^m7 zKQ+IIEvnCcrpzo1+zd4Ce;vWi=z(f?1|cXa%pYQ#x1^HZg+nM{{?i*juqx{E6a_1ah_@6b*|8Rn2@SAo7EaUerp5;x(@d`G zBYL_C`wKAo!g4rI*cvWs3HzAIpZC!d9yDC|$L?=Om7&%lA^)5a{j39_KhEs0w!tOe zdjj)J;^ZbKyLf}*0HUmdWdr2qWHt)SOB|PQMUJpPX>h7@BIye+O zLij>OV{kk)gxXbckJgkl``NuJ6iL_i*fHM|+vrikX%SA)bbQ6%e^Jgkh$yaHQ;P!S zZfzI_+e*{C$tk0#lE0}^&N;1rdwYXIiOYDXsr5MP!D|0DePh8o=o2%{8RQ%$9a6ZK zMvF+zaKevj1_cS4^lXH?F&F8MQRIyYrHVN)UcXLJmZY7Zo@1-1SksSLH~U{Ncs8cL zJ7z5ZYyE`iGFWKZa+V^D?gh*1mnAd^H4w}FSaae#FZ9OS{6Y)!^W)gP{OcXYZMlM4%o2H1@Sed zlW?xf`Dxp#e)}^h4@ikhiL_LeSfOd`Um4SFkcpKI+vQyWwNunqB~cad9SaNNZ9}O$vJPb9H>3O4LCXobEfW6ucAOrJ64{t%hq$H4@(NA=bKFsy#~eHud6& zZ;8iB0PeG_=sq4INnWGsr$Wov&@b%Rx(;=Z5N=Mhk2>~DfU+*IzEBS|mWjw7{Vk=k zL~9%{A9E(`S)Xm)`V#^Db+Z%l;MYC$bo8Yv{hRwk_fb5GVQ8e;aKP}-CAB|dzzDN|JSNV zayp*xqt#6Wbso+fYQS#1)Y8Fs9kOz>H@g&WOwge|^|1gm`BlvAL*Z$&PCO-jnw67q2$@l;O literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 58bcff9559..6e857cfd3c 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -204,6 +204,7 @@ pub mod tests { use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; + use crate::utilities::test_circuit::{Proof, read_test_case, test_proof_size, write_test_case}; const MERKLE_DEPTH: usize = 32; @@ -421,7 +422,42 @@ pub mod tests { } // Test that the proof size is as expected. - crate::utilities::lookup_range_check::tests::test_proof_size(k, circuit, params, vk) + test_proof_size(k, circuit, params, vk) + } + + #[test] + fn serialized_proof_test_case() { + use std::fs; + + let circuit = generate_circuit(); + // Setup phase: generate parameters, vk for the circuit. + let params:Params = Params::new(11); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let proof = Proof::create( + &vk, + ¶ms, + circuit, + ).unwrap(); + assert!(proof.verify(&vk, ¶ms).is_ok()); + + + let file = std::fs::File::create("src/sinsemilla/circuit_proof_test_case_merkle.bin")?; + write_test_case(file, &proof) + }; + create_proof().expect("should be able to write new proof"); + } + + // Parse the hardcoded proof test case. + let proof= { + let test_case_bytes = fs::read("src/sinsemilla/circuit_proof_test_case_merkle.bin").unwrap(); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + + assert_eq!(proof.as_ref().len(), 4160); + assert!(proof.verify(&vk, ¶ms).is_ok()); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/utilities.rs b/halo2_gadgets/src/utilities.rs index 739f4411de..515b02caaa 100644 --- a/halo2_gadgets/src/utilities.rs +++ b/halo2_gadgets/src/utilities.rs @@ -12,6 +12,7 @@ use std::ops::Range; pub mod cond_swap; pub mod decompose_running_sum; pub mod lookup_range_check; +pub mod test_circuit; /// A type that has a value at either keygen or proving time. pub trait FieldValue { diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 370e3cadf7..b2e1b956c5 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -454,41 +454,14 @@ pub(crate) mod tests { plonk, plonk::{Circuit, ConstraintSystem, Error}, }; - use pasta_curves::{pallas, vesta}; + use pasta_curves::{pallas}; - use halo2_proofs::plonk::{SingleVerifier, VerifyingKey}; use halo2_proofs::poly::commitment::Params; - use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite, Challenge255}; use pasta_curves::vesta::Affine; - use rand::rngs::OsRng; - use std::{convert::TryInto, marker::PhantomData}; - - pub(crate) fn test_proof_size( - k: u32, - circuit: C, - params: Params, - vk: VerifyingKey, - ) where - C: Circuit, - { - // Test that the proof size is as expected. - let circuit_cost = - halo2_proofs::dev::CircuitCost::::measure(k, &circuit); - let expected_proof_size = usize::from(circuit_cost.proof_size(1)); - - let pk = plonk::keygen_pk(¶ms, vk.clone(), &circuit).unwrap(); - let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]); - plonk::create_proof(¶ms, &pk, &[circuit], &[&[]], OsRng, &mut transcript).unwrap(); - let proof = transcript.finalize(); - - let strategy = SingleVerifier::new(¶ms); - let mut transcript: Blake2bRead<&[u8], vesta::Affine, Challenge255> = - Blake2bRead::init(&proof[..]); - let verify = plonk::verify_proof(¶ms, &vk, strategy, &[&[]], &mut transcript); - // Round-trip assertion: check the proof is valid and matches expected values. - assert!(verify.is_ok()); - assert_eq!(proof.len(), expected_proof_size); - } + use std::{convert::TryInto, fs, marker::PhantomData}; + use crate::utilities::test_circuit::{Proof, read_test_case, test_proof_size, write_test_case}; + + #[test] fn lookup_range_check() { #[derive(Clone, Copy)] @@ -598,6 +571,33 @@ pub(crate) mod tests { ); } + // serialized_proof_test_case + { + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let proof = Proof::create( + &vk, + ¶ms, + circuit, + ).unwrap(); + assert!(proof.verify(&vk, ¶ms).is_ok()); + + let file = std::fs::File::create("src/utilities/circuit_proof_test_case_lookup_range_check.bin")?; + write_test_case(file, &proof) + }; + create_proof().expect("should be able to write new proof"); + } + // Parse the hardcoded proof test case. + let proof= { + let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_lookup_range_check.bin").unwrap(); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + + // todo: check size + assert_eq!(proof.as_ref().len(), 4160); + assert!(proof.verify(&vk, ¶ms).is_ok()); + } + // Test that the proof size is as expected. test_proof_size(11, circuit, params, vk) } diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs new file mode 100644 index 0000000000..9e3108bb18 --- /dev/null +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -0,0 +1,95 @@ +use std::io::{Read, Write}; +use pasta_curves::{pallas, vesta}; +use pasta_curves::vesta::Affine; +use rand::rngs::OsRng; +use halo2_proofs::plonk; +use halo2_proofs::plonk::{Circuit, SingleVerifier, VerifyingKey}; +use halo2_proofs::poly::commitment::Params; +use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite}; + +/// A proof structure +#[derive(Clone, Debug)] +pub struct Proof(Vec); +impl AsRef<[u8]> for Proof { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl Proof { + /// Creates a proof for the given circuits and instances. + pub fn create( + vk: &VerifyingKey, + params: &Params, + circuit: C, + ) + -> Result + where + C: Circuit, + { + let pk = plonk::keygen_pk(¶ms, vk.clone(), &circuit).unwrap(); + + let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]); + plonk::create_proof( + ¶ms, + &pk, + &[circuit], + &[&[]], + OsRng, + &mut transcript, + )?; + let proof = transcript.finalize(); + + Ok(Proof(proof)) + } + + /// Verifies this proof with the instances. + pub fn verify( + &self, + vk: &VerifyingKey, + params: &Params, + ) -> Result<(), plonk::Error> { + + let strategy = SingleVerifier::new(¶ms); + let mut transcript = Blake2bRead::init(&self.0[..]); + plonk::verify_proof(¶ms, &vk, strategy, &[&[]], &mut transcript) + } + pub fn new(bytes: Vec) -> Self { + Proof(bytes) + } +} + +pub(crate) fn test_proof_size( + k: u32, + circuit: C, + params: Params, + vk: VerifyingKey, +) where + C: Circuit, +{ + // Test that the proof size is as expected. + let circuit_cost = + halo2_proofs::dev::CircuitCost::::measure(k, &circuit); + let expected_proof_size = usize::from(circuit_cost.proof_size(1)); + + + let proof = Proof::create(&vk,¶ms,circuit).unwrap(); + + assert!(proof.verify(&vk, ¶ms).is_ok()); + assert_eq!(proof.as_ref().len(), expected_proof_size); +} +pub fn write_test_case( + mut w: W, + proof: &Proof, +) -> std::io::Result<()> { + w.write_all(proof.as_ref())?; + Ok(()) +} + +pub fn read_test_case(mut r: R) -> std::io::Result { + let mut proof_bytes = vec![]; + r.read_to_end(&mut proof_bytes)?; + let proof = Proof::new(proof_bytes); + + Ok(proof) +} From a25a6adc27014e49831fe28f10022a296d66f5fb Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 6 May 2024 13:52:22 +0200 Subject: [PATCH 015/121] update --- halo2_gadgets/src/ecc.rs | 13 ++--- halo2_gadgets/src/sinsemilla.rs | 12 ++--- halo2_gadgets/src/sinsemilla/merkle.rs | 19 +++----- ...uit_proof_test_case_lookup_range_check.bin | Bin 0 -> 1888 bytes .../src/utilities/lookup_range_check.rs | 24 +++++---- halo2_gadgets/src/utilities/test_circuit.rs | 46 ++++++++---------- 6 files changed, 47 insertions(+), 67 deletions(-) create mode 100644 halo2_gadgets/src/utilities/circuit_proof_test_case_lookup_range_check.bin diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 66ec826e41..4325cc3e39 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -599,7 +599,7 @@ pub(crate) mod tests { FixedPoints, }; use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; - use crate::utilities::test_circuit::{Proof, read_test_case, test_proof_size, write_test_case}; + use crate::utilities::test_circuit::{read_test_case, test_proof_size, write_test_case, Proof}; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -938,16 +938,12 @@ pub(crate) mod tests { let circuit = MyCircuit { test_errors: false }; // Setup phase: generate parameters, vk for the circuit. - let params:Params = Params::new(11); + let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { - let proof = Proof::create( - &vk, - ¶ms, - circuit, - ).unwrap(); + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); let file = std::fs::File::create("src/circuit_proof_test_case_ecc.bin")?; @@ -957,12 +953,11 @@ pub(crate) mod tests { } // Parse the hardcoded proof test case. - let proof= { + let proof = { let test_case_bytes = fs::read("src/circuit_proof_test_case_ecc.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - // todo: check size assert_eq!(proof.as_ref().len(), 3872); assert!(proof.verify(&vk, ¶ms).is_ok()); } diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index ace786e1fd..0d585e42c2 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -489,10 +489,10 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; + use crate::utilities::test_circuit::{read_test_case, test_proof_size, write_test_case, Proof}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::convert::TryInto; - use crate::utilities::test_circuit::{Proof, read_test_case, test_proof_size, write_test_case}; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; @@ -792,16 +792,12 @@ pub(crate) mod tests { let circuit = MyCircuit {}; // Setup phase: generate parameters, vk for the circuit. - let params:Params = Params::new(11); + let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { - let proof = Proof::create( - &vk, - ¶ms, - circuit, - ).unwrap(); + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); let file = std::fs::File::create("src/circuit_proof_test_case_sinsemilla.bin")?; @@ -811,7 +807,7 @@ pub(crate) mod tests { } // Parse the hardcoded proof test case. - let proof= { + let proof = { let test_case_bytes = fs::read("src/circuit_proof_test_case_sinsemilla.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 6e857cfd3c..4d6a0f2517 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -200,11 +200,11 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; + use crate::utilities::test_circuit::{read_test_case, test_proof_size, write_test_case, Proof}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; - use crate::utilities::test_circuit::{Proof, read_test_case, test_proof_size, write_test_case}; const MERKLE_DEPTH: usize = 32; @@ -431,28 +431,25 @@ pub mod tests { let circuit = generate_circuit(); // Setup phase: generate parameters, vk for the circuit. - let params:Params = Params::new(11); + let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { - let proof = Proof::create( - &vk, - ¶ms, - circuit, - ).unwrap(); + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); - - let file = std::fs::File::create("src/sinsemilla/circuit_proof_test_case_merkle.bin")?; + let file = + std::fs::File::create("src/sinsemilla/circuit_proof_test_case_merkle.bin")?; write_test_case(file, &proof) }; create_proof().expect("should be able to write new proof"); } // Parse the hardcoded proof test case. - let proof= { - let test_case_bytes = fs::read("src/sinsemilla/circuit_proof_test_case_merkle.bin").unwrap(); + let proof = { + let test_case_bytes = + fs::read("src/sinsemilla/circuit_proof_test_case_merkle.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; diff --git a/halo2_gadgets/src/utilities/circuit_proof_test_case_lookup_range_check.bin b/halo2_gadgets/src/utilities/circuit_proof_test_case_lookup_range_check.bin new file mode 100644 index 0000000000000000000000000000000000000000..f3e6a81189e600346b32d64655193c7a8b72c077 GIT binary patch literal 1888 zcmajY=OY^k1AuX}u?aOATPRvY%$&3(sBtA%HEOgqYuBi8A!0PI*u=Qjp0PrtO6}-t z#-?aFwbDlI+M_7g&@L7M7>MSJkbu4MX;N0(G z4C*WJ_V!)`W-6{HY5m5QZ%6$XHSAdFD%g{EKXjiZzk=j$^Htr0Okbm1z~jHMEs?O; z3uXdizV)Fgef3SDoLqh)ny%}{goA2*p!GqcJjbtX$LnxdB=>9GFP(aG>2^uYj!P4W z&eOSl)dBCQDB6Obpk!Ae4mjhx-OR}DMIIS+NW8hz_9RGs!b4%%*?^VY_;axHrP=jX zORsaZ+S!>rAEQs32<$nH4gI3$Etp+(=jQTgnC(eAmEWyk3SInT#_KTr-(imMS>dre z-_9V+oQ}cpo@rTbEV+vm2KX5k^@&x`-cQ;y@@1<0hQHR*6Fi`_;UCo(5u#?iATdg< zjB3QLnJANo;8$bDEPp|L4RWdEM-}RBTry28aA;T6E3j6o7uS~V3v}h^uT)|9O*Y4w zh#xd=hvr;+A0>eu?nu3^=i9SWu11H_*eR?lkF4*{FvHgYQx z_YQzHsJjA$R>d?B%TZAYF|Z_ zrbEp|=H1}MN>r!ZG@c+u@V?|lU*FmJrJYE>5r>uf+&+OrMiBugq&Wemrl{^;`+K}! z=k^BDy^{+o8_~++@0k!8s<3oh!Vf#ALK|Mptw{t_OK?4_OPYvmg(z#z zb{+p{rcG>GOhB5%!vytO){?nE?NGgbSI+f!fyx-{EN3FYxZi0=E;{lY5JN5d>le`_ zFRe(Il^4}$qY`8me(6a4l}hbBWd<5xl?Zhd$S~SRhF_5f)9appyvAQ5zG|_4Ayg=f z2Lr8FuKr3(hZG?hZT(YVc8gy;+7)WmL`#_Z8gxA1vZ1uSCewJo#Yq})y~RC)G?{yH zWt`o*MCgConHp4%nI?=4wc&0{k}TB#5d8(GIP(J%*Ju#0^}G2L%e%&N%BwkvhRx)V zM0D=H+L8`pVSz!sG=%23*2Zj3J0SNz%XZ)vR zuIELg0bCCzof341(+Y*za>}|@_{HVx(mwg2V&#h^btFeH;ogr+2)eY-Li7IRRh$O zy!RKQMVcraHr84jz&B_LQwGILX^d6RT*V|p+!>r5Nrhs9cphpS< z`lGi@bhjDEO}Fp|%QHO@shln6ff{c)vp3mLks?;f@+t~?lT{w%Kw6MQ=?^=ZJkPrO zV;;4wb_M#52i-ux%7Gg{i zn4Y~+J;WNa&1f|nBf*w&S=03;1ouZEcyxE5FZt6}|3DNx7=H)n-q8r!si#sHntf7{ zAypWd5mcY8?cIX#w&5!sBcD`r)|Q((`j1#Pn1XYQ$h-6j)#BpnkcX@voX`2kTW!kt zay88}`673{r5Yn9+Aw0LRR^VE8dI|wjNbY~Gu|Uo1);(M2cYc%e?2$Cv`Lyl)7ho| z37=f0wAvtzN+RME7c2D&c~zr_p*_dF(gsmaYck+s8Z7h1->Ab$vwS@GYWRGXL{jX( zd1BDbks}QqCG9WW3sTBkiH#IvCHj+A^{sT~ox+*=YHn8(ie7Y|?HI$ZqKV)Jc(|j` oQy2?#m@J6xLrjmKUTR(WX%ECLzZp+Qm324~kUyg~@qcjs2ZeNn=l}o! literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index b2e1b956c5..782a7d234b 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -454,13 +454,12 @@ pub(crate) mod tests { plonk, plonk::{Circuit, ConstraintSystem, Error}, }; - use pasta_curves::{pallas}; + use pasta_curves::pallas; + use crate::utilities::test_circuit::{read_test_case, test_proof_size, write_test_case, Proof}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::{convert::TryInto, fs, marker::PhantomData}; - use crate::utilities::test_circuit::{Proof, read_test_case, test_proof_size, write_test_case}; - #[test] fn lookup_range_check() { @@ -575,26 +574,25 @@ pub(crate) mod tests { { if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { - let proof = Proof::create( - &vk, - ¶ms, - circuit, - ).unwrap(); + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); - let file = std::fs::File::create("src/utilities/circuit_proof_test_case_lookup_range_check.bin")?; + let file = std::fs::File::create( + "src/utilities/circuit_proof_test_case_lookup_range_check.bin", + )?; write_test_case(file, &proof) }; create_proof().expect("should be able to write new proof"); } // Parse the hardcoded proof test case. - let proof= { - let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_lookup_range_check.bin").unwrap(); + let proof = { + let test_case_bytes = + fs::read("src/utilities/circuit_proof_test_case_lookup_range_check.bin") + .unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - // todo: check size - assert_eq!(proof.as_ref().len(), 4160); + assert_eq!(proof.as_ref().len(), 1888); assert!(proof.verify(&vk, ¶ms).is_ok()); } diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index 9e3108bb18..5066e3f1f5 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -1,11 +1,13 @@ -use std::io::{Read, Write}; -use pasta_curves::{pallas, vesta}; -use pasta_curves::vesta::Affine; -use rand::rngs::OsRng; +//! functions used for circuit test + use halo2_proofs::plonk; use halo2_proofs::plonk::{Circuit, SingleVerifier, VerifyingKey}; use halo2_proofs::poly::commitment::Params; use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite}; +use pasta_curves::vesta::Affine; +use pasta_curves::{pallas, vesta}; +use rand::rngs::OsRng; +use std::io::{Read, Write}; /// A proof structure #[derive(Clone, Debug)] @@ -22,22 +24,14 @@ impl Proof { vk: &VerifyingKey, params: &Params, circuit: C, - ) - -> Result - where - C: Circuit, + ) -> Result + where + C: Circuit, { - let pk = plonk::keygen_pk(¶ms, vk.clone(), &circuit).unwrap(); + let pk = plonk::keygen_pk(params, vk.clone(), &circuit).unwrap(); let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]); - plonk::create_proof( - ¶ms, - &pk, - &[circuit], - &[&[]], - OsRng, - &mut transcript, - )?; + plonk::create_proof(params, &pk, &[circuit], &[&[]], OsRng, &mut transcript)?; let proof = transcript.finalize(); Ok(Proof(proof)) @@ -49,16 +43,17 @@ impl Proof { vk: &VerifyingKey, params: &Params, ) -> Result<(), plonk::Error> { - - let strategy = SingleVerifier::new(¶ms); + let strategy = SingleVerifier::new(params); let mut transcript = Blake2bRead::init(&self.0[..]); - plonk::verify_proof(¶ms, &vk, strategy, &[&[]], &mut transcript) + plonk::verify_proof(params, vk, strategy, &[&[]], &mut transcript) } + /// Constructs a new Proof value. pub fn new(bytes: Vec) -> Self { Proof(bytes) } } +#[allow(dead_code)] pub(crate) fn test_proof_size( k: u32, circuit: C, @@ -72,20 +67,19 @@ pub(crate) fn test_proof_size( halo2_proofs::dev::CircuitCost::::measure(k, &circuit); let expected_proof_size = usize::from(circuit_cost.proof_size(1)); - - let proof = Proof::create(&vk,¶ms,circuit).unwrap(); + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); assert_eq!(proof.as_ref().len(), expected_proof_size); } -pub fn write_test_case( - mut w: W, - proof: &Proof, -) -> std::io::Result<()> { + +/// write proof to a file +pub fn write_test_case(mut w: W, proof: &Proof) -> std::io::Result<()> { w.write_all(proof.as_ref())?; Ok(()) } +/// read proof from a file pub fn read_test_case(mut r: R) -> std::io::Result { let mut proof_bytes = vec![]; r.read_to_end(&mut proof_bytes)?; From 42f1b0ae535137f651262e9a894803d80ac86b1f Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 6 May 2024 22:59:19 +0200 Subject: [PATCH 016/121] update short lookup test --- halo2_gadgets/src/ecc.rs | 2 +- halo2_gadgets/src/sinsemilla.rs | 2 +- halo2_gadgets/src/sinsemilla/merkle.rs | 2 +- ...cuit_proof_test_case_short_range_check.bin | Bin 0 -> 5664 bytes .../src/utilities/lookup_range_check.rs | 141 +++++++++- halo2_gadgets/src/utilities/test_circuit.rs | 33 ++- ...ort_range_check => vk_short_range_check_0} | 0 .../src/utilities/vk_short_range_check_1 | 244 ++++++++++++++++++ .../src/utilities/vk_short_range_check_2 | 244 ++++++++++++++++++ 9 files changed, 653 insertions(+), 15 deletions(-) create mode 100644 halo2_gadgets/src/utilities/circuit_proof_test_case_short_range_check.bin rename halo2_gadgets/src/utilities/{vk_short_range_check => vk_short_range_check_0} (100%) create mode 100644 halo2_gadgets/src/utilities/vk_short_range_check_1 create mode 100644 halo2_gadgets/src/utilities/vk_short_range_check_2 diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 4325cc3e39..8cb9ce4d57 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -929,7 +929,7 @@ pub(crate) mod tests { include_str!("vk_ecc_chip").replace("\r\n", "\n") ); } - test_proof_size(k, circuit, params, vk) + test_proof_size(k, circuit, ¶ms, &vk) } #[test] diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 0d585e42c2..b9e2b6418e 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -783,7 +783,7 @@ pub(crate) mod tests { include_str!("vk_sinsemilla_chip").replace("\r\n", "\n") ); } - test_proof_size(11, circuit, params, vk) + test_proof_size(11, circuit, ¶ms, &vk) } #[test] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 4d6a0f2517..345877ec24 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -422,7 +422,7 @@ pub mod tests { } // Test that the proof size is as expected. - test_proof_size(k, circuit, params, vk) + test_proof_size(k, circuit, ¶ms, &vk) } #[test] diff --git a/halo2_gadgets/src/utilities/circuit_proof_test_case_short_range_check.bin b/halo2_gadgets/src/utilities/circuit_proof_test_case_short_range_check.bin new file mode 100644 index 0000000000000000000000000000000000000000..61d4e7caaba6043cb67921e1daa37134ef44273d GIT binary patch literal 5664 zcmajgg*zOM1AuWcb-FuFclVu+VcN!+9!^b7$8=419LJpQHr?IbX4-T&zu$lGegB5{ zc|LB9veqe0LWv=DPRAT0->+$X{WBIHoV^h1AV&l!e8%CRs^kr$6(oJ z{LxOjJh#fR=k>-7q*yEWBFd-6-7(fkVd4>8q=j?n0VO>$yyShJVbb`A)e^(Qr40W) zLX7vi!9h|g9>TU2RzqBszC5mk;*pl~9D<>I^y6>JZps%tzl?;gb~#Sp2no{aiF13x z`VVqIHj;ZY#y@WV=1)7{Z9SU~@EMrQ4zd_9^|k3c$s9xFwjwNxDSdq_?yXA^l4o({U?OL(`PkoSS-5W-?;f;T2L1MvSwc<}(K9K2cm|pLKK%q?T zwIUB*e~DjU91JUGTZw*3bliwEm!WhBcdmqgt)XgVgd?;qpc5ID#C+OAz0d9)+@q(4 ze3U9qx0*lOOOQ;CR1J}5k;?$#V(+oxT_qLV_Xr>Jiy$01bC=X|89e4a1~{C&*Gw3_ zZbYg^If)BDvXtS06y919Jyj5WCE&nujn9Pkd=~)w*S%a&Vo3?>ga%?B`*U+>Cr?X} z0Npa2o*fk}d<;yo^d@w!7}$SqoO7jV0qIM!1j7qsaD!@R)?N5+mk0|YITV}DXCF*n zSabG4ySTq)w7e#Zg)0;zT#dP~Iq%n9gx}G3$CyUiiTrEWG-Cl#IkB0Y5bpIv8s%6y z#Lv*FF^XJXiE9cD1+{Z)bEDbLNxW>+U?coTmUvD6cmE3SA*C$q|tx^pA?H1A22 z?`jf{gNfWp_KOUhbc>QqDOdMestPTc^aW5&*)heCCs_SIKh1Aqnu6`l3hr1wKHcCN zm~jZKg}zqTwz7urMjf?}8CnpMH&bel=KINP1jTa?21_lh37Wx}<-Dn>P-GCXQY23} zF-(dHI(1k`@1VBU^(XNJ2=dtoVG(0IQa=VbKt^&nzfJy7PTr@r|@bsT=N7KNUHe z2>)7L@8fC-Xc@`9O5UJTFB4hKJ8hp@8^%gR(uh3OEb$1bWu=*7Wf1MPj6S$zueftEFEl5Bb9AEB`qjN5HExIuxKt}fYT)pU+qp7U(c z(i!`-w|-TWxF&ewc!+lKMMkA~JbDr;{wa;6*gU4YWVT!D)M0wfHU82L2I0vp^rVOR z=#5){FWSFgDLe3xnb9*)B{5xHm~>W05TukzkcL_@4a>8g*#vMs+Pr@K`f8*tmNn4* zX=|}m)c;Kx>!bV`e#`x?Fx~hDI)$F?X$T6M2Cc zdG^1G0{k+B)~SVBEyp98kLewgSrvM7m%u5E0!+ehNlPt%#S%^L)%F;Pvyl#l^33TU z9_rXr48Eh|Wd z(88~A=eFjN#vg05K^;8e##0YN=~Rj=)+%)jAgKrr60|?=^bVx>n9VyAYJvW@qgIHX z$Gl?cQmO17=ZV2FTt2AD!L|yPS?XB##PAz6{(5#pnwnS)z;TDlgD{uO9l&8Nj@1S+gV$@B=x{Xg<5qnDoA+zv=wIQ7pL9qzG|FR~uht!V7+q4WP_I22%k+ zHn`d_-*OdJJ;g=@9WoHy<);PQbzX*RwXcH5vB;&;aaHRWaE)_WY!#t;8mT38v@ujSNjI(rx;+GlDQGO>Z`)U% zY!7pB5N{zhyVD8OCa`@F%~BN zOqY{@kLZ(b@75R8_DIxA{9VT=tocuwseEiPC_6Dpo?w?$HV#F7QlcLgM9-3X;-(N# z@3D)F`@@_uMGs?S(`vg!xHadJWEeM%EG0ShpANrIZhVzBh)bsBghLP$P9Avez{b@Fd)B2Na@ zk8})tLr++QTzB{!Tv}?{LEj25s~5>2m|A!W(PQJ#l7`%;b!J9xRqlJ%?ldC*q4K;d zgZPaP27a87ow8;-@}tUNdeAepzAV`MRBv|k$TV^BDrB=bE+A_G7hMS5*}KiM!i08@ zHFxGKs!IaXfD@1Ixn7Gzd*(O9#m(aN8c9|9M&B8T|26kl_pkk&kDG^r8gIySd>yu zi6hrzX11`b3QZBjH+*C|djrA_6!sEt5nu8KRv6KKxACJTqIZf6HdHjC!s(Q{TI&rU zsy7tQy=)@D;Xdl@>Bw(Ebb5H{O1P|;`Bb$MxDw7DI%~-YiEmeo$2NRo!}>RpXt$q8 zDb=5NCn+P?gfhQMU}Gx4>h~lavCRL*4*6(0R+p6bbFt>OOQEeX6&VJx)ZucKTjIWL zno^>m1#KPi4^DfA?xijx3H7dJVClo6{r3kIBnThD$H0^J+9a&x{U-#NH}5IsOpdHgD?qfIIOk{8#(Uh6ea^@MsbgAu zY=s>qU!fPD-(pp*nfQ${0&6J$EHDJ~qxP(O zmB{QfoA)XV!_+Z>L#ebFpHwORSx!I8%c_Kun$=>#I=G{qk+&v}QQ4@H*Wi4@v+xOr zq*{y_@?GzIkM#!I)w{aF=Z|;p>f=1QoxUM8o1NluffT1fEMz-I1rSWyX6---j3wHa z;yP@)rF^WhrcJ;{Zf;!2t_e@H@Fl5E9%ktHTJz~n4qFVo8U0QB$RZ)xDf*$^z#=)3 zlatLVzA_==_#_o{t)j@}4aVonF5RBWdV9U_g850v#sScJ<&v*u<7HJ&N3MaGS1?lk z1?6vOUWezNSZOU{L&p)NR1m^|E{KyKk0K{o62YbR)#1){;+VCsp7MvT8+-O_xLoqY zvyiu`d11kKo_fS7V=)FIWcMjg9=$|HupY*jI_9>Fkl;;@4)Rk%!>u zs%uV2=B>m1#tE8R739Skx7|+s0)iEU1*n%!qb^B=m$79PH%7LRMexcM2T zrV|{Rj55=Ddz8v3X5E&tMM&yN@E+?XNeW%SxIl7KKX=~qy`~+8HqtgD`S6I9?bOES zm7jG6Ody&!qJlroKT6)WA#03Yg@F+pVi~Jh13xs77FGbVP7btfHu)<%+*=nU%r|U% z$&PTrAKB1wbhxCj029?e)gk`W z^{Vi2Y-HpZ3;)C70KAY1?;!AxF|vE%Ohc?aa~kwzq-DEvIt{~@pBiZszkGn==|3vF zl0h@q6tSQIo|}bO=b)ITJ*Q&%ed9f{TB$>@`vDlRGGCUD*GlxOLdS=#^fMcHNH4Si zuM0K5@s+X!2iAA?N;JB0w-0=%RN?NKFXRqZa3I^JQ#!V57^*`R&?`u8$+Jzr7AFsr z98E{djw>E37*2!#+Q9hbSSr9=s+gxr#}T8+=u%Gak6fNC&7H#MLcu*^f@mH)eL&#U z4#w9UyvsX9GtahO4$qy$m-!cfCM_9i23&+u5xeAgnl*e^EJ=;rQD*;bklKR(`R@pd z9Y_F}oaJ#;mtyOGd}O>hGio2dGD=SZZb?ljbEgAhif*D9@z5u4cJJ;l1Cqo1w7t@P z*t1Nh-)GuqCyZh1*?1$}7J}9W{yifs<5x@IwgsE*bGO5hnalcM1QL7S$!ETAqjr zZ34klz}nICtCo=W&2imWUi)-UCI9y9jnEU4DisSWu)-->v%YL&VS(D{u!;h=PjFt1 z!mHapg+x@Y7(rXM$I;v&^Y;H2ojWNcS~RLlK1TF{+Gjm+xG(po1BwO^qF@+`pP8!5 z5i6#AiT}vgj*N`$_1*=`4co8ZF{L8R3PkU#aQ>IC zy*qS2pSftuL>-SNQ%z|)x>;)TXL&4A^=P(svTDm&-LZOe==5pLQtC8rWnVM;6iL@5 zw&qtSyosq1f#^V@!!2s-#A!F-k*)bf=e#p+HmbWlem}8c69wkZMdcwnK1u=XdL{Zq zO?|ur!OqE2jlyRPZNmyU7>uB6=f=|$lnG1`^*#w$VeILNh8`Tv-%I-XM6mx?6HE`WLxT0@$g%-irPyaeT0VxR)XGdgDxPPcNb4znF43mM zEa?Bbl8c?Q;ZxXMMW&<2Wrstqf(8-CW(mv6`f|{@j`yVPFb0;1lva0a>(?%BNc*Gr;I;O|Cokdq$y)!|)<+p&=A*J;1IAneaWnWg~ar= zh5P7|z)?BeM5BwBkVcv`muYT}`KQ^LF;kJy=)j@^PupI2;tv&UI;I_ppQlBq6{}^q z%W=TPM5YhIeVg$VQSVdG-v!LHx^w(04@A0mh4xS4BD#G9FH8w-q2Rlk4S&mPq<7K* z*Hp=8)^zrgpI(A={MpSYkk~j^pI}7i#*Y1w= z?n@#uvI)vM0{W6WrjL@D-zY)GH%KqqXLh~y4^_N|b=mrHlfLuvj${drZ8~Yxh&*Tl z?DG1LG0)Q6xLCl@^+w5K+pGl4n9TrNmV&gv-2*(hz_VI$57EtWS<2Kdd-PrJZaQmj zhk*1*P(@{FXNVldGM{nhocSGm4{tML@chwi$l$!~l(&#;R52W%4@oO|BlY z=4(e(vopsjkAOK2=d8VoV;gn$@;(;7aAUq|LWoIyTFh+8ZQOBj}h=_mRnC)Ap zIV=If=R)_K6cS!hkIfR%jvdXU@IWy{_A&~@g>&3re(aCYqYEqRqfR^NZx7dRSfa|B zi-N0>cP?(Lm^qWpNM7Q+{NBq9`KvGpD9ALQcikGuw-CG;|0e7atFR*+>eNi-UX}F- zI`|~_yv`|++_Nb~g8M2-ppaxck^}(j6=T zeQT_geHGu#syZSFo|3}VI}9_QV@48EYp_n?j8ZO(hju~JFVnE)S3U`hq8_$)@uye_)ANRuV@FmJxf<7p#RK|aK&>G$69lWU5m { element: Value, num_bits: usize, @@ -647,7 +648,23 @@ pub(crate) mod tests { } } + + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + } + else { + // Parse the hardcoded proof test case. + let proofs= { + let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin").unwrap(); + read_all_proofs(&test_case_bytes[..]).expect("proof must be valid") + }; + } + + // Setup phase: generate parameters + let params: Params = Params::new(11); + let mut proofs = Vec::new(); + // Edge case: zero bits + // case 0 { let circuit: MyCircuit = MyCircuit { element: Value::known(pallas::Base::ZERO), @@ -656,8 +673,7 @@ pub(crate) mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(11); + // generate vk let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); // Test that the pinned verification key (representing the circuit) @@ -666,15 +682,37 @@ pub(crate) mod tests { //panic!("{:#?}", vk.pinned()); assert_eq!( format!("{:#?}\n", vk.pinned()), - include_str!("vk_short_range_check").replace("\r\n", "\n") + include_str!("vk_short_range_check_0").replace("\r\n", "\n") ); } - // Test that the proof size is as expected. - test_proof_size(11, circuit, params, vk) + test_proof_size(11, circuit.clone(), ¶ms, &vk); + + // serialized_proof_test_case + { + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); + assert!(proof.verify(&vk, ¶ms).is_ok()); + proofs.push(proof.clone()); + } + else { + match proofs.get(0) { + Some(proof) => { + println!("proof={:?}", proof); + + assert_eq!(proof.as_ref().len(), 1888); + assert!(proof.verify(&vk, ¶ms).is_ok()); + } + None => println!("Index out of bounds"), + } + } + } + + } // Edge case: K bits + // case 1 { let circuit: MyCircuit = MyCircuit { element: Value::known(pallas::Base::from((1 << K) - 1)), @@ -682,9 +720,46 @@ pub(crate) mod tests { }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); + + // generate vk + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. Which indicates the layouters are the same. + { + //panic!("{:#?}", vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_short_range_check_1").replace("\r\n", "\n") + ); + } + // Test that the proof size is as expected. + test_proof_size(11, circuit.clone(), ¶ms, &vk); + + // serialized_proof_test_case + { + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); + assert!(proof.verify(&vk, ¶ms).is_ok()); + proofs.push(proof.clone()); + } + else { + match proofs.get(1) { + Some(proof) => { + println!("proof={:?}", proof); + + assert_eq!(proof.as_ref().len(), 1888); + assert!(proof.verify(&vk, ¶ms).is_ok()); + } + None => println!("Index out of bounds"), + } + } + } + } // Element within `num_bits` + // case 2 { let circuit: MyCircuit = MyCircuit { element: Value::known(pallas::Base::from((1 << 6) - 1)), @@ -692,6 +767,52 @@ pub(crate) mod tests { }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); + + // generate vk + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. Which indicates the layouters are the same. + { + //panic!("{:#?}", vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_short_range_check_2").replace("\r\n", "\n") + ); + } + // Test that the proof size is as expected. + test_proof_size(11, circuit.clone(), ¶ms, &vk); + + // serialized_proof_test_case + { + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); + assert!(proof.verify(&vk, ¶ms).is_ok()); + proofs.push(proof.clone()); + } + else { + match proofs.get(2) { + Some(proof) => { + println!("proof={:?}", proof); + + assert_eq!(proof.as_ref().len(), 1888); + assert!(proof.verify(&vk, ¶ms).is_ok()); + } + None => println!("Index out of bounds"), + } + } + } + } + + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + + let file = std::fs::File::create( + "src/utilities/circuit_proof_test_case_short_range_check.bin" + )?; + write_all_test_case(file, &proofs) + }; + create_proof().expect("should be able to write new proof"); } // Element larger than `num_bits` but within K bits @@ -711,6 +832,8 @@ pub(crate) mod tests { }, }]) ); + + } // Element larger than K bits @@ -739,6 +862,8 @@ pub(crate) mod tests { }, ]) ); + + } // Element which is not within `num_bits`, but which has a shifted value within @@ -767,6 +892,8 @@ pub(crate) mod tests { }, }]) ); + + } } } diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index 5066e3f1f5..f7618e3970 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -1,5 +1,6 @@ //! functions used for circuit test +use std::io; use halo2_proofs::plonk; use halo2_proofs::plonk::{Circuit, SingleVerifier, VerifyingKey}; use halo2_proofs::poly::commitment::Params; @@ -53,12 +54,12 @@ impl Proof { } } -#[allow(dead_code)] +/// test the proof size. pub(crate) fn test_proof_size( k: u32, circuit: C, - params: Params, - vk: VerifyingKey, + params: &Params, + vk: &VerifyingKey, ) where C: Circuit, { @@ -67,9 +68,9 @@ pub(crate) fn test_proof_size( halo2_proofs::dev::CircuitCost::::measure(k, &circuit); let expected_proof_size = usize::from(circuit_cost.proof_size(1)); - let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); + let proof = Proof::create(vk, params, circuit).unwrap(); - assert!(proof.verify(&vk, ¶ms).is_ok()); + assert!(proof.verify(vk, params).is_ok()); assert_eq!(proof.as_ref().len(), expected_proof_size); } @@ -87,3 +88,25 @@ pub fn read_test_case(mut r: R) -> std::io::Result { Ok(proof) } + +/// write multiple proofs to a file +pub(crate) fn write_all_test_case( + mut w: W, + proofs: &Vec, +) -> std::io::Result<()> { + for proof in proofs { + w.write_all(proof.as_ref())?; + } + Ok(()) +} + +/// read multiple proofs from a file +pub fn read_all_proofs(mut r: R) -> io::Result> { + let mut proofs = Vec::new(); + let mut buffer = vec![0u8; 1888]; + + while let Ok(()) = r.read_exact(&mut buffer) { + proofs.push(Proof::new(buffer.clone())); + } + Ok(proofs) +} \ No newline at end of file diff --git a/halo2_gadgets/src/utilities/vk_short_range_check b/halo2_gadgets/src/utilities/vk_short_range_check_0 similarity index 100% rename from halo2_gadgets/src/utilities/vk_short_range_check rename to halo2_gadgets/src/utilities/vk_short_range_check_0 diff --git a/halo2_gadgets/src/utilities/vk_short_range_check_1 b/halo2_gadgets/src/utilities/vk_short_range_check_1 new file mode 100644 index 0000000000..d17acb3106 --- /dev/null +++ b/halo2_gadgets/src/utilities/vk_short_range_check_1 @@ -0,0 +1,244 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 5, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 3, + gates: [ + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 1, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 1, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x369f0b3422178fecf6e9a4fc7224622da26e8b5c74fb9aca5864c9f72e30bd5c, 0x2d7892875c06c460c9c9f66449103e7b6ef2871fb0a4e39b9af90e938c8e291b), + (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x28d1c924953bc53f232465943d25fd085f85727ae4e2d26249207da1e59559e2, 0x184d19e00f109c4dacf8026c6e0fc4181178b32a236828047c46d9d61eab90fa), + ], + permutation: VerifyingKey { + commitments: [ + (0x3b7b93d7540327328791a14933d8f3345abd943eb35b67a8a4bd2eb72e2a707a, 0x26fff57a6fa3c01dd0d739fc56479303b4302d6baa6f1da06f4013419c40e10c), + (0x3fdf7a15a0d2378accc11f704f4ba4a487b542ace83c7f5a8551b569a3b9a380, 0x34253920878d15d6fe1b5198c31bdd670d32e81621e9fcd569d582e596ed0af5), + ], + }, +} diff --git a/halo2_gadgets/src/utilities/vk_short_range_check_2 b/halo2_gadgets/src/utilities/vk_short_range_check_2 new file mode 100644 index 0000000000..8187051b09 --- /dev/null +++ b/halo2_gadgets/src/utilities/vk_short_range_check_2 @@ -0,0 +1,244 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 5, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 3, + gates: [ + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 1, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 1, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x2ca6650c6fcad471c1c9d29e9115516064a1fe096af3b13821cf1fe7fee088eb, 0x18e61f68d5978b837a3e2295fe7ae7ca672268a519394f41aabd085aadc1221d), + (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x28d1c924953bc53f232465943d25fd085f85727ae4e2d26249207da1e59559e2, 0x184d19e00f109c4dacf8026c6e0fc4181178b32a236828047c46d9d61eab90fa), + ], + permutation: VerifyingKey { + commitments: [ + (0x3b7b93d7540327328791a14933d8f3345abd943eb35b67a8a4bd2eb72e2a707a, 0x26fff57a6fa3c01dd0d739fc56479303b4302d6baa6f1da06f4013419c40e10c), + (0x3fdf7a15a0d2378accc11f704f4ba4a487b542ace83c7f5a8551b569a3b9a380, 0x34253920878d15d6fe1b5198c31bdd670d32e81621e9fcd569d582e596ed0af5), + ], + }, +} From 2b89fae2e78ff1f47e4533e898fdfd903526f8e4 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 6 May 2024 23:03:39 +0200 Subject: [PATCH 017/121] cargo fmt --- .../src/utilities/lookup_range_check.rs | 36 +++++++------------ halo2_gadgets/src/utilities/test_circuit.rs | 9 ++--- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 29a3073d47..fb8d191389 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -456,7 +456,10 @@ pub(crate) mod tests { }; use pasta_curves::pallas; - use crate::utilities::test_circuit::{read_test_case, test_proof_size, write_test_case, Proof, read_all_proofs, write_all_test_case}; + use crate::utilities::test_circuit::{ + read_all_proofs, read_test_case, test_proof_size, write_all_test_case, write_test_case, + Proof, + }; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::{convert::TryInto, fs, marker::PhantomData}; @@ -648,13 +651,13 @@ pub(crate) mod tests { } } - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - } - else { + } else { // Parse the hardcoded proof test case. - let proofs= { - let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin").unwrap(); + let proofs = { + let test_case_bytes = + fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin") + .unwrap(); read_all_proofs(&test_case_bytes[..]).expect("proof must be valid") }; } @@ -694,8 +697,7 @@ pub(crate) mod tests { let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); proofs.push(proof.clone()); - } - else { + } else { match proofs.get(0) { Some(proof) => { println!("proof={:?}", proof); @@ -707,8 +709,6 @@ pub(crate) mod tests { } } } - - } // Edge case: K bits @@ -742,8 +742,7 @@ pub(crate) mod tests { let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); proofs.push(proof.clone()); - } - else { + } else { match proofs.get(1) { Some(proof) => { println!("proof={:?}", proof); @@ -755,7 +754,6 @@ pub(crate) mod tests { } } } - } // Element within `num_bits` @@ -789,8 +787,7 @@ pub(crate) mod tests { let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); proofs.push(proof.clone()); - } - else { + } else { match proofs.get(2) { Some(proof) => { println!("proof={:?}", proof); @@ -806,9 +803,8 @@ pub(crate) mod tests { if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { - let file = std::fs::File::create( - "src/utilities/circuit_proof_test_case_short_range_check.bin" + "src/utilities/circuit_proof_test_case_short_range_check.bin", )?; write_all_test_case(file, &proofs) }; @@ -832,8 +828,6 @@ pub(crate) mod tests { }, }]) ); - - } // Element larger than K bits @@ -862,8 +856,6 @@ pub(crate) mod tests { }, ]) ); - - } // Element which is not within `num_bits`, but which has a shifted value within @@ -892,8 +884,6 @@ pub(crate) mod tests { }, }]) ); - - } } } diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index f7618e3970..c8c64079f9 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -1,6 +1,5 @@ //! functions used for circuit test -use std::io; use halo2_proofs::plonk; use halo2_proofs::plonk::{Circuit, SingleVerifier, VerifyingKey}; use halo2_proofs::poly::commitment::Params; @@ -8,6 +7,7 @@ use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite}; use pasta_curves::vesta::Affine; use pasta_curves::{pallas, vesta}; use rand::rngs::OsRng; +use std::io; use std::io::{Read, Write}; /// A proof structure @@ -90,10 +90,7 @@ pub fn read_test_case(mut r: R) -> std::io::Result { } /// write multiple proofs to a file -pub(crate) fn write_all_test_case( - mut w: W, - proofs: &Vec, -) -> std::io::Result<()> { +pub(crate) fn write_all_test_case(mut w: W, proofs: &Vec) -> std::io::Result<()> { for proof in proofs { w.write_all(proof.as_ref())?; } @@ -109,4 +106,4 @@ pub fn read_all_proofs(mut r: R) -> io::Result> { proofs.push(Proof::new(buffer.clone())); } Ok(proofs) -} \ No newline at end of file +} From 8552c97859d1b67dac76e85b089d115e5dad2f8f Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 6 May 2024 23:22:05 +0200 Subject: [PATCH 018/121] fix Clippy error --- .../src/utilities/lookup_range_check.rs | 76 ++++++------------- halo2_gadgets/src/utilities/test_circuit.rs | 2 + 2 files changed, 25 insertions(+), 53 deletions(-) diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index fb8d191389..525d953dcd 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -651,20 +651,14 @@ pub(crate) mod tests { } } - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - } else { - // Parse the hardcoded proof test case. - let proofs = { - let test_case_bytes = - fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin") - .unwrap(); - read_all_proofs(&test_case_bytes[..]).expect("proof must be valid") - }; - } + let proofs = { + let test_case_bytes = + fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin").unwrap(); + read_all_proofs(&test_case_bytes[..]).expect("proof must be valid") + }; // Setup phase: generate parameters let params: Params = Params::new(11); - let mut proofs = Vec::new(); // Edge case: zero bits // case 0 @@ -689,24 +683,16 @@ pub(crate) mod tests { ); } // Test that the proof size is as expected. - test_proof_size(11, circuit.clone(), ¶ms, &vk); + test_proof_size(11, circuit, ¶ms, &vk); // serialized_proof_test_case { - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); - assert!(proof.verify(&vk, ¶ms).is_ok()); - proofs.push(proof.clone()); - } else { - match proofs.get(0) { - Some(proof) => { - println!("proof={:?}", proof); - - assert_eq!(proof.as_ref().len(), 1888); - assert!(proof.verify(&vk, ¶ms).is_ok()); - } - None => println!("Index out of bounds"), + match proofs.get(0) { + Some(proof) => { + assert_eq!(proof.as_ref().len(), 1888); + assert!(proof.verify(&vk, ¶ms).is_ok()); } + None => println!("Index out of bounds"), } } } @@ -734,24 +720,16 @@ pub(crate) mod tests { ); } // Test that the proof size is as expected. - test_proof_size(11, circuit.clone(), ¶ms, &vk); + test_proof_size(11, circuit, ¶ms, &vk); // serialized_proof_test_case { - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); - assert!(proof.verify(&vk, ¶ms).is_ok()); - proofs.push(proof.clone()); - } else { - match proofs.get(1) { - Some(proof) => { - println!("proof={:?}", proof); - - assert_eq!(proof.as_ref().len(), 1888); - assert!(proof.verify(&vk, ¶ms).is_ok()); - } - None => println!("Index out of bounds"), + match proofs.get(1) { + Some(proof) => { + assert_eq!(proof.as_ref().len(), 1888); + assert!(proof.verify(&vk, ¶ms).is_ok()); } + None => println!("Index out of bounds"), } } } @@ -779,24 +757,16 @@ pub(crate) mod tests { ); } // Test that the proof size is as expected. - test_proof_size(11, circuit.clone(), ¶ms, &vk); + test_proof_size(11, circuit, ¶ms, &vk); // serialized_proof_test_case { - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); - assert!(proof.verify(&vk, ¶ms).is_ok()); - proofs.push(proof.clone()); - } else { - match proofs.get(2) { - Some(proof) => { - println!("proof={:?}", proof); - - assert_eq!(proof.as_ref().len(), 1888); - assert!(proof.verify(&vk, ¶ms).is_ok()); - } - None => println!("Index out of bounds"), + match proofs.get(2) { + Some(proof) => { + assert_eq!(proof.as_ref().len(), 1888); + assert!(proof.verify(&vk, ¶ms).is_ok()); } + None => println!("Index out of bounds"), } } } diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index c8c64079f9..51ea0e0a27 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -55,6 +55,7 @@ impl Proof { } /// test the proof size. +#[allow(dead_code)] pub(crate) fn test_proof_size( k: u32, circuit: C, @@ -90,6 +91,7 @@ pub fn read_test_case(mut r: R) -> std::io::Result { } /// write multiple proofs to a file +#[allow(dead_code)] pub(crate) fn write_all_test_case(mut w: W, proofs: &Vec) -> std::io::Result<()> { for proof in proofs { w.write_all(proof.as_ref())?; From f35cbe940d60466c22eff253505168c7344b6900 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 7 May 2024 15:01:20 +0200 Subject: [PATCH 019/121] clean up code --- halo2_gadgets/src/ecc_opt.rs | 123 +----------------- halo2_gadgets/src/sinsemilla.rs | 47 +++---- halo2_gadgets/src/sinsemilla_opt.rs | 16 +-- .../src/utilities/lookup_range_check.rs | 2 +- halo2_gadgets/src/utilities/test_circuit.rs | 7 +- 5 files changed, 33 insertions(+), 162 deletions(-) diff --git a/halo2_gadgets/src/ecc_opt.rs b/halo2_gadgets/src/ecc_opt.rs index b7a7dca5a4..4275d47f8a 100644 --- a/halo2_gadgets/src/ecc_opt.rs +++ b/halo2_gadgets/src/ecc_opt.rs @@ -61,7 +61,6 @@ impl + Clone + Debug + Eq> } #[cfg(test)] pub(crate) mod tests { - use ff::PrimeField; use group::{prime::PrimeCurveAffine, Curve, Group}; use halo2_proofs::{ @@ -69,132 +68,12 @@ pub(crate) mod tests { dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::ecc::{ - chip::{ - find_zs_and_us, BaseFieldElem, EccChip, EccConfig, FixedPoint, FullScalar, ShortScalar, - H, NUM_WINDOWS, NUM_WINDOWS_SHORT, - }, - FixedPoints, - }; + use crate::ecc::chip::{EccChip, EccConfig}; use crate::utilities::lookup_range_check::LookupRangeCheck; use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; - #[derive(Debug, Eq, PartialEq, Clone)] - pub(crate) struct TestFixedBases; - #[derive(Debug, Eq, PartialEq, Clone)] - pub(crate) struct FullWidth(pallas::Affine, &'static [(u64, [pallas::Base; H])]); - #[derive(Debug, Eq, PartialEq, Clone)] - pub(crate) struct BaseField; - #[derive(Debug, Eq, PartialEq, Clone)] - pub(crate) struct Short; - - lazy_static! { - static ref BASE: pallas::Affine = pallas::Point::generator().to_affine(); - static ref ZS_AND_US: Vec<(u64, [pallas::Base; H])> = - find_zs_and_us(*BASE, NUM_WINDOWS).unwrap(); - static ref ZS_AND_US_SHORT: Vec<(u64, [pallas::Base; H])> = - find_zs_and_us(*BASE, NUM_WINDOWS_SHORT).unwrap(); - } - - impl FixedPoint for FullWidth { - type FixedScalarKind = FullScalar; - - fn generator(&self) -> pallas::Affine { - self.0 - } - - fn u(&self) -> Vec<[[u8; 32]; H]> { - self.1 - .iter() - .map(|(_, us)| { - [ - us[0].to_repr(), - us[1].to_repr(), - us[2].to_repr(), - us[3].to_repr(), - us[4].to_repr(), - us[5].to_repr(), - us[6].to_repr(), - us[7].to_repr(), - ] - }) - .collect() - } - - fn z(&self) -> Vec { - self.1.iter().map(|(z, _)| *z).collect() - } - } - - impl FixedPoint for BaseField { - type FixedScalarKind = BaseFieldElem; - - fn generator(&self) -> pallas::Affine { - *BASE - } - - fn u(&self) -> Vec<[[u8; 32]; H]> { - ZS_AND_US - .iter() - .map(|(_, us)| { - [ - us[0].to_repr(), - us[1].to_repr(), - us[2].to_repr(), - us[3].to_repr(), - us[4].to_repr(), - us[5].to_repr(), - us[6].to_repr(), - us[7].to_repr(), - ] - }) - .collect() - } - - fn z(&self) -> Vec { - ZS_AND_US.iter().map(|(z, _)| *z).collect() - } - } - - impl FixedPoint for Short { - type FixedScalarKind = ShortScalar; - - fn generator(&self) -> pallas::Affine { - *BASE - } - - fn u(&self) -> Vec<[[u8; 32]; H]> { - ZS_AND_US_SHORT - .iter() - .map(|(_, us)| { - [ - us[0].to_repr(), - us[1].to_repr(), - us[2].to_repr(), - us[3].to_repr(), - us[4].to_repr(), - us[5].to_repr(), - us[6].to_repr(), - us[7].to_repr(), - ] - }) - .collect() - } - - fn z(&self) -> Vec { - ZS_AND_US_SHORT.iter().map(|(z, _)| *z).collect() - } - } - - impl FixedPoints for TestFixedBases { - type FullScalar = FullWidth; - type ShortScalar = Short; - type Base = BaseField; - } - struct MyCircuit { test_errors: bool, } diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index b9e2b6418e..d5b0dab5e2 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -276,12 +276,12 @@ pub struct HashDomain< > where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< - C, - NonIdentityPoint = >::NonIdentityPoint, - FixedPoints = >::FixedPoints, - > + Clone - + Debug - + Eq, + C, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, { pub(crate) sinsemilla_chip: SinsemillaChip, pub(crate) ecc_chip: EccChip, @@ -289,10 +289,10 @@ pub struct HashDomain< } impl - HashDomain -where - SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, - EccChip: EccInstructions< +HashDomain + where + SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, + EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, @@ -376,22 +376,22 @@ pub struct CommitDomain< > where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< - C, - NonIdentityPoint = >::NonIdentityPoint, - FixedPoints = >::FixedPoints, - > + Clone - + Debug - + Eq, + C, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, { pub(crate) M: HashDomain, pub(crate) R: ecc::FixedPoint, } impl - CommitDomain -where - SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, - EccChip: EccInstructions< +CommitDomain + where + SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, + EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, @@ -403,7 +403,6 @@ where pub fn new( sinsemilla_chip: SinsemillaChip, ecc_chip: EccChip, - // TODO: Instead of using SinsemilllaChip::CommitDomains, just use something that implements a CommitDomains trait domain: &SinsemillaChip::CommitDomains, ) -> Self { CommitDomain { @@ -429,12 +428,6 @@ where Error, > { assert_eq!(self.M.sinsemilla_chip, message.chip); - - // FIXME: consider returning ZSA version of the following lines. - // It's not a breaking change because `blinding_factor` simply wraps `R.mul` - // and `hash` simply wraps `M.hash_to_point` - are those wrapper really needed? - //let blind = self.blinding_factor(layouter.namespace(|| "[r] R"), r)?; - //let (p, zs) = self.hash(layouter.namespace(|| "M"), message)?; let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; let (p, zs) = self.M.hash_to_point(layouter.namespace(|| "M"), message)?; let commitment = p.add(layouter.namespace(|| "M + [r] R"), &blind)?; diff --git a/halo2_gadgets/src/sinsemilla_opt.rs b/halo2_gadgets/src/sinsemilla_opt.rs index 79e788be06..30d1d2c83c 100644 --- a/halo2_gadgets/src/sinsemilla_opt.rs +++ b/halo2_gadgets/src/sinsemilla_opt.rs @@ -41,10 +41,10 @@ pub trait SinsemillaInstructionsOptimized - HashDomain -where - SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, - EccChip: EccInstructions< +HashDomain + where + SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, + EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, @@ -70,10 +70,10 @@ where } impl - CommitDomain -where - SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, - EccChip: EccInstructions< +CommitDomain + where + SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, + EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 525d953dcd..73e14bec06 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -654,7 +654,7 @@ pub(crate) mod tests { let proofs = { let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin").unwrap(); - read_all_proofs(&test_case_bytes[..]).expect("proof must be valid") + read_all_proofs(&test_case_bytes[..], 1888).expect("proof must be valid") }; // Setup phase: generate parameters diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index 51ea0e0a27..c42bcf0c63 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -54,7 +54,7 @@ impl Proof { } } -/// test the proof size. +/// Test that the proof size is as expected. #[allow(dead_code)] pub(crate) fn test_proof_size( k: u32, @@ -64,7 +64,6 @@ pub(crate) fn test_proof_size( ) where C: Circuit, { - // Test that the proof size is as expected. let circuit_cost = halo2_proofs::dev::CircuitCost::::measure(k, &circuit); let expected_proof_size = usize::from(circuit_cost.proof_size(1)); @@ -100,9 +99,9 @@ pub(crate) fn write_all_test_case(mut w: W, proofs: &Vec) -> st } /// read multiple proofs from a file -pub fn read_all_proofs(mut r: R) -> io::Result> { +pub fn read_all_proofs(mut r: R, proof_size: usize) -> io::Result> { let mut proofs = Vec::new(); - let mut buffer = vec![0u8; 1888]; + let mut buffer = vec![0u8; proof_size]; while let Ok(()) = r.read_exact(&mut buffer) { proofs.push(Proof::new(buffer.clone())); From f65d5a330bac57efb47cafec4bfb1a4392edf463 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Fri, 10 May 2024 14:56:33 +0200 Subject: [PATCH 020/121] add initial files --- halo2_gadgets/src/ecc_opt.rs | 289 --------- halo2_gadgets/src/ecc_opt/chip.rs | 61 -- halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs | 1 - .../src/ecc_opt/chip/mul_fixed/short.rs | 597 ------------------ .../src/ecc_opt/chip/witness_point.rs | 50 -- halo2_gadgets/src/lib.rs | 3 - halo2_gadgets/src/sinsemilla.rs | 1 + halo2_gadgets/src/sinsemilla/merkle/chip.rs | 2 + halo2_gadgets/src/sinsemilla/primitives.rs | 2 - halo2_gadgets/src/sinsemilla_opt.rs | 464 -------------- halo2_gadgets/src/sinsemilla_opt/chip.rs | 219 ------- .../sinsemilla_opt/chip/generator_table.rs | 111 ---- .../src/sinsemilla_opt/chip/hash_to_point.rs | 181 ------ halo2_gadgets/src/sinsemilla_opt/merkle.rs | 246 -------- .../src/sinsemilla_opt/merkle/chip.rs | 209 ------ .../src/sinsemilla_opt/primitives.rs | 74 --- halo2_gadgets/src/utilities_opt.rs | 4 - halo2_gadgets/src/utilities_opt/cond_swap.rs | 352 ----------- .../src/utilities_opt/lookup_range_check.rs | 566 ----------------- 19 files changed, 3 insertions(+), 3429 deletions(-) delete mode 100644 halo2_gadgets/src/ecc_opt.rs delete mode 100644 halo2_gadgets/src/ecc_opt/chip.rs delete mode 100644 halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs delete mode 100644 halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs delete mode 100644 halo2_gadgets/src/ecc_opt/chip/witness_point.rs delete mode 100644 halo2_gadgets/src/sinsemilla_opt.rs delete mode 100644 halo2_gadgets/src/sinsemilla_opt/chip.rs delete mode 100644 halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs delete mode 100644 halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs delete mode 100644 halo2_gadgets/src/sinsemilla_opt/merkle.rs delete mode 100644 halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs delete mode 100644 halo2_gadgets/src/sinsemilla_opt/primitives.rs delete mode 100644 halo2_gadgets/src/utilities_opt.rs delete mode 100644 halo2_gadgets/src/utilities_opt/cond_swap.rs delete mode 100644 halo2_gadgets/src/utilities_opt/lookup_range_check.rs diff --git a/halo2_gadgets/src/ecc_opt.rs b/halo2_gadgets/src/ecc_opt.rs deleted file mode 100644 index 4275d47f8a..0000000000 --- a/halo2_gadgets/src/ecc_opt.rs +++ /dev/null @@ -1,289 +0,0 @@ -//! Elliptic curve operations. - -use std::fmt::Debug; - -use halo2_proofs::{ - arithmetic::CurveAffine, - circuit::{AssignedCell, Layouter}, - plonk::Error, -}; - -use crate::ecc::{EccInstructions, Point}; - -pub(crate) mod chip; - -/// The set of circuit instructions required to use the ECC gadgets. -pub trait EccInstructionsOptimized: EccInstructions { - /// Witnesses the given constant point as a private input to the circuit. - /// This allows the point to be the identity, mapped to (0, 0) in - /// affine coordinates. - fn witness_point_from_constant( - &self, - layouter: &mut impl Layouter, - value: C, - ) -> Result; - - /// Performs variable-base sign-scalar multiplication, returning `[sign] point` - /// `sign` must be in {-1, 1}. - fn mul_sign( - &self, - layouter: &mut impl Layouter, - sign: &AssignedCell, - point: &Self::Point, - ) -> Result; -} - -impl + Clone + Debug + Eq> Point { - /// Constructs a new point with the given fixed value. - pub fn new_from_constant( - chip: EccChip, - mut layouter: impl Layouter, - value: C, - ) -> Result { - let point = chip.witness_point_from_constant(&mut layouter, value); - point.map(|inner| Point { chip, inner }) - } - - /// Returns `[sign] self`. - /// `sign` must be in {-1, 1}. - pub fn mul_sign( - &self, - mut layouter: impl Layouter, - sign: &AssignedCell, - ) -> Result, Error> { - self.chip - .mul_sign(&mut layouter, sign, &self.inner) - .map(|point| Point { - chip: self.chip.clone(), - inner: point, - }) - } -} -#[cfg(test)] -pub(crate) mod tests { - use group::{prime::PrimeCurveAffine, Curve, Group}; - - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use pasta_curves::pallas; - - use crate::ecc::chip::{EccChip, EccConfig}; - use crate::utilities::lookup_range_check::LookupRangeCheck; - use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; - - struct MyCircuit { - test_errors: bool, - } - - #[allow(non_snake_case)] - impl Circuit for MyCircuit { - type Config = EccConfig< - crate::ecc::tests::TestFixedBases, - LookupRangeCheckConfigOptimized, - >; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - MyCircuit { test_errors: false } - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); - EccChip::< - crate::ecc::tests::TestFixedBases, - LookupRangeCheckConfigOptimized, - >::configure(meta, advices, lagrange_coeffs, range_check) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let chip = EccChip::construct(config.clone()); - - // Load 10-bit lookup table. In the Action circuit, this will be - // provided by the Sinsemilla chip. - config.lookup_config.load(&mut layouter)?; - - // Generate a random non-identity point P - let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P - let p = crate::ecc::NonIdentityPoint::new( - chip.clone(), - layouter.namespace(|| "P"), - Value::known(p_val), - )?; - let p_neg = -p_val; - let p_neg = crate::ecc::NonIdentityPoint::new( - chip.clone(), - layouter.namespace(|| "-P"), - Value::known(p_neg), - )?; - - // Generate a random non-identity point Q - let q_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // Q - let q = crate::ecc::NonIdentityPoint::new( - chip.clone(), - layouter.namespace(|| "Q"), - Value::known(q_val), - )?; - - // Make sure P and Q are not the same point. - assert_ne!(p_val, q_val); - - // Test that we can witness the identity as a point, but not as a non-identity point. - { - let _ = super::Point::new( - chip.clone(), - layouter.namespace(|| "identity"), - Value::known(pallas::Affine::identity()), - )?; - - crate::ecc::NonIdentityPoint::new( - chip.clone(), - layouter.namespace(|| "identity"), - Value::known(pallas::Affine::identity()), - ) - .expect_err("Trying to witness the identity should return an error"); - } - - // Test witness non-identity point - { - crate::ecc::chip::witness_point::tests::test_witness_non_id( - chip.clone(), - layouter.namespace(|| "witness non-identity point"), - ) - } - - // Test complete addition - { - crate::ecc::chip::add::tests::test_add( - chip.clone(), - layouter.namespace(|| "complete addition"), - p_val, - &p, - q_val, - &q, - &p_neg, - )?; - } - - // Test incomplete addition - { - crate::ecc::chip::add_incomplete::tests::test_add_incomplete( - chip.clone(), - layouter.namespace(|| "incomplete addition"), - p_val, - &p, - q_val, - &q, - &p_neg, - self.test_errors, - )?; - } - - // Test variable-base scalar multiplication - { - crate::ecc::chip::mul::tests::test_mul( - chip.clone(), - layouter.namespace(|| "variable-base scalar mul"), - &p, - p_val, - )?; - } - - // Test variable-base sign-scalar multiplication - { - super::chip::mul_fixed::short::tests::test_mul_sign( - chip.clone(), - layouter.namespace(|| "variable-base sign-scalar mul"), - )?; - } - - // Test full-width fixed-base scalar multiplication - { - crate::ecc::chip::mul_fixed::full_width::tests::test_mul_fixed( - chip.clone(), - layouter.namespace(|| "full-width fixed-base scalar mul"), - )?; - } - - // Test signed short fixed-base scalar multiplication - { - crate::ecc::chip::mul_fixed::short::tests::test_mul_fixed_short( - chip.clone(), - layouter.namespace(|| "signed short fixed-base scalar mul"), - )?; - } - - // Test fixed-base scalar multiplication with a base field element - { - crate::ecc::chip::mul_fixed::base_field_elem::tests::test_mul_fixed_base_field( - chip, - layouter.namespace(|| "fixed-base scalar mul with base field element"), - )?; - } - - Ok(()) - } - } - - #[test] - fn ecc_chip() { - let k = 13; - let circuit = MyCircuit { test_errors: true }; - let prover = MockProver::run(k, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())) - } - - #[cfg(feature = "test-dev-graph")] - #[test] - fn print_ecc_chip() { - use plotters::prelude::*; - - let root = BitMapBackend::new("ecc-chip-layout.png", (1024, 7680)).into_drawing_area(); - root.fill(&WHITE).unwrap(); - let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - - let circuit = MyCircuit { test_errors: false }; - halo2_proofs::dev::CircuitLayout::default() - .render(13, &circuit, &root) - .unwrap(); - } -} diff --git a/halo2_gadgets/src/ecc_opt/chip.rs b/halo2_gadgets/src/ecc_opt/chip.rs deleted file mode 100644 index c2c70bc17f..0000000000 --- a/halo2_gadgets/src/ecc_opt/chip.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Chip implementations for the ECC gadgets. - -use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter}, - plonk::Error, -}; -use pasta_curves::pallas; - -use crate::{ - ecc::{ - chip::{BaseFieldElem, EccChip, FixedPoint, FullScalar, ShortScalar}, - FixedPoints, - }, - utilities::lookup_range_check::DefaultLookupRangeCheck, -}; - -use super::EccInstructionsOptimized; - -pub(crate) mod mul_fixed; -pub(super) mod witness_point; - -impl, Lookup: DefaultLookupRangeCheck> - EccInstructionsOptimized for EccChip -where - >::Base: - FixedPoint, - >::FullScalar: - FixedPoint, - >::ShortScalar: - FixedPoint, -{ - fn witness_point_from_constant( - &self, - layouter: &mut impl Layouter, - value: pallas::Affine, - ) -> Result { - let config = self.config().witness_point; - layouter.assign_region( - || "witness point (constant)", - |mut region| config.constant_point(value, 0, &mut region), - ) - } - - /// Performs variable-base sign-scalar multiplication, returning `[sign] point` - /// `sign` must be in {-1, 1}. - fn mul_sign( - &self, - layouter: &mut impl Layouter, - sign: &AssignedCell, - point: &Self::Point, - ) -> Result { - // Multiply point by sign, using the same gate as mul_fixed::short. - // This also constrains sign to be in {-1, 1}. - let config_short = self.config().mul_fixed_short.clone(); - config_short.assign_scalar_sign( - layouter.namespace(|| "variable-base sign-scalar mul"), - sign, - point, - ) - } -} diff --git a/halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs b/halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs deleted file mode 100644 index d1dea74e22..0000000000 --- a/halo2_gadgets/src/ecc_opt/chip/mul_fixed.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod short; diff --git a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs deleted file mode 100644 index 830eec83b2..0000000000 --- a/halo2_gadgets/src/ecc_opt/chip/mul_fixed/short.rs +++ /dev/null @@ -1,597 +0,0 @@ -use crate::ecc::chip::EccPoint; - -use super::super::FixedPoints; - -use halo2_proofs::{ - circuit::{AssignedCell, Layouter}, - plonk::Error, -}; -use pasta_curves::pallas; - -use crate::ecc::chip::mul_fixed::short::Config; - -impl> Config { - /// Multiply the point by sign, using the q_mul_fixed_short gate. - /// Constraints `sign` in {-1, 1} - pub fn assign_scalar_sign( - &self, - mut layouter: impl Layouter, - sign: &AssignedCell, - point: &EccPoint, - ) -> Result { - let signed_point = layouter.assign_region( - || "Signed point", - |mut region| { - let offset = 0; - - // Enable mul_fixed_short selector to check the sign logic. - self.q_mul_fixed_short.enable(&mut region, offset)?; - - // Set "last window" to 0 (this field is irrelevant here). - region.assign_advice_from_constant( - || "u=0", - self.super_config.u, - offset, - pallas::Base::zero(), - )?; - - // Copy sign to `window` column - sign.copy_advice(|| "sign", &mut region, self.super_config.window, offset)?; - - // Assign the input y-coordinate. - point.y.copy_advice( - || "unsigned y", - &mut region, - self.super_config.add_config.y_qr, - offset, - )?; - - // Conditionally negate y-coordinate according to the value of sign - let signed_y_val = sign.value().and_then(|sign| { - if sign == &-pallas::Base::one() { - -point.y.value() - } else { - point.y.value().cloned() - } - }); - - // Assign the output signed y-coordinate. - let signed_y = region.assign_advice( - || "signed y", - self.super_config.add_config.y_p, - offset, - || signed_y_val, - )?; - - Ok(EccPoint { - x: point.x.clone(), - y: signed_y, - }) - }, - )?; - - Ok(signed_point) - } -} - -#[cfg(test)] -pub mod tests { - use ff::PrimeField; - use group::{Curve, Group}; - use halo2_proofs::{ - arithmetic::CurveAffine, - circuit::{AssignedCell, Chip, Layouter, Value}, - plonk::{Any, Error}, - }; - use pasta_curves::pallas; - - use crate::ecc::tests::Short; - use crate::ecc::ScalarFixedShort; - use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; - use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; - use crate::{ - ecc::{chip::EccChip, tests::TestFixedBases, Point}, - utilities::UtilitiesInstructions, - }; - - pub(crate) fn test_mul_sign( - chip: EccChip, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Generate a random non-identity point P - let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); - let p = Point::new( - chip.clone(), - layouter.namespace(|| "P"), - Value::known(p_val), - )?; - - // Create -P - let p_neg_val = -p_val; - let p_neg = Point::new( - chip.clone(), - layouter.namespace(|| "-P"), - Value::known(p_neg_val), - )?; - - // Create the identity point - let identity = Point::new( - chip.clone(), - layouter.namespace(|| "identity"), - Value::known(pallas::Point::identity().to_affine()), - )?; - - // Create -1 and 1 scalars - let pos_sign = chip.load_private( - layouter.namespace(|| "positive sign"), - chip.config().advices[0], - Value::known(pallas::Base::one()), - )?; - let neg_sign = chip.load_private( - layouter.namespace(|| "negative sign"), - chip.config().advices[1], - Value::known(-pallas::Base::one()), - )?; - - // [1] P == P - { - let result = p.mul_sign(layouter.namespace(|| "[1] P"), &pos_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p)?; - } - - // [-1] P == -P - { - let result = p.mul_sign(layouter.namespace(|| "[1] P"), &neg_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p_neg)?; - } - - // [1] 0 == 0 - { - let result = identity.mul_sign(layouter.namespace(|| "[1] O"), &pos_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; - } - - // [-1] 0 == 0 - { - let result = identity.mul_sign(layouter.namespace(|| "[-1] O"), &neg_sign)?; - result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; - } - - Ok(()) - } - - #[test] - fn invalid_magnitude_sign() { - use crate::{ - ecc::chip::{EccConfig, FixedPoint}, - utilities::UtilitiesInstructions, - }; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::{FailureLocation, MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - - #[derive(Default)] - struct MyCircuit { - magnitude: Value, - sign: Value, - // For test checking - magnitude_error: Value, - } - - impl UtilitiesInstructions for MyCircuit { - type Var = AssignedCell; - } - - impl Circuit for MyCircuit { - type Config = EccConfig< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); - EccChip::< - TestFixedBases, - LookupRangeCheckConfigOptimized< - pallas::Base, - { crate::sinsemilla::primitives::K }, - >, - >::configure(meta, advices, lagrange_coeffs, range_check) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let column = config.advices[0]; - - let short_config = config.mul_fixed_short.clone(); - let magnitude_sign = { - let magnitude = self.load_private( - layouter.namespace(|| "load magnitude"), - column, - self.magnitude, - )?; - let sign = - self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; - ScalarFixedShort::new( - EccChip::construct(config), - layouter.namespace(|| "signed short scalar"), - (magnitude, sign), - )? - }; - - short_config.assign(layouter, &magnitude_sign.inner, &Short)?; - - Ok(()) - } - } - - // Copied from halo2_proofs::dev::util - fn format_value(v: pallas::Base) -> String { - use ff::Field; - if v.is_zero_vartime() { - "0".into() - } else if v == pallas::Base::one() { - "1".into() - } else if v == -pallas::Base::one() { - "-1".into() - } else { - // Format value as hex. - let s = format!("{:?}", v); - // Remove leading zeroes. - let s = s.strip_prefix("0x").unwrap(); - let s = s.trim_start_matches('0'); - format!("0x{}", s) - } - } - - // Magnitude larger than 64 bits should fail - { - let circuits = [ - // 2^64 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 64)), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 1)), - }, - // -2^64 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 64)), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 1)), - }, - // 2^66 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 66)), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 3)), - }, - // -2^66 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 66)), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 3)), - }, - // 2^254 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known( - pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), - ), - }, - // -2^254 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known( - pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), - ), - }, - ]; - - for circuit in circuits.iter() { - let prover = MockProver::::run(11, circuit, vec![]).unwrap(); - circuit.magnitude_error.assert_if_known(|magnitude_error| { - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 0, - "last_window_check", - ) - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)") - .into(), - offset: 1, - }, - cell_values: vec![( - ((Any::Advice, 5).into(), 0).into(), - format_value(*magnitude_error), - )], - }, - VerifyFailure::Permutation { - column: (Any::Fixed, 10).into(), - location: FailureLocation::OutsideRegion { row: 0 }, - }, - VerifyFailure::Permutation { - column: (Any::Advice, 4).into(), - location: FailureLocation::InRegion { - region: (2, "Short fixed-base mul (incomplete addition)") - .into(), - offset: 22, - }, - }, - ]) - ); - true - }); - } - } - - // Sign that is not +/- 1 should fail - { - let magnitude_u64 = rand::random::(); - let circuit = MyCircuit { - magnitude: Value::known(pallas::Base::from(magnitude_u64)), - sign: Value::known(pallas::Base::zero()), - magnitude_error: Value::unknown(), - }; - - let negation_check_y = { - *(Short.generator() * pallas::Scalar::from(magnitude_u64)) - .to_affine() - .coordinates() - .unwrap() - .y() - }; - - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check") - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)").into(), - offset: 1, - }, - cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], - }, - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 3, - "negation_check" - ) - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)").into(), - offset: 1, - }, - cell_values: vec![ - ( - ((Any::Advice, 1).into(), 0).into(), - format_value(negation_check_y), - ), - ( - ((Any::Advice, 3).into(), 0).into(), - format_value(negation_check_y), - ), - (((Any::Advice, 4).into(), 0).into(), "0".to_string()), - ], - } - ]) - ); - } - } - - #[test] - fn invalid_sign_in_mul_sign() { - use crate::{ecc::chip::EccConfig, utilities::UtilitiesInstructions}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::{FailureLocation, MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - - #[derive(Default)] - struct MyCircuit { - base: Value, - sign: Value, - } - - impl UtilitiesInstructions for MyCircuit { - type Var = AssignedCell; - } - - impl Circuit for MyCircuit { - type Config = EccConfig< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); - EccChip::< - TestFixedBases, - LookupRangeCheckConfigOptimized< - pallas::Base, - { crate::sinsemilla::primitives::K }, - >, - >::configure(meta, advices, lagrange_coeffs, range_check) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let chip = EccChip::construct(config.clone()); - - let column = config.advices[0]; - - //let short_config = config.mul_fixed_short.clone(); - let base = Point::new(chip, layouter.namespace(|| "load base"), self.base)?; - - let sign = - self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; - - base.mul_sign(layouter.namespace(|| "[sign] base"), &sign)?; - - Ok(()) - } - } - - // Copied from halo2_proofs::dev::util - fn format_value(v: pallas::Base) -> String { - use ff::Field; - if v.is_zero_vartime() { - "0".into() - } else if v == pallas::Base::one() { - "1".into() - } else if v == -pallas::Base::one() { - "-1".into() - } else { - // Format value as hex. - let s = format!("{:?}", v); - // Remove leading zeroes. - let s = s.strip_prefix("0x").unwrap(); - let s = s.trim_start_matches('0'); - format!("0x{}", s) - } - } - - // Sign that is not +/- 1 should fail - // Generate a random non-identity point - let point = pallas::Point::random(rand::rngs::OsRng); - let circuit = MyCircuit { - base: Value::known(point.to_affine()), - sign: Value::known(pallas::Base::zero()), - }; - - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check").into(), - location: FailureLocation::InRegion { - region: (2, "Signed point").into(), - offset: 0, - }, - cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], - }, - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 3, - "negation_check" - ) - .into(), - location: FailureLocation::InRegion { - region: (2, "Signed point").into(), - offset: 0, - }, - cell_values: vec![ - ( - ((Any::Advice, 1).into(), 0).into(), - format_value(*point.to_affine().coordinates().unwrap().y()), - ), - ( - ((Any::Advice, 3).into(), 0).into(), - format_value(*point.to_affine().coordinates().unwrap().y()), - ), - (((Any::Advice, 4).into(), 0).into(), "0".to_string()), - ], - } - ]) - ); - } -} diff --git a/halo2_gadgets/src/ecc_opt/chip/witness_point.rs b/halo2_gadgets/src/ecc_opt/chip/witness_point.rs deleted file mode 100644 index 9e1bfeae6d..0000000000 --- a/halo2_gadgets/src/ecc_opt/chip/witness_point.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::ecc::chip::EccPoint; - -use group::prime::PrimeCurveAffine; - -use halo2_proofs::{ - circuit::Region, - plonk::{Assigned, Error}, -}; -use pasta_curves::{arithmetic::CurveAffine, pallas}; - -use crate::ecc::chip::witness_point::{Config, Coordinates}; - -impl Config { - fn assign_xy_from_constant( - &self, - value: (Assigned, Assigned), - offset: usize, - region: &mut Region<'_, pallas::Base>, - ) -> Result { - // Assign `x` value - let x_var = region.assign_advice_from_constant(|| "x", self.x, offset, value.0)?; - - // Assign `y` value - let y_var = region.assign_advice_from_constant(|| "y", self.y, offset, value.1)?; - - Ok((x_var, y_var)) - } - - /// Assigns a constant point that can be the identity. - pub(crate) fn constant_point( - &self, - value: pallas::Affine, - offset: usize, - region: &mut Region<'_, pallas::Base>, - ) -> Result { - // Enable `q_point` selector - self.q_point.enable(region, offset)?; - - let value = if value == pallas::Affine::identity() { - // Map the identity to (0, 0). - (Assigned::Zero, Assigned::Zero) - } else { - let value = value.coordinates().unwrap(); - (value.x().into(), value.y().into()) - }; - - self.assign_xy_from_constant(value, offset, region) - .map(|(x, y)| EccPoint::from_coordinates_unchecked(x, y)) - } -} diff --git a/halo2_gadgets/src/lib.rs b/halo2_gadgets/src/lib.rs index 33ffcfa6b8..2ac2623a99 100644 --- a/halo2_gadgets/src/lib.rs +++ b/halo2_gadgets/src/lib.rs @@ -22,12 +22,9 @@ #![deny(unsafe_code)] pub mod ecc; -pub mod ecc_opt; pub mod poseidon; #[cfg(feature = "unstable-sha256-gadget")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable-sha256-gadget")))] pub mod sha256; pub mod sinsemilla; -pub mod sinsemilla_opt; pub mod utilities; -pub mod utilities_opt; diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index d5b0dab5e2..e10e504013 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -403,6 +403,7 @@ CommitDomain pub fn new( sinsemilla_chip: SinsemillaChip, ecc_chip: EccChip, + // TODO: Instead of using SinsemilllaChip::CommitDomains, just use something that implements a CommitDomains trait domain: &SinsemillaChip::CommitDomains, ) -> Self { CommitDomain { diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 4ce0662e91..5c26cff058 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -200,6 +200,8 @@ where } } +/// The MerkleSinsemillaInstructions trait extends the capabilities of SinsemillaInstructions, +/// for specific cryptographic operations involving generic lookup. pub(crate) trait MerkleSinsemillaInstructions where Self: SinsemillaInstructions< diff --git a/halo2_gadgets/src/sinsemilla/primitives.rs b/halo2_gadgets/src/sinsemilla/primitives.rs index 2ebde8faf4..c47ac1b379 100644 --- a/halo2_gadgets/src/sinsemilla/primitives.rs +++ b/halo2_gadgets/src/sinsemilla/primitives.rs @@ -184,8 +184,6 @@ impl HashDomain { #[derive(Debug)] #[allow(non_snake_case)] pub struct CommitDomain { - // FIXME: THis comment came from ZSA version - /// A domain in which $\mathsf{SinsemillaHashToPoint}$ and $\mathsf{SinsemillaHash}$ can be used pub(crate) M: HashDomain, pub(crate) R: pallas::Point, } diff --git a/halo2_gadgets/src/sinsemilla_opt.rs b/halo2_gadgets/src/sinsemilla_opt.rs deleted file mode 100644 index 30d1d2c83c..0000000000 --- a/halo2_gadgets/src/sinsemilla_opt.rs +++ /dev/null @@ -1,464 +0,0 @@ -//! The [Sinsemilla] hash function. -//! -//! [Sinsemilla]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash - -use std::fmt::Debug; - -use pasta_curves::arithmetic::CurveAffine; - -use halo2_proofs::{circuit::Layouter, plonk::Error}; - -use crate::{ - ecc::{self, EccInstructions}, - sinsemilla::{CommitDomain, HashDomain, Message, SinsemillaInstructions}, -}; - -pub mod chip; -pub mod merkle; -pub mod primitives; - -/// `SinsemillaInstructionsOptimized` provides an optimized set of instructions -/// for implementing the Sinsemilla hash function and commitment scheme -/// on elliptic curves. This trait is an extension of the `SinsemillaInstructions` trait, -/// designed to enhance performance in specific cryptographic scenarios.ld - -pub trait SinsemillaInstructionsOptimized: - SinsemillaInstructions -{ - /// Hashes a message to an ECC curve point. - /// This returns both the resulting point, as well as the message - /// decomposition in the form of intermediate values in a cumulative - /// sum. - /// The initial point `Q` is a private point. - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( - &self, - layouter: impl Layouter, - Q: &Self::NonIdentityPoint, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec), Error>; -} - -impl -HashDomain - where - SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, - EccChip: EccInstructions< - C, - NonIdentityPoint = >::NonIdentityPoint, - FixedPoints = >::FixedPoints, - > + Clone - + Debug - + Eq, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - /// Evaluate the Sinsemilla hash of `message` from the private initial point `Q`. - pub fn hash_to_point_with_private_init( - &self, - layouter: impl Layouter, - Q: &>::NonIdentityPoint, - message: Message, - ) -> Result<(ecc::NonIdentityPoint, Vec), Error> { - assert_eq!(self.sinsemilla_chip, message.chip); - self.sinsemilla_chip - .hash_to_point_with_private_init(layouter, Q, message.inner) - .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) - } - -} - -impl -CommitDomain - where - SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, - EccChip: EccInstructions< - C, - NonIdentityPoint = >::NonIdentityPoint, - FixedPoints = >::FixedPoints, - > + Clone - + Debug - + Eq, -{ - #[allow(clippy::type_complexity)] - /// Evaluates the Sinsemilla hash of `message` from the public initial point `Q` stored - /// into `CommitDomain`. - pub fn hash( - &self, - layouter: impl Layouter, - message: Message, - ) -> Result< - ( - ecc::NonIdentityPoint, - Vec, - ), - Error, - > { - assert_eq!(self.M.sinsemilla_chip, message.chip); - self.M.hash_to_point(layouter, message) - } - - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - /// Evaluates the Sinsemilla hash of `message` from the private initial point `Q`. - pub fn hash_with_private_init( - &self, - layouter: impl Layouter, - Q: &>::NonIdentityPoint, - message: Message, - ) -> Result< - ( - ecc::NonIdentityPoint, - Vec, - ), - Error, - > { - assert_eq!(self.M.sinsemilla_chip, message.chip); - self.M.hash_to_point_with_private_init(layouter, Q, message) - } - - #[allow(clippy::type_complexity)] - /// Returns the public initial point `Q` stored into `CommitDomain`. - pub fn q_init(&self) -> C { - self.M.Q - } - - #[allow(clippy::type_complexity)] - /// Evaluates the blinding factor equal to $\[r\] R$ where `r` is stored in the `CommitDomain`. - pub fn blinding_factor( - &self, - mut layouter: impl Layouter, - r: ecc::ScalarFixed, - ) -> Result< - ecc::Point, - Error, - > { - let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; - Ok(blind) - } -} - -#[cfg(test)] -pub(crate) mod tests { - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use rand::rngs::OsRng; - - use crate::sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, - CommitDomain, CommitDomains, HashDomain, HashDomains, Message, MessagePiece, - }; - - use crate::{ - ecc::ScalarFixed, - ecc::{ - chip::{find_zs_and_us, EccChip, EccConfig, H, NUM_WINDOWS}, - tests::{FullWidth, TestFixedBases}, - NonIdentityPoint, - }, - sinsemilla::primitives::{self as sinsemilla, K}, - }; - - use group::{ff::Field, Curve}; - use lazy_static::lazy_static; - use pasta_curves::pallas; - - use crate::sinsemilla_opt::chip::SinsemillaChipOptimized; - use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; - use std::convert::TryInto; - - pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; - - lazy_static! { - static ref COMMIT_DOMAIN: sinsemilla::CommitDomain = - sinsemilla::CommitDomain::new(PERSONALIZATION); - static ref Q: pallas::Affine = COMMIT_DOMAIN.Q().to_affine(); - static ref R: pallas::Affine = COMMIT_DOMAIN.R().to_affine(); - static ref R_ZS_AND_US: Vec<(u64, [pallas::Base; H])> = - find_zs_and_us(*R, NUM_WINDOWS).unwrap(); - } - - #[derive(Debug, Clone, Eq, PartialEq)] - pub(crate) struct TestHashDomain; - impl HashDomains for TestHashDomain { - fn Q(&self) -> pallas::Affine { - *Q - } - } - - // This test does not make use of the CommitDomain. - #[derive(Debug, Clone, Eq, PartialEq)] - pub(crate) struct TestCommitDomain; - impl CommitDomains for TestCommitDomain { - fn r(&self) -> FullWidth { - FullWidth::from_parts(*R, &R_ZS_AND_US) - } - - fn hash_domain(&self) -> TestHashDomain { - TestHashDomain - } - } - - struct MyCircuit {} - - impl Circuit for MyCircuit { - #[allow(clippy::type_complexity)] - type Config = ( - EccConfig< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - SinsemillaConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - SinsemillaConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - ); - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - MyCircuit {} - } - - #[allow(non_snake_case)] - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - // Fixed columns for the Sinsemilla generator lookup table - let lookup = ( - table_idx, - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - table_idx, - table_range_check_tag, - ); - - let ecc_config = EccChip::< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >::configure(meta, advices, lagrange_coeffs, range_check); - - let config1 = SinsemillaChip::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - lagrange_coeffs[0], - lookup, - range_check, - ); - let config2 = SinsemillaChip::configure( - meta, - advices[5..].try_into().unwrap(), - advices[7], - lagrange_coeffs[1], - lookup, - range_check, - ); - (ecc_config, config1, config2) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let rng = OsRng; - - let ecc_chip = EccChip::construct(config.0); - - // The two `SinsemillaChip`s share the same lookup table. - SinsemillaChipOptimized::::load( - config.1.clone(), - &mut layouter, - )?; - - // This MerkleCRH example is purely for illustrative purposes. - // It is not an implementation of the Orchard protocol spec. - { - let chip1 = SinsemillaChip::construct(config.1); - - let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); - - // Layer 31, l = MERKLE_DEPTH - 1 - layer = 0 - let l_bitstring = vec![Value::known(false); K]; - let l = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "l"), - &l_bitstring, - )?; - - // Left leaf - let left_bitstring: Vec> = (0..250) - .map(|_| Value::known(rand::random::())) - .collect(); - let left = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "left"), - &left_bitstring, - )?; - - // Right leaf - let right_bitstring: Vec> = (0..250) - .map(|_| Value::known(rand::random::())) - .collect(); - let right = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "right"), - &right_bitstring, - )?; - - let l_bitstring: Value> = l_bitstring.into_iter().collect(); - let left_bitstring: Value> = left_bitstring.into_iter().collect(); - let right_bitstring: Value> = right_bitstring.into_iter().collect(); - - // Witness expected parent - let expected_parent = { - let expected_parent = l_bitstring.zip(left_bitstring.zip(right_bitstring)).map( - |(l, (left, right))| { - let merkle_crh = sinsemilla::HashDomain::from_Q((*Q).into()); - let point = merkle_crh - .hash_to_point( - l.into_iter() - .chain(left.into_iter()) - .chain(right.into_iter()), - ) - .unwrap(); - point.to_affine() - }, - ); - - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "Witness expected parent"), - expected_parent, - )? - }; - - // Parent - let (parent, _) = { - let message = Message::from_pieces(chip1, vec![l, left, right]); - merkle_crh.hash_to_point(layouter.namespace(|| "parent"), message)? - }; - - parent.constrain_equal( - layouter.namespace(|| "parent == expected parent"), - &expected_parent, - )?; - } - - { - let chip2 = SinsemillaChip::construct(config.2); - - let test_commit = - CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); - let r_val = pallas::Scalar::random(rng); - let message: Vec> = (0..500) - .map(|_| Value::known(rand::random::())) - .collect(); - - let (result, _) = { - let r = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "r"), - Value::known(r_val), - )?; - let message = Message::from_bitstring( - chip2, - layouter.namespace(|| "witness message"), - message.clone(), - )?; - test_commit.commit(layouter.namespace(|| "commit"), message, r)? - }; - - // Witness expected result. - let expected_result = { - let message: Value> = message.into_iter().collect(); - let expected_result = message.map(|message| { - let domain = sinsemilla::CommitDomain::new(PERSONALIZATION); - let point = domain.commit(message.into_iter(), &r_val).unwrap(); - point.to_affine() - }); - - NonIdentityPoint::new( - ecc_chip, - layouter.namespace(|| "Witness expected result"), - expected_result, - )? - }; - - result.constrain_equal( - layouter.namespace(|| "result == expected result"), - &expected_result, - ) - } - } - } - - #[test] - fn sinsemilla_chip() { - let k = 11; - let circuit = MyCircuit {}; - let prover = MockProver::run(k, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())) - } - - #[cfg(feature = "test-dev-graph")] - #[test] - fn print_sinsemilla_chip() { - use plotters::prelude::*; - - let root = - BitMapBackend::new("sinsemilla-hash-layout.png", (1024, 7680)).into_drawing_area(); - root.fill(&WHITE).unwrap(); - let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); - - let circuit = MyCircuit {}; - halo2_proofs::dev::CircuitLayout::default() - .render(11, &circuit, &root) - .unwrap(); - } -} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip.rs b/halo2_gadgets/src/sinsemilla_opt/chip.rs deleted file mode 100644 index 1b544edf75..0000000000 --- a/halo2_gadgets/src/sinsemilla_opt/chip.rs +++ /dev/null @@ -1,219 +0,0 @@ -//! Chip implementations for the Sinsemilla gadgets. - -use super::SinsemillaInstructionsOptimized; -use crate::{ - ecc::{chip::NonIdentityEccPoint, FixedPoints}, - sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, - message::{Message, MessagePiece}, - primitives as sinsemilla, CommitDomains, HashDomains, SinsemillaInstructions, - }, - utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, -}; -use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter, Value}, - plonk::{ - Advice, Column, ConstraintSystem, Constraints, Error, Fixed, TableColumn, VirtualCells, - }, - poly::Rotation, -}; -use pasta_curves::pallas; - -pub(crate) mod generator_table; - -mod hash_to_point; - -/// A chip that implements 10-bit Sinsemilla using a lookup table and 5 advice columns. -/// -/// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). -#[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, -{ - inner: SinsemillaChip, -} - -impl Chip for SinsemillaChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, -{ - type Config = SinsemillaConfig; - type Loaded = (); - - fn config(&self) -> &Self::Config { - self.inner.config() - } - - fn loaded(&self) -> &Self::Loaded { - &() - } -} - -impl SinsemillaChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ - /// Reconstructs this chip from the given config. - pub fn construct(config: >::Config) -> Self { - Self { - inner: - SinsemillaChip::::construct( - config, - ), - } - } - - /// Loads the lookup table required by this chip into the circuit. - pub fn load( - config: SinsemillaConfig, - layouter: &mut impl Layouter, - ) -> Result<>::Loaded, Error> { - // Load the lookup table. - generator_table::load_with_tag( - &config.generator_table, - config.lookup_config.table_range_check_tag(), - layouter, - ) - } - - #[allow(non_snake_case)] - fn create_initial_y_q_gate( - meta: &mut ConstraintSystem, - config: &SinsemillaConfig, - ) { - let two = pallas::Base::from(2); - - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) - let Y_A = |meta: &mut VirtualCells, rotation| { - config.double_and_add.Y_A(meta, rotation) - }; - - // Check that the initial x_A, x_P, lambda_1, lambda_2 are consistent with y_Q. - // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial - meta.create_gate("Initial y_Q", |meta| { - let q_s4 = meta.query_selector(config.q_sinsemilla4); - let y_q = meta.query_advice(config.double_and_add.x_p, Rotation::prev()); - - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) - let Y_A_cur = Y_A(meta, Rotation::cur()); - - // 2 * y_q - Y_{A,0} = 0 - let init_y_q_check = y_q * two - Y_A_cur; - - Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) - }); - } - - /// # Side-effects - /// - /// All columns in `advices` and will be equality-enabled. - #[allow(clippy::too_many_arguments)] - #[allow(non_snake_case)] - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - lookup: (TableColumn, TableColumn, TableColumn), - range_check: DefaultLookupRangeCheckConfigOptimized, - ) -> >::Config { - let config = SinsemillaChip::::create_config( - meta, - advices, - witness_pieces, - fixed_y_q, - lookup, - range_check, - ); - - Self::create_initial_y_q_gate(meta, &config); - - SinsemillaChip::::create_sinsemilla_gate( - meta, &config, - ); - - config - } -} - -// Implement `SinsemillaInstructions` for `SinsemillaChipOptimized` -impl SinsemillaInstructions - for SinsemillaChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ - type CellValue = AssignedCell; - - type Message = Message; - type MessagePiece = MessagePiece; - - type RunningSum = Vec; - - type X = AssignedCell; - type NonIdentityPoint = NonIdentityEccPoint; - type FixedPoints = F; - - type HashDomains = Hash; - type CommitDomains = Commit; - - fn witness_message_piece( - &self, - layouter: impl Layouter, - field_elem: Value, - num_words: usize, - ) -> Result { - self.inner - .witness_message_piece(layouter, field_elem, num_words) - } - - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point( - &self, - mut layouter: impl Layouter, - Q: pallas::Affine, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec), Error> { - layouter.assign_region( - || "hash_to_point", - |mut region| self.hash_message(&mut region, Q, &message), - ) - } - - fn extract(point: &Self::NonIdentityPoint) -> Self::X { - point.x() - } -} - -// Implement `SinsemillaInstructionsOptimized` for `SinsemillaChipOptimized` -impl - SinsemillaInstructionsOptimized - for SinsemillaChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( - &self, - mut layouter: impl Layouter, - Q: &Self::NonIdentityPoint, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec), Error> { - layouter.assign_region( - || "hash_to_point", - |mut region| self.hash_message_with_private_init(&mut region, Q, &message), - ) - } -} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs deleted file mode 100644 index fc87e48c07..0000000000 --- a/halo2_gadgets/src/sinsemilla_opt/chip/generator_table.rs +++ /dev/null @@ -1,111 +0,0 @@ -use halo2_proofs::{ - circuit::{Layouter, Value}, - plonk::{Error, TableColumn}, -}; - -use pasta_curves::pallas; - -use crate::sinsemilla::{ - chip::generator_table::GeneratorTableConfig, - primitives::{K, SINSEMILLA_S}, -}; - -/// Load the generator table into the circuit. -/// -/// | table_idx | table_x | table_y | table_range_check_tag | -/// ------------------------------------------------------------------- -/// | 0 | X(S\[0\]) | Y(S\[0\]) | 0 | -/// | 1 | X(S\[1\]) | Y(S\[1\]) | 0 | -/// | ... | ... | ... | 0 | -/// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | 0 | -/// | 0 | X(S\[0\]) | Y(S\[0\]) | 4 | -/// | 1 | X(S\[1\]) | Y(S\[1\]) | 4 | -/// | ... | ... | ... | 4 | -/// | 2^4-1 | X(S\[2^4-1\]) | Y(S\[2^4-1\]) | 4 | -/// | 0 | X(S\[0\]) | Y(S\[0\]) | 5 | -/// | 1 | X(S\[1\]) | Y(S\[1\]) | 5 | -/// | ... | ... | ... | 5 | -/// | 2^5-1 | X(S\[2^5-1\]) | Y(S\[2^5-1\]) | 5 | -pub fn load_with_tag( - config: &GeneratorTableConfig, - table_range_check_tag: TableColumn, - layouter: &mut impl Layouter, -) -> Result<(), Error> { - layouter.assign_table( - || "generator_table", - |mut table| { - for (index, (x, y)) in SINSEMILLA_S.iter().enumerate() { - table.assign_cell( - || "table_idx", - config.table_idx, - index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell(|| "table_x", config.table_x, index, || Value::known(*x))?; - table.assign_cell(|| "table_y", config.table_y, index, || Value::known(*y))?; - - table.assign_cell( - || "table_range_check_tag", - table_range_check_tag, - index, - || Value::known(pallas::Base::zero()), - )?; - if index < (1 << 4) { - let new_index = index + (1 << K); - table.assign_cell( - || "table_idx", - config.table_idx, - new_index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell( - || "table_x", - config.table_x, - new_index, - || Value::known(*x), - )?; - table.assign_cell( - || "table_y", - config.table_y, - new_index, - || Value::known(*y), - )?; - table.assign_cell( - || "table_range_check_tag", - table_range_check_tag, - new_index, - || Value::known(pallas::Base::from(4_u64)), - )?; - } - if index < (1 << 5) { - let new_index = index + (1 << 10) + (1 << 4); - table.assign_cell( - || "table_idx", - config.table_idx, - new_index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell( - || "table_x", - config.table_x, - new_index, - || Value::known(*x), - )?; - table.assign_cell( - || "table_y", - config.table_y, - new_index, - || Value::known(*y), - )?; - table.assign_cell( - || "table_range_check_tag", - table_range_check_tag, - new_index, - || Value::known(pallas::Base::from(5_u64)), - )?; - } - } - Ok(()) - }, - ) -} diff --git a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs deleted file mode 100644 index 8ef33ab4ef..0000000000 --- a/halo2_gadgets/src/sinsemilla_opt/chip/hash_to_point.rs +++ /dev/null @@ -1,181 +0,0 @@ -use pasta_curves::{arithmetic::CurveAffine, pallas}; - -use halo2_proofs::{ - circuit::{AssignedCell, Chip, Region}, - plonk::{Assigned, Error}, -}; - -use crate::sinsemilla::chip::hash_to_point::EccPointQ; -use crate::sinsemilla::chip::SinsemillaChip; -use crate::sinsemilla_opt::chip::SinsemillaChipOptimized; -use crate::{ - ecc::{chip::NonIdentityEccPoint, FixedPoints}, - sinsemilla::{ - chip::hash_to_point::{X, Y}, - primitives::{self as sinsemilla}, - CommitDomains, HashDomains, SinsemillaInstructions, - }, -}; - -impl SinsemillaChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(crate) fn hash_message( - &self, - region: &mut Region<'_, pallas::Base>, - Q: pallas::Affine, - message: &>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - // Coordinates of the initial point `Q` are assigned to advice columns - let (offset, x_a, y_a) = self.public_initialization(region, Q)?; - - let (x_a, y_a, zs_sum) = - SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; - - SinsemillaChip::check_hash_result( - &self.inner, - EccPointQ::PublicPoint(Q), - message, - x_a, - y_a, - zs_sum, - ) - } - /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(crate) fn hash_message_with_private_init( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - message: &>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - let (offset, x_a, y_a) = self.private_initialization(region, Q)?; - - let (x_a, y_a, zs_sum) = - SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; - - SinsemillaChip::check_hash_result( - &self.inner, - EccPointQ::PrivatePoint(Q), - message, - x_a, - y_a, - zs_sum, - ) - } - - #[allow(non_snake_case)] - /// Assign the coordinates of the initial public point `Q` to advice columns - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - pub(crate) fn public_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: pallas::Affine, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - let mut offset = 0; - - // Get the `x`- and `y`-coordinates of the starting `Q` base. - let x_q = *Q.coordinates().unwrap().x(); - let y_q = *Q.coordinates().unwrap().y(); - - // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 - // selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, offset + 1)?; - let y_a: AssignedCell, pallas::Base> = region - .assign_advice_from_constant( - || "fixed y_q", - config.double_and_add.x_p, - offset, - y_q.into(), - )?; - - y_a.value_field().into() - }; - offset += 1; - - // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. - let x_a: X = { - let x_a = region.assign_advice_from_constant( - || "fixed x_q", - config.double_and_add.x_a, - offset, - x_q.into(), - )?; - - x_a.into() - }; - - Ok((offset, x_a, y_a)) - } - - #[allow(non_snake_case)] - /// Assign the coordinates of the initial private point `Q` - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn private_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - let mut offset = 0; - - // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, - // x_p, y_Q using the q_sinsemilla4 selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, offset + 1)?; - let q_y: AssignedCell, pallas::Base> = Q.y().into(); - let y_a: AssignedCell, pallas::Base> = - q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, offset)?; - - y_a.value_field().into() - }; - offset += 1; - - let x_a: X = { - let q_x: AssignedCell, pallas::Base> = Q.x().into(); - let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, offset)?; - - x_a.into() - }; - - Ok((offset, x_a, y_a)) - } -} diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle.rs b/halo2_gadgets/src/sinsemilla_opt/merkle.rs deleted file mode 100644 index 3983e42659..0000000000 --- a/halo2_gadgets/src/sinsemilla_opt/merkle.rs +++ /dev/null @@ -1,246 +0,0 @@ -//! Gadgets for implementing a Merkle tree with Sinsemilla. - -pub mod chip; - -#[cfg(test)] -pub mod tests { - - use crate::{ - ecc::tests::TestFixedBases, - sinsemilla::{ - tests::{TestCommitDomain, TestHashDomain}, - HashDomains, - }, - utilities::{i2lebsp, UtilitiesInstructions}, - }; - - use group::ff::{Field, PrimeField, PrimeFieldBits}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - pasta::pallas, - plonk::{Circuit, ConstraintSystem, Error}, - }; - - use crate::sinsemilla::merkle::chip::MerkleConfig; - use crate::sinsemilla::merkle::MerklePath; - use crate::sinsemilla_opt::chip::SinsemillaChipOptimized; - use crate::sinsemilla_opt::merkle::chip::MerkleChipOptimized; - use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; - use rand::{rngs::OsRng, RngCore}; - use std::{convert::TryInto, iter}; - - const MERKLE_DEPTH: usize = 32; - - #[derive(Default)] - struct MyCircuit { - leaf: Value, - leaf_pos: Value, - merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, - } - - impl Circuit for MyCircuit { - type Config = ( - MerkleConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - MerkleConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - ); - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - // NB: In the actual Action circuit, these fixed columns will be reused - // by other chips. For this test, we are creating new fixed columns. - let fixed_y_q_1 = meta.fixed_column(); - let fixed_y_q_2 = meta.fixed_column(); - - // Fixed columns for the Sinsemilla generator lookup table - let lookup = ( - meta.lookup_table_column(), - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - let table_range_check_tag = meta.lookup_table_column(); - - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup.0, - table_range_check_tag, - ); - - let sinsemilla_config_1 = SinsemillaChipOptimized::configure( - meta, - advices[5..].try_into().unwrap(), - advices[7], - fixed_y_q_1, - lookup, - range_check, - ); - let config1 = MerkleChipOptimized::configure(meta, sinsemilla_config_1); - - let sinsemilla_config_2 = SinsemillaChipOptimized::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - fixed_y_q_2, - lookup, - range_check, - ); - let config2 = MerkleChipOptimized::configure(meta, sinsemilla_config_2); - - (config1, config2) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load generator table (shared across both configs) for SinsemillaChipOptimized - SinsemillaChipOptimized::::load( - config.0.sinsemilla_config.clone(), - &mut layouter, - )?; - - // Construct Merkle chips which will be placed side-by-side in the circuit. - let chip_1 = MerkleChipOptimized::construct(config.0.clone()); - let chip_2 = MerkleChipOptimized::construct(config.1.clone()); - - let leaf = chip_1.load_private( - layouter.namespace(|| ""), - config.0.cond_swap_config.a(), - self.leaf, - )?; - - let path = MerklePath { - chips: [chip_1, chip_2], - domain: TestHashDomain, - leaf_pos: self.leaf_pos, - path: self.merkle_path, - }; - - let computed_final_root = - path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?; - - self.leaf - .zip(self.leaf_pos) - .zip(self.merkle_path) - .zip(computed_final_root.value()) - .assert_if_known(|(((leaf, leaf_pos), merkle_path), computed_final_root)| { - // The expected final root - let final_root = - merkle_path - .iter() - .enumerate() - .fold(*leaf, |node, (l, sibling)| { - let l = l as u8; - let (left, right) = if leaf_pos & (1 << l) == 0 { - (&node, sibling) - } else { - (sibling, &node) - }; - - use crate::sinsemilla::primitives as sinsemilla; - let merkle_crh = - sinsemilla::HashDomain::from_Q(TestHashDomain.Q().into()); - - merkle_crh - .hash( - iter::empty() - .chain(i2lebsp::<10>(l as u64).iter().copied()) - .chain( - left.to_le_bits() - .iter() - .by_vals() - .take(pallas::Base::NUM_BITS as usize), - ) - .chain( - right - .to_le_bits() - .iter() - .by_vals() - .take(pallas::Base::NUM_BITS as usize), - ), - ) - .unwrap_or(pallas::Base::zero()) - }); - - // Check the computed final root against the expected final root. - computed_final_root == &&final_root - }); - - Ok(()) - } - } - - #[test] - fn merkle_chip() { - let mut rng = OsRng; - - // Choose a random leaf and position - let leaf = pallas::Base::random(rng); - let pos = rng.next_u32(); - - // Choose a path of random inner nodes - let path: Vec<_> = (0..(MERKLE_DEPTH)) - .map(|_| pallas::Base::random(rng)) - .collect(); - - // The root is provided as a public input in the Orchard circuit. - - let circuit = MyCircuit { - leaf: Value::known(leaf), - leaf_pos: Value::known(pos), - merkle_path: Value::known(path.try_into().unwrap()), - }; - - let prover = MockProver::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())) - } - - #[cfg(feature = "test-dev-graph")] - #[test] - fn print_merkle_chip() { - use plotters::prelude::*; - - let root = BitMapBackend::new("merkle-path-layout.png", (1024, 7680)).into_drawing_area(); - root.fill(&WHITE).unwrap(); - let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); - - let circuit = MyCircuit::default(); - halo2_proofs::dev::CircuitLayout::default() - .show_labels(false) - .render(11, &circuit, &root) - .unwrap(); - } -} diff --git a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs b/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs deleted file mode 100644 index b11cf6b57e..0000000000 --- a/halo2_gadgets/src/sinsemilla_opt/merkle/chip.rs +++ /dev/null @@ -1,209 +0,0 @@ -//! Chip implementing a Merkle hash using Sinsemilla as the hash function. - -use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter, Value}, - plonk::{ConstraintSystem, Error}, -}; -use pasta_curves::pallas; - -use crate::{ - sinsemilla::{ - merkle::chip::{MerkleChip, MerkleConfig, MerkleSinsemillaInstructions}, - primitives as sinsemilla, - }, - sinsemilla_opt::chip::SinsemillaChipOptimized, - utilities_opt::lookup_range_check::DefaultLookupRangeCheckConfigOptimized, - { - ecc::FixedPoints, - sinsemilla::{chip::SinsemillaConfig, CommitDomains, HashDomains, SinsemillaInstructions}, - utilities::{cond_swap::CondSwapInstructions, UtilitiesInstructions}, - }, -}; - -/// Chip implementing `MerkleInstructions`. -/// -/// This chip specifically implements `MerkleInstructions::hash_layer` as the `MerkleCRH` -/// function `hash = SinsemillaHash(Q, 𝑙⋆ || left⋆ || right⋆)`, where: -/// - `𝑙⋆ = I2LEBSP_10(l)` -/// - `left⋆ = I2LEBSP_255(left)` -/// - `right⋆ = I2LEBSP_255(right)` -/// -/// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of -/// `left` and `right`. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, -{ - base: MerkleChip, -} - -impl Chip for MerkleChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, -{ - type Config = MerkleConfig; - type Loaded = (); - - fn config(&self) -> &Self::Config { - &self.base.config - } - - fn loaded(&self) -> &Self::Loaded { - &() - } -} - -impl MerkleChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ - /// Configures the [`MerkleChip`]. - pub fn configure( - meta: &mut ConstraintSystem, - sinsemilla_config: SinsemillaConfig< - Hash, - Commit, - F, - DefaultLookupRangeCheckConfigOptimized, - >, - ) -> MerkleConfig { - MerkleChip::configure(meta, sinsemilla_config) - } - - /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. - pub fn construct( - config: MerkleConfig, - ) -> Self { - MerkleChipOptimized { - base: MerkleChip { config }, - } - } -} - -impl - MerkleSinsemillaInstructions - for MerkleChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ -} - -impl UtilitiesInstructions for MerkleChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ - type Var = AssignedCell; -} - -impl CondSwapInstructions for MerkleChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ - #[allow(clippy::type_complexity)] - fn swap( - &self, - layouter: impl Layouter, - pair: (Self::Var, Value), - swap: Value, - ) -> Result<(Self::Var, Self::Var), Error> { - self.base.swap(layouter, pair, swap) - } -} - -impl SinsemillaInstructions - for MerkleChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ - type CellValue = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CellValue; - - type Message = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::Message; - type MessagePiece = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::MessagePiece; - type RunningSum = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::RunningSum; - - type X = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::X; - type NonIdentityPoint = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::NonIdentityPoint; - type FixedPoints = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::FixedPoints; - - type HashDomains = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::HashDomains; - type CommitDomains = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CommitDomains; - - fn witness_message_piece( - &self, - layouter: impl Layouter, - value: Value, - num_words: usize, - ) -> Result { - let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChipOptimized::::construct(config); - chip.witness_message_piece(layouter, value, num_words) - } - - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point( - &self, - layouter: impl Layouter, - Q: pallas::Affine, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { - let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChipOptimized::::construct(config); - chip.hash_to_point(layouter, Q, message) - } - - fn extract(point: &Self::NonIdentityPoint) -> Self::X { - SinsemillaChipOptimized::::extract(point) - } -} diff --git a/halo2_gadgets/src/sinsemilla_opt/primitives.rs b/halo2_gadgets/src/sinsemilla_opt/primitives.rs deleted file mode 100644 index dd2930d6d2..0000000000 --- a/halo2_gadgets/src/sinsemilla_opt/primitives.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Implementation of Sinsemilla outside the circuit. - -use group::Wnaf; -use halo2_proofs::arithmetic::CurveExt; -use pasta_curves::pallas; -use subtle::CtOption; - -use crate::sinsemilla::primitives::{CommitDomain, HashDomain}; - -impl CommitDomain { - /// Constructs a new `CommitDomain` from different values for `hash_domain` and `blind_domain` - pub fn new_with_personalization(hash_domain: &str, blind_domain: &str) -> Self { - let m_prefix = format!("{}-M", hash_domain); - let r_prefix = format!("{}-r", blind_domain); - let hasher_r = pallas::Point::hash_to_curve(&r_prefix); - CommitDomain { - M: HashDomain::new(&m_prefix), - R: hasher_r(&[]), - } - } - - /// $\mathsf{SinsemillaHashToPoint}$ from [§ 5.4.1.9][concretesinsemillahash]. - /// - /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash - pub fn hash_to_point(&self, msg: impl Iterator) -> CtOption { - self.M.hash_to_point(msg) - } - - /// Returns `SinsemillaCommit_r(personalization, msg) = hash_point + [r]R` - /// where `SinsemillaHash(personalization, msg) = hash_point` - /// and `R` is derived from the `personalization`. - #[allow(non_snake_case)] - pub fn commit_from_hash_point( - &self, - hash_point: CtOption, - r: &pallas::Scalar, - ) -> CtOption { - // We use complete addition for the blinding factor. - hash_point.map(|p| p + Wnaf::new().scalar(r).base(self.R)) - } -} - -#[cfg(test)] -mod tests { - use pasta_curves::pallas; - - #[test] - fn commit_in_several_steps() { - use rand::{rngs::OsRng, Rng}; - - use ff::Field; - - use crate::sinsemilla::primitives::CommitDomain; - - let domain = CommitDomain::new("z.cash:ZSA-NoteCommit"); - - let mut os_rng = OsRng::default(); - let msg: Vec = (0..36).map(|_| os_rng.gen::()).collect(); - - let rcm = pallas::Scalar::random(&mut os_rng); - - // Evaluate the commitment with commit function - let commit1 = domain.commit(msg.clone().into_iter(), &rcm); - - // Evaluate the commitment with the following steps - // 1. hash msg - // 2. evaluate the commitment from the hash point - let hash_point = domain.M.hash_to_point(msg.into_iter()); - let commit2 = domain.commit_from_hash_point(hash_point, &rcm); - - // Test equality - assert_eq!(commit1.unwrap(), commit2.unwrap()); - } -} diff --git a/halo2_gadgets/src/utilities_opt.rs b/halo2_gadgets/src/utilities_opt.rs deleted file mode 100644 index ddd75ce739..0000000000 --- a/halo2_gadgets/src/utilities_opt.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! Utility gadgets. - -pub mod cond_swap; -pub mod lookup_range_check; diff --git a/halo2_gadgets/src/utilities_opt/cond_swap.rs b/halo2_gadgets/src/utilities_opt/cond_swap.rs deleted file mode 100644 index eae0b148fd..0000000000 --- a/halo2_gadgets/src/utilities_opt/cond_swap.rs +++ /dev/null @@ -1,352 +0,0 @@ -//! Gadget and chip for a conditional swap utility. - -use group::ff::{Field, PrimeField}; -use pasta_curves::pallas; - -use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter}, - plonk::{self, Error}, -}; - -use crate::ecc::chip::{EccPoint, NonIdentityEccPoint}; - -use crate::utilities::cond_swap::{CondSwapChip, CondSwapInstructions}; - -/// Instructions for a conditional swap gadget. -pub trait CondSwapInstructionsOptimized: CondSwapInstructions { - /// Given an input `(choice, left, right)` where `choice` is a boolean flag, - /// returns `left` if `choice` is not set and `right` if `choice` is set. - fn mux( - &self, - layouter: &mut impl Layouter, - choice: Self::Var, - left: Self::Var, - right: Self::Var, - ) -> Result; -} - -impl CondSwapInstructionsOptimized for CondSwapChip { - fn mux( - &self, - layouter: &mut impl Layouter, - choice: Self::Var, - left: Self::Var, - right: Self::Var, - ) -> Result { - let config = self.config(); - - layouter.assign_region( - || "mux", - |mut region| { - // Enable `q_swap` selector - config.q_swap.enable(&mut region, 0)?; - - // Copy in `a` value - let left = left.copy_advice(|| "copy left", &mut region, config.a, 0)?; - - // Copy in `b` value - let right = right.copy_advice(|| "copy right", &mut region, config.b, 0)?; - - // Copy `choice` value - let choice = choice.copy_advice(|| "copy choice", &mut region, config.swap, 0)?; - - let a_swapped = left - .value() - .zip(right.value()) - .zip(choice.value()) - .map(|((left, right), choice)| { - if *choice == F::from(0_u64) { - left - } else { - right - } - }) - .cloned(); - let b_swapped = left - .value() - .zip(right.value()) - .zip(choice.value()) - .map(|((left, right), choice)| { - if *choice == F::from(0_u64) { - right - } else { - left - } - }) - .cloned(); - - region.assign_advice(|| "out b_swap", self.config.b_swapped, 0, || b_swapped)?; - region.assign_advice(|| "out a_swap", self.config.a_swapped, 0, || a_swapped) - }, - ) - } -} - -impl CondSwapChip { - /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are `EccPoint`, - /// returns `left` if `choice` is not set and `right` if `choice` is set. - pub fn mux_on_points( - &self, - mut layouter: impl Layouter, - choice: &AssignedCell, - left: &EccPoint, - right: &EccPoint, - ) -> Result { - let x_cell = self.mux(&mut layouter, choice.clone(), left.x(), right.x())?; - let y_cell = self.mux(&mut layouter, choice.clone(), left.y(), right.y())?; - Ok(EccPoint::from_coordinates_unchecked( - x_cell.into(), - y_cell.into(), - )) - } - - /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are - /// `NonIdentityEccPoint`, returns `left` if `choice` is not set and `right` if `choice` is set. - pub fn mux_on_non_identity_points( - &self, - mut layouter: impl Layouter, - choice: &AssignedCell, - left: &NonIdentityEccPoint, - right: &NonIdentityEccPoint, - ) -> Result { - let x_cell = self.mux(&mut layouter, choice.clone(), left.x(), right.x())?; - let y_cell = self.mux(&mut layouter, choice.clone(), left.y(), right.y())?; - Ok(NonIdentityEccPoint::from_coordinates_unchecked( - x_cell.into(), - y_cell.into(), - )) - } -} - -#[cfg(test)] -mod tests { - use crate::utilities::cond_swap::{CondSwapChip, CondSwapConfig}; - use crate::utilities_opt::lookup_range_check::LookupRangeCheckConfigOptimized; - - #[test] - fn test_mux() { - use crate::{ - ecc::{ - chip::{EccChip, EccConfig}, - tests::TestFixedBases, - NonIdentityPoint, Point, - }, - utilities::lookup_range_check::LookupRangeCheck, - }; - - use group::{cofactor::CofactorCurveAffine, Curve, Group}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, - }; - use pasta_curves::arithmetic::CurveAffine; - use pasta_curves::{pallas, EpAffine}; - - use rand::rngs::OsRng; - - #[derive(Clone, Debug)] - pub struct MyConfig { - primary: Column, - advice: Column, - cond_swap_config: CondSwapConfig, - ecc_config: EccConfig< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, - } - - #[derive(Default)] - struct MyCircuit { - left_point: Value, - right_point: Value, - choice: Value, - } - - impl Circuit for MyCircuit { - type Config = MyConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - // Instance column used for public inputs - let primary = meta.instance_column(); - meta.enable_equality(primary); - - let cond_swap_config = - CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - let table_idx = meta.lookup_table_column(); - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], table_idx); - - let ecc_config = - EccChip::< - TestFixedBases, - LookupRangeCheckConfigOptimized< - pallas::Base, - { crate::sinsemilla::primitives::K }, - >, - >::configure(meta, advices, lagrange_coeffs, range_check); - - MyConfig { - primary, - advice: advices[0], - cond_swap_config, - ecc_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Construct a CondSwap chip - let cond_swap_chip = CondSwapChip::construct(config.cond_swap_config); - - // Construct an ECC chip - let ecc_chip = EccChip::construct(config.ecc_config); - - // Assign choice - let choice = layouter.assign_region( - || "load private", - |mut region| { - region.assign_advice(|| "load private", config.advice, 0, || self.choice) - }, - )?; - - // Test mux on non identity points - // Assign left point - let left_non_identity_point = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "left point"), - self.left_point.map(|left_point| left_point), - )?; - - // Assign right point - let right_non_identity_point = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "right point"), - self.right_point.map(|right_point| right_point), - )?; - - // Apply mux - let result_non_identity_point = cond_swap_chip.mux_on_non_identity_points( - layouter.namespace(|| "MUX"), - &choice, - left_non_identity_point.inner(), - right_non_identity_point.inner(), - )?; - - // Check equality with instance - layouter.constrain_instance( - result_non_identity_point.x().cell(), - config.primary, - 0, - )?; - layouter.constrain_instance( - result_non_identity_point.y().cell(), - config.primary, - 1, - )?; - - // Test mux on points - // Assign left point - let left_point = Point::new( - ecc_chip.clone(), - layouter.namespace(|| "left point"), - self.left_point.map(|left_point| left_point), - )?; - - // Assign right point - let right_point = Point::new( - ecc_chip, - layouter.namespace(|| "right point"), - self.right_point.map(|right_point| right_point), - )?; - - // Apply mux - let result = cond_swap_chip.mux_on_points( - layouter.namespace(|| "MUX"), - &choice, - left_point.inner(), - right_point.inner(), - )?; - - // Check equality with instance - layouter.constrain_instance(result.x().cell(), config.primary, 0)?; - layouter.constrain_instance(result.y().cell(), config.primary, 1) - } - } - - // Test different circuits - let mut circuits = vec![]; - let mut instances = vec![]; - for choice in [false, true] { - let choice_value = if choice { - pallas::Base::one() - } else { - pallas::Base::zero() - }; - let left_point = pallas::Point::random(OsRng).to_affine(); - let right_point = pallas::Point::random(OsRng).to_affine(); - circuits.push(MyCircuit { - left_point: Value::known(left_point), - right_point: Value::known(right_point), - choice: Value::known(choice_value), - }); - let expected_output = if choice { right_point } else { left_point }; - let (expected_x, expected_y) = if bool::from(expected_output.is_identity()) { - (pallas::Base::zero(), pallas::Base::zero()) - } else { - let coords = expected_output.coordinates().unwrap(); - (*coords.x(), *coords.y()) - }; - instances.push([[expected_x, expected_y]]); - } - - for (circuit, instance) in circuits.iter().zip(instances.iter()) { - let prover = MockProver::::run( - 5, - circuit, - instance.iter().map(|p| p.to_vec()).collect(), - ) - .unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - } -} diff --git a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs b/halo2_gadgets/src/utilities_opt/lookup_range_check.rs deleted file mode 100644 index e2c1a808a9..0000000000 --- a/halo2_gadgets/src/utilities_opt/lookup_range_check.rs +++ /dev/null @@ -1,566 +0,0 @@ -//! Make use of a K-bit lookup table to decompose a field element into K-bit -//! words. - -use std::marker::PhantomData; - -use halo2_proofs::{ - circuit::{AssignedCell, Region}, - plonk::{ - Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector, TableColumn, - }, - poly::Rotation, -}; - -#[cfg(test)] -use halo2_proofs::circuit::{Layouter, Value}; - -use ff::PrimeFieldBits; - -use pasta_curves::pallas; - -use crate::{ - sinsemilla::primitives as sinsemilla, - utilities::lookup_range_check::{ - DefaultLookupRangeCheck, LookupRangeCheck, LookupRangeCheckConfig, - }, -}; - -/// Configuration that provides methods for a lookup range check. -#[derive(Eq, PartialEq, Debug, Clone, Copy)] -pub struct LookupRangeCheckConfigOptimized { - base: LookupRangeCheckConfig, - q_range_check_4: Selector, - q_range_check_5: Selector, - table_range_check_tag: TableColumn, -} - -impl LookupRangeCheckConfigOptimized { - /// The `running_sum` advice column breaks the field element into `K`-bit - /// words. It is used to construct the input expression to the lookup - /// argument. - /// - /// The `table_idx` fixed column contains values from [0..2^K). Looking up - /// a value in `table_idx` constrains it to be within this range. The table - /// can be loaded outside this helper. - /// - /// # Side-effects - /// - /// Both the `running_sum` and `constants` columns will be equality-enabled. - pub(crate) fn configure_with_tag( - meta: &mut ConstraintSystem, - running_sum: Column, - table_idx: TableColumn, - table_range_check_tag: TableColumn, - ) -> Self { - meta.enable_equality(running_sum); - - let q_lookup = meta.complex_selector(); - let q_running = meta.complex_selector(); - let q_bitshift = meta.selector(); - - let q_range_check_4 = meta.complex_selector(); - let q_range_check_5 = meta.complex_selector(); - - // if the order of the creation makes a difference - let config = LookupRangeCheckConfigOptimized { - base: LookupRangeCheckConfig { - q_lookup, - q_running, - q_bitshift, - running_sum, - table_idx, - _marker: PhantomData, - }, - q_range_check_4, - q_range_check_5, - table_range_check_tag, - }; - - // https://p.z.cash/halo2-0.1:decompose-combined-lookup - meta.lookup(|meta| { - let q_lookup = meta.query_selector(config.base.q_lookup); - let q_running = meta.query_selector(config.base.q_running); - // if the order of the creation makes a difference - let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); - let one = Expression::Constant(F::ONE); - - // In the case of a running sum decomposition, we recover the word from - // the difference of the running sums: - // z_i = 2^{K}⋅z_{i + 1} + a_i - // => a_i = z_i - 2^{K}⋅z_{i + 1} - let running_sum_lookup = { - let running_sum_word = { - let z_next = meta.query_advice(config.base.running_sum, Rotation::next()); - z_cur.clone() - z_next * F::from(1 << K) - }; - - q_running.clone() * running_sum_word - }; - - // In the short range check, the word is directly witnessed. - let short_lookup = { - let short_word = z_cur.clone(); - let q_short = one.clone() - q_running; - - q_short * short_word - }; - - let q_range_check_4 = meta.query_selector(config.q_range_check_4); - let q_range_check_5 = meta.query_selector(config.q_range_check_5); - - // q_range_check is equal to - // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 - // - 0 otherwise - let q_range_check = one.clone() - - (one.clone() - q_range_check_4.clone()) * (one.clone() - q_range_check_5.clone()); - - // num_bits is equal to - // - 5 if q_range_check_5 = 1 - // - 4 if q_range_check_4 = 1 and q_range_check_5 = 0 - // - 0 otherwise - let num_bits = q_range_check_5.clone() * Expression::Constant(F::from(5_u64)) - + (one.clone() - q_range_check_5) - * q_range_check_4 - * Expression::Constant(F::from(4_u64)); - - // Combine the running sum, short lookups and optimized range checks: - vec![ - ( - q_lookup.clone() - * ((one - q_range_check.clone()) * (running_sum_lookup + short_lookup) - + q_range_check.clone() * z_cur), - config.base.table_idx, - ), - ( - q_lookup * q_range_check * num_bits, - config.table_range_check_tag, - ), - ] - }); - - // For short lookups, check that the word has been shifted by the correct number of bits. - // https://p.z.cash/halo2-0.1:decompose-short-lookup - meta.create_gate("Short lookup bitshift", |meta| { - let q_bitshift = meta.query_selector(config.base.q_bitshift); - let word = meta.query_advice(config.base.running_sum, Rotation::prev()); - let shifted_word = meta.query_advice(config.base.running_sum, Rotation::cur()); - let inv_two_pow_s = meta.query_advice(config.base.running_sum, Rotation::next()); - - let two_pow_k = F::from(1 << K); - - // shifted_word = word * 2^{K-s} - // = word * 2^K * inv_two_pow_s - Constraints::with_selector( - q_bitshift, - Some(word * two_pow_k * inv_two_pow_s - shifted_word), - ) - }); - - config - } - - pub(crate) fn table_range_check_tag(&self) -> TableColumn { - self.table_range_check_tag - } -} - -impl LookupRangeCheck - for LookupRangeCheckConfigOptimized -{ - fn config(&self) -> &LookupRangeCheckConfig { - &self.base - } - - fn configure( - meta: &mut ConstraintSystem, - running_sum: Column, - table_idx: TableColumn, - ) -> Self { - let table_range_check_tag = meta.lookup_table_column(); - Self::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) - } - - #[cfg(test)] - // Fill `table_idx` and `table_range_check_tag`. - // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table - // in the Orchard context. - fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { - layouter.assign_table( - || "table_idx", - |mut table| { - let mut assign_cells = - |offset: usize, table_size, value: u64| -> Result { - for index in 0..table_size { - let new_index = index + offset; - table.assign_cell( - || "table_idx", - self.base.table_idx, - new_index, - || Value::known(F::from(index as u64)), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(F::from(value)), - )?; - } - Ok(offset + table_size) - }; - - // We generate the row values lazily (we only need them during keygen). - let mut offset = 0; - - //annotation: &'v (dyn Fn() -> String + 'v), - //column: TableColumn, - //offset: usize, - //to: &'v mut (dyn FnMut() -> Value> + 'v), - - offset = assign_cells(offset, 1 << K, 0)?; - offset = assign_cells(offset, 1 << 4, 4)?; - assign_cells(offset, 1 << 5, 5)?; - - Ok(()) - }, - ) - } - - /// Constrain `x` to be a NUM_BITS word. - /// - /// `element` must have been assigned to `self.running_sum` at offset 0. - fn short_range_check( - &self, - region: &mut Region<'_, F>, - element: AssignedCell, - num_bits: usize, - ) -> Result<(), Error> { - match num_bits { - 4 => { - self.base.q_lookup.enable(region, 0)?; - self.q_range_check_4.enable(region, 0)?; - Ok(()) - } - - 5 => { - self.base.q_lookup.enable(region, 0)?; - self.q_range_check_5.enable(region, 0)?; - Ok(()) - } - - _ => self.base.short_range_check(region, element, num_bits), - } - } -} - -#[cfg(test)] -mod tests { - use super::{LookupRangeCheck, LookupRangeCheckConfigOptimized}; - - use crate::sinsemilla::primitives::K; - use crate::utilities::lebs2ip; - - use ff::{Field, PrimeFieldBits}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::{FailureLocation, MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use pasta_curves::pallas; - - use std::{convert::TryInto, marker::PhantomData}; - - #[test] - fn lookup_range_check() { - #[derive(Clone, Copy)] - struct MyCircuit { - num_words: usize, - _marker: PhantomData, - } - - impl Circuit for MyCircuit { - type Config = LookupRangeCheckConfigOptimized; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - *self - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - LookupRangeCheckConfigOptimized::::configure_with_tag( - meta, - running_sum, - table_idx, - table_range_check_tag, - ) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_words * K bits. - let elements_and_expected_final_zs = [ - (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long - (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long - ]; - - fn expected_zs( - element: F, - num_words: usize, - ) -> Vec { - let chunks = { - element - .to_le_bits() - .iter() - .by_vals() - .take(num_words * K) - .collect::>() - .chunks_exact(K) - .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) - .collect::>() - }; - let expected_zs = { - let inv_two_pow_k = F::from(1 << K).invert().unwrap(); - chunks.iter().fold(vec![element], |mut zs, a_i| { - // z_{i + 1} = (z_i - a_i) / 2^{K} - let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; - zs.push(z); - zs - }) - }; - expected_zs - } - - for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { - let expected_zs = expected_zs::(*element, self.num_words); - - let zs = config.witness_check( - layouter.namespace(|| format!("Lookup {:?}", self.num_words)), - Value::known(*element), - self.num_words, - *strict, - )?; - - assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); - - for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { - z.value().assert_if_known(|z| &&expected_z == z); - } - } - Ok(()) - } - } - - { - let circuit: MyCircuit = MyCircuit { - num_words: 6, - _marker: PhantomData, - }; - - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - } - - #[test] - fn short_range_check() { - struct MyCircuit { - element: Value, - num_bits: usize, - } - - impl Circuit for MyCircuit { - type Config = LookupRangeCheckConfigOptimized; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - MyCircuit { - element: Value::unknown(), - num_bits: self.num_bits, - } - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - LookupRangeCheckConfigOptimized::::configure_with_tag( - meta, - running_sum, - table_idx, - table_range_check_tag, - ) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_bits. - config.witness_short_check( - layouter.namespace(|| format!("Lookup {:?} bits", self.num_bits)), - self.element, - self.num_bits, - )?; - - Ok(()) - } - } - - // Edge case: zero bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::ZERO), - num_bits: 0, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - - // Edge case: K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << K) - 1)), - num_bits: K, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - - // Element within `num_bits` - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << 6) - 1)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - - // Element larger than `num_bits` but within K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << 6)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }]) - ); - } - - // Element larger than K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << K)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }, - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }, - ]) - ); - } - - // Element which is not within `num_bits`, but which has a shifted value within - // num_bits - { - let num_bits = 6; - let shifted = pallas::Base::from((1 << num_bits) - 1); - // Recall that shifted = element * 2^{K-s} - // => element = shifted * 2^{s-K} - let element = shifted - * pallas::Base::from(1 << (K as u64 - num_bits)) - .invert() - .unwrap(); - let circuit: MyCircuit = MyCircuit { - element: Value::known(element), - num_bits: num_bits as usize, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }]) - ); - } - - // Element within 4 bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << 4) - 1)), - num_bits: 4, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - - // Element larger than 5 bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << 5)), - num_bits: 5, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 5 bits").into(), - offset: 0, - }, - }]) - ); - } - } -} - -pub(crate) type DefaultLookupRangeCheckConfigOptimized = - LookupRangeCheckConfigOptimized; - -impl DefaultLookupRangeCheck for DefaultLookupRangeCheckConfigOptimized {} From 7e50d0b72c75991a04820373db5730c0556371ab Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Fri, 10 May 2024 15:30:36 +0200 Subject: [PATCH 021/121] minor update --- halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 8818147f41..5d7b6081d9 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -19,6 +19,7 @@ use std::ops::Deref; /// Define an enum that can hold either type #[derive(Debug, Clone)] +#[allow(dead_code)] pub enum EccPointQ<'a> { PublicPoint(pallas::Affine), PrivatePoint(&'a NonIdentityEccPoint), From 58f8b3f5c387a440fb05fb6d529c27208ee54092 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 13:34:49 +0200 Subject: [PATCH 022/121] remove pub(crate) in ecc --- halo2_gadgets/src/ecc.rs | 6 +++--- halo2_gadgets/src/ecc/chip.rs | 20 +++++++++---------- halo2_gadgets/src/ecc/chip/mul.rs | 5 +++-- halo2_gadgets/src/ecc/chip/mul_fixed.rs | 6 +++--- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 6 ++---- halo2_gadgets/src/ecc/chip/witness_point.rs | 4 ++-- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 8cb9ce4d57..2e16b3d1a6 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -231,7 +231,7 @@ impl> ScalarFixed { #[derive(Debug)] pub struct ScalarFixedShort> { chip: EccChip, - pub(crate) inner: EccChip::ScalarFixedShort, + inner: EccChip::ScalarFixedShort, } impl> ScalarFixedShort { @@ -375,8 +375,8 @@ impl + Clone + Debug + Eq> /// A point on a specific elliptic curve. #[derive(Copy, Clone, Debug)] pub struct Point + Clone + Debug + Eq> { - pub(crate) chip: EccChip, - pub(crate) inner: EccChip::Point, + chip: EccChip, + inner: EccChip::Point, } impl + Clone + Debug + Eq> Point { diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index c27a34ca6b..7133bdfd78 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -14,12 +14,12 @@ use pasta_curves::{arithmetic::CurveAffine, pallas}; use std::convert::TryInto; -pub(crate) mod add; -pub(crate) mod add_incomplete; +pub(super) mod add; +pub(super) mod add_incomplete; pub mod constants; -pub(crate) mod mul; -pub(crate) mod mul_fixed; -pub(crate) mod witness_point; +pub(super) mod mul; +pub(super) mod mul_fixed; +pub(super) mod witness_point; pub use constants::*; @@ -34,11 +34,11 @@ pub struct EccPoint { /// x-coordinate /// /// Stored as an `Assigned` to enable batching inversions. - pub(crate) x: AssignedCell, pallas::Base>, + x: AssignedCell, pallas::Base>, /// y-coordinate /// /// Stored as an `Assigned` to enable batching inversions. - pub(crate) y: AssignedCell, pallas::Base>, + y: AssignedCell, pallas::Base>, } impl EccPoint { @@ -153,12 +153,12 @@ pub struct EccConfig< /// Fixed-base full-width scalar multiplication mul_fixed_full: mul_fixed::full_width::Config, /// Fixed-base signed short scalar multiplication - pub(crate) mul_fixed_short: mul_fixed::short::Config, + mul_fixed_short: mul_fixed::short::Config, /// Fixed-base mul using a base field element as a scalar mul_fixed_base_field: mul_fixed::base_field_elem::Config, /// Witness point - pub(crate) witness_point: witness_point::Config, + witness_point: witness_point::Config, /// Lookup range check using 10-bit lookup table pub lookup_config: Lookup, @@ -345,7 +345,7 @@ pub struct EccScalarFixed { type MagnitudeCell = AssignedCell; // TODO: Make V an enum Sign { Positive, Negative } type SignCell = AssignedCell; -pub(crate) type MagnitudeSign = (MagnitudeCell, SignCell); +type MagnitudeSign = (MagnitudeCell, SignCell); /// A signed short scalar used for fixed-base scalar multiplication. /// A short scalar must have magnitude in the range [0..2^64), with diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index a67b77b0e8..02d2e2d805 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -62,7 +62,7 @@ pub struct Config { } impl Config { - pub(crate) fn configure( + pub(super) fn configure( meta: &mut ConstraintSystem, add_config: add::Config, lookup_config: Lookup, @@ -460,6 +460,7 @@ pub mod tests { ff::{Field, PrimeField}, Curve, }; + use halo2_proofs::circuit::Chip; use halo2_proofs::{ circuit::{Layouter, Value}, plonk::Error, @@ -483,7 +484,7 @@ pub mod tests { p: &NonIdentityPoint>, p_val: pallas::Affine, ) -> Result<(), Error> { - let column = chip.config.advices[0]; + let column = chip.config().advices[0]; fn constrain_equal_non_id< EccChip: EccInstructions + Clone + Eq + std::fmt::Debug, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed.rs b/halo2_gadgets/src/ecc/chip/mul_fixed.rs index 686cb6203e..d0781056b8 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed.rs @@ -41,11 +41,11 @@ pub struct Config> { fixed_z: Column, // Decomposition of an `n-1`-bit scalar into `k`-bit windows: // a = a_0 + 2^k(a_1) + 2^{2k}(a_2) + ... + 2^{(n-1)k}(a_{n-1}) - pub(crate) window: Column, + window: Column, // y-coordinate of accumulator (only used in the final row). - pub(crate) u: Column, + u: Column, // Configuration for `add` - pub(crate) add_config: add::Config, + add_config: add::Config, // Configuration for `add_incomplete` add_incomplete_config: add_incomplete::Config, _marker: PhantomData, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 48a1cbf88a..acbba7cc3a 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -13,8 +13,8 @@ use pasta_curves::pallas; #[derive(Clone, Debug, Eq, PartialEq)] pub struct Config> { // Selector used for fixed-base scalar mul with short signed exponent. - pub(crate) q_mul_fixed_short: Selector, - pub(crate) super_config: super::Config, + q_mul_fixed_short: Selector, + super_config: super::Config, } impl> Config { @@ -401,8 +401,6 @@ pub mod tests { Ok(()) } - // todo: fixit - #[test] fn invalid_magnitude_sign() { use crate::{ diff --git a/halo2_gadgets/src/ecc/chip/witness_point.rs b/halo2_gadgets/src/ecc/chip/witness_point.rs index 580a07ca1d..7cba8d6f87 100644 --- a/halo2_gadgets/src/ecc/chip/witness_point.rs +++ b/halo2_gadgets/src/ecc/chip/witness_point.rs @@ -12,14 +12,14 @@ use halo2_proofs::{ }; use pasta_curves::{arithmetic::CurveAffine, pallas}; -pub(crate) type Coordinates = ( +type Coordinates = ( AssignedCell, pallas::Base>, AssignedCell, pallas::Base>, ); #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { - pub(crate) q_point: Selector, + q_point: Selector, q_point_non_id: Selector, // x-coordinate pub x: Column, From 738eabeb27a79af4a75b7b5fe0f538be982473f3 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 13:45:39 +0200 Subject: [PATCH 023/121] add a line after cargo.toml --- halo2_gadgets/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_gadgets/Cargo.toml b/halo2_gadgets/Cargo.toml index 2021d77e25..09ab4efc84 100644 --- a/halo2_gadgets/Cargo.toml +++ b/halo2_gadgets/Cargo.toml @@ -82,4 +82,4 @@ harness = false [[bench]] name = "sha256" harness = false -required-features = ["unstable-sha256-gadget"] \ No newline at end of file +required-features = ["unstable-sha256-gadget"] From 0fb6dd4c1d05845d93feecf1d905ca620bfc24ff Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 13:46:51 +0200 Subject: [PATCH 024/121] add a line after cargo.toml --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index c7ceac9436..8c33191917 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2280,4 +2280,4 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", -] \ No newline at end of file +] From e2c9c30a5a50ac8473f08da3dc2859124b859529 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 13:50:11 +0200 Subject: [PATCH 025/121] slide lines in base_field_elem --- halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 5ea0b38eef..c9861e24e9 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -463,10 +463,10 @@ pub mod tests { { let h = pallas::Base::from(H as u64); let scalar_fixed = "1333333333333333333333333333333333333333333333333333333333333333333333333333333333334" - .chars() - .fold(pallas::Base::zero(), |acc, c| { - acc * &h + &pallas::Base::from(c.to_digit(8).unwrap() as u64) - }); + .chars() + .fold(pallas::Base::zero(), |acc, c| { + acc * &h + &pallas::Base::from(c.to_digit(8).unwrap() as u64) + }); let result = { let scalar_fixed = chip.load_private( layouter.namespace(|| "mul with double"), From 5322c81bf61dc9e57bb48af2dd3bace81c6430b3 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 13:51:11 +0200 Subject: [PATCH 026/121] slide lines in base_field_elem --- halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index c9861e24e9..24f7114b4a 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -463,10 +463,10 @@ pub mod tests { { let h = pallas::Base::from(H as u64); let scalar_fixed = "1333333333333333333333333333333333333333333333333333333333333333333333333333333333334" - .chars() - .fold(pallas::Base::zero(), |acc, c| { - acc * &h + &pallas::Base::from(c.to_digit(8).unwrap() as u64) - }); + .chars() + .fold(pallas::Base::zero(), |acc, c| { + acc * &h + &pallas::Base::from(c.to_digit(8).unwrap() as u64) + }); let result = { let scalar_fixed = chip.load_private( layouter.namespace(|| "mul with double"), From 46773e3963d766030f88cd77056b2c6654f8fad3 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 14:01:58 +0200 Subject: [PATCH 027/121] adjuct function orders for configure in sinsemilla/chip --- halo2_gadgets/src/sinsemilla.rs | 58 +++++---- halo2_gadgets/src/sinsemilla/chip.rs | 168 +++++++++++++-------------- 2 files changed, 112 insertions(+), 114 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index e10e504013..8c5a4eaf37 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -15,7 +15,7 @@ use std::fmt::Debug; pub mod chip; pub mod merkle; -pub(crate) mod message; +mod message; pub mod primitives; /// The set of circuit instructions required to use the [`Sinsemilla`](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html) gadget. @@ -102,8 +102,8 @@ pub struct Message + Clone + Debug + Eq, { - pub(crate) chip: SinsemillaChip, - pub(crate) inner: SinsemillaChip::Message, + chip: SinsemillaChip, + inner: SinsemillaChip::Message, } impl @@ -112,7 +112,7 @@ where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, { #![allow(dead_code)] - pub(crate) fn from_bitstring( + fn from_bitstring( chip: SinsemillaChip, mut layouter: impl Layouter, bitstring: Vec>, @@ -186,7 +186,7 @@ where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, { #![allow(dead_code)] - pub(crate) fn from_bitstring( + fn from_bitstring( chip: SinsemillaChip, layouter: impl Layouter, bitstring: &[Value], @@ -276,23 +276,22 @@ pub struct HashDomain< > where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< - C, - NonIdentityPoint = >::NonIdentityPoint, - FixedPoints = >::FixedPoints, - > + Clone - + Debug - + Eq, + C, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, { - pub(crate) sinsemilla_chip: SinsemillaChip, - pub(crate) ecc_chip: EccChip, - pub(crate) Q: C, + sinsemilla_chip: SinsemillaChip, + ecc_chip: EccChip, + Q: C, } impl -HashDomain - where - SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, - EccChip: EccInstructions< + HashDomain where + SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, + EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, @@ -376,22 +375,21 @@ pub struct CommitDomain< > where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< - C, - NonIdentityPoint = >::NonIdentityPoint, - FixedPoints = >::FixedPoints, - > + Clone - + Debug - + Eq, + C, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, { - pub(crate) M: HashDomain, - pub(crate) R: ecc::FixedPoint, + M: HashDomain, + R: ecc::FixedPoint, } impl -CommitDomain - where - SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, - EccChip: EccInstructions< + CommitDomain where + SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, + EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 7d96f2c8f3..419cea1609 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -23,10 +23,10 @@ use halo2_proofs::{ }; use pasta_curves::pallas; -pub(crate) mod generator_table; +mod generator_table; use generator_table::GeneratorTableConfig; -pub(crate) mod hash_to_point; +mod hash_to_point; /// Configuration for the Sinsemilla hash chip #[derive(Eq, PartialEq, Clone, Debug)] @@ -38,29 +38,29 @@ where Lookup: DefaultLookupRangeCheck, { /// Binary selector used in lookup argument and in the body of the Sinsemilla hash. - pub(crate) q_sinsemilla1: Selector, + q_sinsemilla1: Selector, /// Non-binary selector used in lookup argument and in the body of the Sinsemilla hash. - pub(crate) q_sinsemilla2: Column, + q_sinsemilla2: Column, /// q_sinsemilla2 is used to define a synthetic selector, /// q_sinsemilla3 = (q_sinsemilla2) ⋅ (q_sinsemilla2 - 1) /// Simple selector used to constrain hash initialization to be consistent with /// the y-coordinate of the domain $Q$. - pub(crate) q_sinsemilla4: Selector, + q_sinsemilla4: Selector, /// Fixed column used to load the y-coordinate of the domain $Q$. - pub(crate) fixed_y_q: Column, + fixed_y_q: Column, /// Logic specific to merged double-and-add. - pub(crate) double_and_add: DoubleAndAdd, + double_and_add: DoubleAndAdd, /// Advice column used to load the message. - pub(crate) bits: Column, + bits: Column, /// Advice column used to witness message pieces. This may or may not be the same /// column as `bits`. - pub(crate) witness_pieces: Column, + witness_pieces: Column, /// The lookup table where $(\mathsf{idx}, x_p, y_p)$ are loaded for the $2^K$ /// generators of the Sinsemilla hash. - pub(crate) generator_table: GeneratorTableConfig, + pub(super) generator_table: GeneratorTableConfig, /// An advice column configured to perform lookup range checks. - pub(crate) lookup_config: Lookup, - pub(crate) _marker: PhantomData<(Hash, Commit, F)>, + lookup_config: Lookup, + _marker: PhantomData<(Hash, Commit, F)>, } impl SinsemillaConfig @@ -149,8 +149,79 @@ where config.generator_table.load(layouter) } + /// # Side-effects + /// + /// All columns in `advices` and will be equality-enabled. + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] + pub fn configure( + meta: &mut ConstraintSystem, + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + lookup: (TableColumn, TableColumn, TableColumn), + range_check: Lookup, + ) -> >::Config { + // create SinsemillaConfig + let config = Self::create_config( + meta, + advices, + witness_pieces, + fixed_y_q, + lookup, + range_check, + ); + + Self::create_initial_y_q_gate(meta, &config); + + Self::create_sinsemilla_gate(meta, &config); + + config + } + + pub(crate) fn create_config( + meta: &mut ConstraintSystem, + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + lookup: (TableColumn, TableColumn, TableColumn), + range_check: Lookup, + ) -> >::Config { + // Enable equality on all advice columns + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let config = SinsemillaConfig:: { + q_sinsemilla1: meta.complex_selector(), + q_sinsemilla2: meta.fixed_column(), + q_sinsemilla4: meta.selector(), + fixed_y_q, + double_and_add: DoubleAndAdd { + x_a: advices[0], + x_p: advices[1], + lambda_1: advices[3], + lambda_2: advices[4], + }, + bits: advices[2], + witness_pieces, + generator_table: GeneratorTableConfig { + table_idx: lookup.0, + table_x: lookup.1, + table_y: lookup.2, + }, + lookup_config: range_check, + _marker: PhantomData, + }; + + // Set up lookup argument + GeneratorTableConfig::configure(meta, &config); + + config + } + #[allow(non_snake_case)] - pub(crate) fn create_initial_y_q_gate( + fn create_initial_y_q_gate( meta: &mut ConstraintSystem, config: &SinsemillaConfig, ) { @@ -240,77 +311,6 @@ where Constraints::with_selector(q_s1, [("Secant line", secant_line), ("y check", y_check)]) }); } - - pub(crate) fn create_config( - meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - lookup: (TableColumn, TableColumn, TableColumn), - range_check: Lookup, - ) -> >::Config { - // Enable equality on all advice columns - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let config = SinsemillaConfig:: { - q_sinsemilla1: meta.complex_selector(), - q_sinsemilla2: meta.fixed_column(), - q_sinsemilla4: meta.selector(), - fixed_y_q, - double_and_add: DoubleAndAdd { - x_a: advices[0], - x_p: advices[1], - lambda_1: advices[3], - lambda_2: advices[4], - }, - bits: advices[2], - witness_pieces, - generator_table: GeneratorTableConfig { - table_idx: lookup.0, - table_x: lookup.1, - table_y: lookup.2, - }, - lookup_config: range_check, - _marker: PhantomData, - }; - - // Set up lookup argument - GeneratorTableConfig::configure(meta, &config); - - config - } - - /// # Side-effects - /// - /// All columns in `advices` and will be equality-enabled. - #[allow(clippy::too_many_arguments)] - #[allow(non_snake_case)] - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - lookup: (TableColumn, TableColumn, TableColumn), - range_check: Lookup, - ) -> >::Config { - // create SinsemillaConfig - let config = Self::create_config( - meta, - advices, - witness_pieces, - fixed_y_q, - lookup, - range_check, - ); - - Self::create_initial_y_q_gate(meta, &config); - - Self::create_sinsemilla_gate(meta, &config); - - config - } } // Implement `SinsemillaInstructions` for `SinsemillaChip` From 3621e0e36768e56cf6ec3fb8f8fc1209b4a70995 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 14:13:16 +0200 Subject: [PATCH 028/121] adjuct function orders for hash_message --- halo2_gadgets/src/sinsemilla/chip.rs | 2 +- .../src/sinsemilla/chip/generator_table.rs | 2 +- .../src/sinsemilla/chip/hash_to_point.rs | 136 +++++++++--------- 3 files changed, 70 insertions(+), 70 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 419cea1609..95e40ec0f3 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -215,7 +215,7 @@ where }; // Set up lookup argument - GeneratorTableConfig::configure(meta, &config); + GeneratorTableConfig::configure(meta, config.clone()); config } diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 80551a6c91..41e2f42c99 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -28,7 +28,7 @@ impl GeneratorTableConfig { /// controlled by `q_sinsemilla`, and would likely not apply to other chips. pub fn configure( meta: &mut ConstraintSystem, - config: &super::SinsemillaConfig, + config: super::SinsemillaConfig, ) where Hash: HashDomains, F: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 5d7b6081d9..0c1bf9fa04 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -39,7 +39,7 @@ where /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - pub(crate) fn hash_message( + pub(super) fn hash_message( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, @@ -56,73 +56,6 @@ where self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum) } - #[allow(non_snake_case)] - #[allow(unused_variables)] - // Check equivalence to result from primitives::sinsemilla::hash_to_point - pub(crate) fn check_hash_result( - &self, - Q: EccPointQ, - message: &>::Message, - x_a: X, - y_a: AssignedCell, pallas::Base>, - zs_sum: Vec>>, - ) -> HashResult { - #[cfg(test)] - { - use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; - - use group::{prime::PrimeCurveAffine, Curve}; - use pasta_curves::arithmetic::CurveExt; - - let field_elems: Value> = message - .iter() - .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) - .collect(); - - let value_Q = match Q { - EccPointQ::PublicPoint(p) => Value::known(p), - EccPointQ::PrivatePoint(p) => p.point(), - }; - - field_elems - .zip(x_a.value().zip(y_a.value())) - .zip(value_Q) - .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { - // Get message as a bitstring. - let bitstring: Vec = field_elems - .iter() - .flat_map(|(elem, num_words)| { - elem.to_le_bits().into_iter().take(K * num_words) - }) - .collect(); - - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - - // We can use complete addition here because it differs from - // incomplete addition with negligible probability. - let expected_point = bitstring - .chunks(K) - .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); - let actual_point = - pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); - expected_point.to_affine() == actual_point - }); - } - - x_a.value() - .zip(y_a.value()) - .error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?; - Ok(( - NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a), - zs_sum, - )) - } - #[allow(non_snake_case)] /// Assign the coordinates of the initial public point `Q`, /// y_Q to a fixed column @@ -244,6 +177,73 @@ where Ok((x_a, y_a, zs_sum)) } + #[allow(non_snake_case)] + #[allow(unused_variables)] + // Check equivalence to result from primitives::sinsemilla::hash_to_point + pub(crate) fn check_hash_result( + &self, + Q: EccPointQ, + message: &>::Message, + x_a: X, + y_a: AssignedCell, pallas::Base>, + zs_sum: Vec>>, + ) -> HashResult { + #[cfg(test)] + { + use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; + + use group::{prime::PrimeCurveAffine, Curve}; + use pasta_curves::arithmetic::CurveExt; + + let field_elems: Value> = message + .iter() + .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) + .collect(); + + let value_Q = match Q { + EccPointQ::PublicPoint(p) => Value::known(p), + EccPointQ::PrivatePoint(p) => p.point(), + }; + + field_elems + .zip(x_a.value().zip(y_a.value())) + .zip(value_Q) + .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { + // Get message as a bitstring. + let bitstring: Vec = field_elems + .iter() + .flat_map(|(elem, num_words)| { + elem.to_le_bits().into_iter().take(K * num_words) + }) + .collect(); + + let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); + let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); + + // We can use complete addition here because it differs from + // incomplete addition with negligible probability. + let expected_point = bitstring + .chunks(K) + .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); + let actual_point = + pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); + expected_point.to_affine() == actual_point + }); + } + + x_a.value() + .zip(y_a.value()) + .error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?; + Ok(( + NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a), + zs_sum, + )) + } + #[allow(clippy::type_complexity)] /// Hashes a message piece containing `piece.length` number of `K`-bit words. /// From a30596b0bab90c6c4fe52c552290b57158960838 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 14:17:41 +0200 Subject: [PATCH 029/121] adjuct function orders for hash_message --- .../src/sinsemilla/chip/hash_to_point.rs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 0c1bf9fa04..48a085e9b7 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -25,10 +25,6 @@ pub enum EccPointQ<'a> { PrivatePoint(&'a NonIdentityEccPoint), } -type HashOutput = NonIdentityEccPoint; -type CellMatrix = Vec>>; -type HashResult = Result<(HashOutput, CellMatrix), Error>; - impl SinsemillaChip where Hash: HashDomains, @@ -48,7 +44,13 @@ where { sinsemilla::K }, { sinsemilla::C }, >>::Message, - ) -> HashResult { + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { let (offset, x_a, y_a) = self.public_initialization(region, Q)?; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; @@ -177,9 +179,7 @@ where Ok((x_a, y_a, zs_sum)) } - #[allow(non_snake_case)] #[allow(unused_variables)] - // Check equivalence to result from primitives::sinsemilla::hash_to_point pub(crate) fn check_hash_result( &self, Q: EccPointQ, @@ -191,8 +191,16 @@ where x_a: X, y_a: AssignedCell, pallas::Base>, zs_sum: Vec>>, - ) -> HashResult { + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { #[cfg(test)] + #[allow(non_snake_case)] + // Check equivalence to result from primitives::sinsemilla::hash_to_point { use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; @@ -452,7 +460,7 @@ where } /// The x-coordinate of the accumulator in a Sinsemilla hash instance. -pub(crate) struct X(pub(crate) AssignedCell, F>); +struct X(AssignedCell, F>); impl From, F>> for X { fn from(cell_value: AssignedCell, F>) -> Self { @@ -473,7 +481,7 @@ impl Deref for X { /// This is never actually witnessed until the last round, since it /// can be derived from other variables. Thus it only exists as a field /// element, not a `CellValue`. -pub(crate) struct Y(pub(crate) Value>); +struct Y(Value>); impl From>> for Y { fn from(value: Value>) -> Self { From b3cb4531d6b6c73495cf615dc7628f5fc4d72589 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 15:14:52 +0200 Subject: [PATCH 030/121] cleanup code --- halo2_gadgets/src/ecc.rs | 11 ++--- halo2_gadgets/src/sinsemilla.rs | 11 ++--- .../src/sinsemilla/chip/hash_to_point.rs | 9 ++-- halo2_gadgets/src/sinsemilla/merkle.rs | 21 +++++---- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 10 ++--- halo2_gadgets/src/sinsemilla/primitives.rs | 6 +-- halo2_gadgets/src/utilities/cond_swap.rs | 14 +++--- .../src/utilities/lookup_range_check.rs | 43 ++++++++----------- halo2_gadgets/src/utilities/test_circuit.rs | 29 +++---------- halo2_proofs/src/circuit.rs | 10 ----- 10 files changed, 67 insertions(+), 97 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 2e16b3d1a6..4b7d0e291b 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -599,7 +599,7 @@ pub(crate) mod tests { FixedPoints, }; use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; - use crate::utilities::test_circuit::{read_test_case, test_proof_size, write_test_case, Proof}; + use crate::utilities::test_circuit::{read_test_case, write_test_case, Proof}; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -912,7 +912,7 @@ pub(crate) mod tests { } #[test] - fn round_trip() { + fn fixed_verification_key_test() { let k = 11; let circuit = MyCircuit { test_errors: false }; @@ -929,7 +929,6 @@ pub(crate) mod tests { include_str!("vk_ecc_chip").replace("\r\n", "\n") ); } - test_proof_size(k, circuit, ¶ms, &vk) } #[test] @@ -941,6 +940,8 @@ pub(crate) mod tests { let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, + // write the old proof in a file if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); @@ -952,13 +953,13 @@ pub(crate) mod tests { create_proof().expect("should be able to write new proof"); } - // Parse the hardcoded proof test case. + // Read the old proof into 'proof' let proof = { let test_case_bytes = fs::read("src/circuit_proof_test_case_ecc.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - assert_eq!(proof.as_ref().len(), 3872); + // Verify the old proof with the new vk assert!(proof.verify(&vk, ¶ms).is_ok()); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 8c5a4eaf37..9d5f26f18a 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -481,7 +481,7 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::utilities::test_circuit::{read_test_case, test_proof_size, write_test_case, Proof}; + use crate::utilities::test_circuit::{read_test_case, write_test_case, Proof}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::convert::TryInto; @@ -758,7 +758,7 @@ pub(crate) mod tests { } #[test] - fn round_trip() { + fn fixed_verification_key_test() { let k = 11; let circuit = MyCircuit {}; @@ -775,7 +775,6 @@ pub(crate) mod tests { include_str!("vk_sinsemilla_chip").replace("\r\n", "\n") ); } - test_proof_size(11, circuit, ¶ms, &vk) } #[test] @@ -787,6 +786,8 @@ pub(crate) mod tests { let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, + // write the old proof in a file if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); @@ -798,13 +799,13 @@ pub(crate) mod tests { create_proof().expect("should be able to write new proof"); } - // Parse the hardcoded proof test case. + // Read the old proof into 'proof' let proof = { let test_case_bytes = fs::read("src/circuit_proof_test_case_sinsemilla.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - assert_eq!(proof.as_ref().len(), 4576); + // Verify the old proof with the new vk assert!(proof.verify(&vk, ¶ms).is_ok()); } diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 48a085e9b7..7efef14635 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -65,7 +65,7 @@ where /// | offset | x_A | q_sinsemilla4 | fixed_y_q | /// -------------------------------------- /// | 0 | x_Q | 1 | y_Q | - pub(crate) fn public_initialization( + fn public_initialization( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, @@ -109,7 +109,7 @@ where #[allow(clippy::type_complexity)] /// Hash `message` from the initial point `Q`. - pub(crate) fn hash_all_pieces( + fn hash_all_pieces( &self, region: &mut Region<'_, pallas::Base>, mut offset: usize, @@ -180,7 +180,9 @@ where } #[allow(unused_variables)] - pub(crate) fn check_hash_result( + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn check_hash_result( &self, Q: EccPointQ, message: & { #[cfg(test)] - #[allow(non_snake_case)] // Check equivalence to result from primitives::sinsemilla::hash_to_point { use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 345877ec24..19fdd8d424 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -56,11 +56,11 @@ pub struct MerklePath< > where MerkleChip: MerkleInstructions + Clone, { - pub(crate) chips: [MerkleChip; PAR], - pub(crate) domain: MerkleChip::HashDomains, - pub(crate) leaf_pos: Value, + chips: [MerkleChip; PAR], + domain: MerkleChip::HashDomains, + leaf_pos: Value, // The Merkle path is ordered from leaves to root. - pub(crate) path: Value<[C::Base; PATH_LENGTH]>, + path: Value<[C::Base; PATH_LENGTH]>, } impl< @@ -200,7 +200,7 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::utilities::test_circuit::{read_test_case, test_proof_size, write_test_case, Proof}; + use crate::utilities::test_circuit::{read_test_case, write_test_case, Proof}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; @@ -403,7 +403,7 @@ pub mod tests { } #[test] - fn round_trip() { + fn fixed_verification_key_test() { let k = 11; let circuit = generate_circuit(); @@ -420,9 +420,6 @@ pub mod tests { include_str!("vk_merkle_chip").replace("\r\n", "\n") ); } - - // Test that the proof size is as expected. - test_proof_size(k, circuit, ¶ms, &vk) } #[test] @@ -434,6 +431,8 @@ pub mod tests { let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, + // write the old proof in a file if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); @@ -446,14 +445,14 @@ pub mod tests { create_proof().expect("should be able to write new proof"); } - // Parse the hardcoded proof test case. + // Read the old proof into 'proof' let proof = { let test_case_bytes = fs::read("src/sinsemilla/circuit_proof_test_case_merkle.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - assert_eq!(proof.as_ref().len(), 4160); + // Verify the old proof with the new vk assert!(proof.verify(&vk, ¶ms).is_ok()); } diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 5c26cff058..033967dbd7 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -35,10 +35,10 @@ where Commit: CommitDomains, Lookup: DefaultLookupRangeCheck, { - pub(crate) advices: [Column; 5], - pub(crate) q_decompose: Selector, - pub(crate) cond_swap_config: CondSwapConfig, - pub(crate) sinsemilla_config: SinsemillaConfig, + advices: [Column; 5], + q_decompose: Selector, + pub(super) cond_swap_config: CondSwapConfig, + pub(super) sinsemilla_config: SinsemillaConfig, } /// Chip implementing `MerkleInstructions`. @@ -59,7 +59,7 @@ where Commit: CommitDomains, Lookup: DefaultLookupRangeCheck, { - pub(crate) config: MerkleConfig, + config: MerkleConfig, } impl Chip for MerkleChip diff --git a/halo2_gadgets/src/sinsemilla/primitives.rs b/halo2_gadgets/src/sinsemilla/primitives.rs index c47ac1b379..9bf6a72332 100644 --- a/halo2_gadgets/src/sinsemilla/primitives.rs +++ b/halo2_gadgets/src/sinsemilla/primitives.rs @@ -56,7 +56,7 @@ fn extract_p_bottom(point: CtOption) -> CtOption { /// Pads the given iterator (which MUST have length $\leq K * C$) with zero-bits to a /// multiple of $K$ bits. -pub(crate) struct Pad> { +struct Pad> { /// The iterator we are padding. inner: I, /// The measured length of the inner iterator. @@ -184,8 +184,8 @@ impl HashDomain { #[derive(Debug)] #[allow(non_snake_case)] pub struct CommitDomain { - pub(crate) M: HashDomain, - pub(crate) R: pallas::Point, + M: HashDomain, + R: pallas::Point, } impl CommitDomain { diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 7712c89b2a..d733e6c4fb 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -29,7 +29,7 @@ pub trait CondSwapInstructions: UtilitiesInstructions { /// A chip implementing a conditional swap. #[derive(Clone, Debug)] pub struct CondSwapChip { - pub(crate) config: CondSwapConfig, + config: CondSwapConfig, _marker: PhantomData, } @@ -49,12 +49,12 @@ impl Chip for CondSwapChip { /// Configuration for the [`CondSwapChip`]. #[derive(Clone, Debug, PartialEq, Eq)] pub struct CondSwapConfig { - pub(crate) q_swap: Selector, - pub(crate) a: Column, - pub(crate) b: Column, - pub(crate) a_swapped: Column, - pub(crate) b_swapped: Column, - pub(crate) swap: Column, + q_swap: Selector, + a: Column, + b: Column, + a_swapped: Column, + b_swapped: Column, + swap: Column, } #[cfg(test)] diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 73e14bec06..63f97278bc 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -53,7 +53,7 @@ impl RangeConstrained> { .map(|inner| Self { inner, num_bits, - _phantom: PhantomData, + _phantom: PhantomData::default(), }) } } @@ -61,12 +61,12 @@ impl RangeConstrained> { /// Configuration that provides methods for a lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] pub struct LookupRangeCheckConfig { - pub(crate) q_lookup: Selector, - pub(crate) q_running: Selector, - pub(crate) q_bitshift: Selector, - pub(crate) running_sum: Column, - pub(crate) table_idx: TableColumn, - pub(crate) _marker: PhantomData, + q_lookup: Selector, + q_running: Selector, + q_bitshift: Selector, + running_sum: Column, + table_idx: TableColumn, + _marker: PhantomData, } /// Trait that provides common methods for a lookup range check. @@ -441,7 +441,7 @@ pub trait DefaultLookupRangeCheck: impl DefaultLookupRangeCheck for LookupRangeCheckConfig {} #[cfg(test)] -pub(crate) mod tests { +mod tests { use super::{LookupRangeCheck, LookupRangeCheckConfig}; use super::super::lebs2ip; @@ -457,8 +457,7 @@ pub(crate) mod tests { use pasta_curves::pallas; use crate::utilities::test_circuit::{ - read_all_proofs, read_test_case, test_proof_size, write_all_test_case, write_test_case, - Proof, + read_all_proofs, read_test_case, write_all_test_case, write_test_case, Proof, }; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; @@ -575,6 +574,8 @@ pub(crate) mod tests { // serialized_proof_test_case { + // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, + // write the old proof in a file if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); @@ -587,7 +588,7 @@ pub(crate) mod tests { }; create_proof().expect("should be able to write new proof"); } - // Parse the hardcoded proof test case. + // Read the old proof into 'proof' let proof = { let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_lookup_range_check.bin") @@ -595,12 +596,9 @@ pub(crate) mod tests { read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - assert_eq!(proof.as_ref().len(), 1888); + // Verify the old proof with the new vk assert!(proof.verify(&vk, ¶ms).is_ok()); } - - // Test that the proof size is as expected. - test_proof_size(11, circuit, ¶ms, &vk) } } @@ -651,6 +649,7 @@ pub(crate) mod tests { } } + // Read the old proofs into 'proofs' let proofs = { let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin").unwrap(); @@ -682,14 +681,12 @@ pub(crate) mod tests { include_str!("vk_short_range_check_0").replace("\r\n", "\n") ); } - // Test that the proof size is as expected. - test_proof_size(11, circuit, ¶ms, &vk); // serialized_proof_test_case { match proofs.get(0) { Some(proof) => { - assert_eq!(proof.as_ref().len(), 1888); + // Verify the old proofs[0] with the new vk assert!(proof.verify(&vk, ¶ms).is_ok()); } None => println!("Index out of bounds"), @@ -719,14 +716,12 @@ pub(crate) mod tests { include_str!("vk_short_range_check_1").replace("\r\n", "\n") ); } - // Test that the proof size is as expected. - test_proof_size(11, circuit, ¶ms, &vk); // serialized_proof_test_case { match proofs.get(1) { Some(proof) => { - assert_eq!(proof.as_ref().len(), 1888); + // Verify the old proofs[1] with the new vk assert!(proof.verify(&vk, ¶ms).is_ok()); } None => println!("Index out of bounds"), @@ -756,14 +751,12 @@ pub(crate) mod tests { include_str!("vk_short_range_check_2").replace("\r\n", "\n") ); } - // Test that the proof size is as expected. - test_proof_size(11, circuit, ¶ms, &vk); // serialized_proof_test_case { match proofs.get(2) { Some(proof) => { - assert_eq!(proof.as_ref().len(), 1888); + // Verify the old proofs[2] with the new vk assert!(proof.verify(&vk, ¶ms).is_ok()); } None => println!("Index out of bounds"), @@ -771,6 +764,8 @@ pub(crate) mod tests { } } + // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, + // write the old proofs in a file if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { let file = std::fs::File::create( diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index c42bcf0c63..b224540b72 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -54,34 +54,16 @@ impl Proof { } } -/// Test that the proof size is as expected. -#[allow(dead_code)] -pub(crate) fn test_proof_size( - k: u32, - circuit: C, - params: &Params, - vk: &VerifyingKey, -) where - C: Circuit, -{ - let circuit_cost = - halo2_proofs::dev::CircuitCost::::measure(k, &circuit); - let expected_proof_size = usize::from(circuit_cost.proof_size(1)); - - let proof = Proof::create(vk, params, circuit).unwrap(); - - assert!(proof.verify(vk, params).is_ok()); - assert_eq!(proof.as_ref().len(), expected_proof_size); -} - /// write proof to a file -pub fn write_test_case(mut w: W, proof: &Proof) -> std::io::Result<()> { +#[allow(dead_code)] +pub(crate) fn write_test_case(mut w: W, proof: &Proof) -> std::io::Result<()> { w.write_all(proof.as_ref())?; Ok(()) } /// read proof from a file -pub fn read_test_case(mut r: R) -> std::io::Result { +#[allow(dead_code)] +pub(crate) fn read_test_case(mut r: R) -> std::io::Result { let mut proof_bytes = vec![]; r.read_to_end(&mut proof_bytes)?; let proof = Proof::new(proof_bytes); @@ -99,7 +81,8 @@ pub(crate) fn write_all_test_case(mut w: W, proofs: &Vec) -> st } /// read multiple proofs from a file -pub fn read_all_proofs(mut r: R, proof_size: usize) -> io::Result> { +#[allow(dead_code)] +pub(crate) fn read_all_proofs(mut r: R, proof_size: usize) -> io::Result> { let mut proofs = Vec::new(); let mut buffer = vec![0u8; proof_size]; diff --git a/halo2_proofs/src/circuit.rs b/halo2_proofs/src/circuit.rs index 1083339fed..0822d8d8aa 100644 --- a/halo2_proofs/src/circuit.rs +++ b/halo2_proofs/src/circuit.rs @@ -139,16 +139,6 @@ impl AssignedCell, F> { } } -impl From> for AssignedCell, F> { - fn from(ac: AssignedCell) -> Self { - AssignedCell { - value: ac.value.map(|a| a.into()), - cell: ac.cell, - _marker: Default::default(), - } - } -} - impl AssignedCell where for<'v> Assigned: From<&'v V>, From cf2bd37ac8fc5b9b7b2009ee7fcf74436e52aa91 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 15:21:33 +0200 Subject: [PATCH 031/121] cleanup code --- halo2_gadgets/src/sinsemilla.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 9d5f26f18a..1b51a187f6 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -289,7 +289,8 @@ pub struct HashDomain< } impl - HashDomain where + HashDomain + where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, @@ -387,7 +388,8 @@ pub struct CommitDomain< } impl - CommitDomain where + CommitDomain + where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, From da85c7183751b52a5a23d9e649ff8de9dc4539d0 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 13 May 2024 15:22:38 +0200 Subject: [PATCH 032/121] cleanup code --- halo2_gadgets/src/sinsemilla.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 1b51a187f6..cbeb069fd8 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -290,7 +290,7 @@ pub struct HashDomain< impl HashDomain - where +where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, @@ -389,7 +389,7 @@ pub struct CommitDomain< impl CommitDomain - where +where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, From a5bf5eeaa19e2093b0297b1bd3112b43f7b4d63a Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 14 May 2024 10:27:59 +0200 Subject: [PATCH 033/121] resolve review --- halo2_gadgets/src/ecc.rs | 13 ++- halo2_gadgets/src/ecc/chip.rs | 24 +++--- halo2_gadgets/src/ecc/chip/mul.rs | 10 +-- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 8 +- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 14 ++-- .../src/ecc/chip/mul_fixed/full_width.rs | 8 +- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 8 +- halo2_gadgets/src/sinsemilla.rs | 13 ++- halo2_gadgets/src/sinsemilla/chip.rs | 14 ++-- .../src/sinsemilla/chip/generator_table.rs | 4 +- .../src/sinsemilla/chip/hash_to_point.rs | 4 +- halo2_gadgets/src/sinsemilla/merkle.rs | 22 +++-- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 22 ++--- .../{vk_merkle_chip => vk_merkle_chip_0} | 0 .../src/utilities/lookup_range_check.rs | 80 +++++++++---------- ...up_range_check => vk_lookup_range_check_0} | 0 .../src/{vk_ecc_chip => vk_ecc_chip_0} | 0 ...k_sinsemilla_chip => vk_sinsemilla_chip_0} | 0 18 files changed, 112 insertions(+), 132 deletions(-) rename halo2_gadgets/src/sinsemilla/{vk_merkle_chip => vk_merkle_chip_0} (100%) rename halo2_gadgets/src/utilities/{vk_lookup_range_check => vk_lookup_range_check_0} (100%) rename halo2_gadgets/src/{vk_ecc_chip => vk_ecc_chip_0} (100%) rename halo2_gadgets/src/{vk_sinsemilla_chip => vk_sinsemilla_chip_0} (100%) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 4b7d0e291b..9786701d4a 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -922,13 +922,10 @@ pub(crate) mod tests { // Test that the pinned verification key (representing the circuit) // is as expected. - { - //panic!("{:#?}", vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("vk_ecc_chip").replace("\r\n", "\n") - ); - } + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_ecc_chip_0").replace("\r\n", "\n") + ); } #[test] @@ -953,7 +950,7 @@ pub(crate) mod tests { create_proof().expect("should be able to write new proof"); } - // Read the old proof into 'proof' + // read proof from disk let proof = { let test_case_bytes = fs::read("src/circuit_proof_test_case_ecc.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 7133bdfd78..d7a0c92219 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -1,7 +1,7 @@ //! Chip implementations for the ECC gadgets. use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; -use crate::utilities::{lookup_range_check::DefaultLookupRangeCheck, UtilitiesInstructions}; +use crate::utilities::{lookup_range_check::PallasLookupRC, UtilitiesInstructions}; use arrayvec::ArrayVec; use ff::PrimeField; @@ -134,10 +134,7 @@ impl From for EccPoint { /// Configuration for [`EccChip`]. #[derive(Clone, Debug, Eq, PartialEq)] #[allow(non_snake_case)] -pub struct EccConfig< - FixedPoints: super::FixedPoints, - Lookup: DefaultLookupRangeCheck, -> { +pub struct EccConfig, Lookup: PallasLookupRC> { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], @@ -227,13 +224,12 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { /// An [`EccInstructions`] chip that uses 10 advice columns. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct EccChip, Lookup: DefaultLookupRangeCheck> -{ +pub struct EccChip, Lookup: PallasLookupRC> { config: EccConfig, } -impl, Lookup: DefaultLookupRangeCheck> - Chip for EccChip +impl, Lookup: PallasLookupRC> Chip + for EccChip { type Config = EccConfig; type Loaded = (); @@ -247,13 +243,13 @@ impl, Lookup: DefaultLookupRange } } -impl, Lookup: DefaultLookupRangeCheck> +impl, Lookup: PallasLookupRC> UtilitiesInstructions for EccChip { type Var = AssignedCell; } -impl, Lookup: DefaultLookupRangeCheck> +impl, Lookup: PallasLookupRC> EccChip { /// Reconstructs this chip from the given config. @@ -413,8 +409,8 @@ pub enum ScalarVar { FullWidth, } -impl, Lookup: DefaultLookupRangeCheck> - EccInstructions for EccChip +impl, Lookup: PallasLookupRC> EccInstructions + for EccChip where >::Base: FixedPoint, @@ -601,7 +597,7 @@ where } } -impl, Lookup: DefaultLookupRangeCheck> +impl, Lookup: PallasLookupRC> BaseFitsInScalarInstructions for EccChip where >::Base: diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 02d2e2d805..70c14df284 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -1,6 +1,6 @@ use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q}; use crate::utilities::{ - lookup_range_check::DefaultLookupRangeCheck, + lookup_range_check::PallasLookupRC, {bool_check, ternary}, }; use std::{ @@ -46,7 +46,7 @@ const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, // Configuration used in complete addition @@ -61,7 +61,7 @@ pub struct Config { overflow_config: overflow::Config, } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, add_config: add::Config, @@ -468,7 +468,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; + use crate::utilities::lookup_range_check::PallasLookupRC; use crate::{ ecc::{ chip::{EccChip, EccPoint}, @@ -478,7 +478,7 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul( + pub(crate) fn test_mul( chip: EccChip, mut layouter: impl Layouter, p: &NonIdentityPoint>, diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index 0912bd3a39..eb5810fac5 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -1,7 +1,5 @@ use super::{T_Q, Z}; -use crate::{ - sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::DefaultLookupRangeCheck, -}; +use crate::{sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::PallasLookupRC}; use group::ff::PrimeField; use halo2_proofs::circuit::AssignedCell; @@ -15,7 +13,7 @@ use pasta_curves::pallas; use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, // 10-bit lookup table @@ -24,7 +22,7 @@ pub struct Config { advices: [Column; 3], } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, lookup_config: Lookup, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 24f7114b4a..760ab20b9a 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -2,7 +2,7 @@ use super::super::{EccBaseFieldElemFixed, EccPoint, FixedPoints, NUM_WINDOWS, T_ use super::H_BASE; use crate::utilities::{ - bitrange_subset, bool_check, lookup_range_check::DefaultLookupRangeCheck, range_check, + bitrange_subset, bool_check, lookup_range_check::PallasLookupRC, range_check, }; use group::ff::PrimeField; @@ -16,14 +16,14 @@ use pasta_curves::pallas; use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Config, Lookup: DefaultLookupRangeCheck> { +pub struct Config, Lookup: PallasLookupRC> { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], lookup_config: Lookup, super_config: super::Config, } -impl, Lookup: DefaultLookupRangeCheck> Config { +impl, Lookup: PallasLookupRC> Config { pub(crate) fn configure( meta: &mut ConstraintSystem, canon_advices: [Column; 3], @@ -386,7 +386,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; + use crate::utilities::lookup_range_check::PallasLookupRC; use crate::{ ecc::{ chip::{EccChip, FixedPoint, H}, @@ -396,7 +396,7 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul_fixed_base_field( + pub(crate) fn test_mul_fixed_base_field( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -409,7 +409,7 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( + fn test_single_base( chip: EccChip, mut layouter: impl Layouter, base: FixedPointBaseField>, @@ -419,7 +419,7 @@ pub mod tests { let column = chip.config().advices[0]; - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs index fe2cc22094..fe0ccd8d3d 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs @@ -192,9 +192,9 @@ pub mod tests { tests::{FullWidth, TestFixedBases}, FixedPoint, NonIdentityPoint, Point, ScalarFixed, }; - use crate::utilities::lookup_range_check::DefaultLookupRangeCheck; + use crate::utilities::lookup_range_check::PallasLookupRC; - pub(crate) fn test_mul_fixed( + pub(crate) fn test_mul_fixed( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -210,13 +210,13 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( + fn test_single_base( chip: EccChip, mut layouter: impl Layouter, base: FixedPoint>, base_val: pallas::Affine, ) -> Result<(), Error> { - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index acbba7cc3a..fd88bcd72b 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -253,7 +253,7 @@ pub mod tests { }; use pasta_curves::pallas; - use crate::utilities::lookup_range_check::{DefaultLookupRangeCheck, LookupRangeCheck}; + use crate::utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRC}; use crate::{ ecc::{ chip::{EccChip, FixedPoint, MagnitudeSign}, @@ -264,7 +264,7 @@ pub mod tests { }; #[allow(clippy::op_ref)] - pub(crate) fn test_mul_fixed_short( + pub(crate) fn test_mul_fixed_short( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -272,7 +272,7 @@ pub mod tests { let base_val = Short.generator(); let test_short = FixedPointShort::from_inner(chip.clone(), Short); - fn load_magnitude_sign( + fn load_magnitude_sign( chip: EccChip, mut layouter: impl Layouter, magnitude: pallas::Base, @@ -290,7 +290,7 @@ pub mod tests { Ok((magnitude, sign)) } - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index cbeb069fd8..3877824e45 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -770,13 +770,10 @@ pub(crate) mod tests { // Test that the pinned verification key (representing the circuit) // is as expected. - { - //panic!("{:#?}", vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("vk_sinsemilla_chip").replace("\r\n", "\n") - ); - } + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_sinsemilla_chip_0").replace("\r\n", "\n") + ); } #[test] @@ -801,7 +798,7 @@ pub(crate) mod tests { create_proof().expect("should be able to write new proof"); } - // Read the old proof into 'proof' + // read proof from disk let proof = { let test_case_bytes = fs::read("src/circuit_proof_test_case_sinsemilla.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 95e40ec0f3..b242db41be 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -9,7 +9,7 @@ use crate::{ chip::{DoubleAndAdd, NonIdentityEccPoint}, FixedPoints, }, - utilities::lookup_range_check::DefaultLookupRangeCheck, + utilities::lookup_range_check::PallasLookupRC, }; use std::marker::PhantomData; @@ -35,7 +35,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { /// Binary selector used in lookup argument and in the body of the Sinsemilla hash. q_sinsemilla1: Selector, @@ -68,7 +68,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { /// Returns an array of all advice columns in this config, in arbitrary order. pub(super) fn advices(&self) -> [Column; 5] { @@ -103,7 +103,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { config: SinsemillaConfig, } @@ -113,7 +113,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { type Config = SinsemillaConfig; type Loaded = (); @@ -132,7 +132,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { @@ -321,7 +321,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { type CellValue = AssignedCell; diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 41e2f42c99..013995911c 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -8,7 +8,7 @@ use halo2_proofs::{ use super::{CommitDomains, FixedPoints, HashDomains}; use crate::{ sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, - utilities::lookup_range_check::DefaultLookupRangeCheck, + utilities::lookup_range_check::PallasLookupRC, }; use pasta_curves::pallas; @@ -33,7 +33,7 @@ impl GeneratorTableConfig { Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { let (table_idx, table_x, table_y) = ( config.generator_table.table_idx, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 7efef14635..709da2455d 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -3,7 +3,7 @@ use super::{NonIdentityEccPoint, SinsemillaChip}; use crate::{ ecc::FixedPoints, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, - utilities::lookup_range_check::DefaultLookupRangeCheck, + utilities::lookup_range_check::PallasLookupRC, }; use ff::Field; @@ -30,7 +30,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 19fdd8d424..dfb457808b 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -205,7 +205,6 @@ pub mod tests { use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; - const MERKLE_DEPTH: usize = 32; #[derive(Default)] @@ -413,13 +412,10 @@ pub mod tests { // Test that the pinned verification key (representing the circuit) // is as expected. Which indicates the layouters are the same. - { - //panic!("{:#?}", vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("vk_merkle_chip").replace("\r\n", "\n") - ); - } + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_merkle_chip_0").replace("\r\n", "\n") + ); } #[test] @@ -431,6 +427,8 @@ pub mod tests { let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + let file_name = "src/sinsemilla/circuit_proof_test_case_merkle.bin"; + // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, // write the old proof in a file if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { @@ -438,17 +436,15 @@ pub mod tests { let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); assert!(proof.verify(&vk, ¶ms).is_ok()); - let file = - std::fs::File::create("src/sinsemilla/circuit_proof_test_case_merkle.bin")?; + let file = std::fs::File::create(file_name)?; write_test_case(file, &proof) }; create_proof().expect("should be able to write new proof"); } - // Read the old proof into 'proof' + // read proof from disk let proof = { - let test_case_bytes = - fs::read("src/sinsemilla/circuit_proof_test_case_merkle.bin").unwrap(); + let test_case_bytes = fs::read(file_name).unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 033967dbd7..37aa4e7f99 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -11,7 +11,7 @@ use super::MerkleInstructions; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, - utilities::{lookup_range_check::DefaultLookupRangeCheck, RangeConstrained}, + utilities::{lookup_range_check::PallasLookupRC, RangeConstrained}, { ecc::FixedPoints, sinsemilla::{ @@ -33,7 +33,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { advices: [Column; 5], q_decompose: Selector, @@ -57,7 +57,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { config: MerkleConfig, } @@ -67,7 +67,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { type Config = MerkleConfig; type Loaded = (); @@ -86,7 +86,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { /// Configures the [`MerkleChip`]. pub fn configure( @@ -227,7 +227,7 @@ where Hash: HashDomains, Commit: CommitDomains, F: FixedPoints, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { } @@ -237,7 +237,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { } @@ -255,7 +255,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { #[allow(non_snake_case)] fn hash_layer( @@ -474,7 +474,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { type Var = AssignedCell; } @@ -485,7 +485,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { #[allow(clippy::type_complexity)] fn swap( @@ -507,7 +507,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: DefaultLookupRangeCheck, + Lookup: PallasLookupRC, { type CellValue = as SinsemillaInstructions< pallas::Affine, diff --git a/halo2_gadgets/src/sinsemilla/vk_merkle_chip b/halo2_gadgets/src/sinsemilla/vk_merkle_chip_0 similarity index 100% rename from halo2_gadgets/src/sinsemilla/vk_merkle_chip rename to halo2_gadgets/src/sinsemilla/vk_merkle_chip_0 diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 63f97278bc..36810050f3 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -291,6 +291,17 @@ impl LookupRangeCheck for LookupRangeCh self } + /// The `running_sum` advice column breaks the field element into `K`-bit + /// words. It is used to construct the input expression to the lookup + /// argument. + /// + /// The `table_idx` fixed column contains values from [0..2^K). Looking up + /// a value in `table_idx` constrains it to be within this range. The table + /// can be loaded outside this helper. + /// + /// # Side-effects + /// + /// Both the `running_sum` and `constants` columns will be equality-enabled. fn configure( meta: &mut ConstraintSystem, running_sum: Column, @@ -431,14 +442,14 @@ impl LookupRangeCheck for LookupRangeCh } } -/// The `DefaultLookupRangeCheck` trait extends the `LookupRangeCheck` with additional +/// The `PallasLookupRC` trait extends the `LookupRangeCheck` with additional /// standard traits necessary for effective use in cryptographic contexts. -pub trait DefaultLookupRangeCheck: +pub trait PallasLookupRC: LookupRangeCheck + Eq + PartialEq + Clone + Copy + Debug { } -impl DefaultLookupRangeCheck for LookupRangeCheckConfig {} +impl PallasLookupRC for LookupRangeCheckConfig {} #[cfg(test)] mod tests { @@ -564,13 +575,10 @@ mod tests { // Test that the pinned verification key (representing the circuit) // is as expected. - { - //panic!("{:#?}", vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("vk_lookup_range_check").replace("\r\n", "\n") - ); - } + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_lookup_range_check_0").replace("\r\n", "\n") + ); // serialized_proof_test_case { @@ -588,7 +596,7 @@ mod tests { }; create_proof().expect("should be able to write new proof"); } - // Read the old proof into 'proof' + // read proof from disk let proof = { let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_lookup_range_check.bin") @@ -649,7 +657,7 @@ mod tests { } } - // Read the old proofs into 'proofs' + // read proof from disk let proofs = { let test_case_bytes = fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin").unwrap(); @@ -659,8 +667,7 @@ mod tests { // Setup phase: generate parameters let params: Params = Params::new(11); - // Edge case: zero bits - // case 0 + // Edge case: zero bits (case 0) { let circuit: MyCircuit = MyCircuit { element: Value::known(pallas::Base::ZERO), @@ -674,19 +681,16 @@ mod tests { // Test that the pinned verification key (representing the circuit) // is as expected. Which indicates the layouters are the same. - { - //panic!("{:#?}", vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("vk_short_range_check_0").replace("\r\n", "\n") - ); - } + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_short_range_check_0").replace("\r\n", "\n") + ); // serialized_proof_test_case { match proofs.get(0) { Some(proof) => { - // Verify the old proofs[0] with the new vk + // Verify the stored proof (case 0) against the generated vk assert!(proof.verify(&vk, ¶ms).is_ok()); } None => println!("Index out of bounds"), @@ -694,8 +698,7 @@ mod tests { } } - // Edge case: K bits - // case 1 + // Edge case: K bits (case 1) { let circuit: MyCircuit = MyCircuit { element: Value::known(pallas::Base::from((1 << K) - 1)), @@ -709,19 +712,16 @@ mod tests { // Test that the pinned verification key (representing the circuit) // is as expected. Which indicates the layouters are the same. - { - //panic!("{:#?}", vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("vk_short_range_check_1").replace("\r\n", "\n") - ); - } + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_short_range_check_1").replace("\r\n", "\n") + ); // serialized_proof_test_case { match proofs.get(1) { Some(proof) => { - // Verify the old proofs[1] with the new vk + // Verify the stored proof (case 1) against the generated vk assert!(proof.verify(&vk, ¶ms).is_ok()); } None => println!("Index out of bounds"), @@ -729,8 +729,7 @@ mod tests { } } - // Element within `num_bits` - // case 2 + // Element within `num_bits` (case 2) { let circuit: MyCircuit = MyCircuit { element: Value::known(pallas::Base::from((1 << 6) - 1)), @@ -744,19 +743,16 @@ mod tests { // Test that the pinned verification key (representing the circuit) // is as expected. Which indicates the layouters are the same. - { - //panic!("{:#?}", vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("vk_short_range_check_2").replace("\r\n", "\n") - ); - } + assert_eq!( + format!("{:#?}\n", vk.pinned()), + include_str!("vk_short_range_check_2").replace("\r\n", "\n") + ); // serialized_proof_test_case { match proofs.get(2) { Some(proof) => { - // Verify the old proofs[2] with the new vk + // Verify the stored proof (case 2) against the generated vk assert!(proof.verify(&vk, ¶ms).is_ok()); } None => println!("Index out of bounds"), diff --git a/halo2_gadgets/src/utilities/vk_lookup_range_check b/halo2_gadgets/src/utilities/vk_lookup_range_check_0 similarity index 100% rename from halo2_gadgets/src/utilities/vk_lookup_range_check rename to halo2_gadgets/src/utilities/vk_lookup_range_check_0 diff --git a/halo2_gadgets/src/vk_ecc_chip b/halo2_gadgets/src/vk_ecc_chip_0 similarity index 100% rename from halo2_gadgets/src/vk_ecc_chip rename to halo2_gadgets/src/vk_ecc_chip_0 diff --git a/halo2_gadgets/src/vk_sinsemilla_chip b/halo2_gadgets/src/vk_sinsemilla_chip_0 similarity index 100% rename from halo2_gadgets/src/vk_sinsemilla_chip rename to halo2_gadgets/src/vk_sinsemilla_chip_0 From 8d27dd7c6806a1fd5978b00edd607fa42d206904 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 14 May 2024 12:00:51 +0200 Subject: [PATCH 034/121] Introduce conditionally_save_circuit_to_disk function to reuse the proof saving code in test cases --- halo2_gadgets/src/ecc.rs | 20 +++++++----------- halo2_gadgets/src/sinsemilla.rs | 20 +++++++----------- halo2_gadgets/src/sinsemilla/merkle.rs | 15 ++----------- .../src/utilities/lookup_range_check.rs | 21 +++++++------------ halo2_gadgets/src/utilities/test_circuit.rs | 21 +++++++++++++++++++ 5 files changed, 44 insertions(+), 53 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 9786701d4a..4a697ff413 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -599,7 +599,7 @@ pub(crate) mod tests { FixedPoints, }; use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; - use crate::utilities::test_circuit::{read_test_case, write_test_case, Proof}; + use crate::utilities::test_circuit::{conditionally_save_circuit_to_disk, read_test_case}; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -937,18 +937,12 @@ pub(crate) mod tests { let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, - // write the old proof in a file - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> std::io::Result<()> { - let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); - assert!(proof.verify(&vk, ¶ms).is_ok()); - - let file = std::fs::File::create("src/circuit_proof_test_case_ecc.bin")?; - write_test_case(file, &proof) - }; - create_proof().expect("should be able to write new proof"); - } + conditionally_save_circuit_to_disk( + &vk, + ¶ms, + circuit, + "src/circuit_proof_test_case_ecc.bin", + ); // read proof from disk let proof = { diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 3877824e45..52f1e4327f 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -483,7 +483,7 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::utilities::test_circuit::{read_test_case, write_test_case, Proof}; + use crate::utilities::test_circuit::{conditionally_save_circuit_to_disk, read_test_case}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::convert::TryInto; @@ -785,18 +785,12 @@ pub(crate) mod tests { let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, - // write the old proof in a file - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> std::io::Result<()> { - let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); - assert!(proof.verify(&vk, ¶ms).is_ok()); - - let file = std::fs::File::create("src/circuit_proof_test_case_sinsemilla.bin")?; - write_test_case(file, &proof) - }; - create_proof().expect("should be able to write new proof"); - } + conditionally_save_circuit_to_disk( + &vk, + ¶ms, + circuit, + "src/circuit_proof_test_case_sinsemilla.bin", + ); // read proof from disk let proof = { diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index dfb457808b..95678eec0e 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -200,7 +200,7 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::utilities::test_circuit::{read_test_case, write_test_case, Proof}; + use crate::utilities::test_circuit::{conditionally_save_circuit_to_disk, read_test_case}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; @@ -429,18 +429,7 @@ pub mod tests { let file_name = "src/sinsemilla/circuit_proof_test_case_merkle.bin"; - // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, - // write the old proof in a file - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> std::io::Result<()> { - let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); - assert!(proof.verify(&vk, ¶ms).is_ok()); - - let file = std::fs::File::create(file_name)?; - write_test_case(file, &proof) - }; - create_proof().expect("should be able to write new proof"); - } + conditionally_save_circuit_to_disk(&vk, ¶ms, circuit, file_name); // read proof from disk let proof = { diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 36810050f3..eedf67177e 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -468,7 +468,7 @@ mod tests { use pasta_curves::pallas; use crate::utilities::test_circuit::{ - read_all_proofs, read_test_case, write_all_test_case, write_test_case, Proof, + conditionally_save_circuit_to_disk, read_all_proofs, read_test_case, write_all_test_case, }; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; @@ -582,20 +582,13 @@ mod tests { // serialized_proof_test_case { - // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, - // write the old proof in a file - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> std::io::Result<()> { - let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); - assert!(proof.verify(&vk, ¶ms).is_ok()); + conditionally_save_circuit_to_disk( + &vk, + ¶ms, + circuit, + "src/utilities/circuit_proof_test_case_lookup_range_check.bin", + ); - let file = std::fs::File::create( - "src/utilities/circuit_proof_test_case_lookup_range_check.bin", - )?; - write_test_case(file, &proof) - }; - create_proof().expect("should be able to write new proof"); - } // read proof from disk let proof = { let test_case_bytes = diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index b224540b72..727dd58540 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -91,3 +91,24 @@ pub(crate) fn read_all_proofs(mut r: R, proof_size: usize) -> io::Resul } Ok(proofs) } + +#[cfg(test)] +pub(crate) fn conditionally_save_circuit_to_disk>( + vk: &VerifyingKey, + params: &Params, + circuit: C, + file_name: &str, +) { + // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, + // write the old proof in a file + if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let proof = Proof::create(vk, params, circuit).unwrap(); + assert!(proof.verify(vk, params).is_ok()); + + let file = std::fs::File::create(file_name)?; + write_test_case(file, &proof) + }; + create_proof().expect("should be able to write new proof"); + } +} From 48f941ea5e2270b87e59c95373105fdfce274ccd Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 14 May 2024 12:03:55 +0200 Subject: [PATCH 035/121] Rename conditionally_save_circuit_to_disk function to conditionally_save_proof_to_disk --- halo2_gadgets/src/ecc.rs | 4 ++-- halo2_gadgets/src/sinsemilla.rs | 4 ++-- halo2_gadgets/src/sinsemilla/merkle.rs | 4 ++-- halo2_gadgets/src/utilities/lookup_range_check.rs | 4 ++-- halo2_gadgets/src/utilities/test_circuit.rs | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 4a697ff413..fb243713c9 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -599,7 +599,7 @@ pub(crate) mod tests { FixedPoints, }; use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; - use crate::utilities::test_circuit::{conditionally_save_circuit_to_disk, read_test_case}; + use crate::utilities::test_circuit::{conditionally_save_proof_to_disk, read_test_case}; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -937,7 +937,7 @@ pub(crate) mod tests { let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - conditionally_save_circuit_to_disk( + conditionally_save_proof_to_disk( &vk, ¶ms, circuit, diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 52f1e4327f..8199abd22b 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -483,7 +483,7 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::utilities::test_circuit::{conditionally_save_circuit_to_disk, read_test_case}; + use crate::utilities::test_circuit::{conditionally_save_proof_to_disk, read_test_case}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::convert::TryInto; @@ -785,7 +785,7 @@ pub(crate) mod tests { let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - conditionally_save_circuit_to_disk( + conditionally_save_proof_to_disk( &vk, ¶ms, circuit, diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 95678eec0e..00096f327a 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -200,7 +200,7 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::utilities::test_circuit::{conditionally_save_circuit_to_disk, read_test_case}; + use crate::utilities::test_circuit::{conditionally_save_proof_to_disk, read_test_case}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; @@ -429,7 +429,7 @@ pub mod tests { let file_name = "src/sinsemilla/circuit_proof_test_case_merkle.bin"; - conditionally_save_circuit_to_disk(&vk, ¶ms, circuit, file_name); + conditionally_save_proof_to_disk(&vk, ¶ms, circuit, file_name); // read proof from disk let proof = { diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index eedf67177e..118a20fe34 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -468,7 +468,7 @@ mod tests { use pasta_curves::pallas; use crate::utilities::test_circuit::{ - conditionally_save_circuit_to_disk, read_all_proofs, read_test_case, write_all_test_case, + conditionally_save_proof_to_disk, read_all_proofs, read_test_case, write_all_test_case, }; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; @@ -582,7 +582,7 @@ mod tests { // serialized_proof_test_case { - conditionally_save_circuit_to_disk( + conditionally_save_proof_to_disk( &vk, ¶ms, circuit, diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index 727dd58540..54e7c1af89 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -93,7 +93,7 @@ pub(crate) fn read_all_proofs(mut r: R, proof_size: usize) -> io::Resul } #[cfg(test)] -pub(crate) fn conditionally_save_circuit_to_disk>( +pub(crate) fn conditionally_save_proof_to_disk>( vk: &VerifyingKey, params: &Params, circuit: C, From 58b7effca574f2240a176064b53fb7c3edade46f Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 14 May 2024 12:27:10 +0200 Subject: [PATCH 036/121] Introduce test_serialized_proof_with_vk and test_serialized_proof functions to reuse them and so avoid code duplication in serialized_proof_test_case tests --- halo2_gadgets/src/ecc.rs | 29 +++++-------------- halo2_gadgets/src/sinsemilla.rs | 29 ++++--------------- halo2_gadgets/src/sinsemilla/merkle.rs | 25 ++++------------ .../src/utilities/lookup_range_check.rs | 28 +++++------------- halo2_gadgets/src/utilities/test_circuit.rs | 21 +++++++++++++- 5 files changed, 44 insertions(+), 88 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index fb243713c9..53da5e71de 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -598,8 +598,10 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; - use crate::utilities::test_circuit::{conditionally_save_proof_to_disk, read_test_case}; + use crate::utilities::{ + lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + test_circuit::test_serialized_proof, + }; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -930,29 +932,12 @@ pub(crate) mod tests { #[test] fn serialized_proof_test_case() { - use std::fs; - - let circuit = MyCircuit { test_errors: false }; - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(11); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - conditionally_save_proof_to_disk( - &vk, - ¶ms, - circuit, + test_serialized_proof( + MyCircuit { test_errors: false }, "src/circuit_proof_test_case_ecc.bin", ); - - // read proof from disk - let proof = { - let test_case_bytes = fs::read("src/circuit_proof_test_case_ecc.bin").unwrap(); - read_test_case(&test_case_bytes[..]).expect("proof must be valid") - }; - - // Verify the old proof with the new vk - assert!(proof.verify(&vk, ¶ms).is_ok()); } + #[cfg(feature = "test-dev-graph")] #[test] fn print_ecc_chip() { diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 8199abd22b..791defe3eb 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -475,7 +475,10 @@ pub(crate) mod tests { tests::{FullWidth, TestFixedBases}, NonIdentityPoint, }, - utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + utilities::{ + lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + test_circuit::test_serialized_proof, + }, }, }; @@ -483,7 +486,6 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::utilities::test_circuit::{conditionally_save_proof_to_disk, read_test_case}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::convert::TryInto; @@ -778,28 +780,7 @@ pub(crate) mod tests { #[test] fn serialized_proof_test_case() { - use std::fs; - - let circuit = MyCircuit {}; - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(11); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - conditionally_save_proof_to_disk( - &vk, - ¶ms, - circuit, - "src/circuit_proof_test_case_sinsemilla.bin", - ); - - // read proof from disk - let proof = { - let test_case_bytes = fs::read("src/circuit_proof_test_case_sinsemilla.bin").unwrap(); - read_test_case(&test_case_bytes[..]).expect("proof must be valid") - }; - - // Verify the old proof with the new vk - assert!(proof.verify(&vk, ¶ms).is_ok()); + test_serialized_proof(MyCircuit {}, "src/circuit_proof_test_case_sinsemilla.bin"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 00096f327a..4cbb936095 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -187,6 +187,7 @@ pub mod tests { utilities::{ i2lebsp, lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + test_circuit::test_serialized_proof, UtilitiesInstructions, }, }; @@ -200,7 +201,6 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::utilities::test_circuit::{conditionally_save_proof_to_disk, read_test_case}; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; @@ -420,25 +420,10 @@ pub mod tests { #[test] fn serialized_proof_test_case() { - use std::fs; - - let circuit = generate_circuit(); - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(11); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - let file_name = "src/sinsemilla/circuit_proof_test_case_merkle.bin"; - - conditionally_save_proof_to_disk(&vk, ¶ms, circuit, file_name); - - // read proof from disk - let proof = { - let test_case_bytes = fs::read(file_name).unwrap(); - read_test_case(&test_case_bytes[..]).expect("proof must be valid") - }; - - // Verify the old proof with the new vk - assert!(proof.verify(&vk, ¶ms).is_ok()); + test_serialized_proof( + generate_circuit(), + "src/sinsemilla/circuit_proof_test_case_merkle.bin", + ); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 118a20fe34..31132976d4 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -468,7 +468,7 @@ mod tests { use pasta_curves::pallas; use crate::utilities::test_circuit::{ - conditionally_save_proof_to_disk, read_all_proofs, read_test_case, write_all_test_case, + read_all_proofs, test_serialized_proof_with_vk, write_all_test_case, }; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; @@ -580,26 +580,12 @@ mod tests { include_str!("vk_lookup_range_check_0").replace("\r\n", "\n") ); - // serialized_proof_test_case - { - conditionally_save_proof_to_disk( - &vk, - ¶ms, - circuit, - "src/utilities/circuit_proof_test_case_lookup_range_check.bin", - ); - - // read proof from disk - let proof = { - let test_case_bytes = - fs::read("src/utilities/circuit_proof_test_case_lookup_range_check.bin") - .unwrap(); - read_test_case(&test_case_bytes[..]).expect("proof must be valid") - }; - - // Verify the old proof with the new vk - assert!(proof.verify(&vk, ¶ms).is_ok()); - } + test_serialized_proof_with_vk( + &vk, + ¶ms, + circuit, + "src/utilities/circuit_proof_test_case_lookup_range_check.bin", + ); } } diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index 54e7c1af89..2d1251b768 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -93,7 +93,7 @@ pub(crate) fn read_all_proofs(mut r: R, proof_size: usize) -> io::Resul } #[cfg(test)] -pub(crate) fn conditionally_save_proof_to_disk>( +pub(crate) fn test_serialized_proof_with_vk>( vk: &VerifyingKey, params: &Params, circuit: C, @@ -111,4 +111,23 @@ pub(crate) fn conditionally_save_proof_to_disk>( }; create_proof().expect("should be able to write new proof"); } + + // read proof from disk + let proof = { + let test_case_bytes = std::fs::read(file_name).unwrap(); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + + // Verify the old proof with the new vk + assert!(proof.verify(&vk, ¶ms).is_ok()); +} + +#[cfg(test)] +pub(crate) fn test_serialized_proof>(circuit: C, file_name: &str) { + // Setup phase: generate parameters, vk for the circuit. + let params: Params = Params::new(11); + + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); + + test_serialized_proof_with_vk(&vk, ¶ms, circuit, file_name); } From 756bb78d37cc147c3c60ed702a2f68a98973e708 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 14 May 2024 12:31:59 +0200 Subject: [PATCH 037/121] Fix cargo clippy error --- halo2_gadgets/src/utilities/test_circuit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index 2d1251b768..5a258c761f 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -119,7 +119,7 @@ pub(crate) fn test_serialized_proof_with_vk>( }; // Verify the old proof with the new vk - assert!(proof.verify(&vk, ¶ms).is_ok()); + assert!(proof.verify(&vk, params).is_ok()); } #[cfg(test)] From 6814fc2ebbfb5943db505f69da53fd2a2aab06c1 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 14 May 2024 13:03:14 +0200 Subject: [PATCH 038/121] rename --- halo2_gadgets/src/ecc.rs | 15 ++++------ halo2_gadgets/src/sinsemilla.rs | 11 ++++---- halo2_gadgets/src/sinsemilla/merkle.rs | 10 +++---- .../src/utilities/lookup_range_check.rs | 11 +++----- halo2_gadgets/src/utilities/test_circuit.rs | 28 +++++++++++-------- 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 53da5e71de..be57d50bac 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -598,10 +598,8 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::utilities::{ - lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, - test_circuit::test_serialized_proof, - }; + use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; + use crate::utilities::test_circuit::serialized_proof_test_case_with_circuit; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -932,12 +930,11 @@ pub(crate) mod tests { #[test] fn serialized_proof_test_case() { - test_serialized_proof( - MyCircuit { test_errors: false }, - "src/circuit_proof_test_case_ecc.bin", - ); - } + let circuit = MyCircuit { test_errors: false }; + let file_name = "src/circuit_proof_test_case_ecc.bin"; + serialized_proof_test_case_with_circuit(circuit, file_name); + } #[cfg(feature = "test-dev-graph")] #[test] fn print_ecc_chip() { diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 791defe3eb..7bd9edc106 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -475,10 +475,7 @@ pub(crate) mod tests { tests::{FullWidth, TestFixedBases}, NonIdentityPoint, }, - utilities::{ - lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, - test_circuit::test_serialized_proof, - }, + utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, }, }; @@ -486,6 +483,7 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; + use crate::utilities::test_circuit::serialized_proof_test_case_with_circuit; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::convert::TryInto; @@ -780,7 +778,10 @@ pub(crate) mod tests { #[test] fn serialized_proof_test_case() { - test_serialized_proof(MyCircuit {}, "src/circuit_proof_test_case_sinsemilla.bin"); + let circuit = MyCircuit {}; + let file_name = "src/circuit_proof_test_case_sinsemilla.bin"; + + serialized_proof_test_case_with_circuit(circuit, file_name); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 4cbb936095..14214a6e8c 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -187,7 +187,6 @@ pub mod tests { utilities::{ i2lebsp, lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, - test_circuit::test_serialized_proof, UtilitiesInstructions, }, }; @@ -201,6 +200,7 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; + use crate::utilities::test_circuit::serialized_proof_test_case_with_circuit; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; @@ -420,10 +420,10 @@ pub mod tests { #[test] fn serialized_proof_test_case() { - test_serialized_proof( - generate_circuit(), - "src/sinsemilla/circuit_proof_test_case_merkle.bin", - ); + let circuit = generate_circuit(); + let file_name = "src/sinsemilla/circuit_proof_test_case_merkle.bin"; + + serialized_proof_test_case_with_circuit(circuit, file_name); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 31132976d4..7ef97b6f9e 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -468,7 +468,7 @@ mod tests { use pasta_curves::pallas; use crate::utilities::test_circuit::{ - read_all_proofs, test_serialized_proof_with_vk, write_all_test_case, + read_all_proofs, serialized_proof_test_case_with_circuit, write_all_test_case, }; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; @@ -580,12 +580,9 @@ mod tests { include_str!("vk_lookup_range_check_0").replace("\r\n", "\n") ); - test_serialized_proof_with_vk( - &vk, - ¶ms, - circuit, - "src/utilities/circuit_proof_test_case_lookup_range_check.bin", - ); + // serialized_proof_test_case + let file_name = "src/utilities/circuit_proof_test_case_lookup_range_check.bin"; + serialized_proof_test_case_with_circuit(circuit, file_name); } } diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index 5a258c761f..a2877df66d 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -93,7 +93,7 @@ pub(crate) fn read_all_proofs(mut r: R, proof_size: usize) -> io::Resul } #[cfg(test)] -pub(crate) fn test_serialized_proof_with_vk>( +pub(crate) fn conditionally_save_proof_to_disk>( vk: &VerifyingKey, params: &Params, circuit: C, @@ -111,23 +111,27 @@ pub(crate) fn test_serialized_proof_with_vk>( }; create_proof().expect("should be able to write new proof"); } - - // read proof from disk - let proof = { - let test_case_bytes = std::fs::read(file_name).unwrap(); - read_test_case(&test_case_bytes[..]).expect("proof must be valid") - }; - - // Verify the old proof with the new vk - assert!(proof.verify(&vk, params).is_ok()); } #[cfg(test)] -pub(crate) fn test_serialized_proof>(circuit: C, file_name: &str) { +pub(crate) fn serialized_proof_test_case_with_circuit>( + circuit: C, + file_name: &str, +) { // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - test_serialized_proof_with_vk(&vk, ¶ms, circuit, file_name); + // Conditionally save proof to disk + conditionally_save_proof_to_disk(&vk, ¶ms, circuit, file_name); + + // Read proof from disk + let proof = { + let test_case_bytes = fs::read(file_name).unwrap(); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + + // Verify the old proof with the new vk + assert!(proof.verify(&vk, ¶ms).is_ok()); } From 64a8ac2f0ad42dfc7c76511e2a95a4b32bc45ab5 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 14 May 2024 13:09:10 +0200 Subject: [PATCH 039/121] fix git error --- halo2_gadgets/src/utilities/test_circuit.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/utilities/test_circuit.rs index a2877df66d..440a4474cd 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/utilities/test_circuit.rs @@ -7,8 +7,9 @@ use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite}; use pasta_curves::vesta::Affine; use pasta_curves::{pallas, vesta}; use rand::rngs::OsRng; -use std::io; use std::io::{Read, Write}; +#[allow(unused_imports)] +use std::{fs, io}; /// A proof structure #[derive(Clone, Debug)] From 704d3f6b22837211e73b16c19611faa41a7be296 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 14 May 2024 13:24:30 +0200 Subject: [PATCH 040/121] Move all test .bin files and test_circuit.rs module to new tests folder in the root of src --- halo2_gadgets/src/ecc.rs | 8 +-- halo2_gadgets/src/lib.rs | 3 ++ halo2_gadgets/src/sinsemilla.rs | 19 +++---- halo2_gadgets/src/sinsemilla/merkle.rs | 4 +- .../test_circuit.rs => tests/circuit.rs} | 47 ++++++++++-------- .../circuit_proof_test_case_ecc.bin | Bin .../circuit_proof_test_case_sinsemilla.bin | Bin halo2_gadgets/src/utilities.rs | 1 - .../src/utilities/lookup_range_check.rs | 8 +-- 9 files changed, 48 insertions(+), 42 deletions(-) rename halo2_gadgets/src/{utilities/test_circuit.rs => tests/circuit.rs} (79%) rename halo2_gadgets/src/{ => tests}/circuit_proof_test_case_ecc.bin (100%) rename halo2_gadgets/src/{ => tests}/circuit_proof_test_case_sinsemilla.bin (100%) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index be57d50bac..56123d4116 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -598,8 +598,10 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}; - use crate::utilities::test_circuit::serialized_proof_test_case_with_circuit; + use crate::{ + tests::circuit::serialized_proof_test_case_with_circuit, + utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + }; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -931,7 +933,7 @@ pub(crate) mod tests { #[test] fn serialized_proof_test_case() { let circuit = MyCircuit { test_errors: false }; - let file_name = "src/circuit_proof_test_case_ecc.bin"; + let file_name = "src/tests/circuit_proof_test_case_ecc.bin"; serialized_proof_test_case_with_circuit(circuit, file_name); } diff --git a/halo2_gadgets/src/lib.rs b/halo2_gadgets/src/lib.rs index 2ac2623a99..cef325c385 100644 --- a/halo2_gadgets/src/lib.rs +++ b/halo2_gadgets/src/lib.rs @@ -28,3 +28,6 @@ pub mod poseidon; pub mod sha256; pub mod sinsemilla; pub mod utilities; + +#[cfg(test)] +pub mod tests; diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 7bd9edc106..f3a6cb15e0 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -467,23 +467,20 @@ pub(crate) mod tests { }; use crate::{ - ecc::ScalarFixed, - sinsemilla::primitives::{self as sinsemilla, K}, - { - ecc::{ - chip::{find_zs_and_us, EccChip, EccConfig, H, NUM_WINDOWS}, - tests::{FullWidth, TestFixedBases}, - NonIdentityPoint, - }, - utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + ecc::{ + chip::{find_zs_and_us, EccChip, EccConfig, H, NUM_WINDOWS}, + tests::{FullWidth, TestFixedBases}, + NonIdentityPoint, ScalarFixed, }, + sinsemilla::primitives::{self as sinsemilla, K}, + tests::circuit::serialized_proof_test_case_with_circuit, + utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, }; use group::{ff::Field, Curve}; use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::utilities::test_circuit::serialized_proof_test_case_with_circuit; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use std::convert::TryInto; @@ -779,7 +776,7 @@ pub(crate) mod tests { #[test] fn serialized_proof_test_case() { let circuit = MyCircuit {}; - let file_name = "src/circuit_proof_test_case_sinsemilla.bin"; + let file_name = "src/tests/circuit_proof_test_case_sinsemilla.bin"; serialized_proof_test_case_with_circuit(circuit, file_name); } diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 14214a6e8c..18d031142b 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -184,6 +184,7 @@ pub mod tests { tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, + tests::circuit::serialized_proof_test_case_with_circuit, utilities::{ i2lebsp, lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, @@ -200,7 +201,6 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::utilities::test_circuit::serialized_proof_test_case_with_circuit; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; @@ -421,7 +421,7 @@ pub mod tests { #[test] fn serialized_proof_test_case() { let circuit = generate_circuit(); - let file_name = "src/sinsemilla/circuit_proof_test_case_merkle.bin"; + let file_name = "src/tests/circuit_proof_test_case_merkle.bin"; serialized_proof_test_case_with_circuit(circuit, file_name); } diff --git a/halo2_gadgets/src/utilities/test_circuit.rs b/halo2_gadgets/src/tests/circuit.rs similarity index 79% rename from halo2_gadgets/src/utilities/test_circuit.rs rename to halo2_gadgets/src/tests/circuit.rs index 440a4474cd..136b1efb2b 100644 --- a/halo2_gadgets/src/utilities/test_circuit.rs +++ b/halo2_gadgets/src/tests/circuit.rs @@ -1,15 +1,26 @@ //! functions used for circuit test -use halo2_proofs::plonk; -use halo2_proofs::plonk::{Circuit, SingleVerifier, VerifyingKey}; -use halo2_proofs::poly::commitment::Params; -use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite}; -use pasta_curves::vesta::Affine; -use pasta_curves::{pallas, vesta}; +use std::{ + env, fs, + io::{ + self, {Read, Write}, + }, +}; + use rand::rngs::OsRng; -use std::io::{Read, Write}; -#[allow(unused_imports)] -use std::{fs, io}; + +use pasta_curves::{ + vesta::Affine, + {pallas, vesta}, +}; + +use halo2_proofs::{ + plonk::{ + self, {Circuit, SingleVerifier, VerifyingKey}, + }, + poly::commitment::Params, + transcript::{Blake2bRead, Blake2bWrite}, +}; /// A proof structure #[derive(Clone, Debug)] @@ -56,15 +67,13 @@ impl Proof { } /// write proof to a file -#[allow(dead_code)] -pub(crate) fn write_test_case(mut w: W, proof: &Proof) -> std::io::Result<()> { +fn write_test_case(mut w: W, proof: &Proof) -> io::Result<()> { w.write_all(proof.as_ref())?; Ok(()) } /// read proof from a file -#[allow(dead_code)] -pub(crate) fn read_test_case(mut r: R) -> std::io::Result { +fn read_test_case(mut r: R) -> io::Result { let mut proof_bytes = vec![]; r.read_to_end(&mut proof_bytes)?; let proof = Proof::new(proof_bytes); @@ -73,8 +82,7 @@ pub(crate) fn read_test_case(mut r: R) -> std::io::Result { } /// write multiple proofs to a file -#[allow(dead_code)] -pub(crate) fn write_all_test_case(mut w: W, proofs: &Vec) -> std::io::Result<()> { +pub(crate) fn write_all_test_case(mut w: W, proofs: &Vec) -> io::Result<()> { for proof in proofs { w.write_all(proof.as_ref())?; } @@ -82,7 +90,6 @@ pub(crate) fn write_all_test_case(mut w: W, proofs: &Vec) -> st } /// read multiple proofs from a file -#[allow(dead_code)] pub(crate) fn read_all_proofs(mut r: R, proof_size: usize) -> io::Result> { let mut proofs = Vec::new(); let mut buffer = vec![0u8; proof_size]; @@ -93,7 +100,6 @@ pub(crate) fn read_all_proofs(mut r: R, proof_size: usize) -> io::Resul Ok(proofs) } -#[cfg(test)] pub(crate) fn conditionally_save_proof_to_disk>( vk: &VerifyingKey, params: &Params, @@ -102,19 +108,18 @@ pub(crate) fn conditionally_save_proof_to_disk>( ) { // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, // write the old proof in a file - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> std::io::Result<()> { + if env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> io::Result<()> { let proof = Proof::create(vk, params, circuit).unwrap(); assert!(proof.verify(vk, params).is_ok()); - let file = std::fs::File::create(file_name)?; + let file = fs::File::create(file_name)?; write_test_case(file, &proof) }; create_proof().expect("should be able to write new proof"); } } -#[cfg(test)] pub(crate) fn serialized_proof_test_case_with_circuit>( circuit: C, file_name: &str, diff --git a/halo2_gadgets/src/circuit_proof_test_case_ecc.bin b/halo2_gadgets/src/tests/circuit_proof_test_case_ecc.bin similarity index 100% rename from halo2_gadgets/src/circuit_proof_test_case_ecc.bin rename to halo2_gadgets/src/tests/circuit_proof_test_case_ecc.bin diff --git a/halo2_gadgets/src/circuit_proof_test_case_sinsemilla.bin b/halo2_gadgets/src/tests/circuit_proof_test_case_sinsemilla.bin similarity index 100% rename from halo2_gadgets/src/circuit_proof_test_case_sinsemilla.bin rename to halo2_gadgets/src/tests/circuit_proof_test_case_sinsemilla.bin diff --git a/halo2_gadgets/src/utilities.rs b/halo2_gadgets/src/utilities.rs index 515b02caaa..739f4411de 100644 --- a/halo2_gadgets/src/utilities.rs +++ b/halo2_gadgets/src/utilities.rs @@ -12,7 +12,6 @@ use std::ops::Range; pub mod cond_swap; pub mod decompose_running_sum; pub mod lookup_range_check; -pub mod test_circuit; /// A type that has a value at either keygen or proving time. pub trait FieldValue { diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 7ef97b6f9e..57b8bb8dec 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -467,7 +467,7 @@ mod tests { }; use pasta_curves::pallas; - use crate::utilities::test_circuit::{ + use crate::tests::circuit::{ read_all_proofs, serialized_proof_test_case_with_circuit, write_all_test_case, }; use halo2_proofs::poly::commitment::Params; @@ -581,7 +581,7 @@ mod tests { ); // serialized_proof_test_case - let file_name = "src/utilities/circuit_proof_test_case_lookup_range_check.bin"; + let file_name = "src/tests/circuit_proof_test_case_lookup_range_check.bin"; serialized_proof_test_case_with_circuit(circuit, file_name); } } @@ -636,7 +636,7 @@ mod tests { // read proof from disk let proofs = { let test_case_bytes = - fs::read("src/utilities/circuit_proof_test_case_short_range_check.bin").unwrap(); + fs::read("src/tests/circuit_proof_test_case_short_range_check.bin").unwrap(); read_all_proofs(&test_case_bytes[..], 1888).expect("proof must be valid") }; @@ -741,7 +741,7 @@ mod tests { if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { let create_proof = || -> std::io::Result<()> { let file = std::fs::File::create( - "src/utilities/circuit_proof_test_case_short_range_check.bin", + "src/tests/circuit_proof_test_case_short_range_check.bin", )?; write_all_test_case(file, &proofs) }; From d0d3a6f7857558f96a7b7e2fd65bc3af816bca6a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 14 May 2024 13:34:34 +0200 Subject: [PATCH 041/121] Add missed files --- halo2_gadgets/src/tests.rs | 1 + 1 file changed, 1 insertion(+) create mode 100644 halo2_gadgets/src/tests.rs diff --git a/halo2_gadgets/src/tests.rs b/halo2_gadgets/src/tests.rs new file mode 100644 index 0000000000..a9af55fc06 --- /dev/null +++ b/halo2_gadgets/src/tests.rs @@ -0,0 +1 @@ +pub(crate) mod circuit; From 35f161db606dd6586d1b904fe300c12ae448061d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 14 May 2024 13:46:03 +0200 Subject: [PATCH 042/121] Move all .bin and vk_ test data files into src/tests folder --- halo2_gadgets/src/ecc.rs | 2 +- halo2_gadgets/src/sinsemilla.rs | 2 +- halo2_gadgets/src/sinsemilla/merkle.rs | 2 +- .../circuit_proof_test_case_lookup_range_check.bin | Bin .../circuit_proof_test_case_merkle.bin | Bin .../circuit_proof_test_case_short_range_check.bin | Bin halo2_gadgets/src/{ => tests}/vk_ecc_chip_0 | 0 .../{utilities => tests}/vk_lookup_range_check_0 | 0 .../src/{sinsemilla => tests}/vk_merkle_chip_0 | 0 .../src/{utilities => tests}/vk_short_range_check_0 | 0 .../src/{utilities => tests}/vk_short_range_check_1 | 0 .../src/{utilities => tests}/vk_short_range_check_2 | 0 halo2_gadgets/src/{ => tests}/vk_sinsemilla_chip_0 | 0 halo2_gadgets/src/utilities/lookup_range_check.rs | 8 ++++---- 14 files changed, 7 insertions(+), 7 deletions(-) rename halo2_gadgets/src/{utilities => tests}/circuit_proof_test_case_lookup_range_check.bin (100%) rename halo2_gadgets/src/{sinsemilla => tests}/circuit_proof_test_case_merkle.bin (100%) rename halo2_gadgets/src/{utilities => tests}/circuit_proof_test_case_short_range_check.bin (100%) rename halo2_gadgets/src/{ => tests}/vk_ecc_chip_0 (100%) rename halo2_gadgets/src/{utilities => tests}/vk_lookup_range_check_0 (100%) rename halo2_gadgets/src/{sinsemilla => tests}/vk_merkle_chip_0 (100%) rename halo2_gadgets/src/{utilities => tests}/vk_short_range_check_0 (100%) rename halo2_gadgets/src/{utilities => tests}/vk_short_range_check_1 (100%) rename halo2_gadgets/src/{utilities => tests}/vk_short_range_check_2 (100%) rename halo2_gadgets/src/{ => tests}/vk_sinsemilla_chip_0 (100%) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 56123d4116..1fdd2dbec0 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -926,7 +926,7 @@ pub(crate) mod tests { // is as expected. assert_eq!( format!("{:#?}\n", vk.pinned()), - include_str!("vk_ecc_chip_0").replace("\r\n", "\n") + include_str!("tests/vk_ecc_chip_0").replace("\r\n", "\n") ); } diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index f3a6cb15e0..685d7f872c 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -769,7 +769,7 @@ pub(crate) mod tests { // is as expected. assert_eq!( format!("{:#?}\n", vk.pinned()), - include_str!("vk_sinsemilla_chip_0").replace("\r\n", "\n") + include_str!("tests/vk_sinsemilla_chip_0").replace("\r\n", "\n") ); } diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 18d031142b..9bc56e9b04 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -414,7 +414,7 @@ pub mod tests { // is as expected. Which indicates the layouters are the same. assert_eq!( format!("{:#?}\n", vk.pinned()), - include_str!("vk_merkle_chip_0").replace("\r\n", "\n") + include_str!("../tests/vk_merkle_chip_0").replace("\r\n", "\n") ); } diff --git a/halo2_gadgets/src/utilities/circuit_proof_test_case_lookup_range_check.bin b/halo2_gadgets/src/tests/circuit_proof_test_case_lookup_range_check.bin similarity index 100% rename from halo2_gadgets/src/utilities/circuit_proof_test_case_lookup_range_check.bin rename to halo2_gadgets/src/tests/circuit_proof_test_case_lookup_range_check.bin diff --git a/halo2_gadgets/src/sinsemilla/circuit_proof_test_case_merkle.bin b/halo2_gadgets/src/tests/circuit_proof_test_case_merkle.bin similarity index 100% rename from halo2_gadgets/src/sinsemilla/circuit_proof_test_case_merkle.bin rename to halo2_gadgets/src/tests/circuit_proof_test_case_merkle.bin diff --git a/halo2_gadgets/src/utilities/circuit_proof_test_case_short_range_check.bin b/halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check.bin similarity index 100% rename from halo2_gadgets/src/utilities/circuit_proof_test_case_short_range_check.bin rename to halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check.bin diff --git a/halo2_gadgets/src/vk_ecc_chip_0 b/halo2_gadgets/src/tests/vk_ecc_chip_0 similarity index 100% rename from halo2_gadgets/src/vk_ecc_chip_0 rename to halo2_gadgets/src/tests/vk_ecc_chip_0 diff --git a/halo2_gadgets/src/utilities/vk_lookup_range_check_0 b/halo2_gadgets/src/tests/vk_lookup_range_check_0 similarity index 100% rename from halo2_gadgets/src/utilities/vk_lookup_range_check_0 rename to halo2_gadgets/src/tests/vk_lookup_range_check_0 diff --git a/halo2_gadgets/src/sinsemilla/vk_merkle_chip_0 b/halo2_gadgets/src/tests/vk_merkle_chip_0 similarity index 100% rename from halo2_gadgets/src/sinsemilla/vk_merkle_chip_0 rename to halo2_gadgets/src/tests/vk_merkle_chip_0 diff --git a/halo2_gadgets/src/utilities/vk_short_range_check_0 b/halo2_gadgets/src/tests/vk_short_range_check_0 similarity index 100% rename from halo2_gadgets/src/utilities/vk_short_range_check_0 rename to halo2_gadgets/src/tests/vk_short_range_check_0 diff --git a/halo2_gadgets/src/utilities/vk_short_range_check_1 b/halo2_gadgets/src/tests/vk_short_range_check_1 similarity index 100% rename from halo2_gadgets/src/utilities/vk_short_range_check_1 rename to halo2_gadgets/src/tests/vk_short_range_check_1 diff --git a/halo2_gadgets/src/utilities/vk_short_range_check_2 b/halo2_gadgets/src/tests/vk_short_range_check_2 similarity index 100% rename from halo2_gadgets/src/utilities/vk_short_range_check_2 rename to halo2_gadgets/src/tests/vk_short_range_check_2 diff --git a/halo2_gadgets/src/vk_sinsemilla_chip_0 b/halo2_gadgets/src/tests/vk_sinsemilla_chip_0 similarity index 100% rename from halo2_gadgets/src/vk_sinsemilla_chip_0 rename to halo2_gadgets/src/tests/vk_sinsemilla_chip_0 diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 57b8bb8dec..5f408e0e65 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -577,7 +577,7 @@ mod tests { // is as expected. assert_eq!( format!("{:#?}\n", vk.pinned()), - include_str!("vk_lookup_range_check_0").replace("\r\n", "\n") + include_str!("../tests/vk_lookup_range_check_0").replace("\r\n", "\n") ); // serialized_proof_test_case @@ -659,7 +659,7 @@ mod tests { // is as expected. Which indicates the layouters are the same. assert_eq!( format!("{:#?}\n", vk.pinned()), - include_str!("vk_short_range_check_0").replace("\r\n", "\n") + include_str!("../tests/vk_short_range_check_0").replace("\r\n", "\n") ); // serialized_proof_test_case @@ -690,7 +690,7 @@ mod tests { // is as expected. Which indicates the layouters are the same. assert_eq!( format!("{:#?}\n", vk.pinned()), - include_str!("vk_short_range_check_1").replace("\r\n", "\n") + include_str!("../tests/vk_short_range_check_1").replace("\r\n", "\n") ); // serialized_proof_test_case @@ -721,7 +721,7 @@ mod tests { // is as expected. Which indicates the layouters are the same. assert_eq!( format!("{:#?}\n", vk.pinned()), - include_str!("vk_short_range_check_2").replace("\r\n", "\n") + include_str!("../tests/vk_short_range_check_2").replace("\r\n", "\n") ); // serialized_proof_test_case From 497c29000305825fc77ac11d9690b9a775476e0b Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 14 May 2024 15:43:26 +0200 Subject: [PATCH 043/121] add tests for short range check --- halo2_gadgets/src/tests/circuit.rs | 20 ------ ...cuit_proof_test_case_short_range_check.bin | Bin 5664 -> 0 bytes ...it_proof_test_case_short_range_check_0.bin | Bin 0 -> 1888 bytes ...it_proof_test_case_short_range_check_1.bin | Bin 0 -> 1888 bytes ...it_proof_test_case_short_range_check_2.bin | Bin 0 -> 1888 bytes .../src/utilities/lookup_range_check.rs | 58 +++--------------- 6 files changed, 8 insertions(+), 70 deletions(-) delete mode 100644 halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check.bin create mode 100644 halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_1.bin create mode 100644 halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_2.bin diff --git a/halo2_gadgets/src/tests/circuit.rs b/halo2_gadgets/src/tests/circuit.rs index 136b1efb2b..649f775e74 100644 --- a/halo2_gadgets/src/tests/circuit.rs +++ b/halo2_gadgets/src/tests/circuit.rs @@ -81,25 +81,6 @@ fn read_test_case(mut r: R) -> io::Result { Ok(proof) } -/// write multiple proofs to a file -pub(crate) fn write_all_test_case(mut w: W, proofs: &Vec) -> io::Result<()> { - for proof in proofs { - w.write_all(proof.as_ref())?; - } - Ok(()) -} - -/// read multiple proofs from a file -pub(crate) fn read_all_proofs(mut r: R, proof_size: usize) -> io::Result> { - let mut proofs = Vec::new(); - let mut buffer = vec![0u8; proof_size]; - - while let Ok(()) = r.read_exact(&mut buffer) { - proofs.push(Proof::new(buffer.clone())); - } - Ok(proofs) -} - pub(crate) fn conditionally_save_proof_to_disk>( vk: &VerifyingKey, params: &Params, @@ -126,7 +107,6 @@ pub(crate) fn serialized_proof_test_case_with_circuit>( ) { // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); // Conditionally save proof to disk diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check.bin b/halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check.bin deleted file mode 100644 index 61d4e7caaba6043cb67921e1daa37134ef44273d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5664 zcmajgg*zOM1AuWcb-FuFclVu+VcN!+9!^b7$8=419LJpQHr?IbX4-T&zu$lGegB5{ zc|LB9veqe0LWv=DPRAT0->+$X{WBIHoV^h1AV&l!e8%CRs^kr$6(oJ z{LxOjJh#fR=k>-7q*yEWBFd-6-7(fkVd4>8q=j?n0VO>$yyShJVbb`A)e^(Qr40W) zLX7vi!9h|g9>TU2RzqBszC5mk;*pl~9D<>I^y6>JZps%tzl?;gb~#Sp2no{aiF13x z`VVqIHj;ZY#y@WV=1)7{Z9SU~@EMrQ4zd_9^|k3c$s9xFwjwNxDSdq_?yXA^l4o({U?OL(`PkoSS-5W-?;f;T2L1MvSwc<}(K9K2cm|pLKK%q?T zwIUB*e~DjU91JUGTZw*3bliwEm!WhBcdmqgt)XgVgd?;qpc5ID#C+OAz0d9)+@q(4 ze3U9qx0*lOOOQ;CR1J}5k;?$#V(+oxT_qLV_Xr>Jiy$01bC=X|89e4a1~{C&*Gw3_ zZbYg^If)BDvXtS06y919Jyj5WCE&nujn9Pkd=~)w*S%a&Vo3?>ga%?B`*U+>Cr?X} z0Npa2o*fk}d<;yo^d@w!7}$SqoO7jV0qIM!1j7qsaD!@R)?N5+mk0|YITV}DXCF*n zSabG4ySTq)w7e#Zg)0;zT#dP~Iq%n9gx}G3$CyUiiTrEWG-Cl#IkB0Y5bpIv8s%6y z#Lv*FF^XJXiE9cD1+{Z)bEDbLNxW>+U?coTmUvD6cmE3SA*C$q|tx^pA?H1A22 z?`jf{gNfWp_KOUhbc>QqDOdMestPTc^aW5&*)heCCs_SIKh1Aqnu6`l3hr1wKHcCN zm~jZKg}zqTwz7urMjf?}8CnpMH&bel=KINP1jTa?21_lh37Wx}<-Dn>P-GCXQY23} zF-(dHI(1k`@1VBU^(XNJ2=dtoVG(0IQa=VbKt^&nzfJy7PTr@r|@bsT=N7KNUHe z2>)7L@8fC-Xc@`9O5UJTFB4hKJ8hp@8^%gR(uh3OEb$1bWu=*7Wf1MPj6S$zueftEFEl5Bb9AEB`qjN5HExIuxKt}fYT)pU+qp7U(c z(i!`-w|-TWxF&ewc!+lKMMkA~JbDr;{wa;6*gU4YWVT!D)M0wfHU82L2I0vp^rVOR z=#5){FWSFgDLe3xnb9*)B{5xHm~>W05TukzkcL_@4a>8g*#vMs+Pr@K`f8*tmNn4* zX=|}m)c;Kx>!bV`e#`x?Fx~hDI)$F?X$T6M2Cc zdG^1G0{k+B)~SVBEyp98kLewgSrvM7m%u5E0!+ehNlPt%#S%^L)%F;Pvyl#l^33TU z9_rXr48Eh|Wd z(88~A=eFjN#vg05K^;8e##0YN=~Rj=)+%)jAgKrr60|?=^bVx>n9VyAYJvW@qgIHX z$Gl?cQmO17=ZV2FTt2AD!L|yPS?XB##PAz6{(5#pnwnS)z;TDlgD{uO9l&8Nj@1S+gV$@B=x{Xg<5qnDoA+zv=wIQ7pL9qzG|FR~uht!V7+q4WP_I22%k+ zHn`d_-*OdJJ;g=@9WoHy<);PQbzX*RwXcH5vB;&;aaHRWaE)_WY!#t;8mT38v@ujSNjI(rx;+GlDQGO>Z`)U% zY!7pB5N{zhyVD8OCa`@F%~BN zOqY{@kLZ(b@75R8_DIxA{9VT=tocuwseEiPC_6Dpo?w?$HV#F7QlcLgM9-3X;-(N# z@3D)F`@@_uMGs?S(`vg!xHadJWEeM%EG0ShpANrIZhVzBh)bsBghLP$P9Avez{b@Fd)B2Na@ zk8})tLr++QTzB{!Tv}?{LEj25s~5>2m|A!W(PQJ#l7`%;b!J9xRqlJ%?ldC*q4K;d zgZPaP27a87ow8;-@}tUNdeAepzAV`MRBv|k$TV^BDrB=bE+A_G7hMS5*}KiM!i08@ zHFxGKs!IaXfD@1Ixn7Gzd*(O9#m(aN8c9|9M&B8T|26kl_pkk&kDG^r8gIySd>yu zi6hrzX11`b3QZBjH+*C|djrA_6!sEt5nu8KRv6KKxACJTqIZf6HdHjC!s(Q{TI&rU zsy7tQy=)@D;Xdl@>Bw(Ebb5H{O1P|;`Bb$MxDw7DI%~-YiEmeo$2NRo!}>RpXt$q8 zDb=5NCn+P?gfhQMU}Gx4>h~lavCRL*4*6(0R+p6bbFt>OOQEeX6&VJx)ZucKTjIWL zno^>m1#KPi4^DfA?xijx3H7dJVClo6{r3kIBnThD$H0^J+9a&x{U-#NH}5IsOpdHgD?qfIIOk{8#(Uh6ea^@MsbgAu zY=s>qU!fPD-(pp*nfQ${0&6J$EHDJ~qxP(O zmB{QfoA)XV!_+Z>L#ebFpHwORSx!I8%c_Kun$=>#I=G{qk+&v}QQ4@H*Wi4@v+xOr zq*{y_@?GzIkM#!I)w{aF=Z|;p>f=1QoxUM8o1NluffT1fEMz-I1rSWyX6---j3wHa z;yP@)rF^WhrcJ;{Zf;!2t_e@H@Fl5E9%ktHTJz~n4qFVo8U0QB$RZ)xDf*$^z#=)3 zlatLVzA_==_#_o{t)j@}4aVonF5RBWdV9U_g850v#sScJ<&v*u<7HJ&N3MaGS1?lk z1?6vOUWezNSZOU{L&p)NR1m^|E{KyKk0K{o62YbR)#1){;+VCsp7MvT8+-O_xLoqY zvyiu`d11kKo_fS7V=)FIWcMjg9=$|HupY*jI_9>Fkl;;@4)Rk%!>u zs%uV2=B>m1#tE8R739Skx7|+s0)iEU1*n%!qb^B=m$79PH%7LRMexcM2T zrV|{Rj55=Ddz8v3X5E&tMM&yN@E+?XNeW%SxIl7KKX=~qy`~+8HqtgD`S6I9?bOES zm7jG6Ody&!qJlroKT6)WA#03Yg@F+pVi~Jh13xs77FGbVP7btfHu)<%+*=nU%r|U% z$&PTrAKB1wbhxCj029?e)gk`W z^{Vi2Y-HpZ3;)C70KAY1?;!AxF|vE%Ohc?aa~kwzq-DEvIt{~@pBiZszkGn==|3vF zl0h@q6tSQIo|}bO=b)ITJ*Q&%ed9f{TB$>@`vDlRGGCUD*GlxOLdS=#^fMcHNH4Si zuM0K5@s+X!2iAA?N;JB0w-0=%RN?NKFXRqZa3I^JQ#!V57^*`R&?`u8$+Jzr7AFsr z98E{djw>E37*2!#+Q9hbSSr9=s+gxr#}T8+=u%Gak6fNC&7H#MLcu*^f@mH)eL&#U z4#w9UyvsX9GtahO4$qy$m-!cfCM_9i23&+u5xeAgnl*e^EJ=;rQD*;bklKR(`R@pd z9Y_F}oaJ#;mtyOGd}O>hGio2dGD=SZZb?ljbEgAhif*D9@z5u4cJJ;l1Cqo1w7t@P z*t1Nh-)GuqCyZh1*?1$}7J}9W{yifs<5x@IwgsE*bGO5hnalcM1QL7S$!ETAqjr zZ34klz}nICtCo=W&2imWUi)-UCI9y9jnEU4DisSWu)-->v%YL&VS(D{u!;h=PjFt1 z!mHapg+x@Y7(rXM$I;v&^Y;H2ojWNcS~RLlK1TF{+Gjm+xG(po1BwO^qF@+`pP8!5 z5i6#AiT}vgj*N`$_1*=`4co8ZF{L8R3PkU#aQ>IC zy*qS2pSftuL>-SNQ%z|)x>;)TXL&4A^=P(svTDm&-LZOe==5pLQtC8rWnVM;6iL@5 zw&qtSyosq1f#^V@!!2s-#A!F-k*)bf=e#p+HmbWlem}8c69wkZMdcwnK1u=XdL{Zq zO?|ur!OqE2jlyRPZNmyU7>uB6=f=|$lnG1`^*#w$VeILNh8`Tv-%I-XM6mx?6HE`WLxT0@$g%-irPyaeT0VxR)XGdgDxPPcNb4znF43mM zEa?Bbl8c?Q;ZxXMMW&<2Wrstqf(8-CW(mv6`f|{@j`yVPFb0;1lva0a>(?%BNc*Gr;I;O|Cokdq$y)!|)<+p&=A*J;1IAneaWnWg~ar= zh5P7|z)?BeM5BwBkVcv`muYT}`KQ^LF;kJy=)j@^PupI2;tv&UI;I_ppQlBq6{}^q z%W=TPM5YhIeVg$VQSVdG-v!LHx^w(04@A0mh4xS4BD#G9FH8w-q2Rlk4S&mPq<7K* z*Hp=8)^zrgpI(A={MpSYkk~j^pI}7i#*Y1w= z?n@#uvI)vM0{W6WrjL@D-zY)GH%KqqXLh~y4^_N|b=mrHlfLuvj${drZ8~Yxh&*Tl z?DG1LG0)Q6xLCl@^+w5K+pGl4n9TrNmV&gv-2*(hz_VI$57EtWS<2Kdd-PrJZaQmj zhk*1*P(@{FXNVldGM{nhocSGm4{tML@chwi$l$!~l(&#;R52W%4@oO|BlY z=4(e(vopsjkAOK2=d8VoV;gn$@;(;7aAUq|LWoIyTFh+8ZQOBj}h=_mRnC)Ap zIV=If=R)_K6cS!hkIfR%jvdXU@IWy{_A&~@g>&3re(aCYqYEqRqfR^NZx7dRSfa|B zi-N0>cP?(Lm^qWpNM7Q+{NBq9`KvGpD9ALQcikGuw-CG;|0e7atFR*+>eNi-UX}F- zI`|~_yv`|++_Nb~g8M2-ppaxck^}(j6=T zeQT_geHGu#syZSFo|3}VI}9_QV@48EYp_n?j8ZO(hju~JFVnE)S3U`hq8_$)@uye_)ANRuV@FmJxf<7p#RK|aK&>G$69lWU5m%1^IMxJfe;Z3i}nEsoJ(o$2n+*FDt=(u-W z;nxpeTu|>E*8_Lw$(AfcfYdSnu}7aq!?D0%Jh(7fXtYN`3x))6WT5Ayi@^7N*8_k?QkvBzbc{opQ)76X2bPo^)a_0fPj9g z!jj5?QtwF;V8#LDGVm@LE=%RHw1SCd#90Kts1x19n#(T!G3W2*-WD*leUd`0m7Uz- zPHZVj#qR^QHP>Mr@nezl`H9(RE#O@(9gY7Ul6yd1-}ZxuuSE!EwM@er1Dg%_LMQ}C za5*3KI`hxC3W>^d$*@vca$gCqN;ywAjm&|N@H#p}SFgLK#o5^eeJjZlCUW4iffp7) zvGH`0)xGCJyd0hPV;j6NV;kqO8Wpr&oG5YoT7@nE0000000000000000000000000 z00000000000002m`=qgV(jwYQdGwgC^WmI4C@2^C4~*&R(sv%B=p`j=dq#!lG&rPy zq?|}S@mtA9spA=a8J8B!gK@C3E29!?&FSDzXLu`|)2YBBcVZ_M^iuRYNA$3zqtGyE z%CiCQs-{@%**^QPOQH7rO^@S7pW)$^ZRBd6xD1zz>qiCeqqw&MPXY(egvhsqtT2TY z@=Kt3Rppntfz;@^UdI9w%enK0UFx&?O#||w;hS%CpoPVluh!izl1IIz1hBPIxQ;!gNrgab=J*-Zij*E2-~Ad6R?R$;)?G| zBVW)v`yqkjec=G?1s#*yJ5MaZR}jsrZSmPcnfX^MN2~o7^K!R)k!==CPpb*!JgVT8 zF$^Pt8nyW1;_KsAOkvg*c9$wu9|1Y7PfJR!0xowRyW%M%cSjs^4$+Ly7DDilS%xyj z*R>5)9eOQ%={*y;L@oN%o>GFbw`PXTvNlKGwOG#T@u{;HZYJ+s@Tl@1}5gPNRgBDx@lkLXi*jUWsR=Hv%--gQQfxCW16g_t^a`V{2Vyn|A5 z;oI}Kb?A!z1evVKwLFlD29TrginyRnXo+hq+AjTp4Rx~9lG#6HyFWw!5 z33Sm0|Eh96Ln*q99#Ea+$Gzlxj8Or}j-@F-7ICSeW zC>bw=krVeF(a6dmr=_??97nZfA=rs^M-na;@`?9u?CkX+8cPQd;u2~)6o*@ zeb;QCjA_H1_3Y;S#3O*TCfz965#iqyDs;nEIm~`;eKw6OyfLoXm57>uMOI{vLPP*R zr>bFy=|17aJzisn%_2|(ph?ge7jG&_BnRv?jdzyQ&id-8&y_~6R4Oz!1P1W+#81h; z!z$}yoQrT0z3~`lGeWAX;u79wg^K>bwl4dWe(vt^bARnlL; azfNaNQ7wk9H5{#vasf)>7IoK39~UZb5^tMyi=_t7`Dfe0sH)Twt;%m9pq4_ZX5I?xwPyWNC1 z?zs46F-khB2Eo;s)Q*ZFY7#gIGQ9f}z6Yv{Y>^wZe?bhI1BnbYn@slUg#5s3a9D}0 zst(&^<#Qkm1*VguP&bFCkkW+vnb}}y=?mFjot_7|)aE=Y+3g_>{{NVFgtR)!J9^*;`P1U~kf4NT%jcb-D} zh#qEbKxD|L7$P1jQ9hj%&iS4eTt0aD=nS|K$O}R`{|sgRZPffEGX>RI&jBqehY>^D zVylMiCS!uKf?J2C@EtG-U12nU#GBS{ROC1&1~x9?ZiZ!aOl)^K2%kGdL)0-Eick)M z`8W_f59mCpf^50W#UNgT{K5EB@4YrghA(jBRUkC|IjKJFrSI+-ysy@?f3?L>J{d?r=pg^#l(#FvUQB=5$&eaAhwwc z<b1mWU91zUSi17Ts+)@Ze%HVmLhG z5@A>5L=$`xEVRi8L4PEtZi#O`{JB;iJF&w(aJ$?*&~`fjOo21}3_A3xd<6|uiE3U& z@E$;~xH2Ka1vPnyj)3wB>jZX&DUK!j5xrn0M!?qnR_M< z8MtBhTq|mM0|ty~E(3TXY9uPX6Ha_gz!|d#0XB`kio!lQhlOGQGtujateuBv7IS)n zaffY%QKoTEUlJ`dk++huj+}eVNB?9v>FjDm2hfgr-)FG=mKi#y+OsgJ*W8W&M`8Y! z?gMiLf>TOjT+O}fY1pAcL{s?A{|yg?JuI8|6Zb8k=OpGst<3qeDgv7z*h$-uC8@8T zjfpaLIXQ0Oo`KL=r0blWFo&HkR~Ml)OM3sIn(|=&9hDuWjlnRjPWIs=l=e3@fIP+Z zl*6|gLRsBInwvg*-7S!SFR_;j?lz>5+jsR2X2YuH9hjuJWV}x!Mv-Teo0~%^CX)< zm+#1PQtl;t6{iGL$!+8Y$xI_mPl%$8)CAD$`FMLu1ckPd^RWrG;n@stajD*A_Y%&f z(H7`a4F}mXL8&BMKkpu$lgB;hJHslu^fW$RTjM6~1N}%%5=GVlR(^VK?Cq6@cdphX z?D(x%3oT1xPy`+b)z1rb9b3Su7Bbzb4OH7$K00XJ zb}X-m^IBl3mt>K=GddC4Jvd-$A9J7CL#G^)WV?c7j!)~d!!s9~bE^s7@LI3TQ@lNz zDk&jRaG^b1n9!0DoelFImrU;31gQ^?sGO|Bhg>rwQ}w5?2Ey$&q~;-Xi%G@ZOJLEo zjuTJ4jS27Y$>D|)Qf22m`mW@|5*v(^t&pD z;{)NoU+M-4DsnCjg`U1^4HG6^R*`rgCL90Z12~z@QmOhaDTrQ3wkv@=J@E0VgMuVc z##BR6K;|z-4)+k^51J6ba+Tf2T4}awx`GIHK8!{KXo0BvE literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_2.bin b/halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_2.bin new file mode 100644 index 0000000000000000000000000000000000000000..37f223f7c236cdd365ac3a8512eacc2f987b96c0 GIT binary patch literal 1888 zcmV-m2cP(S&XXZm_z|2wJl$9lZC$Ub!)y+=zZjf5A;5lKQ6i7J$4=he2(ukKuaHlY zs9~c1i_zFX^|SxG8U>*`e18%1A~+Xyca6I;D#~ZeBk`dBgsr~>j;QF^)?5{osYwd| zOHrj}>o0kXUk>PV$gopruNklt8FzLR6={)v2Fe!uFEQ`lav7zOO*nI$D-+Q8l^ALc zF0|3|(e2~>p&Fa5H@erwK(qniiSl_r;JNl%uBHq^Xn+3&(3l$RADo}GeKY8~_?ZFM zYHrSOlKgC@BVag-7*;PsPBY&We`$;rr)-U>ZoK15X!fNoO>5KBDq`#3$es(*<&$8t zFUuzi6ui6@1GEa4{&z|)(#9*Lzo{p!?SvMy9|`79jV6rb0@jkfU?ac>EqhdV`)VZ= zD>W94Z-@A<#Htlv`<|7fA^m*3{?U%L-bCzu@l2i($z2f+Pjc%!i_n4rOlouG9 zu$4iqPTeZqB@8Hj6m{y$k*Qd6rWq7?@?{T|HYy$atY6Iwo{q~7N5Jj(|CX6-krxr6 zy_oEZ@-qZcOKNJXq(55_1#3?@3(-Cc_-)3tk~hQZgKZuOtF*ASx1sj(TjKvMwa_F~{A951_0000000000000000000000000 z00000000000001meqJUjlWP1T08`5MlJ4s1yzaq!QH`HapYOH2Mie;L%Mn^4#e7{{ zWf}XgA2*4Rg*Kq}l{TBA6x3i@d&Z)jwGL1m=h`Un|0fQ!Y z%j+Va=VhyIM2Jzpf&hWyCKShUB^=AJDfBL!b=1qDY>_HM_CZ+6V1i=@V(sLuq#`dJ z?(Y6IBml>lI#_$U=It;5f9g~No_GvtL?!f}La;VbeJY-mx_IbM8h`|#vJOk~ zYr8@PL9>eqnbqUF{$sz2$2w-Ry@%_RtY34grQ2p_@%JMQr zmWl}zEfgAPge`f5Z`M*Iya6$7CghlOcgkZ;SFD{u>AcPk0tF5|e*GpR;?bnye(&$4b6I$` z5mZ08cS@pUG#-&8OPGJ+OAz_7{UW3dK~>UBtU>bxgol?am6VS(rab&ga);$qvi@{# zV;kufZgxo&pJ=I8Oa8P_W!#Zpwx$VwMLSP0IvT7x^2p4&GM(mVz@#qb&-){Xl7&%3 zIHWn+L}D*01chENDTnzmjdw=smquEWDEN`HeBs&Y|^x(s_@LY6?qyYneU#fsK zW|wLkxABJ1q@xMfst+s8i+!5G=sBAhOt{E6ti`AvZ|d%V@+#$CHfWzpVGmi8pZ(Pm zk`0?{Y}0DCJOsV z+wIh;)<4BqzbHo*DyO4EA(FIeJfAnql1f-~FIwic|C*XXUe?hb^txkfXR#Q|(=gSN2V>P7HCBCC(y3arQ^3!37{jmklZ zP#shh=pTLGSsU_u3pO+^XFG!ObmHpPI8&E?40U`VoYj*ubNRoJ7|zPq(@EfxeGfRo z%**Q9wqf(r9FcV7nx2}g8IVR<0z}s48XSf)w!%E5CzPe5!o>L0V3!l89>aUvezC<9 zU384R*R^_P?ai_zTJERi^#E2j@VTT3tu-{mI>n`xnnV*Ktm+Ax;W|9#!r`H{1o?JT amHr9D2DTd1g`_$k-1=#$`nay2l7%QM6`VH! literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 5f408e0e65..40741ea7c4 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -467,12 +467,10 @@ mod tests { }; use pasta_curves::pallas; - use crate::tests::circuit::{ - read_all_proofs, serialized_proof_test_case_with_circuit, write_all_test_case, - }; + use crate::tests::circuit::serialized_proof_test_case_with_circuit; use halo2_proofs::poly::commitment::Params; use pasta_curves::vesta::Affine; - use std::{convert::TryInto, fs, marker::PhantomData}; + use std::{convert::TryInto, marker::PhantomData}; #[test] fn lookup_range_check() { @@ -633,13 +631,6 @@ mod tests { } } - // read proof from disk - let proofs = { - let test_case_bytes = - fs::read("src/tests/circuit_proof_test_case_short_range_check.bin").unwrap(); - read_all_proofs(&test_case_bytes[..], 1888).expect("proof must be valid") - }; - // Setup phase: generate parameters let params: Params = Params::new(11); @@ -663,15 +654,8 @@ mod tests { ); // serialized_proof_test_case - { - match proofs.get(0) { - Some(proof) => { - // Verify the stored proof (case 0) against the generated vk - assert!(proof.verify(&vk, ¶ms).is_ok()); - } - None => println!("Index out of bounds"), - } - } + let file_name = "src/tests/circuit_proof_test_case_short_range_check_0.bin"; + serialized_proof_test_case_with_circuit(circuit, file_name); } // Edge case: K bits (case 1) @@ -694,15 +678,8 @@ mod tests { ); // serialized_proof_test_case - { - match proofs.get(1) { - Some(proof) => { - // Verify the stored proof (case 1) against the generated vk - assert!(proof.verify(&vk, ¶ms).is_ok()); - } - None => println!("Index out of bounds"), - } - } + let file_name = "src/tests/circuit_proof_test_case_short_range_check_1.bin"; + serialized_proof_test_case_with_circuit(circuit, file_name); } // Element within `num_bits` (case 2) @@ -725,27 +702,8 @@ mod tests { ); // serialized_proof_test_case - { - match proofs.get(2) { - Some(proof) => { - // Verify the stored proof (case 2) against the generated vk - assert!(proof.verify(&vk, ¶ms).is_ok()); - } - None => println!("Index out of bounds"), - } - } - } - - // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, - // write the old proofs in a file - if std::env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> std::io::Result<()> { - let file = std::fs::File::create( - "src/tests/circuit_proof_test_case_short_range_check.bin", - )?; - write_all_test_case(file, &proofs) - }; - create_proof().expect("should be able to write new proof"); + let file_name = "src/tests/circuit_proof_test_case_short_range_check_2.bin"; + serialized_proof_test_case_with_circuit(circuit, file_name); } // Element larger than `num_bits` but within K bits From d3a9d4edcc689b627846b32c29b92fddea4f6b38 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 15 May 2024 11:33:15 +0200 Subject: [PATCH 044/121] Add fixed_verification_key_test_with_circuit function to generalize VK tests like the proof tests are generalized with serialized_proof_test_case_with_circuit --- halo2_gadgets/src/ecc.rs | 20 ++----- halo2_gadgets/src/sinsemilla.rs | 20 ++----- halo2_gadgets/src/sinsemilla/merkle.rs | 20 ++----- halo2_gadgets/src/tests/circuit.rs | 16 ++++++ .../src/utilities/lookup_range_check.rs | 55 +++---------------- 5 files changed, 38 insertions(+), 93 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 1fdd2dbec0..005e9e8b18 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -580,16 +580,13 @@ pub(crate) mod tests { use ff::PrimeField; use group::{prime::PrimeCurveAffine, Curve, Group}; - use halo2_proofs::poly::commitment::Params; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, - plonk, plonk::{Circuit, ConstraintSystem, Error}, }; use lazy_static::lazy_static; use pasta_curves::pallas; - use pasta_curves::vesta::Affine; use super::{ chip::{ @@ -599,7 +596,9 @@ pub(crate) mod tests { FixedPoints, }; use crate::{ - tests::circuit::serialized_proof_test_case_with_circuit, + tests::circuit::{ + fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, + }, utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, }; @@ -915,19 +914,10 @@ pub(crate) mod tests { #[test] fn fixed_verification_key_test() { - let k = 11; let circuit = MyCircuit { test_errors: false }; + let file_name = "src/tests/vk_ecc_chip_0"; - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(k); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("tests/vk_ecc_chip_0").replace("\r\n", "\n") - ); + fixed_verification_key_test_with_circuit(&circuit, file_name); } #[test] diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 685d7f872c..0288a42fe8 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -456,7 +456,6 @@ pub(crate) mod tests { use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, - plonk, plonk::{Circuit, ConstraintSystem, Error}, }; use rand::rngs::OsRng; @@ -473,7 +472,9 @@ pub(crate) mod tests { NonIdentityPoint, ScalarFixed, }, sinsemilla::primitives::{self as sinsemilla, K}, - tests::circuit::serialized_proof_test_case_with_circuit, + tests::circuit::{ + fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, + }, utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, }; @@ -481,8 +482,6 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; - use halo2_proofs::poly::commitment::Params; - use pasta_curves::vesta::Affine; use std::convert::TryInto; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; @@ -758,19 +757,10 @@ pub(crate) mod tests { #[test] fn fixed_verification_key_test() { - let k = 11; let circuit = MyCircuit {}; + let file_name = "src/tests/vk_sinsemilla_chip_0"; - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(k); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("tests/vk_sinsemilla_chip_0").replace("\r\n", "\n") - ); + fixed_verification_key_test_with_circuit(&circuit, file_name); } #[test] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 9bc56e9b04..c399e608a8 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -184,7 +184,9 @@ pub mod tests { tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, - tests::circuit::serialized_proof_test_case_with_circuit, + tests::circuit::{ + fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, + }, utilities::{ i2lebsp, lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, @@ -197,12 +199,9 @@ pub mod tests { circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, pasta::pallas, - plonk, plonk::{Circuit, ConstraintSystem, Error}, }; - use halo2_proofs::poly::commitment::Params; - use pasta_curves::vesta::Affine; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; const MERKLE_DEPTH: usize = 32; @@ -403,19 +402,10 @@ pub mod tests { #[test] fn fixed_verification_key_test() { - let k = 11; let circuit = generate_circuit(); + let file_name = "src/tests/vk_merkle_chip_0"; - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(k); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. Which indicates the layouters are the same. - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("../tests/vk_merkle_chip_0").replace("\r\n", "\n") - ); + fixed_verification_key_test_with_circuit(&circuit, file_name); } #[test] diff --git a/halo2_gadgets/src/tests/circuit.rs b/halo2_gadgets/src/tests/circuit.rs index 649f775e74..e429c97be6 100644 --- a/halo2_gadgets/src/tests/circuit.rs +++ b/halo2_gadgets/src/tests/circuit.rs @@ -66,6 +66,22 @@ impl Proof { } } +pub(crate) fn fixed_verification_key_test_with_circuit>( + circuit: &C, + file_name: &str, +) { + // Setup phase: generate parameters, vk for the circuit. + let params: Params = Params::new(11); + let vk = plonk::keygen_vk(¶ms, circuit).unwrap(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. + assert_eq!( + format!("{:#?}\n", vk.pinned()), + fs::read_to_string(file_name).unwrap().replace("\r\n", "\n") + ); +} + /// write proof to a file fn write_test_case(mut w: W, proof: &Proof) -> io::Result<()> { w.write_all(proof.as_ref())?; diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 40741ea7c4..4a82dcc6ba 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -462,14 +462,13 @@ mod tests { use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::{FailureLocation, MockProver, VerifyFailure}, - plonk, plonk::{Circuit, ConstraintSystem, Error}, }; use pasta_curves::pallas; - use crate::tests::circuit::serialized_proof_test_case_with_circuit; - use halo2_proofs::poly::commitment::Params; - use pasta_curves::vesta::Affine; + use crate::tests::circuit::{ + fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, + }; use std::{convert::TryInto, marker::PhantomData}; #[test] @@ -567,18 +566,8 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(11); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("../tests/vk_lookup_range_check_0").replace("\r\n", "\n") - ); + fixed_verification_key_test_with_circuit(&circuit, "src/tests/vk_lookup_range_check_0"); - // serialized_proof_test_case let file_name = "src/tests/circuit_proof_test_case_lookup_range_check.bin"; serialized_proof_test_case_with_circuit(circuit, file_name); } @@ -631,9 +620,6 @@ mod tests { } } - // Setup phase: generate parameters - let params: Params = Params::new(11); - // Edge case: zero bits (case 0) { let circuit: MyCircuit = MyCircuit { @@ -643,17 +629,8 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - // generate vk - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. Which indicates the layouters are the same. - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("../tests/vk_short_range_check_0").replace("\r\n", "\n") - ); + fixed_verification_key_test_with_circuit(&circuit, "src/tests/vk_short_range_check_0"); - // serialized_proof_test_case let file_name = "src/tests/circuit_proof_test_case_short_range_check_0.bin"; serialized_proof_test_case_with_circuit(circuit, file_name); } @@ -667,17 +644,8 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - // generate vk - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. Which indicates the layouters are the same. - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("../tests/vk_short_range_check_1").replace("\r\n", "\n") - ); + fixed_verification_key_test_with_circuit(&circuit, "src/tests/vk_short_range_check_1"); - // serialized_proof_test_case let file_name = "src/tests/circuit_proof_test_case_short_range_check_1.bin"; serialized_proof_test_case_with_circuit(circuit, file_name); } @@ -691,17 +659,8 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - // generate vk - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. Which indicates the layouters are the same. - assert_eq!( - format!("{:#?}\n", vk.pinned()), - include_str!("../tests/vk_short_range_check_2").replace("\r\n", "\n") - ); + fixed_verification_key_test_with_circuit(&circuit, "src/tests/vk_short_range_check_2"); - // serialized_proof_test_case let file_name = "src/tests/circuit_proof_test_case_short_range_check_2.bin"; serialized_proof_test_case_with_circuit(circuit, file_name); } From cf8aca05e1293abda75d44f06c47cc695491ec12 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 15 May 2024 12:07:48 +0200 Subject: [PATCH 045/121] Avoid duplicating test data folder name src/tests in every file name, use TEST_DATA_DIR const in test module instead (make the full file name from the fiule names passed, the dir name const and extention (bin for proofs) --- halo2_gadgets/src/ecc.rs | 9 ++--- halo2_gadgets/src/sinsemilla.rs | 8 +--- halo2_gadgets/src/sinsemilla/merkle.rs | 8 +--- halo2_gadgets/src/tests/circuit.rs | 39 ++++++++++++++----- .../src/utilities/lookup_range_check.rs | 32 +++++++++------ 5 files changed, 57 insertions(+), 39 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 005e9e8b18..9b464459e9 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -915,18 +915,15 @@ pub(crate) mod tests { #[test] fn fixed_verification_key_test() { let circuit = MyCircuit { test_errors: false }; - let file_name = "src/tests/vk_ecc_chip_0"; - - fixed_verification_key_test_with_circuit(&circuit, file_name); + fixed_verification_key_test_with_circuit(&circuit, "vk_ecc_chip_0"); } #[test] fn serialized_proof_test_case() { let circuit = MyCircuit { test_errors: false }; - let file_name = "src/tests/circuit_proof_test_case_ecc.bin"; - - serialized_proof_test_case_with_circuit(circuit, file_name); + serialized_proof_test_case_with_circuit(circuit, "circuit_proof_test_case_ecc"); } + #[cfg(feature = "test-dev-graph")] #[test] fn print_ecc_chip() { diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 0288a42fe8..47c6c169d8 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -758,17 +758,13 @@ pub(crate) mod tests { #[test] fn fixed_verification_key_test() { let circuit = MyCircuit {}; - let file_name = "src/tests/vk_sinsemilla_chip_0"; - - fixed_verification_key_test_with_circuit(&circuit, file_name); + fixed_verification_key_test_with_circuit(&circuit, "vk_sinsemilla_chip_0"); } #[test] fn serialized_proof_test_case() { let circuit = MyCircuit {}; - let file_name = "src/tests/circuit_proof_test_case_sinsemilla.bin"; - - serialized_proof_test_case_with_circuit(circuit, file_name); + serialized_proof_test_case_with_circuit(circuit, "circuit_proof_test_case_sinsemilla"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index c399e608a8..26ddfd42ec 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -403,17 +403,13 @@ pub mod tests { #[test] fn fixed_verification_key_test() { let circuit = generate_circuit(); - let file_name = "src/tests/vk_merkle_chip_0"; - - fixed_verification_key_test_with_circuit(&circuit, file_name); + fixed_verification_key_test_with_circuit(&circuit, "vk_merkle_chip_0"); } #[test] fn serialized_proof_test_case() { let circuit = generate_circuit(); - let file_name = "src/tests/circuit_proof_test_case_merkle.bin"; - - serialized_proof_test_case_with_circuit(circuit, file_name); + serialized_proof_test_case_with_circuit(circuit, "circuit_proof_test_case_merkle"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/tests/circuit.rs b/halo2_gadgets/src/tests/circuit.rs index e429c97be6..995c37f3bf 100644 --- a/halo2_gadgets/src/tests/circuit.rs +++ b/halo2_gadgets/src/tests/circuit.rs @@ -5,6 +5,7 @@ use std::{ io::{ self, {Read, Write}, }, + path::Path, }; use rand::rngs::OsRng; @@ -22,6 +23,8 @@ use halo2_proofs::{ transcript::{Blake2bRead, Blake2bWrite}, }; +const TEST_DATA_DIR: &str = "src/tests"; + /// A proof structure #[derive(Clone, Debug)] pub struct Proof(Vec); @@ -70,16 +73,26 @@ pub(crate) fn fixed_verification_key_test_with_circuit> circuit: &C, file_name: &str, ) { + let full_file_name = Path::new(TEST_DATA_DIR).join(file_name); + // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, circuit).unwrap(); - // Test that the pinned verification key (representing the circuit) - // is as expected. - assert_eq!( - format!("{:#?}\n", vk.pinned()), - fs::read_to_string(file_name).unwrap().replace("\r\n", "\n") - ); + let vk_text = format!("{:#?}\n", vk.pinned()); + + if env::var_os("CIRCUIT_TEST_GENERATE_NEW_VK").is_some() { + fs::write(full_file_name, vk_text).expect("Unable to write vk test file") + } else { + // Test that the pinned verification key (representing the circuit) + // is as expected. + assert_eq!( + vk_text, + fs::read_to_string(full_file_name) + .expect("Unable to read vk test file") + .replace("\r\n", "\n") + ); + } } /// write proof to a file @@ -97,12 +110,16 @@ fn read_test_case(mut r: R) -> io::Result { Ok(proof) } -pub(crate) fn conditionally_save_proof_to_disk>( +fn conditionally_save_proof_to_disk>( vk: &VerifyingKey, params: &Params, circuit: C, file_name: &str, ) { + let full_file_name = Path::new(TEST_DATA_DIR) + .join(file_name) + .with_extension("bin"); + // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, // write the old proof in a file if env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { @@ -110,7 +127,7 @@ pub(crate) fn conditionally_save_proof_to_disk>( let proof = Proof::create(vk, params, circuit).unwrap(); assert!(proof.verify(vk, params).is_ok()); - let file = fs::File::create(file_name)?; + let file = fs::File::create(full_file_name).expect("Unable to write proof test file"); write_test_case(file, &proof) }; create_proof().expect("should be able to write new proof"); @@ -121,6 +138,10 @@ pub(crate) fn serialized_proof_test_case_with_circuit>( circuit: C, file_name: &str, ) { + let full_file_name = Path::new(TEST_DATA_DIR) + .join(file_name) + .with_extension("bin"); + // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); @@ -130,7 +151,7 @@ pub(crate) fn serialized_proof_test_case_with_circuit>( // Read proof from disk let proof = { - let test_case_bytes = fs::read(file_name).unwrap(); + let test_case_bytes = fs::read(full_file_name).expect("Unable to read proof test file"); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 4a82dcc6ba..ae6c9d0c99 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -566,10 +566,12 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "src/tests/vk_lookup_range_check_0"); + fixed_verification_key_test_with_circuit(&circuit, "vk_lookup_range_check_0"); - let file_name = "src/tests/circuit_proof_test_case_lookup_range_check.bin"; - serialized_proof_test_case_with_circuit(circuit, file_name); + serialized_proof_test_case_with_circuit( + circuit, + "circuit_proof_test_case_lookup_range_check", + ); } } @@ -629,10 +631,12 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "src/tests/vk_short_range_check_0"); + fixed_verification_key_test_with_circuit(&circuit, "vk_short_range_check_0"); - let file_name = "src/tests/circuit_proof_test_case_short_range_check_0.bin"; - serialized_proof_test_case_with_circuit(circuit, file_name); + serialized_proof_test_case_with_circuit( + circuit, + "circuit_proof_test_case_short_range_check_0", + ); } // Edge case: K bits (case 1) @@ -644,10 +648,12 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "src/tests/vk_short_range_check_1"); + fixed_verification_key_test_with_circuit(&circuit, "vk_short_range_check_1"); - let file_name = "src/tests/circuit_proof_test_case_short_range_check_1.bin"; - serialized_proof_test_case_with_circuit(circuit, file_name); + serialized_proof_test_case_with_circuit( + circuit, + "circuit_proof_test_case_short_range_check_1", + ); } // Element within `num_bits` (case 2) @@ -659,10 +665,12 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "src/tests/vk_short_range_check_2"); + fixed_verification_key_test_with_circuit(&circuit, "vk_short_range_check_2"); - let file_name = "src/tests/circuit_proof_test_case_short_range_check_2.bin"; - serialized_proof_test_case_with_circuit(circuit, file_name); + serialized_proof_test_case_with_circuit( + circuit, + "circuit_proof_test_case_short_range_check_2", + ); } // Element larger than `num_bits` but within K bits From b7c7261a815dfc41a2adaa19e1abd6a9c0f57375 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 15 May 2024 12:15:20 +0200 Subject: [PATCH 046/121] Remove 'else' in fixed_verification_key_test_with_circuit function, to read after write if env var set and so check the writing --- halo2_gadgets/src/tests/circuit.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/halo2_gadgets/src/tests/circuit.rs b/halo2_gadgets/src/tests/circuit.rs index 995c37f3bf..9b0cb8d11d 100644 --- a/halo2_gadgets/src/tests/circuit.rs +++ b/halo2_gadgets/src/tests/circuit.rs @@ -83,16 +83,16 @@ pub(crate) fn fixed_verification_key_test_with_circuit> if env::var_os("CIRCUIT_TEST_GENERATE_NEW_VK").is_some() { fs::write(full_file_name, vk_text).expect("Unable to write vk test file") - } else { - // Test that the pinned verification key (representing the circuit) - // is as expected. - assert_eq!( - vk_text, - fs::read_to_string(full_file_name) - .expect("Unable to read vk test file") - .replace("\r\n", "\n") - ); } + + // Test that the pinned verification key (representing the circuit) + // is as expected. + assert_eq!( + vk_text, + fs::read_to_string(full_file_name) + .expect("Unable to read vk test file") + .replace("\r\n", "\n") + ); } /// write proof to a file From d3c7eb0a6b7ae175bbc2b2673341ab6d929e81ab Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 15 May 2024 12:38:54 +0200 Subject: [PATCH 047/121] Use fs::read, fs::write instad of read_test_case and write_test_case --- halo2_gadgets/src/tests/circuit.rs | 47 ++++++------------------------ 1 file changed, 9 insertions(+), 38 deletions(-) diff --git a/halo2_gadgets/src/tests/circuit.rs b/halo2_gadgets/src/tests/circuit.rs index 9b0cb8d11d..2fc01ab0ab 100644 --- a/halo2_gadgets/src/tests/circuit.rs +++ b/halo2_gadgets/src/tests/circuit.rs @@ -2,10 +2,7 @@ use std::{ env, fs, - io::{ - self, {Read, Write}, - }, - path::Path, + path::{Path, PathBuf}, }; use rand::rngs::OsRng; @@ -82,7 +79,7 @@ pub(crate) fn fixed_verification_key_test_with_circuit> let vk_text = format!("{:#?}\n", vk.pinned()); if env::var_os("CIRCUIT_TEST_GENERATE_NEW_VK").is_some() { - fs::write(full_file_name, vk_text).expect("Unable to write vk test file") + fs::write(&full_file_name, &vk_text).expect("Unable to write vk test file") } // Test that the pinned verification key (representing the circuit) @@ -95,42 +92,19 @@ pub(crate) fn fixed_verification_key_test_with_circuit> ); } -/// write proof to a file -fn write_test_case(mut w: W, proof: &Proof) -> io::Result<()> { - w.write_all(proof.as_ref())?; - Ok(()) -} - -/// read proof from a file -fn read_test_case(mut r: R) -> io::Result { - let mut proof_bytes = vec![]; - r.read_to_end(&mut proof_bytes)?; - let proof = Proof::new(proof_bytes); - - Ok(proof) -} - fn conditionally_save_proof_to_disk>( vk: &VerifyingKey, params: &Params, circuit: C, - file_name: &str, + full_file_name: &PathBuf, ) { - let full_file_name = Path::new(TEST_DATA_DIR) - .join(file_name) - .with_extension("bin"); - // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, // write the old proof in a file if env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> io::Result<()> { - let proof = Proof::create(vk, params, circuit).unwrap(); - assert!(proof.verify(vk, params).is_ok()); - - let file = fs::File::create(full_file_name).expect("Unable to write proof test file"); - write_test_case(file, &proof) - }; - create_proof().expect("should be able to write new proof"); + let proof = Proof::create(vk, params, circuit).unwrap(); + assert!(proof.verify(vk, params).is_ok()); + + fs::write(full_file_name, proof.as_ref()).expect("Unable to write proof test file"); } } @@ -147,13 +121,10 @@ pub(crate) fn serialized_proof_test_case_with_circuit>( let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); // Conditionally save proof to disk - conditionally_save_proof_to_disk(&vk, ¶ms, circuit, file_name); + conditionally_save_proof_to_disk(&vk, ¶ms, circuit, &full_file_name); // Read proof from disk - let proof = { - let test_case_bytes = fs::read(full_file_name).expect("Unable to read proof test file"); - read_test_case(&test_case_bytes[..]).expect("proof must be valid") - }; + let proof = Proof::new(fs::read(full_file_name).expect("Unable to read proof test file")); // Verify the old proof with the new vk assert!(proof.verify(&vk, ¶ms).is_ok()); From 5248a0ab6c5e641dd96ffdf735491dbbaa33eac8 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Wed, 15 May 2024 13:06:03 +0200 Subject: [PATCH 048/121] revert .github/workflows/ci.yml --- .github/workflows/ci.yml | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7cb0e84e71..8f6231d4ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,33 +125,33 @@ jobs: - name: Test halo2 book run: mdbook test -L target/debug/deps book/ -# codecov: -# name: Code coverage -# runs-on: ubuntu-latest -# -# steps: -# - uses: actions/checkout@v3 -# # Use stable for this to ensure that cargo-tarpaulin can be built. -# - id: prepare -# uses: ./.github/actions/prepare -# with: -# toolchain: stable -# nightly-features: true -# - name: Install cargo-tarpaulin -# uses: actions-rs/cargo@v1 -# with: -# command: install -# args: cargo-tarpaulin -# - name: Generate coverage report -# uses: actions-rs/cargo@v1 -# with: -# command: tarpaulin -# args: > -# ${{ steps.prepare.outputs.feature-flags }} -# --timeout 600 -# --out Xml -# - name: Upload coverage to Codecov -# uses: codecov/codecov-action@v3.1.4 + codecov: + name: Code coverage + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + # Use stable for this to ensure that cargo-tarpaulin can be built. + - id: prepare + uses: ./.github/actions/prepare + with: + toolchain: stable + nightly-features: true + - name: Install cargo-tarpaulin + uses: actions-rs/cargo@v1 + with: + command: install + args: cargo-tarpaulin + - name: Generate coverage report + uses: actions-rs/cargo@v1 + with: + command: tarpaulin + args: > + ${{ steps.prepare.outputs.feature-flags }} + --timeout 600 + --out Xml + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3.1.4 doc-links: name: Intra-doc links @@ -184,4 +184,4 @@ jobs: - uses: actions-rs/cargo@v1 with: command: fmt - args: --all -- --check + args: --all -- --check \ No newline at end of file From 8a68152afe953361c491bcd6eedb69f2ea057195 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Wed, 15 May 2024 13:07:47 +0200 Subject: [PATCH 049/121] rename circuit.rs --- halo2_gadgets/src/ecc.rs | 2 +- halo2_gadgets/src/sinsemilla.rs | 2 +- halo2_gadgets/src/sinsemilla/merkle.rs | 2 +- halo2_gadgets/src/tests.rs | 2 +- halo2_gadgets/src/tests/{circuit.rs => test_utils.rs} | 0 halo2_gadgets/src/utilities/lookup_range_check.rs | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename halo2_gadgets/src/tests/{circuit.rs => test_utils.rs} (100%) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 9b464459e9..31101e65cd 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -596,7 +596,7 @@ pub(crate) mod tests { FixedPoints, }; use crate::{ - tests::circuit::{ + tests::test_utils::{ fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, }, utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 47c6c169d8..ad323865d8 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -472,7 +472,7 @@ pub(crate) mod tests { NonIdentityPoint, ScalarFixed, }, sinsemilla::primitives::{self as sinsemilla, K}, - tests::circuit::{ + tests::test_utils::{ fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, }, utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 26ddfd42ec..fd1e6f2bad 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -184,7 +184,7 @@ pub mod tests { tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, - tests::circuit::{ + tests::test_utils::{ fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, }, utilities::{ diff --git a/halo2_gadgets/src/tests.rs b/halo2_gadgets/src/tests.rs index a9af55fc06..1d00cc79b7 100644 --- a/halo2_gadgets/src/tests.rs +++ b/halo2_gadgets/src/tests.rs @@ -1 +1 @@ -pub(crate) mod circuit; +pub(crate) mod test_utils; diff --git a/halo2_gadgets/src/tests/circuit.rs b/halo2_gadgets/src/tests/test_utils.rs similarity index 100% rename from halo2_gadgets/src/tests/circuit.rs rename to halo2_gadgets/src/tests/test_utils.rs diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index ae6c9d0c99..5f74a5bdca 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -466,7 +466,7 @@ mod tests { }; use pasta_curves::pallas; - use crate::tests::circuit::{ + use crate::tests::test_utils::{ fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, }; use std::{convert::TryInto, marker::PhantomData}; From 8dbb582e20e468db41166844dfa23926a7fc9177 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Wed, 15 May 2024 13:09:20 +0200 Subject: [PATCH 050/121] add a line --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f6231d4ec..8f3dad2ffa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -184,4 +184,5 @@ jobs: - uses: actions-rs/cargo@v1 with: command: fmt - args: --all -- --check \ No newline at end of file + args: --all -- --check + \ No newline at end of file From 32842df1ed44891d281b725e967c65a28f725e5a Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Wed, 15 May 2024 13:13:11 +0200 Subject: [PATCH 051/121] fix ci.yml --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f3dad2ffa..d2ecd3ba57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -185,4 +185,3 @@ jobs: with: command: fmt args: --all -- --check - \ No newline at end of file From 3324348b1a332d2ba52b63ea95fdd760c75dedd1 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 15 May 2024 14:48:41 +0200 Subject: [PATCH 052/121] Rename PallasLookupRC LookupRangeCheck trait alias to PallasLookup. Add and use PallasLookupConfig type alias for LookupRangeCheckConfigspecialized with pallas::Base and sinsemilla::K --- halo2_gadgets/src/ecc.rs | 19 +++++----- halo2_gadgets/src/ecc/chip.rs | 16 ++++----- halo2_gadgets/src/ecc/chip/mul.rs | 10 +++--- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 6 ++-- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 14 ++++---- .../src/ecc/chip/mul_fixed/full_width.rs | 8 ++--- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 29 +++++++-------- halo2_gadgets/src/sinsemilla.rs | 35 +++++++------------ halo2_gadgets/src/sinsemilla/chip.rs | 14 ++++---- .../src/sinsemilla/chip/generator_table.rs | 4 +-- .../src/sinsemilla/chip/hash_to_point.rs | 4 +-- halo2_gadgets/src/sinsemilla/merkle.rs | 20 +++-------- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 22 ++++++------ .../src/utilities/lookup_range_check.rs | 16 ++++++--- 14 files changed, 102 insertions(+), 115 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 31101e65cd..7724c21d5a 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -599,7 +599,7 @@ pub(crate) mod tests { tests::test_utils::{ fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, }, - utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + utilities::lookup_range_check::{LookupRangeCheck, PallasLookupConfig}, }; #[derive(Debug, Eq, PartialEq, Clone)] @@ -734,10 +734,7 @@ pub(crate) mod tests { #[allow(non_snake_case)] impl Circuit for MyCircuit { - type Config = EccConfig< - TestFixedBases, - LookupRangeCheckConfig, - >; + type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -772,11 +769,13 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup_table); - EccChip::< - TestFixedBases, - LookupRangeCheckConfig, - >::configure(meta, advices, lagrange_coeffs, range_check) + let range_check = PallasLookupConfig::configure(meta, advices[9], lookup_table); + EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ) } fn synthesize( diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index d7a0c92219..0c8d0902d7 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -1,7 +1,7 @@ //! Chip implementations for the ECC gadgets. use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; -use crate::utilities::{lookup_range_check::PallasLookupRC, UtilitiesInstructions}; +use crate::utilities::{lookup_range_check::PallasLookup, UtilitiesInstructions}; use arrayvec::ArrayVec; use ff::PrimeField; @@ -134,7 +134,7 @@ impl From for EccPoint { /// Configuration for [`EccChip`]. #[derive(Clone, Debug, Eq, PartialEq)] #[allow(non_snake_case)] -pub struct EccConfig, Lookup: PallasLookupRC> { +pub struct EccConfig, Lookup: PallasLookup> { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], @@ -224,11 +224,11 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { /// An [`EccInstructions`] chip that uses 10 advice columns. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct EccChip, Lookup: PallasLookupRC> { +pub struct EccChip, Lookup: PallasLookup> { config: EccConfig, } -impl, Lookup: PallasLookupRC> Chip +impl, Lookup: PallasLookup> Chip for EccChip { type Config = EccConfig; @@ -243,13 +243,13 @@ impl, Lookup: PallasLookupRC> Ch } } -impl, Lookup: PallasLookupRC> +impl, Lookup: PallasLookup> UtilitiesInstructions for EccChip { type Var = AssignedCell; } -impl, Lookup: PallasLookupRC> +impl, Lookup: PallasLookup> EccChip { /// Reconstructs this chip from the given config. @@ -409,7 +409,7 @@ pub enum ScalarVar { FullWidth, } -impl, Lookup: PallasLookupRC> EccInstructions +impl, Lookup: PallasLookup> EccInstructions for EccChip where >::Base: @@ -597,7 +597,7 @@ where } } -impl, Lookup: PallasLookupRC> +impl, Lookup: PallasLookup> BaseFitsInScalarInstructions for EccChip where >::Base: diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 70c14df284..49f19900d0 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -1,6 +1,6 @@ use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q}; use crate::utilities::{ - lookup_range_check::PallasLookupRC, + lookup_range_check::PallasLookup, {bool_check, ternary}, }; use std::{ @@ -46,7 +46,7 @@ const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, // Configuration used in complete addition @@ -61,7 +61,7 @@ pub struct Config { overflow_config: overflow::Config, } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, add_config: add::Config, @@ -468,7 +468,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::PallasLookupRC; + use crate::utilities::lookup_range_check::PallasLookup; use crate::{ ecc::{ chip::{EccChip, EccPoint}, @@ -478,7 +478,7 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul( + pub(crate) fn test_mul( chip: EccChip, mut layouter: impl Layouter, p: &NonIdentityPoint>, diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index eb5810fac5..53cde0f10d 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -1,5 +1,5 @@ use super::{T_Q, Z}; -use crate::{sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::PallasLookupRC}; +use crate::{sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::PallasLookup}; use group::ff::PrimeField; use halo2_proofs::circuit::AssignedCell; @@ -13,7 +13,7 @@ use pasta_curves::pallas; use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, // 10-bit lookup table @@ -22,7 +22,7 @@ pub struct Config { advices: [Column; 3], } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, lookup_config: Lookup, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 760ab20b9a..917d8836a2 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -2,7 +2,7 @@ use super::super::{EccBaseFieldElemFixed, EccPoint, FixedPoints, NUM_WINDOWS, T_ use super::H_BASE; use crate::utilities::{ - bitrange_subset, bool_check, lookup_range_check::PallasLookupRC, range_check, + bitrange_subset, bool_check, lookup_range_check::PallasLookup, range_check, }; use group::ff::PrimeField; @@ -16,14 +16,14 @@ use pasta_curves::pallas; use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Config, Lookup: PallasLookupRC> { +pub struct Config, Lookup: PallasLookup> { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], lookup_config: Lookup, super_config: super::Config, } -impl, Lookup: PallasLookupRC> Config { +impl, Lookup: PallasLookup> Config { pub(crate) fn configure( meta: &mut ConstraintSystem, canon_advices: [Column; 3], @@ -386,7 +386,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::PallasLookupRC; + use crate::utilities::lookup_range_check::PallasLookup; use crate::{ ecc::{ chip::{EccChip, FixedPoint, H}, @@ -396,7 +396,7 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul_fixed_base_field( + pub(crate) fn test_mul_fixed_base_field( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -409,7 +409,7 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( + fn test_single_base( chip: EccChip, mut layouter: impl Layouter, base: FixedPointBaseField>, @@ -419,7 +419,7 @@ pub mod tests { let column = chip.config().advices[0]; - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs index fe0ccd8d3d..0b7f64c635 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs @@ -192,9 +192,9 @@ pub mod tests { tests::{FullWidth, TestFixedBases}, FixedPoint, NonIdentityPoint, Point, ScalarFixed, }; - use crate::utilities::lookup_range_check::PallasLookupRC; + use crate::utilities::lookup_range_check::PallasLookup; - pub(crate) fn test_mul_fixed( + pub(crate) fn test_mul_fixed( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -210,13 +210,13 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( + fn test_single_base( chip: EccChip, mut layouter: impl Layouter, base: FixedPoint>, base_val: pallas::Affine, ) -> Result<(), Error> { - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index fd88bcd72b..5697b6840b 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -253,18 +253,20 @@ pub mod tests { }; use pasta_curves::pallas; - use crate::utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRC}; use crate::{ ecc::{ chip::{EccChip, FixedPoint, MagnitudeSign}, tests::{Short, TestFixedBases}, FixedPointShort, NonIdentityPoint, Point, ScalarFixedShort, }, - utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, + utilities::{ + lookup_range_check::{LookupRangeCheck, PallasLookup, PallasLookupConfig}, + UtilitiesInstructions, + }, }; #[allow(clippy::op_ref)] - pub(crate) fn test_mul_fixed_short( + pub(crate) fn test_mul_fixed_short( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -272,7 +274,7 @@ pub mod tests { let base_val = Short.generator(); let test_short = FixedPointShort::from_inner(chip.clone(), Short); - fn load_magnitude_sign( + fn load_magnitude_sign( chip: EccChip, mut layouter: impl Layouter, magnitude: pallas::Base, @@ -290,7 +292,7 @@ pub mod tests { Ok((magnitude, sign)) } - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, @@ -426,10 +428,7 @@ pub mod tests { } impl Circuit for MyCircuit { - type Config = EccConfig< - TestFixedBases, - LookupRangeCheckConfig, - >; + type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -465,11 +464,13 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup_table); - EccChip::< - TestFixedBases, - LookupRangeCheckConfig, - >::configure(meta, advices, lagrange_coeffs, range_check) + let range_check = PallasLookupConfig::configure(meta, advices[9], lookup_table); + EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ) } fn synthesize( diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index ad323865d8..98274f7d0e 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -475,7 +475,7 @@ pub(crate) mod tests { tests::test_utils::{ fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, }, - utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + utilities::lookup_range_check::{LookupRangeCheck, PallasLookupConfig}, }; use group::{ff::Field, Curve}; @@ -521,22 +521,9 @@ pub(crate) mod tests { impl Circuit for MyCircuit { #[allow(clippy::type_complexity)] type Config = ( - EccConfig< - TestFixedBases, - LookupRangeCheckConfig, - >, - SinsemillaConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfig, - >, - SinsemillaConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfig, - >, + EccConfig, + SinsemillaConfig, + SinsemillaConfig, ); type FloorPlanner = SimpleFloorPlanner; @@ -582,12 +569,14 @@ pub(crate) mod tests { meta.lookup_table_column(), ); - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let range_check = PallasLookupConfig::configure(meta, advices[9], table_idx); - let ecc_config = EccChip::< - TestFixedBases, - LookupRangeCheckConfig, - >::configure(meta, advices, lagrange_coeffs, range_check); + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); let config1 = SinsemillaChip::configure( meta, @@ -622,7 +611,7 @@ pub(crate) mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - LookupRangeCheckConfig, + PallasLookupConfig, >::load(config.1.clone(), &mut layouter)?; // This MerkleCRH example is purely for illustrative purposes. diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index b242db41be..19af2e9bd1 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -9,7 +9,7 @@ use crate::{ chip::{DoubleAndAdd, NonIdentityEccPoint}, FixedPoints, }, - utilities::lookup_range_check::PallasLookupRC, + utilities::lookup_range_check::PallasLookup, }; use std::marker::PhantomData; @@ -35,7 +35,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { /// Binary selector used in lookup argument and in the body of the Sinsemilla hash. q_sinsemilla1: Selector, @@ -68,7 +68,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { /// Returns an array of all advice columns in this config, in arbitrary order. pub(super) fn advices(&self) -> [Column; 5] { @@ -103,7 +103,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { config: SinsemillaConfig, } @@ -113,7 +113,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { type Config = SinsemillaConfig; type Loaded = (); @@ -132,7 +132,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { @@ -321,7 +321,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { type CellValue = AssignedCell; diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 013995911c..5ec7278bf8 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -8,7 +8,7 @@ use halo2_proofs::{ use super::{CommitDomains, FixedPoints, HashDomains}; use crate::{ sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, - utilities::lookup_range_check::PallasLookupRC, + utilities::lookup_range_check::PallasLookup, }; use pasta_curves::pallas; @@ -33,7 +33,7 @@ impl GeneratorTableConfig { Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { let (table_idx, table_x, table_y) = ( config.generator_table.table_idx, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 709da2455d..1cff0a423c 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -3,7 +3,7 @@ use super::{NonIdentityEccPoint, SinsemillaChip}; use crate::{ ecc::FixedPoints, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, - utilities::lookup_range_check::PallasLookupRC, + utilities::lookup_range_check::PallasLookup, }; use ff::Field; @@ -30,7 +30,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index fd1e6f2bad..b113e5908e 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -189,7 +189,7 @@ pub mod tests { }, utilities::{ i2lebsp, - lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + lookup_range_check::{LookupRangeCheck, PallasLookupConfig}, UtilitiesInstructions, }, }; @@ -215,18 +215,8 @@ pub mod tests { impl Circuit for MyCircuit { type Config = ( - MerkleConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfig, - >, - MerkleConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheckConfig, - >, + MerkleConfig, + MerkleConfig, ); type FloorPlanner = SimpleFloorPlanner; @@ -264,7 +254,7 @@ pub mod tests { meta.lookup_table_column(), ); - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup.0); + let range_check = PallasLookupConfig::configure(meta, advices[9], lookup.0); let sinsemilla_config_1 = SinsemillaChip::configure( meta, @@ -299,7 +289,7 @@ pub mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - LookupRangeCheckConfig, + PallasLookupConfig, >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 37aa4e7f99..93f0fc8175 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -11,7 +11,7 @@ use super::MerkleInstructions; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, - utilities::{lookup_range_check::PallasLookupRC, RangeConstrained}, + utilities::{lookup_range_check::PallasLookup, RangeConstrained}, { ecc::FixedPoints, sinsemilla::{ @@ -33,7 +33,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { advices: [Column; 5], q_decompose: Selector, @@ -57,7 +57,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { config: MerkleConfig, } @@ -67,7 +67,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { type Config = MerkleConfig; type Loaded = (); @@ -86,7 +86,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { /// Configures the [`MerkleChip`]. pub fn configure( @@ -227,7 +227,7 @@ where Hash: HashDomains, Commit: CommitDomains, F: FixedPoints, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { } @@ -237,7 +237,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { } @@ -255,7 +255,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { #[allow(non_snake_case)] fn hash_layer( @@ -474,7 +474,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { type Var = AssignedCell; } @@ -485,7 +485,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { #[allow(clippy::type_complexity)] fn swap( @@ -507,7 +507,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookup, { type CellValue = as SinsemillaInstructions< pallas::Affine, diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 5f74a5bdca..a0c77629d0 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -442,14 +442,22 @@ impl LookupRangeCheck for LookupRangeCh } } -/// The `PallasLookupRC` trait extends the `LookupRangeCheck` with additional -/// standard traits necessary for effective use in cryptographic contexts. -pub trait PallasLookupRC: +/// This trait is a shorthand for `LookupRangeCheck` specialized with `pallas::Base` and +/// `sinsemilla::K`. In this crate, `LookupRangeCheck` is always used with these parameters. +/// By defining this trait, we reduce verbosity and improve readability. Besides, it extends +/// the `LookupRangeCheck` with additional standard traits necessary for effective use in +/// cryptographic contexts. +pub trait PallasLookup: LookupRangeCheck + Eq + PartialEq + Clone + Copy + Debug { } -impl PallasLookupRC for LookupRangeCheckConfig {} +/// In this crate, `LookupRangeCheckConfig` is always used with `pallas::Base` as the prime field +/// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, +/// we introduce this alias and use it instead of that long construction. +pub type PallasLookupConfig = LookupRangeCheckConfig; + +impl PallasLookup for PallasLookupConfig {} #[cfg(test)] mod tests { From 92922becd0cb0c7ff329edb9f238f00365d6fa8d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 15 May 2024 16:53:11 +0200 Subject: [PATCH 053/121] Move circuit test data to tests/circuit_reference_data folder, fix names of the test data files to follow the same convention: .proof.bin for proof tests, .vk.txt for verifying key/layout tests --- halo2_gadgets/src/ecc.rs | 4 ++-- halo2_gadgets/src/sinsemilla.rs | 4 ++-- halo2_gadgets/src/sinsemilla/merkle.rs | 4 ++-- .../ecc_chip.proof.bin} | Bin .../ecc_chip.vk.txt} | 0 .../lookup_range_check.proof.bin} | Bin .../lookup_range_check.vk.txt} | 0 .../merkle_chip.proof.bin} | Bin .../merkle_chip.vk.txt} | 0 .../short_range_check_0.proof.bin} | Bin .../short_range_check_0.vk.txt} | 0 .../short_range_check_1.proof.bin} | Bin .../short_range_check_1.vk.txt} | 0 .../short_range_check_2.proof.bin} | Bin .../short_range_check_2.vk.txt} | 0 .../sinsemilla_chip.proof.bin} | Bin .../sinsemilla_chip.vk.txt} | 0 halo2_gadgets/src/tests/test_utils.rs | 8 +++++--- .../src/utilities/lookup_range_check.rs | 16 ++++++++-------- 19 files changed, 19 insertions(+), 17 deletions(-) rename halo2_gadgets/src/tests/{circuit_proof_test_case_ecc.bin => circuit_reference_data/ecc_chip.proof.bin} (100%) rename halo2_gadgets/src/tests/{vk_ecc_chip_0 => circuit_reference_data/ecc_chip.vk.txt} (100%) rename halo2_gadgets/src/tests/{circuit_proof_test_case_lookup_range_check.bin => circuit_reference_data/lookup_range_check.proof.bin} (100%) rename halo2_gadgets/src/tests/{vk_lookup_range_check_0 => circuit_reference_data/lookup_range_check.vk.txt} (100%) rename halo2_gadgets/src/tests/{circuit_proof_test_case_merkle.bin => circuit_reference_data/merkle_chip.proof.bin} (100%) rename halo2_gadgets/src/tests/{vk_merkle_chip_0 => circuit_reference_data/merkle_chip.vk.txt} (100%) rename halo2_gadgets/src/tests/{circuit_proof_test_case_short_range_check_0.bin => circuit_reference_data/short_range_check_0.proof.bin} (100%) rename halo2_gadgets/src/tests/{vk_short_range_check_0 => circuit_reference_data/short_range_check_0.vk.txt} (100%) rename halo2_gadgets/src/tests/{circuit_proof_test_case_short_range_check_1.bin => circuit_reference_data/short_range_check_1.proof.bin} (100%) rename halo2_gadgets/src/tests/{vk_short_range_check_1 => circuit_reference_data/short_range_check_1.vk.txt} (100%) rename halo2_gadgets/src/tests/{circuit_proof_test_case_short_range_check_2.bin => circuit_reference_data/short_range_check_2.proof.bin} (100%) rename halo2_gadgets/src/tests/{vk_short_range_check_2 => circuit_reference_data/short_range_check_2.vk.txt} (100%) rename halo2_gadgets/src/tests/{circuit_proof_test_case_sinsemilla.bin => circuit_reference_data/sinsemilla_chip.proof.bin} (100%) rename halo2_gadgets/src/tests/{vk_sinsemilla_chip_0 => circuit_reference_data/sinsemilla_chip.vk.txt} (100%) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 7724c21d5a..23c4cbf479 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -914,13 +914,13 @@ pub(crate) mod tests { #[test] fn fixed_verification_key_test() { let circuit = MyCircuit { test_errors: false }; - fixed_verification_key_test_with_circuit(&circuit, "vk_ecc_chip_0"); + fixed_verification_key_test_with_circuit(&circuit, "ecc_chip"); } #[test] fn serialized_proof_test_case() { let circuit = MyCircuit { test_errors: false }; - serialized_proof_test_case_with_circuit(circuit, "circuit_proof_test_case_ecc"); + serialized_proof_test_case_with_circuit(circuit, "ecc_chip"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 98274f7d0e..5f2ab2f268 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -747,13 +747,13 @@ pub(crate) mod tests { #[test] fn fixed_verification_key_test() { let circuit = MyCircuit {}; - fixed_verification_key_test_with_circuit(&circuit, "vk_sinsemilla_chip_0"); + fixed_verification_key_test_with_circuit(&circuit, "sinsemilla_chip"); } #[test] fn serialized_proof_test_case() { let circuit = MyCircuit {}; - serialized_proof_test_case_with_circuit(circuit, "circuit_proof_test_case_sinsemilla"); + serialized_proof_test_case_with_circuit(circuit, "sinsemilla_chip"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index b113e5908e..83f284352d 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -393,13 +393,13 @@ pub mod tests { #[test] fn fixed_verification_key_test() { let circuit = generate_circuit(); - fixed_verification_key_test_with_circuit(&circuit, "vk_merkle_chip_0"); + fixed_verification_key_test_with_circuit(&circuit, "merkle_chip"); } #[test] fn serialized_proof_test_case() { let circuit = generate_circuit(); - serialized_proof_test_case_with_circuit(circuit, "circuit_proof_test_case_merkle"); + serialized_proof_test_case_with_circuit(circuit, "merkle_chip"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_ecc.bin b/halo2_gadgets/src/tests/circuit_reference_data/ecc_chip.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_proof_test_case_ecc.bin rename to halo2_gadgets/src/tests/circuit_reference_data/ecc_chip.proof.bin diff --git a/halo2_gadgets/src/tests/vk_ecc_chip_0 b/halo2_gadgets/src/tests/circuit_reference_data/ecc_chip.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/vk_ecc_chip_0 rename to halo2_gadgets/src/tests/circuit_reference_data/ecc_chip.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_lookup_range_check.bin b/halo2_gadgets/src/tests/circuit_reference_data/lookup_range_check.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_proof_test_case_lookup_range_check.bin rename to halo2_gadgets/src/tests/circuit_reference_data/lookup_range_check.proof.bin diff --git a/halo2_gadgets/src/tests/vk_lookup_range_check_0 b/halo2_gadgets/src/tests/circuit_reference_data/lookup_range_check.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/vk_lookup_range_check_0 rename to halo2_gadgets/src/tests/circuit_reference_data/lookup_range_check.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_merkle.bin b/halo2_gadgets/src/tests/circuit_reference_data/merkle_chip.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_proof_test_case_merkle.bin rename to halo2_gadgets/src/tests/circuit_reference_data/merkle_chip.proof.bin diff --git a/halo2_gadgets/src/tests/vk_merkle_chip_0 b/halo2_gadgets/src/tests/circuit_reference_data/merkle_chip.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/vk_merkle_chip_0 rename to halo2_gadgets/src/tests/circuit_reference_data/merkle_chip.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_0.bin b/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_0.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_0.bin rename to halo2_gadgets/src/tests/circuit_reference_data/short_range_check_0.proof.bin diff --git a/halo2_gadgets/src/tests/vk_short_range_check_0 b/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_0.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/vk_short_range_check_0 rename to halo2_gadgets/src/tests/circuit_reference_data/short_range_check_0.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_1.bin b/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_1.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_1.bin rename to halo2_gadgets/src/tests/circuit_reference_data/short_range_check_1.proof.bin diff --git a/halo2_gadgets/src/tests/vk_short_range_check_1 b/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_1.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/vk_short_range_check_1 rename to halo2_gadgets/src/tests/circuit_reference_data/short_range_check_1.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_2.bin b/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_2.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_proof_test_case_short_range_check_2.bin rename to halo2_gadgets/src/tests/circuit_reference_data/short_range_check_2.proof.bin diff --git a/halo2_gadgets/src/tests/vk_short_range_check_2 b/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_2.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/vk_short_range_check_2 rename to halo2_gadgets/src/tests/circuit_reference_data/short_range_check_2.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_proof_test_case_sinsemilla.bin b/halo2_gadgets/src/tests/circuit_reference_data/sinsemilla_chip.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_proof_test_case_sinsemilla.bin rename to halo2_gadgets/src/tests/circuit_reference_data/sinsemilla_chip.proof.bin diff --git a/halo2_gadgets/src/tests/vk_sinsemilla_chip_0 b/halo2_gadgets/src/tests/circuit_reference_data/sinsemilla_chip.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/vk_sinsemilla_chip_0 rename to halo2_gadgets/src/tests/circuit_reference_data/sinsemilla_chip.vk.txt diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index 2fc01ab0ab..962bcc23d3 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -20,7 +20,7 @@ use halo2_proofs::{ transcript::{Blake2bRead, Blake2bWrite}, }; -const TEST_DATA_DIR: &str = "src/tests"; +const TEST_DATA_DIR: &str = "src/tests/circuit_reference_data"; /// A proof structure #[derive(Clone, Debug)] @@ -70,7 +70,9 @@ pub(crate) fn fixed_verification_key_test_with_circuit> circuit: &C, file_name: &str, ) { - let full_file_name = Path::new(TEST_DATA_DIR).join(file_name); + let full_file_name = Path::new(TEST_DATA_DIR) + .join(file_name) + .with_extension("vk.txt"); // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); @@ -114,7 +116,7 @@ pub(crate) fn serialized_proof_test_case_with_circuit>( ) { let full_file_name = Path::new(TEST_DATA_DIR) .join(file_name) - .with_extension("bin"); + .with_extension("proof.bin"); // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index a0c77629d0..2ffe4eb942 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -574,11 +574,11 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "vk_lookup_range_check_0"); + fixed_verification_key_test_with_circuit(&circuit, "lookup_range_check"); serialized_proof_test_case_with_circuit( circuit, - "circuit_proof_test_case_lookup_range_check", + "lookup_range_check", ); } } @@ -639,11 +639,11 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "vk_short_range_check_0"); + fixed_verification_key_test_with_circuit(&circuit, "short_range_check_0"); serialized_proof_test_case_with_circuit( circuit, - "circuit_proof_test_case_short_range_check_0", + "short_range_check_0", ); } @@ -656,11 +656,11 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "vk_short_range_check_1"); + fixed_verification_key_test_with_circuit(&circuit, "short_range_check_1"); serialized_proof_test_case_with_circuit( circuit, - "circuit_proof_test_case_short_range_check_1", + "short_range_check_1", ); } @@ -673,11 +673,11 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "vk_short_range_check_2"); + fixed_verification_key_test_with_circuit(&circuit, "short_range_check_2"); serialized_proof_test_case_with_circuit( circuit, - "circuit_proof_test_case_short_range_check_2", + "short_range_check_2", ); } From 6c7713f9f52ffc1bcb46207ab2195100a77343a8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 15 May 2024 17:06:31 +0200 Subject: [PATCH 054/121] Rename circuit_reference_data to circuit_data --- .../ecc_chip.proof.bin | Bin .../ecc_chip.vk.txt | 0 .../lookup_range_check.proof.bin | Bin .../lookup_range_check.vk.txt | 0 .../merkle_chip.proof.bin | Bin .../merkle_chip.vk.txt | 0 .../short_range_check_0.proof.bin | Bin .../short_range_check_0.vk.txt | 0 .../short_range_check_1.proof.bin | Bin .../short_range_check_1.vk.txt | 0 .../short_range_check_2.proof.bin | Bin .../short_range_check_2.vk.txt | 0 .../sinsemilla_chip.proof.bin | Bin .../sinsemilla_chip.vk.txt | 0 halo2_gadgets/src/tests/test_utils.rs | 2 +- 15 files changed, 1 insertion(+), 1 deletion(-) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/ecc_chip.proof.bin (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/ecc_chip.vk.txt (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/lookup_range_check.proof.bin (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/lookup_range_check.vk.txt (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/merkle_chip.proof.bin (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/merkle_chip.vk.txt (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/short_range_check_0.proof.bin (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/short_range_check_0.vk.txt (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/short_range_check_1.proof.bin (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/short_range_check_1.vk.txt (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/short_range_check_2.proof.bin (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/short_range_check_2.vk.txt (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/sinsemilla_chip.proof.bin (100%) rename halo2_gadgets/src/tests/{circuit_reference_data => circuit_data}/sinsemilla_chip.vk.txt (100%) diff --git a/halo2_gadgets/src/tests/circuit_reference_data/ecc_chip.proof.bin b/halo2_gadgets/src/tests/circuit_data/ecc_chip.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/ecc_chip.proof.bin rename to halo2_gadgets/src/tests/circuit_data/ecc_chip.proof.bin diff --git a/halo2_gadgets/src/tests/circuit_reference_data/ecc_chip.vk.txt b/halo2_gadgets/src/tests/circuit_data/ecc_chip.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/ecc_chip.vk.txt rename to halo2_gadgets/src/tests/circuit_data/ecc_chip.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_reference_data/lookup_range_check.proof.bin b/halo2_gadgets/src/tests/circuit_data/lookup_range_check.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/lookup_range_check.proof.bin rename to halo2_gadgets/src/tests/circuit_data/lookup_range_check.proof.bin diff --git a/halo2_gadgets/src/tests/circuit_reference_data/lookup_range_check.vk.txt b/halo2_gadgets/src/tests/circuit_data/lookup_range_check.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/lookup_range_check.vk.txt rename to halo2_gadgets/src/tests/circuit_data/lookup_range_check.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_reference_data/merkle_chip.proof.bin b/halo2_gadgets/src/tests/circuit_data/merkle_chip.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/merkle_chip.proof.bin rename to halo2_gadgets/src/tests/circuit_data/merkle_chip.proof.bin diff --git a/halo2_gadgets/src/tests/circuit_reference_data/merkle_chip.vk.txt b/halo2_gadgets/src/tests/circuit_data/merkle_chip.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/merkle_chip.vk.txt rename to halo2_gadgets/src/tests/circuit_data/merkle_chip.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_0.proof.bin b/halo2_gadgets/src/tests/circuit_data/short_range_check_0.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/short_range_check_0.proof.bin rename to halo2_gadgets/src/tests/circuit_data/short_range_check_0.proof.bin diff --git a/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_0.vk.txt b/halo2_gadgets/src/tests/circuit_data/short_range_check_0.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/short_range_check_0.vk.txt rename to halo2_gadgets/src/tests/circuit_data/short_range_check_0.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_1.proof.bin b/halo2_gadgets/src/tests/circuit_data/short_range_check_1.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/short_range_check_1.proof.bin rename to halo2_gadgets/src/tests/circuit_data/short_range_check_1.proof.bin diff --git a/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_1.vk.txt b/halo2_gadgets/src/tests/circuit_data/short_range_check_1.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/short_range_check_1.vk.txt rename to halo2_gadgets/src/tests/circuit_data/short_range_check_1.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_2.proof.bin b/halo2_gadgets/src/tests/circuit_data/short_range_check_2.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/short_range_check_2.proof.bin rename to halo2_gadgets/src/tests/circuit_data/short_range_check_2.proof.bin diff --git a/halo2_gadgets/src/tests/circuit_reference_data/short_range_check_2.vk.txt b/halo2_gadgets/src/tests/circuit_data/short_range_check_2.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/short_range_check_2.vk.txt rename to halo2_gadgets/src/tests/circuit_data/short_range_check_2.vk.txt diff --git a/halo2_gadgets/src/tests/circuit_reference_data/sinsemilla_chip.proof.bin b/halo2_gadgets/src/tests/circuit_data/sinsemilla_chip.proof.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/sinsemilla_chip.proof.bin rename to halo2_gadgets/src/tests/circuit_data/sinsemilla_chip.proof.bin diff --git a/halo2_gadgets/src/tests/circuit_reference_data/sinsemilla_chip.vk.txt b/halo2_gadgets/src/tests/circuit_data/sinsemilla_chip.vk.txt similarity index 100% rename from halo2_gadgets/src/tests/circuit_reference_data/sinsemilla_chip.vk.txt rename to halo2_gadgets/src/tests/circuit_data/sinsemilla_chip.vk.txt diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index 962bcc23d3..0999cba67f 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -20,7 +20,7 @@ use halo2_proofs::{ transcript::{Blake2bRead, Blake2bWrite}, }; -const TEST_DATA_DIR: &str = "src/tests/circuit_reference_data"; +const TEST_DATA_DIR: &str = "src/tests/circuit_data"; /// A proof structure #[derive(Clone, Debug)] From 8922ed6436b5e73088969d1eec72f80d30fc6e77 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 15 May 2024 17:09:57 +0200 Subject: [PATCH 055/121] Fix cargo fmt issues --- .../src/utilities/lookup_range_check.rs | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 2ffe4eb942..c1f6647b1f 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -576,10 +576,7 @@ mod tests { fixed_verification_key_test_with_circuit(&circuit, "lookup_range_check"); - serialized_proof_test_case_with_circuit( - circuit, - "lookup_range_check", - ); + serialized_proof_test_case_with_circuit(circuit, "lookup_range_check"); } } @@ -641,10 +638,7 @@ mod tests { fixed_verification_key_test_with_circuit(&circuit, "short_range_check_0"); - serialized_proof_test_case_with_circuit( - circuit, - "short_range_check_0", - ); + serialized_proof_test_case_with_circuit(circuit, "short_range_check_0"); } // Edge case: K bits (case 1) @@ -658,10 +652,7 @@ mod tests { fixed_verification_key_test_with_circuit(&circuit, "short_range_check_1"); - serialized_proof_test_case_with_circuit( - circuit, - "short_range_check_1", - ); + serialized_proof_test_case_with_circuit(circuit, "short_range_check_1"); } // Element within `num_bits` (case 2) @@ -675,10 +666,7 @@ mod tests { fixed_verification_key_test_with_circuit(&circuit, "short_range_check_2"); - serialized_proof_test_case_with_circuit( - circuit, - "short_range_check_2", - ); + serialized_proof_test_case_with_circuit(circuit, "short_range_check_2"); } // Element larger than `num_bits` but within K bits From f75b054dac309474e80c59e04ae424d12c8a19d4 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 16 May 2024 15:10:34 +0200 Subject: [PATCH 056/121] Try to increase cargo-tarpaulin timeout in ci.yml from 600 to 1800 to see if it helps to resolve test failing on GitHub --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2ecd3ba57..f41730f6e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -148,7 +148,7 @@ jobs: command: tarpaulin args: > ${{ steps.prepare.outputs.feature-flags }} - --timeout 600 + --timeout 1800 --out Xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v3.1.4 From 5414d9526c0e774b0d0597b3fcfea06b656f4ab3 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 17 May 2024 09:51:33 +0200 Subject: [PATCH 057/121] Add default generic arguments for PallasLookup to improve backward compatibility This change adds default generic arguments for types implementing the PallasLookup trait, assigning them to PallasLookupConfig by default. This adjustment allows existing code to function without requiring users to explicitly specify PallasLookupConfig, thus minimizing breaking changes. Users will still need to bring the PallasLookup trait into scope using 'use ... PallasLookup'. --- halo2_gadgets/src/ecc/chip.rs | 15 ++++++++++++--- halo2_gadgets/src/ecc/chip/mul.rs | 4 ++-- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 7 +++++-- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 6 ++++-- halo2_gadgets/src/sinsemilla/chip.rs | 6 +++--- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 9 ++++++--- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 0c8d0902d7..abfb75538e 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -1,7 +1,10 @@ //! Chip implementations for the ECC gadgets. use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; -use crate::utilities::{lookup_range_check::PallasLookup, UtilitiesInstructions}; +use crate::utilities::{ + lookup_range_check::{PallasLookup, PallasLookupConfig}, + UtilitiesInstructions, +}; use arrayvec::ArrayVec; use ff::PrimeField; @@ -134,7 +137,10 @@ impl From for EccPoint { /// Configuration for [`EccChip`]. #[derive(Clone, Debug, Eq, PartialEq)] #[allow(non_snake_case)] -pub struct EccConfig, Lookup: PallasLookup> { +pub struct EccConfig< + FixedPoints: super::FixedPoints, + Lookup: PallasLookup = PallasLookupConfig, +> { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], @@ -224,7 +230,10 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { /// An [`EccInstructions`] chip that uses 10 advice columns. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct EccChip, Lookup: PallasLookup> { +pub struct EccChip< + FixedPoints: super::FixedPoints, + Lookup: PallasLookup = PallasLookupConfig, +> { config: EccConfig, } diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 49f19900d0..2826719267 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -1,6 +1,6 @@ use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q}; use crate::utilities::{ - lookup_range_check::PallasLookup, + lookup_range_check::{PallasLookup, PallasLookupConfig}, {bool_check, ternary}, }; use std::{ @@ -46,7 +46,7 @@ const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, // Configuration used in complete addition diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index 53cde0f10d..75b81f9d14 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -1,5 +1,8 @@ use super::{T_Q, Z}; -use crate::{sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::PallasLookup}; +use crate::{ + sinsemilla::primitives as sinsemilla, + utilities::lookup_range_check::{PallasLookup, PallasLookupConfig}, +}; use group::ff::PrimeField; use halo2_proofs::circuit::AssignedCell; @@ -13,7 +16,7 @@ use pasta_curves::pallas; use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, // 10-bit lookup table diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 917d8836a2..1618f2b474 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -2,7 +2,9 @@ use super::super::{EccBaseFieldElemFixed, EccPoint, FixedPoints, NUM_WINDOWS, T_ use super::H_BASE; use crate::utilities::{ - bitrange_subset, bool_check, lookup_range_check::PallasLookup, range_check, + bitrange_subset, bool_check, + lookup_range_check::{PallasLookup, PallasLookupConfig}, + range_check, }; use group::ff::PrimeField; @@ -16,7 +18,7 @@ use pasta_curves::pallas; use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Config, Lookup: PallasLookup> { +pub struct Config, Lookup: PallasLookup = PallasLookupConfig> { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], lookup_config: Lookup, diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 19af2e9bd1..a87fc67cc5 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -9,7 +9,7 @@ use crate::{ chip::{DoubleAndAdd, NonIdentityEccPoint}, FixedPoints, }, - utilities::lookup_range_check::PallasLookup, + utilities::lookup_range_check::{PallasLookup, PallasLookupConfig}, }; use std::marker::PhantomData; @@ -30,7 +30,7 @@ mod hash_to_point; /// Configuration for the Sinsemilla hash chip #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaConfig +pub struct SinsemillaConfig where Hash: HashDomains, F: FixedPoints, @@ -98,7 +98,7 @@ where /// /// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaChip +pub struct SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 93f0fc8175..6cf1b647f5 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -11,7 +11,10 @@ use super::MerkleInstructions; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, - utilities::{lookup_range_check::PallasLookup, RangeConstrained}, + utilities::{ + lookup_range_check::{PallasLookup, PallasLookupConfig}, + RangeConstrained, + }, { ecc::FixedPoints, sinsemilla::{ @@ -28,7 +31,7 @@ use group::ff::PrimeField; /// Configuration for the `MerkleChip` implementation. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleConfig +pub struct MerkleConfig where Hash: HashDomains, Fixed: FixedPoints, @@ -52,7 +55,7 @@ where /// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of /// `left` and `right`. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleChip +pub struct MerkleChip where Hash: HashDomains, Fixed: FixedPoints, From 396bbdea5db073f12aea172a60f5533951611944 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 22 May 2024 09:34:05 +0200 Subject: [PATCH 058/121] Try to increase cargo-tarpaulin timeout in ci.yml from to 3600 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f41730f6e1..9c2efa385d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -148,7 +148,7 @@ jobs: command: tarpaulin args: > ${{ steps.prepare.outputs.feature-flags }} - --timeout 1800 + --timeout 3600 --out Xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v3.1.4 From 1ae0a3135f548cfe3e1e71e2056aae799b97090c Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 28 May 2024 11:41:51 +0200 Subject: [PATCH 059/121] update --- halo2_gadgets/src/ecc.rs | 14 +++---- halo2_gadgets/src/ecc/chip.rs | 16 ++++---- halo2_gadgets/src/ecc/chip/mul.rs | 10 ++--- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 6 +-- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 14 +++---- .../src/ecc/chip/mul_fixed/full_width.rs | 8 ++-- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 14 +++---- halo2_gadgets/src/sinsemilla.rs | 20 +++++----- halo2_gadgets/src/sinsemilla/chip.rs | 15 +++---- .../src/sinsemilla/chip/generator_table.rs | 4 +- .../src/sinsemilla/chip/hash_to_point.rs | 4 +- halo2_gadgets/src/sinsemilla/merkle.rs | 16 ++++---- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 25 ++++++------ ...{ecc_chip.proof.bin => proof_ecc_chip.bin} | Bin ...proof.bin => proof_lookup_range_check.bin} | Bin ...e_chip.proof.bin => proof_merkle_chip.bin} | Bin ...roof.bin => proof_short_range_check_0.bin} | Bin ...roof.bin => proof_short_range_check_1.bin} | Bin ...roof.bin => proof_short_range_check_2.bin} | Bin ...ip.proof.bin => proof_sinsemilla_chip.bin} | Bin .../{ecc_chip.vk.txt => vk_ecc_chip.rdata} | 0 ...eck.vk.txt => vk_lookup_range_check.rdata} | 0 ...erkle_chip.vk.txt => vk_merkle_chip.rdata} | 0 ..._0.vk.txt => vk_short_range_check_0.rdata} | 0 ..._1.vk.txt => vk_short_range_check_1.rdata} | 0 ..._2.vk.txt => vk_short_range_check_2.rdata} | 0 ...a_chip.vk.txt => vk_sinsemilla_chip.rdata} | 0 halo2_gadgets/src/tests/test_utils.rs | 30 +++++++------- .../src/utilities/lookup_range_check.rs | 37 ++++++++---------- 29 files changed, 116 insertions(+), 117 deletions(-) rename halo2_gadgets/src/tests/circuit_data/{ecc_chip.proof.bin => proof_ecc_chip.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{lookup_range_check.proof.bin => proof_lookup_range_check.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{merkle_chip.proof.bin => proof_merkle_chip.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{short_range_check_0.proof.bin => proof_short_range_check_0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{short_range_check_1.proof.bin => proof_short_range_check_1.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{short_range_check_2.proof.bin => proof_short_range_check_2.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{sinsemilla_chip.proof.bin => proof_sinsemilla_chip.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{ecc_chip.vk.txt => vk_ecc_chip.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{lookup_range_check.vk.txt => vk_lookup_range_check.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{merkle_chip.vk.txt => vk_merkle_chip.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{short_range_check_0.vk.txt => vk_short_range_check_0.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{short_range_check_1.vk.txt => vk_short_range_check_1.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{short_range_check_2.vk.txt => vk_short_range_check_2.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{sinsemilla_chip.vk.txt => vk_sinsemilla_chip.rdata} (100%) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 23c4cbf479..58b9acc4ef 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -597,9 +597,9 @@ pub(crate) mod tests { }; use crate::{ tests::test_utils::{ - fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, + test_against_stored_vk, test_against_stored_proof, }, - utilities::lookup_range_check::{LookupRangeCheck, PallasLookupConfig}, + utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, }; #[derive(Debug, Eq, PartialEq, Clone)] @@ -734,7 +734,7 @@ pub(crate) mod tests { #[allow(non_snake_case)] impl Circuit for MyCircuit { - type Config = EccConfig; + type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -769,8 +769,8 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = PallasLookupConfig::configure(meta, advices[9], lookup_table); - EccChip::::configure( + let range_check = PallasLookupRC10b::configure(meta, advices[9], lookup_table); + EccChip::::configure( meta, advices, lagrange_coeffs, @@ -914,13 +914,13 @@ pub(crate) mod tests { #[test] fn fixed_verification_key_test() { let circuit = MyCircuit { test_errors: false }; - fixed_verification_key_test_with_circuit(&circuit, "ecc_chip"); + test_against_stored_vk(&circuit, "ecc_chip"); } #[test] fn serialized_proof_test_case() { let circuit = MyCircuit { test_errors: false }; - serialized_proof_test_case_with_circuit(circuit, "ecc_chip"); + test_against_stored_proof(circuit, "ecc_chip"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 0c8d0902d7..d7a0c92219 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -1,7 +1,7 @@ //! Chip implementations for the ECC gadgets. use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; -use crate::utilities::{lookup_range_check::PallasLookup, UtilitiesInstructions}; +use crate::utilities::{lookup_range_check::PallasLookupRC, UtilitiesInstructions}; use arrayvec::ArrayVec; use ff::PrimeField; @@ -134,7 +134,7 @@ impl From for EccPoint { /// Configuration for [`EccChip`]. #[derive(Clone, Debug, Eq, PartialEq)] #[allow(non_snake_case)] -pub struct EccConfig, Lookup: PallasLookup> { +pub struct EccConfig, Lookup: PallasLookupRC> { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], @@ -224,11 +224,11 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { /// An [`EccInstructions`] chip that uses 10 advice columns. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct EccChip, Lookup: PallasLookup> { +pub struct EccChip, Lookup: PallasLookupRC> { config: EccConfig, } -impl, Lookup: PallasLookup> Chip +impl, Lookup: PallasLookupRC> Chip for EccChip { type Config = EccConfig; @@ -243,13 +243,13 @@ impl, Lookup: PallasLookup> Chip } } -impl, Lookup: PallasLookup> +impl, Lookup: PallasLookupRC> UtilitiesInstructions for EccChip { type Var = AssignedCell; } -impl, Lookup: PallasLookup> +impl, Lookup: PallasLookupRC> EccChip { /// Reconstructs this chip from the given config. @@ -409,7 +409,7 @@ pub enum ScalarVar { FullWidth, } -impl, Lookup: PallasLookup> EccInstructions +impl, Lookup: PallasLookupRC> EccInstructions for EccChip where >::Base: @@ -597,7 +597,7 @@ where } } -impl, Lookup: PallasLookup> +impl, Lookup: PallasLookupRC> BaseFitsInScalarInstructions for EccChip where >::Base: diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 49f19900d0..70c14df284 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -1,6 +1,6 @@ use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q}; use crate::utilities::{ - lookup_range_check::PallasLookup, + lookup_range_check::PallasLookupRC, {bool_check, ternary}, }; use std::{ @@ -46,7 +46,7 @@ const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, // Configuration used in complete addition @@ -61,7 +61,7 @@ pub struct Config { overflow_config: overflow::Config, } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, add_config: add::Config, @@ -468,7 +468,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::PallasLookup; + use crate::utilities::lookup_range_check::PallasLookupRC; use crate::{ ecc::{ chip::{EccChip, EccPoint}, @@ -478,7 +478,7 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul( + pub(crate) fn test_mul( chip: EccChip, mut layouter: impl Layouter, p: &NonIdentityPoint>, diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index 53cde0f10d..eb5810fac5 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -1,5 +1,5 @@ use super::{T_Q, Z}; -use crate::{sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::PallasLookup}; +use crate::{sinsemilla::primitives as sinsemilla, utilities::lookup_range_check::PallasLookupRC}; use group::ff::PrimeField; use halo2_proofs::circuit::AssignedCell; @@ -13,7 +13,7 @@ use pasta_curves::pallas; use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, // 10-bit lookup table @@ -22,7 +22,7 @@ pub struct Config { advices: [Column; 3], } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, lookup_config: Lookup, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 917d8836a2..760ab20b9a 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -2,7 +2,7 @@ use super::super::{EccBaseFieldElemFixed, EccPoint, FixedPoints, NUM_WINDOWS, T_ use super::H_BASE; use crate::utilities::{ - bitrange_subset, bool_check, lookup_range_check::PallasLookup, range_check, + bitrange_subset, bool_check, lookup_range_check::PallasLookupRC, range_check, }; use group::ff::PrimeField; @@ -16,14 +16,14 @@ use pasta_curves::pallas; use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Config, Lookup: PallasLookup> { +pub struct Config, Lookup: PallasLookupRC> { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], lookup_config: Lookup, super_config: super::Config, } -impl, Lookup: PallasLookup> Config { +impl, Lookup: PallasLookupRC> Config { pub(crate) fn configure( meta: &mut ConstraintSystem, canon_advices: [Column; 3], @@ -386,7 +386,7 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::PallasLookup; + use crate::utilities::lookup_range_check::PallasLookupRC; use crate::{ ecc::{ chip::{EccChip, FixedPoint, H}, @@ -396,7 +396,7 @@ pub mod tests { utilities::UtilitiesInstructions, }; - pub(crate) fn test_mul_fixed_base_field( + pub(crate) fn test_mul_fixed_base_field( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -409,7 +409,7 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( + fn test_single_base( chip: EccChip, mut layouter: impl Layouter, base: FixedPointBaseField>, @@ -419,7 +419,7 @@ pub mod tests { let column = chip.config().advices[0]; - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs index 0b7f64c635..fe0ccd8d3d 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs @@ -192,9 +192,9 @@ pub mod tests { tests::{FullWidth, TestFixedBases}, FixedPoint, NonIdentityPoint, Point, ScalarFixed, }; - use crate::utilities::lookup_range_check::PallasLookup; + use crate::utilities::lookup_range_check::PallasLookupRC; - pub(crate) fn test_mul_fixed( + pub(crate) fn test_mul_fixed( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -210,13 +210,13 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( + fn test_single_base( chip: EccChip, mut layouter: impl Layouter, base: FixedPoint>, base_val: pallas::Affine, ) -> Result<(), Error> { - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 5697b6840b..d7e78c3090 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -260,13 +260,13 @@ pub mod tests { FixedPointShort, NonIdentityPoint, Point, ScalarFixedShort, }, utilities::{ - lookup_range_check::{LookupRangeCheck, PallasLookup, PallasLookupConfig}, + lookup_range_check::{LookupRangeCheck, PallasLookupRC, PallasLookupRC10b}, UtilitiesInstructions, }, }; #[allow(clippy::op_ref)] - pub(crate) fn test_mul_fixed_short( + pub(crate) fn test_mul_fixed_short( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -274,7 +274,7 @@ pub mod tests { let base_val = Short.generator(); let test_short = FixedPointShort::from_inner(chip.clone(), Short); - fn load_magnitude_sign( + fn load_magnitude_sign( chip: EccChip, mut layouter: impl Layouter, magnitude: pallas::Base, @@ -292,7 +292,7 @@ pub mod tests { Ok((magnitude, sign)) } - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, @@ -428,7 +428,7 @@ pub mod tests { } impl Circuit for MyCircuit { - type Config = EccConfig; + type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -464,8 +464,8 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = PallasLookupConfig::configure(meta, advices[9], lookup_table); - EccChip::::configure( + let range_check = PallasLookupRC10b::configure(meta, advices[9], lookup_table); + EccChip::::configure( meta, advices, lagrange_coeffs, diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 5f2ab2f268..d3ab13312a 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -473,9 +473,9 @@ pub(crate) mod tests { }, sinsemilla::primitives::{self as sinsemilla, K}, tests::test_utils::{ - fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, + test_against_stored_vk, test_against_stored_proof, }, - utilities::lookup_range_check::{LookupRangeCheck, PallasLookupConfig}, + utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, }; use group::{ff::Field, Curve}; @@ -521,9 +521,9 @@ pub(crate) mod tests { impl Circuit for MyCircuit { #[allow(clippy::type_complexity)] type Config = ( - EccConfig, - SinsemillaConfig, - SinsemillaConfig, + EccConfig, + SinsemillaConfig, + SinsemillaConfig, ); type FloorPlanner = SimpleFloorPlanner; @@ -569,9 +569,9 @@ pub(crate) mod tests { meta.lookup_table_column(), ); - let range_check = PallasLookupConfig::configure(meta, advices[9], table_idx); + let range_check = PallasLookupRC10b::configure(meta, advices[9], table_idx); - let ecc_config = EccChip::::configure( + let ecc_config = EccChip::::configure( meta, advices, lagrange_coeffs, @@ -611,7 +611,7 @@ pub(crate) mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - PallasLookupConfig, + PallasLookupRC10b, >::load(config.1.clone(), &mut layouter)?; // This MerkleCRH example is purely for illustrative purposes. @@ -747,13 +747,13 @@ pub(crate) mod tests { #[test] fn fixed_verification_key_test() { let circuit = MyCircuit {}; - fixed_verification_key_test_with_circuit(&circuit, "sinsemilla_chip"); + test_against_stored_vk(&circuit, "sinsemilla_chip"); } #[test] fn serialized_proof_test_case() { let circuit = MyCircuit {}; - serialized_proof_test_case_with_circuit(circuit, "sinsemilla_chip"); + test_against_stored_proof(circuit, "sinsemilla_chip"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 19af2e9bd1..72a9159e61 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -9,7 +9,7 @@ use crate::{ chip::{DoubleAndAdd, NonIdentityEccPoint}, FixedPoints, }, - utilities::lookup_range_check::PallasLookup, + utilities::lookup_range_check::PallasLookupRC, }; use std::marker::PhantomData; @@ -35,7 +35,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { /// Binary selector used in lookup argument and in the body of the Sinsemilla hash. q_sinsemilla1: Selector, @@ -68,7 +68,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { /// Returns an array of all advice columns in this config, in arbitrary order. pub(super) fn advices(&self) -> [Column; 5] { @@ -103,7 +103,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { config: SinsemillaConfig, } @@ -113,7 +113,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { type Config = SinsemillaConfig; type Loaded = (); @@ -132,7 +132,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { @@ -220,6 +220,7 @@ where config } + /// Assign y_q to a fixed column #[allow(non_snake_case)] fn create_initial_y_q_gate( meta: &mut ConstraintSystem, @@ -321,7 +322,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { type CellValue = AssignedCell; diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 5ec7278bf8..013995911c 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -8,7 +8,7 @@ use halo2_proofs::{ use super::{CommitDomains, FixedPoints, HashDomains}; use crate::{ sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, - utilities::lookup_range_check::PallasLookup, + utilities::lookup_range_check::PallasLookupRC, }; use pasta_curves::pallas; @@ -33,7 +33,7 @@ impl GeneratorTableConfig { Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { let (table_idx, table_x, table_y) = ( config.generator_table.table_idx, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 1cff0a423c..709da2455d 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -3,7 +3,7 @@ use super::{NonIdentityEccPoint, SinsemillaChip}; use crate::{ ecc::FixedPoints, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, - utilities::lookup_range_check::PallasLookup, + utilities::lookup_range_check::PallasLookupRC, }; use ff::Field; @@ -30,7 +30,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 83f284352d..32be00e0da 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -185,11 +185,11 @@ pub mod tests { HashDomains, }, tests::test_utils::{ - fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, + test_against_stored_vk, test_against_stored_proof, }, utilities::{ i2lebsp, - lookup_range_check::{LookupRangeCheck, PallasLookupConfig}, + lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, UtilitiesInstructions, }, }; @@ -215,8 +215,8 @@ pub mod tests { impl Circuit for MyCircuit { type Config = ( - MerkleConfig, - MerkleConfig, + MerkleConfig, + MerkleConfig, ); type FloorPlanner = SimpleFloorPlanner; @@ -254,7 +254,7 @@ pub mod tests { meta.lookup_table_column(), ); - let range_check = PallasLookupConfig::configure(meta, advices[9], lookup.0); + let range_check = PallasLookupRC10b::configure(meta, advices[9], lookup.0); let sinsemilla_config_1 = SinsemillaChip::configure( meta, @@ -289,7 +289,7 @@ pub mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - PallasLookupConfig, + PallasLookupRC10b, >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. @@ -393,13 +393,13 @@ pub mod tests { #[test] fn fixed_verification_key_test() { let circuit = generate_circuit(); - fixed_verification_key_test_with_circuit(&circuit, "merkle_chip"); + test_against_stored_vk(&circuit, "merkle_chip"); } #[test] fn serialized_proof_test_case() { let circuit = generate_circuit(); - serialized_proof_test_case_with_circuit(circuit, "merkle_chip"); + test_against_stored_proof(circuit, "merkle_chip"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 93f0fc8175..04c7c57d68 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -11,7 +11,7 @@ use super::MerkleInstructions; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, - utilities::{lookup_range_check::PallasLookup, RangeConstrained}, + utilities::{lookup_range_check::PallasLookupRC, RangeConstrained}, { ecc::FixedPoints, sinsemilla::{ @@ -33,7 +33,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { advices: [Column; 5], q_decompose: Selector, @@ -57,7 +57,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { config: MerkleConfig, } @@ -67,7 +67,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { type Config = MerkleConfig; type Loaded = (); @@ -86,7 +86,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { /// Configures the [`MerkleChip`]. pub fn configure( @@ -200,8 +200,7 @@ where } } -/// The MerkleSinsemillaInstructions trait extends the capabilities of SinsemillaInstructions, -/// for specific cryptographic operations involving generic lookup. +/// Defines the concrete types of `SinsemillaInstructions` required by the `MerkleCRH`. pub(crate) trait MerkleSinsemillaInstructions where Self: SinsemillaInstructions< @@ -227,7 +226,7 @@ where Hash: HashDomains, Commit: CommitDomains, F: FixedPoints, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { } @@ -237,7 +236,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { } @@ -255,7 +254,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { #[allow(non_snake_case)] fn hash_layer( @@ -474,7 +473,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { type Var = AssignedCell; } @@ -485,7 +484,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { #[allow(clippy::type_complexity)] fn swap( @@ -507,7 +506,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookup, + Lookup: PallasLookupRC, { type CellValue = as SinsemillaInstructions< pallas::Affine, diff --git a/halo2_gadgets/src/tests/circuit_data/ecc_chip.proof.bin b/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/ecc_chip.proof.bin rename to halo2_gadgets/src/tests/circuit_data/proof_ecc_chip.bin diff --git a/halo2_gadgets/src/tests/circuit_data/lookup_range_check.proof.bin b/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/lookup_range_check.proof.bin rename to halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check.bin diff --git a/halo2_gadgets/src/tests/circuit_data/merkle_chip.proof.bin b/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/merkle_chip.proof.bin rename to halo2_gadgets/src/tests/circuit_data/proof_merkle_chip.bin diff --git a/halo2_gadgets/src/tests/circuit_data/short_range_check_0.proof.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/short_range_check_0.proof.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/short_range_check_1.proof.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_1.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/short_range_check_1.proof.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_1.bin diff --git a/halo2_gadgets/src/tests/circuit_data/short_range_check_2.proof.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_2.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/short_range_check_2.proof.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_2.bin diff --git a/halo2_gadgets/src/tests/circuit_data/sinsemilla_chip.proof.bin b/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/sinsemilla_chip.proof.bin rename to halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip.bin diff --git a/halo2_gadgets/src/tests/circuit_data/ecc_chip.vk.txt b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/ecc_chip.vk.txt rename to halo2_gadgets/src/tests/circuit_data/vk_ecc_chip.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/lookup_range_check.vk.txt b/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/lookup_range_check.vk.txt rename to halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/merkle_chip.vk.txt b/halo2_gadgets/src/tests/circuit_data/vk_merkle_chip.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/merkle_chip.vk.txt rename to halo2_gadgets/src/tests/circuit_data/vk_merkle_chip.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/short_range_check_0.vk.txt b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_0.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/short_range_check_0.vk.txt rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_0.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/short_range_check_1.vk.txt b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_1.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/short_range_check_1.vk.txt rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_1.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/short_range_check_2.vk.txt b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_2.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/short_range_check_2.vk.txt rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_2.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/sinsemilla_chip.vk.txt b/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_chip.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/sinsemilla_chip.vk.txt rename to halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_chip.rdata diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index 0999cba67f..8f23eefbe2 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -21,6 +21,8 @@ use halo2_proofs::{ }; const TEST_DATA_DIR: &str = "src/tests/circuit_data"; +const GEN_ENV_VAR_VK: &str = "CIRCUIT_TEST_GENERATE_NEW_VK"; +const GEN_ENV_VAR_PROOF: &str = "CIRCUIT_TEST_GENERATE_NEW_PROOF"; /// A proof structure #[derive(Clone, Debug)] @@ -66,13 +68,14 @@ impl Proof { } } -pub(crate) fn fixed_verification_key_test_with_circuit>( +/// Test the generated vk against the stored vk. +pub(crate) fn test_against_stored_vk>( circuit: &C, - file_name: &str, + circuit_name: &str, ) { let full_file_name = Path::new(TEST_DATA_DIR) - .join(file_name) - .with_extension("vk.txt"); + .join(format!("vk_{circuit_name}")) + .with_extension("rdata"); // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); @@ -80,12 +83,10 @@ pub(crate) fn fixed_verification_key_test_with_circuit> let vk_text = format!("{:#?}\n", vk.pinned()); - if env::var_os("CIRCUIT_TEST_GENERATE_NEW_VK").is_some() { + if env::var_os(GEN_ENV_VAR_VK).is_some() { fs::write(&full_file_name, &vk_text).expect("Unable to write vk test file") } - // Test that the pinned verification key (representing the circuit) - // is as expected. assert_eq!( vk_text, fs::read_to_string(full_file_name) @@ -94,15 +95,15 @@ pub(crate) fn fixed_verification_key_test_with_circuit> ); } +/// If the environment variable GEN_ENV_VAR_PROOF is set, +/// write the old proof in a file fn conditionally_save_proof_to_disk>( vk: &VerifyingKey, params: &Params, circuit: C, full_file_name: &PathBuf, ) { - // If the environment variable CIRCUIT_TEST_GENERATE_NEW_PROOF is set, - // write the old proof in a file - if env::var_os("CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + if env::var_os(GEN_ENV_VAR_PROOF).is_some() { let proof = Proof::create(vk, params, circuit).unwrap(); assert!(proof.verify(vk, params).is_ok()); @@ -110,13 +111,14 @@ fn conditionally_save_proof_to_disk>( } } -pub(crate) fn serialized_proof_test_case_with_circuit>( +/// Test the generated circuit against the stored proof. +pub(crate) fn test_against_stored_proof>( circuit: C, - file_name: &str, + circuit_name: &str, ) { let full_file_name = Path::new(TEST_DATA_DIR) - .join(file_name) - .with_extension("proof.bin"); + .join(format!("proof_{circuit_name}")) + .with_extension("bin"); // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index c1f6647b1f..0344d3873f 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -442,22 +442,19 @@ impl LookupRangeCheck for LookupRangeCh } } -/// This trait is a shorthand for `LookupRangeCheck` specialized with `pallas::Base` and -/// `sinsemilla::K`. In this crate, `LookupRangeCheck` is always used with these parameters. -/// By defining this trait, we reduce verbosity and improve readability. Besides, it extends -/// the `LookupRangeCheck` with additional standard traits necessary for effective use in -/// cryptographic contexts. -pub trait PallasLookup: +/// `PallasLookupRC` a shorthand for `LookupRangeCheck` specialized with `pallas::Base` and +/// `sinsemilla::K` and used to improve readability. In addition, it extends +/// the `LookupRangeCheck` with additional standard traits. +pub trait PallasLookupRC: LookupRangeCheck + Eq + PartialEq + Clone + Copy + Debug { } -/// In this crate, `LookupRangeCheckConfig` is always used with `pallas::Base` as the prime field -/// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, -/// we introduce this alias and use it instead of that long construction. -pub type PallasLookupConfig = LookupRangeCheckConfig; +/// `PallasLookupRC10b` is a shorthand for `LookupRangeCheckConfig` specialized with +/// `pallas::Base` and `sinsemilla::K` and used to improve readability``` +pub type PallasLookupRC10b = LookupRangeCheckConfig; -impl PallasLookup for PallasLookupConfig {} +impl PallasLookupRC for PallasLookupRC10b {} #[cfg(test)] mod tests { @@ -475,7 +472,7 @@ mod tests { use pasta_curves::pallas; use crate::tests::test_utils::{ - fixed_verification_key_test_with_circuit, serialized_proof_test_case_with_circuit, + test_against_stored_vk, test_against_stored_proof, }; use std::{convert::TryInto, marker::PhantomData}; @@ -574,9 +571,9 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "lookup_range_check"); + test_against_stored_vk(&circuit, "lookup_range_check"); - serialized_proof_test_case_with_circuit(circuit, "lookup_range_check"); + test_against_stored_proof(circuit, "lookup_range_check"); } } @@ -636,9 +633,9 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "short_range_check_0"); + test_against_stored_vk(&circuit, "short_range_check_0"); - serialized_proof_test_case_with_circuit(circuit, "short_range_check_0"); + test_against_stored_proof(circuit, "short_range_check_0"); } // Edge case: K bits (case 1) @@ -650,9 +647,9 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "short_range_check_1"); + test_against_stored_vk(&circuit, "short_range_check_1"); - serialized_proof_test_case_with_circuit(circuit, "short_range_check_1"); + test_against_stored_proof(circuit, "short_range_check_1"); } // Element within `num_bits` (case 2) @@ -664,9 +661,9 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - fixed_verification_key_test_with_circuit(&circuit, "short_range_check_2"); + test_against_stored_vk(&circuit, "short_range_check_2"); - serialized_proof_test_case_with_circuit(circuit, "short_range_check_2"); + test_against_stored_proof(circuit, "short_range_check_2"); } // Element larger than `num_bits` but within K bits From adf4d0d9891ed59f7e212e6dc8270df6524193bd Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 28 May 2024 11:56:50 +0200 Subject: [PATCH 060/121] cargo fmt --- halo2_gadgets/src/ecc.rs | 4 +--- halo2_gadgets/src/sinsemilla.rs | 4 +--- halo2_gadgets/src/sinsemilla/merkle.rs | 4 +--- halo2_gadgets/src/tests/test_utils.rs | 10 ++-------- halo2_gadgets/src/utilities/lookup_range_check.rs | 4 +--- 5 files changed, 6 insertions(+), 20 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 58b9acc4ef..879ac803a7 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -596,9 +596,7 @@ pub(crate) mod tests { FixedPoints, }; use crate::{ - tests::test_utils::{ - test_against_stored_vk, test_against_stored_proof, - }, + tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, }; diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index d3ab13312a..299c16bdd4 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -472,9 +472,7 @@ pub(crate) mod tests { NonIdentityPoint, ScalarFixed, }, sinsemilla::primitives::{self as sinsemilla, K}, - tests::test_utils::{ - test_against_stored_vk, test_against_stored_proof, - }, + tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, }; diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 32be00e0da..05130b878e 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -184,9 +184,7 @@ pub mod tests { tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, - tests::test_utils::{ - test_against_stored_vk, test_against_stored_proof, - }, + tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, utilities::{ i2lebsp, lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index 8f23eefbe2..9dfbf5908c 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -69,10 +69,7 @@ impl Proof { } /// Test the generated vk against the stored vk. -pub(crate) fn test_against_stored_vk>( - circuit: &C, - circuit_name: &str, -) { +pub(crate) fn test_against_stored_vk>(circuit: &C, circuit_name: &str) { let full_file_name = Path::new(TEST_DATA_DIR) .join(format!("vk_{circuit_name}")) .with_extension("rdata"); @@ -112,10 +109,7 @@ fn conditionally_save_proof_to_disk>( } /// Test the generated circuit against the stored proof. -pub(crate) fn test_against_stored_proof>( - circuit: C, - circuit_name: &str, -) { +pub(crate) fn test_against_stored_proof>(circuit: C, circuit_name: &str) { let full_file_name = Path::new(TEST_DATA_DIR) .join(format!("proof_{circuit_name}")) .with_extension("bin"); diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 0344d3873f..bc0db35182 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -471,9 +471,7 @@ mod tests { }; use pasta_curves::pallas; - use crate::tests::test_utils::{ - test_against_stored_vk, test_against_stored_proof, - }; + use crate::tests::test_utils::{test_against_stored_proof, test_against_stored_vk}; use std::{convert::TryInto, marker::PhantomData}; #[test] From 1bb0b844887b19d07045309e4d516595ec630c42 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 28 May 2024 14:17:44 +0200 Subject: [PATCH 061/121] add index to proofs --- .github/workflows/ci.yml | 1 + halo2_gadgets/src/ecc.rs | 2 +- halo2_gadgets/src/sinsemilla.rs | 2 +- halo2_gadgets/src/sinsemilla/merkle.rs | 2 +- .../{proof_ecc_chip.bin => proof_ecc_chip_0.bin} | Bin ..._check.bin => proof_lookup_range_check_0.bin} | Bin ...f_merkle_chip.bin => proof_merkle_chip_0.bin} | Bin ...0.bin => proof_short_range_check_case0_0.bin} | Bin ...1.bin => proof_short_range_check_case1_0.bin} | Bin ...2.bin => proof_short_range_check_case2_0.bin} | Bin ...illa_chip.bin => proof_sinsemilla_chip_0.bin} | Bin ..._0.rdata => vk_short_range_check_case0.rdata} | 0 ..._1.rdata => vk_short_range_check_case1.rdata} | 0 ..._2.rdata => vk_short_range_check_case2.rdata} | 0 halo2_gadgets/src/tests/test_utils.rs | 15 +++++++++------ .../src/utilities/lookup_range_check.rs | 14 +++++++------- 16 files changed, 20 insertions(+), 16 deletions(-) rename halo2_gadgets/src/tests/circuit_data/{proof_ecc_chip.bin => proof_ecc_chip_0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_lookup_range_check.bin => proof_lookup_range_check_0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_merkle_chip.bin => proof_merkle_chip_0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_0.bin => proof_short_range_check_case0_0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_1.bin => proof_short_range_check_case1_0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_2.bin => proof_short_range_check_case2_0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_sinsemilla_chip.bin => proof_sinsemilla_chip_0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_short_range_check_0.rdata => vk_short_range_check_case0.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_short_range_check_1.rdata => vk_short_range_check_case1.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_short_range_check_2.rdata => vk_short_range_check_case2.rdata} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c2efa385d..ce5cafc981 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,6 +146,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: tarpaulin + # Extend the timeout to 3600 to ensure the code coverage test pass args: > ${{ steps.prepare.outputs.feature-flags }} --timeout 3600 diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 879ac803a7..45bf63acf6 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -918,7 +918,7 @@ pub(crate) mod tests { #[test] fn serialized_proof_test_case() { let circuit = MyCircuit { test_errors: false }; - test_against_stored_proof(circuit, "ecc_chip"); + test_against_stored_proof(circuit, "ecc_chip", 0); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 299c16bdd4..46cd2ad659 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -751,7 +751,7 @@ pub(crate) mod tests { #[test] fn serialized_proof_test_case() { let circuit = MyCircuit {}; - test_against_stored_proof(circuit, "sinsemilla_chip"); + test_against_stored_proof(circuit, "sinsemilla_chip", 0); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 05130b878e..5c453a81ac 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -397,7 +397,7 @@ pub mod tests { #[test] fn serialized_proof_test_case() { let circuit = generate_circuit(); - test_against_stored_proof(circuit, "merkle_chip"); + test_against_stored_proof(circuit, "merkle_chip", 0); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip.bin b/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_ecc_chip.bin rename to halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check.bin b/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check.bin rename to halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip.bin b/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_merkle_chip.bin rename to halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case0_0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case0_0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_1.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case1_0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_1.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case1_0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_2.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case2_0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_2.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case2_0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip.bin b/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip.bin rename to halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_0.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_case0.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_short_range_check_0.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_case0.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_1.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_case1.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_short_range_check_1.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_case1.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_2.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_case2.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_short_range_check_2.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_case2.rdata diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index 9dfbf5908c..d9a2ead12f 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -21,8 +21,7 @@ use halo2_proofs::{ }; const TEST_DATA_DIR: &str = "src/tests/circuit_data"; -const GEN_ENV_VAR_VK: &str = "CIRCUIT_TEST_GENERATE_NEW_VK"; -const GEN_ENV_VAR_PROOF: &str = "CIRCUIT_TEST_GENERATE_NEW_PROOF"; +const GEN_ENV_VAR: &str = "CIRCUIT_TEST_GENERATE_NEW_DATA"; /// A proof structure #[derive(Clone, Debug)] @@ -80,7 +79,7 @@ pub(crate) fn test_against_stored_vk>(circuit: &C, circ let vk_text = format!("{:#?}\n", vk.pinned()); - if env::var_os(GEN_ENV_VAR_VK).is_some() { + if env::var_os(GEN_ENV_VAR).is_some() { fs::write(&full_file_name, &vk_text).expect("Unable to write vk test file") } @@ -100,7 +99,7 @@ fn conditionally_save_proof_to_disk>( circuit: C, full_file_name: &PathBuf, ) { - if env::var_os(GEN_ENV_VAR_PROOF).is_some() { + if env::var_os(GEN_ENV_VAR).is_some() { let proof = Proof::create(vk, params, circuit).unwrap(); assert!(proof.verify(vk, params).is_ok()); @@ -109,9 +108,13 @@ fn conditionally_save_proof_to_disk>( } /// Test the generated circuit against the stored proof. -pub(crate) fn test_against_stored_proof>(circuit: C, circuit_name: &str) { +pub(crate) fn test_against_stored_proof>( + circuit: C, + circuit_name: &str, + index: usize, +) { let full_file_name = Path::new(TEST_DATA_DIR) - .join(format!("proof_{circuit_name}")) + .join(format!("proof_{circuit_name}_{index}")) .with_extension("bin"); // Setup phase: generate parameters, vk for the circuit. diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index bc0db35182..7ed6386d9a 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -571,7 +571,7 @@ mod tests { test_against_stored_vk(&circuit, "lookup_range_check"); - test_against_stored_proof(circuit, "lookup_range_check"); + test_against_stored_proof(circuit, "lookup_range_check", 0); } } @@ -631,9 +631,9 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - test_against_stored_vk(&circuit, "short_range_check_0"); + test_against_stored_vk(&circuit, "short_range_check_case0"); - test_against_stored_proof(circuit, "short_range_check_0"); + test_against_stored_proof(circuit, "short_range_check_case0", 0); } // Edge case: K bits (case 1) @@ -645,9 +645,9 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - test_against_stored_vk(&circuit, "short_range_check_1"); + test_against_stored_vk(&circuit, "short_range_check_case1"); - test_against_stored_proof(circuit, "short_range_check_1"); + test_against_stored_proof(circuit, "short_range_check_case1", 0); } // Element within `num_bits` (case 2) @@ -659,9 +659,9 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - test_against_stored_vk(&circuit, "short_range_check_2"); + test_against_stored_vk(&circuit, "short_range_check_case2"); - test_against_stored_proof(circuit, "short_range_check_2"); + test_against_stored_proof(circuit, "short_range_check_case2", 0); } // Element larger than `num_bits` but within K bits From 923293b0d51651ab04bd9f9e40905bcd0b308723 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Thu, 30 May 2024 11:27:36 +0200 Subject: [PATCH 062/121] rename PallasLookupRC10b to PallasLookupRCConfig --- halo2_gadgets/src/ecc.rs | 8 +++---- halo2_gadgets/src/ecc/chip.rs | 6 ++--- halo2_gadgets/src/ecc/chip/mul.rs | 4 ++-- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 4 ++-- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 5 ++-- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 8 +++---- halo2_gadgets/src/sinsemilla.rs | 24 +++++++++++++------ halo2_gadgets/src/sinsemilla/chip.rs | 6 ++--- halo2_gadgets/src/sinsemilla/merkle.rs | 10 ++++---- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 6 ++--- .../src/utilities/lookup_range_check.rs | 6 ++--- 11 files changed, 49 insertions(+), 38 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 45bf63acf6..b6e68b40e4 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -597,7 +597,7 @@ pub(crate) mod tests { }; use crate::{ tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, - utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, + utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, }; #[derive(Debug, Eq, PartialEq, Clone)] @@ -732,7 +732,7 @@ pub(crate) mod tests { #[allow(non_snake_case)] impl Circuit for MyCircuit { - type Config = EccConfig; + type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -767,8 +767,8 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = PallasLookupRC10b::configure(meta, advices[9], lookup_table); - EccChip::::configure( + let range_check = PallasLookupRCConfig::configure(meta, advices[9], lookup_table); + EccChip::::configure( meta, advices, lagrange_coeffs, diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index c168e0f45e..926da7906e 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -2,7 +2,7 @@ use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; use crate::utilities::{ - lookup_range_check::{PallasLookupRC, PallasLookupRC10b}, + lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, UtilitiesInstructions, }; use arrayvec::ArrayVec; @@ -139,7 +139,7 @@ impl From for EccPoint { #[allow(non_snake_case)] pub struct EccConfig< FixedPoints: super::FixedPoints, - Lookup: PallasLookupRC = PallasLookupRC10b, + Lookup: PallasLookupRC = PallasLookupRCConfig, > { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], @@ -232,7 +232,7 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { #[derive(Clone, Debug, Eq, PartialEq)] pub struct EccChip< FixedPoints: super::FixedPoints, - Lookup: PallasLookupRC = PallasLookupRC10b, + Lookup: PallasLookupRC = PallasLookupRCConfig, > { config: EccConfig, } diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index bc2c00e7c6..e4e2004882 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -1,6 +1,6 @@ use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q}; use crate::utilities::{ - lookup_range_check::{PallasLookupRC, PallasLookupRC10b}, + lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, {bool_check, ternary}, }; use std::{ @@ -46,7 +46,7 @@ const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, // Configuration used in complete addition diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index 8853439bd3..482594e62b 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -1,7 +1,7 @@ use super::{T_Q, Z}; use crate::{ sinsemilla::primitives as sinsemilla, - utilities::lookup_range_check::{PallasLookupRC, PallasLookupRC10b}, + utilities::lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, }; use group::ff::PrimeField; @@ -16,7 +16,7 @@ use pasta_curves::pallas; use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, // 10-bit lookup table diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index 1116497aba..e6060ec426 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -3,7 +3,7 @@ use super::H_BASE; use crate::utilities::{ bitrange_subset, bool_check, - lookup_range_check::{PallasLookupRC, PallasLookupRC10b}, + lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, range_check, }; @@ -18,7 +18,8 @@ use pasta_curves::pallas; use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Config, Lookup: PallasLookupRC = PallasLookupRC10b> { +pub struct Config, Lookup: PallasLookupRC = PallasLookupRCConfig> +{ q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], lookup_config: Lookup, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index d7e78c3090..eb402d0f27 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -260,7 +260,7 @@ pub mod tests { FixedPointShort, NonIdentityPoint, Point, ScalarFixedShort, }, utilities::{ - lookup_range_check::{LookupRangeCheck, PallasLookupRC, PallasLookupRC10b}, + lookup_range_check::{LookupRangeCheck, PallasLookupRC, PallasLookupRCConfig}, UtilitiesInstructions, }, }; @@ -428,7 +428,7 @@ pub mod tests { } impl Circuit for MyCircuit { - type Config = EccConfig; + type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -464,8 +464,8 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = PallasLookupRC10b::configure(meta, advices[9], lookup_table); - EccChip::::configure( + let range_check = PallasLookupRCConfig::configure(meta, advices[9], lookup_table); + EccChip::::configure( meta, advices, lagrange_coeffs, diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 46cd2ad659..e79797b612 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -473,7 +473,7 @@ pub(crate) mod tests { }, sinsemilla::primitives::{self as sinsemilla, K}, tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, - utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, + utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, }; use group::{ff::Field, Curve}; @@ -519,9 +519,19 @@ pub(crate) mod tests { impl Circuit for MyCircuit { #[allow(clippy::type_complexity)] type Config = ( - EccConfig, - SinsemillaConfig, - SinsemillaConfig, + EccConfig, + SinsemillaConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + PallasLookupRCConfig, + >, + SinsemillaConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + PallasLookupRCConfig, + >, ); type FloorPlanner = SimpleFloorPlanner; @@ -567,9 +577,9 @@ pub(crate) mod tests { meta.lookup_table_column(), ); - let range_check = PallasLookupRC10b::configure(meta, advices[9], table_idx); + let range_check = PallasLookupRCConfig::configure(meta, advices[9], table_idx); - let ecc_config = EccChip::::configure( + let ecc_config = EccChip::::configure( meta, advices, lagrange_coeffs, @@ -609,7 +619,7 @@ pub(crate) mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - PallasLookupRC10b, + PallasLookupRCConfig, >::load(config.1.clone(), &mut layouter)?; // This MerkleCRH example is purely for illustrative purposes. diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 454b6c9151..069c115b2b 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -9,7 +9,7 @@ use crate::{ chip::{DoubleAndAdd, NonIdentityEccPoint}, FixedPoints, }, - utilities::lookup_range_check::{PallasLookupRC, PallasLookupRC10b}, + utilities::lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, }; use std::marker::PhantomData; @@ -30,7 +30,7 @@ mod hash_to_point; /// Configuration for the Sinsemilla hash chip #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaConfig +pub struct SinsemillaConfig where Hash: HashDomains, F: FixedPoints, @@ -98,7 +98,7 @@ where /// /// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaChip +pub struct SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 5c453a81ac..95e9e401b9 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -187,7 +187,7 @@ pub mod tests { tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, utilities::{ i2lebsp, - lookup_range_check::{LookupRangeCheck, PallasLookupRC10b}, + lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, UtilitiesInstructions, }, }; @@ -213,8 +213,8 @@ pub mod tests { impl Circuit for MyCircuit { type Config = ( - MerkleConfig, - MerkleConfig, + MerkleConfig, + MerkleConfig, ); type FloorPlanner = SimpleFloorPlanner; @@ -252,7 +252,7 @@ pub mod tests { meta.lookup_table_column(), ); - let range_check = PallasLookupRC10b::configure(meta, advices[9], lookup.0); + let range_check = PallasLookupRCConfig::configure(meta, advices[9], lookup.0); let sinsemilla_config_1 = SinsemillaChip::configure( meta, @@ -287,7 +287,7 @@ pub mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - PallasLookupRC10b, + PallasLookupRCConfig, >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 2410f8f726..b8ea59ead7 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -12,7 +12,7 @@ use super::MerkleInstructions; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, utilities::{ - lookup_range_check::{PallasLookupRC, PallasLookupRC10b}, + lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, RangeConstrained, }, { @@ -31,7 +31,7 @@ use group::ff::PrimeField; /// Configuration for the `MerkleChip` implementation. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleConfig +pub struct MerkleConfig where Hash: HashDomains, Fixed: FixedPoints, @@ -55,7 +55,7 @@ where /// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of /// `left` and `right`. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleChip +pub struct MerkleChip where Hash: HashDomains, Fixed: FixedPoints, diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 7ed6386d9a..10a302e82b 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -450,11 +450,11 @@ pub trait PallasLookupRC: { } -/// `PallasLookupRC10b` is a shorthand for `LookupRangeCheckConfig` specialized with +/// `PallasLookupRCConfig` is a shorthand for `LookupRangeCheckConfig` specialized with /// `pallas::Base` and `sinsemilla::K` and used to improve readability``` -pub type PallasLookupRC10b = LookupRangeCheckConfig; +pub type PallasLookupRCConfig = LookupRangeCheckConfig; -impl PallasLookupRC for PallasLookupRC10b {} +impl PallasLookupRC for PallasLookupRCConfig {} #[cfg(test)] mod tests { From 9ecbd6513163175efb4b699f9e80e0a14e70c1e6 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Thu, 30 May 2024 11:46:40 +0200 Subject: [PATCH 063/121] resolve some comments --- halo2_gadgets/src/tests/test_utils.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index d9a2ead12f..ed73cc3c17 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -23,9 +23,9 @@ use halo2_proofs::{ const TEST_DATA_DIR: &str = "src/tests/circuit_data"; const GEN_ENV_VAR: &str = "CIRCUIT_TEST_GENERATE_NEW_DATA"; -/// A proof structure #[derive(Clone, Debug)] pub struct Proof(Vec); + impl AsRef<[u8]> for Proof { fn as_ref(&self) -> &[u8] { &self.0 @@ -61,6 +61,7 @@ impl Proof { let mut transcript = Blake2bRead::init(&self.0[..]); plonk::verify_proof(params, vk, strategy, &[&[]], &mut transcript) } + /// Constructs a new Proof value. pub fn new(bytes: Vec) -> Self { Proof(bytes) @@ -91,8 +92,7 @@ pub(crate) fn test_against_stored_vk>(circuit: &C, circ ); } -/// If the environment variable GEN_ENV_VAR_PROOF is set, -/// write the old proof in a file +/// If the env variable GEN_ENV_VAR is set, write the `Proof` to a file fn conditionally_save_proof_to_disk>( vk: &VerifyingKey, params: &Params, @@ -121,12 +121,11 @@ pub(crate) fn test_against_stored_proof>( let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - // Conditionally save proof to disk conditionally_save_proof_to_disk(&vk, ¶ms, circuit, &full_file_name); - // Read proof from disk + // Read the proof from storage let proof = Proof::new(fs::read(full_file_name).expect("Unable to read proof test file")); - // Verify the old proof with the new vk + // Verify the stored proof with the generated vk assert!(proof.verify(&vk, ¶ms).is_ok()); } From 9337142d2753f6617c7709e993e7846eb7a28bcc Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 3 Jun 2024 14:32:53 +0200 Subject: [PATCH 064/121] add zsa feature --- halo2_gadgets/src/ecc.rs | 235 ++++++++ halo2_gadgets/src/ecc/chip.rs | 43 +- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 561 +++++++++++++++++- halo2_gadgets/src/ecc/chip/witness_point.rs | 37 ++ halo2_gadgets/src/sinsemilla.rs | 377 ++++++++++++ halo2_gadgets/src/sinsemilla/chip.rs | 196 ++++++ .../src/sinsemilla/chip/generator_table.rs | 101 ++++ .../src/sinsemilla/chip/hash_to_point.rs | 165 +++++- halo2_gadgets/src/sinsemilla/merkle.rs | 211 +++++++ halo2_gadgets/src/sinsemilla/merkle/chip.rs | 182 ++++++ halo2_gadgets/src/sinsemilla/primitives.rs | 60 ++ halo2_gadgets/src/utilities/cond_swap.rs | 333 +++++++++++ .../src/utilities/lookup_range_check.rs | 517 +++++++++++++++- halo2_proofs/src/circuit.rs | 10 + 14 files changed, 3024 insertions(+), 4 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index b6e68b40e4..0bfb3fff5b 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -2,6 +2,7 @@ use std::fmt::Debug; +use halo2_proofs::circuit::AssignedCell; use halo2_proofs::{ arithmetic::CurveAffine, circuit::{Chip, Layouter, Value}, @@ -575,6 +576,53 @@ impl> FixedPointShort { } } +/// The set of circuit instructions required to use the ECC gadgets. +pub trait EccInstructionsOptimized: EccInstructions { + /// Witnesses the given constant point as a private input to the circuit. + /// This allows the point to be the identity, mapped to (0, 0) in + /// affine coordinates. + fn witness_point_from_constant( + &self, + layouter: &mut impl Layouter, + value: C, + ) -> Result; + + /// Performs variable-base sign-scalar multiplication, returning `[sign] point` + /// `sign` must be in {-1, 1}. + fn mul_sign( + &self, + layouter: &mut impl Layouter, + sign: &AssignedCell, + point: &Self::Point, + ) -> Result; +} + +impl + Clone + Debug + Eq> Point { + /// Constructs a new point with the given fixed value. + pub fn new_from_constant( + chip: EccChip, + mut layouter: impl Layouter, + value: C, + ) -> Result { + let point = chip.witness_point_from_constant(&mut layouter, value); + point.map(|inner| Point { chip, inner }) + } + + /// Returns `[sign] self`. + /// `sign` must be in {-1, 1}. + pub fn mul_sign( + &self, + mut layouter: impl Layouter, + sign: &AssignedCell, + ) -> Result, Error> { + self.chip + .mul_sign(&mut layouter, sign, &self.inner) + .map(|point| Point { + chip: self.chip.clone(), + inner: point, + }) + } +} #[cfg(test)] pub(crate) mod tests { use ff::PrimeField; @@ -587,6 +635,7 @@ pub(crate) mod tests { }; use lazy_static::lazy_static; use pasta_curves::pallas; + use pasta_curves::vesta::Affine; use super::{ chip::{ @@ -595,6 +644,7 @@ pub(crate) mod tests { }, FixedPoints, }; + use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, @@ -935,4 +985,189 @@ pub(crate) mod tests { .render(13, &circuit, &root) .unwrap(); } + + struct MyCircuit_4_5_b { + test_errors: bool, + } + + #[allow(non_snake_case)] + impl Circuit for MyCircuit_4_5_b { + type Config = EccConfig< + crate::ecc::tests::TestFixedBases, + LookupRangeCheckConfigOptimized, + >; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + MyCircuit_4_5_b { test_errors: false } + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let lookup_table = meta.lookup_table_column(); + + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + EccChip::< + crate::ecc::tests::TestFixedBases, + LookupRangeCheckConfigOptimized, + >::configure(meta, advices, lagrange_coeffs, range_check) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = EccChip::construct(config.clone()); + + // Load 10-bit lookup table. In the Action circuit, this will be + // provided by the Sinsemilla chip. + config.lookup_config.load(&mut layouter)?; + + // Generate a random non-identity point P + let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P + let p = crate::ecc::NonIdentityPoint::new( + chip.clone(), + layouter.namespace(|| "P"), + Value::known(p_val), + )?; + let p_neg = -p_val; + let p_neg = crate::ecc::NonIdentityPoint::new( + chip.clone(), + layouter.namespace(|| "-P"), + Value::known(p_neg), + )?; + + // Generate a random non-identity point Q + let q_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // Q + let q = crate::ecc::NonIdentityPoint::new( + chip.clone(), + layouter.namespace(|| "Q"), + Value::known(q_val), + )?; + + // Make sure P and Q are not the same point. + assert_ne!(p_val, q_val); + + // Test that we can witness the identity as a point, but not as a non-identity point. + { + let _ = super::Point::new( + chip.clone(), + layouter.namespace(|| "identity"), + Value::known(pallas::Affine::identity()), + )?; + + crate::ecc::NonIdentityPoint::new( + chip.clone(), + layouter.namespace(|| "identity"), + Value::known(pallas::Affine::identity()), + ) + .expect_err("Trying to witness the identity should return an error"); + } + + // Test witness non-identity point + { + crate::ecc::chip::witness_point::tests::test_witness_non_id( + chip.clone(), + layouter.namespace(|| "witness non-identity point"), + ) + } + + // Test complete addition + { + crate::ecc::chip::add::tests::test_add( + chip.clone(), + layouter.namespace(|| "complete addition"), + p_val, + &p, + q_val, + &q, + &p_neg, + )?; + } + + // Test incomplete addition + { + crate::ecc::chip::add_incomplete::tests::test_add_incomplete( + chip.clone(), + layouter.namespace(|| "incomplete addition"), + p_val, + &p, + q_val, + &q, + &p_neg, + self.test_errors, + )?; + } + + // Test variable-base scalar multiplication + { + crate::ecc::chip::mul::tests::test_mul( + chip.clone(), + layouter.namespace(|| "variable-base scalar mul"), + &p, + p_val, + )?; + } + + // Test variable-base sign-scalar multiplication + { + crate::ecc::chip::mul_fixed::short::tests::test_mul_sign( + chip.clone(), + layouter.namespace(|| "variable-base sign-scalar mul"), + )?; + } + + Ok(()) + } + } + + #[test] + fn ecc_chip() { + let k = 11; + let circuit = MyCircuit_4_5_b { test_errors: true }; + let prover = MockProver::run(k, &circuit, vec![]).unwrap(); + + assert_eq!(prover.verify(), Ok(())) + } + #[cfg(feature = "test-dev-graph")] + #[test] + fn print_ecc_chip() { + use plotters::prelude::*; + + let root = BitMapBackend::new("ecc-chip-layout.png", (1024, 7680)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); + + let circuit = MyCircuit_4_5_b { test_errors: false }; + halo2_proofs::dev::CircuitLayout::default() + .render(13, &circuit, &root) + .unwrap(); + } } diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 926da7906e..34186c4a49 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -1,6 +1,6 @@ //! Chip implementations for the ECC gadgets. -use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; +use super::{BaseFitsInScalarInstructions, EccInstructions, EccInstructionsOptimized, FixedPoints}; use crate::utilities::{ lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, UtilitiesInstructions, @@ -624,3 +624,44 @@ where Ok(ScalarVar::BaseFieldElem(base.clone())) } } + +impl, Lookup: PallasLookupRC> + EccInstructionsOptimized for EccChip +where + >::Base: + FixedPoint, + >::FullScalar: + FixedPoint, + >::ShortScalar: + FixedPoint, +{ + fn witness_point_from_constant( + &self, + layouter: &mut impl Layouter, + value: pallas::Affine, + ) -> Result { + let config = self.config().witness_point; + layouter.assign_region( + || "witness point (constant)", + |mut region| config.constant_point(value, 0, &mut region), + ) + } + + /// Performs variable-base sign-scalar multiplication, returning `[sign] point` + /// `sign` must be in {-1, 1}. + fn mul_sign( + &self, + layouter: &mut impl Layouter, + sign: &AssignedCell, + point: &Self::Point, + ) -> Result { + // Multiply point by sign, using the same gate as mul_fixed::short. + // This also constrains sign to be in {-1, 1}. + let config_short = self.config().mul_fixed_short.clone(); + config_short.assign_scalar_sign( + layouter.namespace(|| "variable-base sign-scalar mul"), + sign, + point, + ) + } +} diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index eb402d0f27..c618f0f801 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -3,6 +3,7 @@ use std::convert::TryInto; use super::super::{EccPoint, EccScalarFixedShort, FixedPoints, L_SCALAR_SHORT, NUM_WINDOWS_SHORT}; use crate::{ecc::chip::MagnitudeSign, utilities::bool_check}; +use halo2_proofs::circuit::AssignedCell; use halo2_proofs::{ circuit::{Layouter, Region}, plonk::{ConstraintSystem, Constraints, Error, Expression, Selector}, @@ -241,11 +242,73 @@ impl> Config { Ok((result, scalar)) } + + /// Multiply the point by sign, using the q_mul_fixed_short gate. + /// Constraints `sign` in {-1, 1} + pub fn assign_scalar_sign( + &self, + mut layouter: impl Layouter, + sign: &AssignedCell, + point: &EccPoint, + ) -> Result { + let signed_point = layouter.assign_region( + || "Signed point", + |mut region| { + let offset = 0; + + // Enable mul_fixed_short selector to check the sign logic. + self.q_mul_fixed_short.enable(&mut region, offset)?; + + // Set "last window" to 0 (this field is irrelevant here). + region.assign_advice_from_constant( + || "u=0", + self.super_config.u, + offset, + pallas::Base::zero(), + )?; + + // Copy sign to `window` column + sign.copy_advice(|| "sign", &mut region, self.super_config.window, offset)?; + + // Assign the input y-coordinate. + point.y.copy_advice( + || "unsigned y", + &mut region, + self.super_config.add_config.y_qr, + offset, + )?; + + // Conditionally negate y-coordinate according to the value of sign + let signed_y_val = sign.value().and_then(|sign| { + if sign == &-pallas::Base::one() { + -point.y.value() + } else { + point.y.value().cloned() + } + }); + + // Assign the output signed y-coordinate. + let signed_y = region.assign_advice( + || "signed y", + self.super_config.add_config.y_p, + offset, + || signed_y_val, + )?; + + Ok(EccPoint { + x: point.x.clone(), + y: signed_y, + }) + }, + )?; + + Ok(signed_point) + } } #[cfg(test)] pub mod tests { - use group::{ff::PrimeField, Curve}; + use group::{ff::PrimeField, Curve, Group}; use halo2_proofs::{ arithmetic::CurveAffine, circuit::{AssignedCell, Chip, Layouter, Value}, @@ -253,6 +316,7 @@ pub mod tests { }; use pasta_curves::pallas; + use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ ecc::{ chip::{EccChip, FixedPoint, MagnitudeSign}, @@ -665,4 +729,499 @@ pub mod tests { ); } } + + #[test] + fn invalid_magnitude_sign_4_5_b() { + use crate::{ + ecc::chip::{EccConfig, FixedPoint}, + utilities::UtilitiesInstructions, + }; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner}, + dev::{FailureLocation, MockProver, VerifyFailure}, + plonk::{Circuit, ConstraintSystem, Error}, + }; + + #[derive(Default)] + struct MyCircuit { + magnitude: Value, + sign: Value, + // For test checking + magnitude_error: Value, + } + + impl UtilitiesInstructions for MyCircuit { + type Var = AssignedCell; + } + + impl Circuit for MyCircuit { + type Config = EccConfig< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let lookup_table = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + EccChip::< + TestFixedBases, + LookupRangeCheckConfigOptimized< + pallas::Base, + { crate::sinsemilla::primitives::K }, + >, + >::configure(meta, advices, lagrange_coeffs, range_check) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let column = config.advices[0]; + + let short_config = config.mul_fixed_short.clone(); + let magnitude_sign = { + let magnitude = self.load_private( + layouter.namespace(|| "load magnitude"), + column, + self.magnitude, + )?; + let sign = + self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; + ScalarFixedShort::new( + EccChip::construct(config), + layouter.namespace(|| "signed short scalar"), + (magnitude, sign), + )? + }; + + short_config.assign(layouter, &magnitude_sign.inner, &Short)?; + + Ok(()) + } + } + + // Copied from halo2_proofs::dev::util + fn format_value(v: pallas::Base) -> String { + use ff::Field; + if v.is_zero_vartime() { + "0".into() + } else if v == pallas::Base::one() { + "1".into() + } else if v == -pallas::Base::one() { + "-1".into() + } else { + // Format value as hex. + let s = format!("{:?}", v); + // Remove leading zeroes. + let s = s.strip_prefix("0x").unwrap(); + let s = s.trim_start_matches('0'); + format!("0x{}", s) + } + } + + // Magnitude larger than 64 bits should fail + { + let circuits = [ + // 2^64 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 64)), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 1)), + }, + // -2^64 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 64)), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 1)), + }, + // 2^66 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 66)), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 3)), + }, + // -2^66 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 66)), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 3)), + }, + // 2^254 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known( + pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), + ), + }, + // -2^254 + MyCircuit { + magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known( + pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), + ), + }, + ]; + + for circuit in circuits.iter() { + let prover = MockProver::::run(11, circuit, vec![]).unwrap(); + circuit.magnitude_error.assert_if_known(|magnitude_error| { + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 0, + "last_window_check", + ) + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)") + .into(), + offset: 1, + }, + cell_values: vec![( + ((Any::Advice, 5).into(), 0).into(), + format_value(*magnitude_error), + )], + }, + VerifyFailure::Permutation { + column: (Any::Fixed, 10).into(), + location: FailureLocation::OutsideRegion { row: 0 }, + }, + VerifyFailure::Permutation { + column: (Any::Advice, 4).into(), + location: FailureLocation::InRegion { + region: (2, "Short fixed-base mul (incomplete addition)") + .into(), + offset: 22, + }, + }, + ]) + ); + true + }); + } + } + + // Sign that is not +/- 1 should fail + { + let magnitude_u64 = rand::random::(); + let circuit = MyCircuit { + magnitude: Value::known(pallas::Base::from(magnitude_u64)), + sign: Value::known(pallas::Base::zero()), + magnitude_error: Value::unknown(), + }; + + let negation_check_y = { + *(Short.generator() * pallas::Scalar::from(magnitude_u64)) + .to_affine() + .coordinates() + .unwrap() + .y() + }; + + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check") + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)").into(), + offset: 1, + }, + cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], + }, + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 3, + "negation_check" + ) + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)").into(), + offset: 1, + }, + cell_values: vec![ + ( + ((Any::Advice, 1).into(), 0).into(), + format_value(negation_check_y), + ), + ( + ((Any::Advice, 3).into(), 0).into(), + format_value(negation_check_y), + ), + (((Any::Advice, 4).into(), 0).into(), "0".to_string()), + ], + } + ]) + ); + } + } + + pub(crate) fn test_mul_sign( + chip: EccChip, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Generate a random non-identity point P + let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); + let p = Point::new( + chip.clone(), + layouter.namespace(|| "P"), + Value::known(p_val), + )?; + + // Create -P + let p_neg_val = -p_val; + let p_neg = Point::new( + chip.clone(), + layouter.namespace(|| "-P"), + Value::known(p_neg_val), + )?; + + // Create the identity point + let identity = Point::new( + chip.clone(), + layouter.namespace(|| "identity"), + Value::known(pallas::Point::identity().to_affine()), + )?; + + // Create -1 and 1 scalars + let pos_sign = chip.load_private( + layouter.namespace(|| "positive sign"), + chip.config().advices[0], + Value::known(pallas::Base::one()), + )?; + let neg_sign = chip.load_private( + layouter.namespace(|| "negative sign"), + chip.config().advices[1], + Value::known(-pallas::Base::one()), + )?; + + // [1] P == P + { + let result = p.mul_sign(layouter.namespace(|| "[1] P"), &pos_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p)?; + } + + // [-1] P == -P + { + let result = p.mul_sign(layouter.namespace(|| "[1] P"), &neg_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] P"), &p_neg)?; + } + + // [1] 0 == 0 + { + let result = identity.mul_sign(layouter.namespace(|| "[1] O"), &pos_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; + } + + // [-1] 0 == 0 + { + let result = identity.mul_sign(layouter.namespace(|| "[-1] O"), &neg_sign)?; + result.constrain_equal(layouter.namespace(|| "constrain [1] 0"), &identity)?; + } + + Ok(()) + } + #[test] + fn invalid_sign_in_mul_sign() { + use crate::{ecc::chip::EccConfig, utilities::UtilitiesInstructions}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner}, + dev::{FailureLocation, MockProver, VerifyFailure}, + plonk::{Circuit, ConstraintSystem, Error}, + }; + + #[derive(Default)] + struct MyCircuit { + base: Value, + sign: Value, + } + + impl UtilitiesInstructions for MyCircuit { + type Var = AssignedCell; + } + + impl Circuit for MyCircuit { + type Config = EccConfig< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let lookup_table = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup_table, + table_range_check_tag, + ); + EccChip::< + TestFixedBases, + LookupRangeCheckConfigOptimized< + pallas::Base, + { crate::sinsemilla::primitives::K }, + >, + >::configure(meta, advices, lagrange_coeffs, range_check) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = EccChip::construct(config.clone()); + + let column = config.advices[0]; + + //let short_config = config.mul_fixed_short.clone(); + let base = Point::new(chip, layouter.namespace(|| "load base"), self.base)?; + + let sign = + self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; + + base.mul_sign(layouter.namespace(|| "[sign] base"), &sign)?; + + Ok(()) + } + } + + // Copied from halo2_proofs::dev::util + fn format_value(v: pallas::Base) -> String { + use ff::Field; + if v.is_zero_vartime() { + "0".into() + } else if v == pallas::Base::one() { + "1".into() + } else if v == -pallas::Base::one() { + "-1".into() + } else { + // Format value as hex. + let s = format!("{:?}", v); + // Remove leading zeroes. + let s = s.strip_prefix("0x").unwrap(); + let s = s.trim_start_matches('0'); + format!("0x{}", s) + } + } + + // Sign that is not +/- 1 should fail + // Generate a random non-identity point + let point = pallas::Point::random(rand::rngs::OsRng); + let circuit = MyCircuit { + base: Value::known(point.to_affine()), + sign: Value::known(pallas::Base::zero()), + }; + + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check").into(), + location: FailureLocation::InRegion { + region: (2, "Signed point").into(), + offset: 0, + }, + cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], + }, + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 3, + "negation_check" + ) + .into(), + location: FailureLocation::InRegion { + region: (2, "Signed point").into(), + offset: 0, + }, + cell_values: vec![ + ( + ((Any::Advice, 1).into(), 0).into(), + format_value(*point.to_affine().coordinates().unwrap().y()), + ), + ( + ((Any::Advice, 3).into(), 0).into(), + format_value(*point.to_affine().coordinates().unwrap().y()), + ), + (((Any::Advice, 4).into(), 0).into(), "0".to_string()), + ], + } + ]) + ); + } } diff --git a/halo2_gadgets/src/ecc/chip/witness_point.rs b/halo2_gadgets/src/ecc/chip/witness_point.rs index 7cba8d6f87..e2cbba372f 100644 --- a/halo2_gadgets/src/ecc/chip/witness_point.rs +++ b/halo2_gadgets/src/ecc/chip/witness_point.rs @@ -102,6 +102,21 @@ impl Config { Ok((x_var, y_var)) } + fn assign_xy_from_constant( + &self, + value: (Assigned, Assigned), + offset: usize, + region: &mut Region<'_, pallas::Base>, + ) -> Result { + // Assign `x` value + let x_var = region.assign_advice_from_constant(|| "x", self.x, offset, value.0)?; + + // Assign `y` value + let y_var = region.assign_advice_from_constant(|| "y", self.y, offset, value.1)?; + + Ok((x_var, y_var)) + } + /// Assigns a point that can be the identity. pub(super) fn point( &self, @@ -126,6 +141,28 @@ impl Config { .map(|(x, y)| EccPoint::from_coordinates_unchecked(x, y)) } + /// Assigns a constant point that can be the identity. + pub(crate) fn constant_point( + &self, + value: pallas::Affine, + offset: usize, + region: &mut Region<'_, pallas::Base>, + ) -> Result { + // Enable `q_point` selector + self.q_point.enable(region, offset)?; + + let value = if value == pallas::Affine::identity() { + // Map the identity to (0, 0). + (Assigned::Zero, Assigned::Zero) + } else { + let value = value.coordinates().unwrap(); + (value.x().into(), value.y().into()) + }; + + self.assign_xy_from_constant(value, offset, region) + .map(|(x, y)| EccPoint::from_coordinates_unchecked(x, y)) + } + /// Assigns a non-identity point. pub(super) fn point_non_id( &self, diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index e79797b612..aba408c8cd 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -451,6 +451,128 @@ where } } +/// `SinsemillaInstructionsOptimized` provides an optimized set of instructions +/// for implementing the Sinsemilla hash function and commitment scheme +/// on elliptic curves. This trait is an extension of the `SinsemillaInstructions` trait, +/// designed to enhance performance in specific cryptographic scenarios.ld + +pub trait SinsemillaInstructionsOptimized: + SinsemillaInstructions +{ + /// Hashes a message to an ECC curve point. + /// This returns both the resulting point, as well as the message + /// decomposition in the form of intermediate values in a cumulative + /// sum. + /// The initial point `Q` is a private point. + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point_with_private_init( + &self, + layouter: impl Layouter, + Q: &Self::NonIdentityPoint, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec), Error>; +} + +impl +HashDomain + where + SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, + EccChip: EccInstructions< + C, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + /// Evaluate the Sinsemilla hash of `message` from the private initial point `Q`. + pub fn hash_to_point_with_private_init( + &self, + layouter: impl Layouter, + Q: &>::NonIdentityPoint, + message: Message, + ) -> Result<(ecc::NonIdentityPoint, Vec), Error> { + assert_eq!(self.sinsemilla_chip, message.chip); + self.sinsemilla_chip + .hash_to_point_with_private_init(layouter, Q, message.inner) + .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) + } + +} + +impl +CommitDomain + where + SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, + EccChip: EccInstructions< + C, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + > + Clone + + Debug + + Eq, +{ + #[allow(clippy::type_complexity)] + /// Evaluates the Sinsemilla hash of `message` from the public initial point `Q` stored + /// into `CommitDomain`. + pub fn hash( + &self, + layouter: impl Layouter, + message: Message, + ) -> Result< + ( + ecc::NonIdentityPoint, + Vec, + ), + Error, + > { + assert_eq!(self.M.sinsemilla_chip, message.chip); + self.M.hash_to_point(layouter, message) + } + + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + /// Evaluates the Sinsemilla hash of `message` from the private initial point `Q`. + pub fn hash_with_private_init( + &self, + layouter: impl Layouter, + Q: &>::NonIdentityPoint, + message: Message, + ) -> Result< + ( + ecc::NonIdentityPoint, + Vec, + ), + Error, + > { + assert_eq!(self.M.sinsemilla_chip, message.chip); + self.M.hash_to_point_with_private_init(layouter, Q, message) + } + + #[allow(clippy::type_complexity)] + /// Returns the public initial point `Q` stored into `CommitDomain`. + pub fn q_init(&self) -> C { + self.M.Q + } + + #[allow(clippy::type_complexity)] + /// Evaluates the blinding factor equal to $\[r\] R$ where `r` is stored in the `CommitDomain`. + pub fn blinding_factor( + &self, + mut layouter: impl Layouter, + r: ecc::ScalarFixed, + ) -> Result< + ecc::Point, + Error, + > { + let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; + Ok(blind) + } +} + #[cfg(test)] pub(crate) mod tests { use halo2_proofs::{ @@ -480,6 +602,8 @@ pub(crate) mod tests { use lazy_static::lazy_static; use pasta_curves::pallas; + use crate::sinsemilla::chip::SinsemillaChipOptimized; + use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use std::convert::TryInto; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; @@ -779,4 +903,257 @@ pub(crate) mod tests { .render(11, &circuit, &root) .unwrap(); } + + struct MyCircuit45B {} + + impl Circuit for MyCircuit45B { + #[allow(clippy::type_complexity)] + type Config = ( + EccConfig< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + SinsemillaConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + SinsemillaConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + ); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + MyCircuit45B {} + } + + #[allow(non_snake_case)] + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + // Fixed columns for the Sinsemilla generator lookup table + let lookup = ( + meta.lookup_table_column(), + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup.0); + + let ecc_config = EccChip::< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >::configure(meta, advices, lagrange_coeffs, range_check); + + let config1 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + lagrange_coeffs[0], + lookup, + range_check, + ); + let config2 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + lagrange_coeffs[1], + lookup, + range_check, + ); + (ecc_config, config1, config2) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let rng = OsRng; + + let ecc_chip = EccChip::construct(config.0); + + // The two `SinsemillaChip`s share the same lookup table. + SinsemillaChipOptimized::::load( + config.1.clone(), + &mut layouter, + )?; + + // This MerkleCRH example is purely for illustrative purposes. + // It is not an implementation of the Orchard protocol spec. + { + let chip1 = SinsemillaChip::construct(config.1); + + let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); + + // Layer 31, l = MERKLE_DEPTH - 1 - layer = 0 + let l_bitstring = vec![Value::known(false); K]; + let l = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "l"), + &l_bitstring, + )?; + + // Left leaf + let left_bitstring: Vec> = (0..250) + .map(|_| Value::known(rand::random::())) + .collect(); + let left = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "left"), + &left_bitstring, + )?; + + // Right leaf + let right_bitstring: Vec> = (0..250) + .map(|_| Value::known(rand::random::())) + .collect(); + let right = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "right"), + &right_bitstring, + )?; + + let l_bitstring: Value> = l_bitstring.into_iter().collect(); + let left_bitstring: Value> = left_bitstring.into_iter().collect(); + let right_bitstring: Value> = right_bitstring.into_iter().collect(); + + // Witness expected parent + let expected_parent = { + let expected_parent = l_bitstring.zip(left_bitstring.zip(right_bitstring)).map( + |(l, (left, right))| { + let merkle_crh = sinsemilla::HashDomain::from_Q((*Q).into()); + let point = merkle_crh + .hash_to_point( + l.into_iter() + .chain(left.into_iter()) + .chain(right.into_iter()), + ) + .unwrap(); + point.to_affine() + }, + ); + + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "Witness expected parent"), + expected_parent, + )? + }; + + // Parent + let (parent, _) = { + let message = Message::from_pieces(chip1, vec![l, left, right]); + merkle_crh.hash_to_point(layouter.namespace(|| "parent"), message)? + }; + + parent.constrain_equal( + layouter.namespace(|| "parent == expected parent"), + &expected_parent, + )?; + } + + { + let chip2 = SinsemillaChip::construct(config.2); + + let test_commit = + CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); + let r_val = pallas::Scalar::random(rng); + let message: Vec> = (0..500) + .map(|_| Value::known(rand::random::())) + .collect(); + + let (result, _) = { + let r = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "r"), + Value::known(r_val), + )?; + let message = Message::from_bitstring( + chip2, + layouter.namespace(|| "witness message"), + message.clone(), + )?; + test_commit.commit(layouter.namespace(|| "commit"), message, r)? + }; + + // Witness expected result. + let expected_result = { + let message: Value> = message.into_iter().collect(); + let expected_result = message.map(|message| { + let domain = sinsemilla::CommitDomain::new(PERSONALIZATION); + let point = domain.commit(message.into_iter(), &r_val).unwrap(); + point.to_affine() + }); + + NonIdentityPoint::new( + ecc_chip, + layouter.namespace(|| "Witness expected result"), + expected_result, + )? + }; + + result.constrain_equal( + layouter.namespace(|| "result == expected result"), + &expected_result, + ) + } + } + } + + #[test] + fn sinsemilla_chip_4_5_b() { + let k = 11; + let circuit = MyCircuit45B {}; + let prover = MockProver::run(k, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())) + } + + #[cfg(feature = "test-dev-graph")] + #[test] + fn print_sinsemilla_chip_4_5_b() { + use plotters::prelude::*; + + let root = + BitMapBackend::new("sinsemilla-hash-layout.png", (1024, 7680)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); + + let circuit = MyCircuit45B {}; + halo2_proofs::dev::CircuitLayout::default() + .render(11, &circuit, &root) + .unwrap(); + } } diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 069c115b2b..ffe2bcc35a 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -3,6 +3,7 @@ use super::{ message::{Message, MessagePiece}, primitives as sinsemilla, CommitDomains, HashDomains, SinsemillaInstructions, + SinsemillaInstructionsOptimized, }; use crate::{ ecc::{ @@ -24,6 +25,7 @@ use halo2_proofs::{ use pasta_curves::pallas; mod generator_table; +use crate::utilities::lookup_range_check::PallasLookupConfigOptimized; use generator_table::GeneratorTableConfig; mod hash_to_point; @@ -378,3 +380,197 @@ where point.x() } } + +/// A chip that implements 10-bit Sinsemilla using a lookup table and 5 advice columns. +/// +/// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct SinsemillaChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + inner: SinsemillaChip, +} + +impl Chip for SinsemillaChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + type Config = SinsemillaConfig; + type Loaded = (); + + fn config(&self) -> &Self::Config { + self.inner.config() + } + + fn loaded(&self) -> &Self::Loaded { + &() + } +} + +impl SinsemillaChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + /// Reconstructs this chip from the given config. + pub fn construct(config: >::Config) -> Self { + Self { + inner: SinsemillaChip::::construct( + config, + ), + } + } + + /// Loads the lookup table required by this chip into the circuit. + pub fn load( + config: SinsemillaConfig, + layouter: &mut impl Layouter, + ) -> Result<>::Loaded, Error> { + // Load the lookup table. + generator_table::load_with_tag( + &config.generator_table, + config.lookup_config.table_range_check_tag(), + layouter, + ) + } + + #[allow(non_snake_case)] + fn create_initial_y_q_gate( + meta: &mut ConstraintSystem, + config: &SinsemillaConfig, + ) { + let two = pallas::Base::from(2); + + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) + let Y_A = |meta: &mut VirtualCells, rotation| { + config.double_and_add.Y_A(meta, rotation) + }; + + // Check that the initial x_A, x_P, lambda_1, lambda_2 are consistent with y_Q. + // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial + meta.create_gate("Initial y_Q", |meta| { + let q_s4 = meta.query_selector(config.q_sinsemilla4); + let y_q = meta.query_advice(config.double_and_add.x_p, Rotation::prev()); + + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) + let Y_A_cur = Y_A(meta, Rotation::cur()); + + // 2 * y_q - Y_{A,0} = 0 + let init_y_q_check = y_q * two - Y_A_cur; + + Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) + }); + } + + /// # Side-effects + /// + /// All columns in `advices` and will be equality-enabled. + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] + pub fn configure( + meta: &mut ConstraintSystem, + advices: [Column; 5], + witness_pieces: Column, + fixed_y_q: Column, + lookup: (TableColumn, TableColumn, TableColumn), + range_check: PallasLookupConfigOptimized, + ) -> >::Config { + let config = SinsemillaChip::::create_config( + meta, + advices, + witness_pieces, + fixed_y_q, + lookup, + range_check, + ); + + Self::create_initial_y_q_gate(meta, &config); + + SinsemillaChip::::create_sinsemilla_gate( + meta, &config, + ); + + config + } +} + +// Implement `SinsemillaInstructions` for `SinsemillaChipOptimized` +impl SinsemillaInstructions + for SinsemillaChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + type CellValue = AssignedCell; + + type Message = Message; + type MessagePiece = MessagePiece; + + type RunningSum = Vec; + + type X = AssignedCell; + type NonIdentityPoint = NonIdentityEccPoint; + type FixedPoints = F; + + type HashDomains = Hash; + type CommitDomains = Commit; + + fn witness_message_piece( + &self, + layouter: impl Layouter, + field_elem: Value, + num_words: usize, + ) -> Result { + self.inner + .witness_message_piece(layouter, field_elem, num_words) + } + + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point( + &self, + mut layouter: impl Layouter, + Q: pallas::Affine, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec), Error> { + layouter.assign_region( + || "hash_to_point", + |mut region| self.hash_message(&mut region, Q, &message), + ) + } + + fn extract(point: &Self::NonIdentityPoint) -> Self::X { + point.x() + } +} + +// Implement `SinsemillaInstructionsOptimized` for `SinsemillaChipOptimized` +impl + SinsemillaInstructionsOptimized + for SinsemillaChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point_with_private_init( + &self, + mut layouter: impl Layouter, + Q: &Self::NonIdentityPoint, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec), Error> { + layouter.assign_region( + || "hash_to_point", + |mut region| self.hash_message_with_private_init(&mut region, Q, &message), + ) + } +} diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 013995911c..f01bb6766f 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -6,6 +6,7 @@ use halo2_proofs::{ }; use super::{CommitDomains, FixedPoints, HashDomains}; +use crate::sinsemilla::primitives::K; use crate::{ sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, utilities::lookup_range_check::PallasLookupRC, @@ -100,3 +101,103 @@ impl GeneratorTableConfig { ) } } + +/// Load the generator table into the circuit. +/// +/// | table_idx | table_x | table_y | table_range_check_tag | +/// ------------------------------------------------------------------- +/// | 0 | X(S\[0\]) | Y(S\[0\]) | 0 | +/// | 1 | X(S\[1\]) | Y(S\[1\]) | 0 | +/// | ... | ... | ... | 0 | +/// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | 0 | +/// | 0 | X(S\[0\]) | Y(S\[0\]) | 4 | +/// | 1 | X(S\[1\]) | Y(S\[1\]) | 4 | +/// | ... | ... | ... | 4 | +/// | 2^4-1 | X(S\[2^4-1\]) | Y(S\[2^4-1\]) | 4 | +/// | 0 | X(S\[0\]) | Y(S\[0\]) | 5 | +/// | 1 | X(S\[1\]) | Y(S\[1\]) | 5 | +/// | ... | ... | ... | 5 | +/// | 2^5-1 | X(S\[2^5-1\]) | Y(S\[2^5-1\]) | 5 | +pub fn load_with_tag( + config: &GeneratorTableConfig, + table_range_check_tag: TableColumn, + layouter: &mut impl Layouter, +) -> Result<(), Error> { + layouter.assign_table( + || "generator_table", + |mut table| { + for (index, (x, y)) in SINSEMILLA_S.iter().enumerate() { + table.assign_cell( + || "table_idx", + config.table_idx, + index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell(|| "table_x", config.table_x, index, || Value::known(*x))?; + table.assign_cell(|| "table_y", config.table_y, index, || Value::known(*y))?; + + table.assign_cell( + || "table_range_check_tag", + table_range_check_tag, + index, + || Value::known(pallas::Base::zero()), + )?; + if index < (1 << 4) { + let new_index = index + (1 << K); + table.assign_cell( + || "table_idx", + config.table_idx, + new_index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell( + || "table_x", + config.table_x, + new_index, + || Value::known(*x), + )?; + table.assign_cell( + || "table_y", + config.table_y, + new_index, + || Value::known(*y), + )?; + table.assign_cell( + || "table_range_check_tag", + table_range_check_tag, + new_index, + || Value::known(pallas::Base::from(4_u64)), + )?; + } + if index < (1 << 5) { + let new_index = index + (1 << 10) + (1 << 4); + table.assign_cell( + || "table_idx", + config.table_idx, + new_index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell( + || "table_x", + config.table_x, + new_index, + || Value::known(*x), + )?; + table.assign_cell( + || "table_y", + config.table_y, + new_index, + || Value::known(*y), + )?; + table.assign_cell( + || "table_range_check_tag", + table_range_check_tag, + new_index, + || Value::known(pallas::Base::from(5_u64)), + )?; + } + } + Ok(()) + }, + ) +} diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 709da2455d..fc4567974c 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -1,5 +1,5 @@ use super::super::{CommitDomains, HashDomains, SinsemillaInstructions}; -use super::{NonIdentityEccPoint, SinsemillaChip}; +use super::{NonIdentityEccPoint, SinsemillaChip, SinsemillaChipOptimized}; use crate::{ ecc::FixedPoints, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, @@ -460,6 +460,169 @@ where } } +impl SinsemillaChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(crate) fn hash_message( + &self, + region: &mut Region<'_, pallas::Base>, + Q: pallas::Affine, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + // Coordinates of the initial point `Q` are assigned to advice columns + let (offset, x_a, y_a) = self.public_initialization(region, Q)?; + + let (x_a, y_a, zs_sum) = + SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; + + SinsemillaChip::check_hash_result( + &self.inner, + EccPointQ::PublicPoint(Q), + message, + x_a, + y_a, + zs_sum, + ) + } + /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(crate) fn hash_message_with_private_init( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + let (offset, x_a, y_a) = self.private_initialization(region, Q)?; + + let (x_a, y_a, zs_sum) = + SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; + + SinsemillaChip::check_hash_result( + &self.inner, + EccPointQ::PrivatePoint(Q), + message, + x_a, + y_a, + zs_sum, + ) + } + + #[allow(non_snake_case)] + /// Assign the coordinates of the initial public point `Q` to advice columns + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + fn public_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: pallas::Affine, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + let mut offset = 0; + + // Get the `x`- and `y`-coordinates of the starting `Q` base. + let x_q = *Q.coordinates().unwrap().x(); + let y_q = *Q.coordinates().unwrap().y(); + + // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 + // selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, offset + 1)?; + let y_a: AssignedCell, pallas::Base> = region + .assign_advice_from_constant( + || "fixed y_q", + config.double_and_add.x_p, + offset, + y_q.into(), + )?; + + y_a.value_field().into() + }; + offset += 1; + + // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. + let x_a: X = { + let x_a = region.assign_advice_from_constant( + || "fixed x_q", + config.double_and_add.x_a, + offset, + x_q.into(), + )?; + + x_a.into() + }; + + Ok((offset, x_a, y_a)) + } + + #[allow(non_snake_case)] + /// Assign the coordinates of the initial private point `Q` + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + fn private_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + let mut offset = 0; + + // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, + // x_p, y_Q using the q_sinsemilla4 selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, offset + 1)?; + let q_y: AssignedCell, pallas::Base> = Q.y().into(); + let y_a: AssignedCell, pallas::Base> = + q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, offset)?; + + y_a.value_field().into() + }; + offset += 1; + + let x_a: X = { + let q_x: AssignedCell, pallas::Base> = Q.x().into(); + let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, offset)?; + + x_a.into() + }; + + Ok((offset, x_a, y_a)) + } +} + /// The x-coordinate of the accumulator in a Sinsemilla hash instance. struct X(AssignedCell, F>); diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 95e9e401b9..13272e0141 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -200,8 +200,12 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; + use crate::sinsemilla::chip::SinsemillaChipOptimized; + use crate::sinsemilla::merkle::chip::MerkleChipOptimized; + use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; + const MERKLE_DEPTH: usize = 32; #[derive(Default)] @@ -415,4 +419,211 @@ pub mod tests { .render(11, &circuit, &root) .unwrap(); } + + #[derive(Default)] + struct MyCircuit45B { + leaf: Value, + leaf_pos: Value, + merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, + } + + impl Circuit for MyCircuit45B { + type Config = ( + MerkleConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + MerkleConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + ); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + // NB: In the actual Action circuit, these fixed columns will be reused + // by other chips. For this test, we are creating new fixed columns. + let fixed_y_q_1 = meta.fixed_column(); + let fixed_y_q_2 = meta.fixed_column(); + + // Fixed columns for the Sinsemilla generator lookup table + let lookup = ( + meta.lookup_table_column(), + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup.0); + + let sinsemilla_config_1 = SinsemillaChipOptimized::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + fixed_y_q_1, + lookup, + range_check, + ); + let config1 = MerkleChip::configure(meta, sinsemilla_config_1); + + let sinsemilla_config_2 = SinsemillaChipOptimized::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + fixed_y_q_2, + lookup, + range_check, + ); + let config2 = MerkleChip::configure(meta, sinsemilla_config_2); + + (config1, config2) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load generator table (shared across both configs) for SinsemillaChipOptimized + SinsemillaChipOptimized::::load( + config.0.sinsemilla_config.clone(), + &mut layouter, + )?; + + // Construct Merkle chips which will be placed side-by-side in the circuit. + let chip_1 = MerkleChipOptimized::construct(config.0.clone()); + let chip_2 = MerkleChipOptimized::construct(config.1.clone()); + + let leaf = chip_1.load_private( + layouter.namespace(|| ""), + config.0.cond_swap_config.a(), + self.leaf, + )?; + + let path = MerklePath { + chips: [chip_1, chip_2], + domain: TestHashDomain, + leaf_pos: self.leaf_pos, + path: self.merkle_path, + }; + + let computed_final_root = + path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?; + + self.leaf + .zip(self.leaf_pos) + .zip(self.merkle_path) + .zip(computed_final_root.value()) + .assert_if_known(|(((leaf, leaf_pos), merkle_path), computed_final_root)| { + // The expected final root + let final_root = + merkle_path + .iter() + .enumerate() + .fold(*leaf, |node, (l, sibling)| { + let l = l as u8; + let (left, right) = if leaf_pos & (1 << l) == 0 { + (&node, sibling) + } else { + (sibling, &node) + }; + + use crate::sinsemilla::primitives as sinsemilla; + let merkle_crh = + sinsemilla::HashDomain::from_Q(TestHashDomain.Q().into()); + + merkle_crh + .hash( + iter::empty() + .chain(i2lebsp::<10>(l as u64).iter().copied()) + .chain( + left.to_le_bits() + .iter() + .by_vals() + .take(pallas::Base::NUM_BITS as usize), + ) + .chain( + right + .to_le_bits() + .iter() + .by_vals() + .take(pallas::Base::NUM_BITS as usize), + ), + ) + .unwrap_or(pallas::Base::zero()) + }); + + // Check the computed final root against the expected final root. + computed_final_root == &&final_root + }); + + Ok(()) + } + } + + #[test] + fn merkle_chip_4_5_b() { + let mut rng = OsRng; + + // Choose a random leaf and position + let leaf = pallas::Base::random(rng); + let pos = rng.next_u32(); + + // Choose a path of random inner nodes + let path: Vec<_> = (0..(MERKLE_DEPTH)) + .map(|_| pallas::Base::random(rng)) + .collect(); + + // The root is provided as a public input in the Orchard circuit. + + let circuit = MyCircuit45B { + leaf: Value::known(leaf), + leaf_pos: Value::known(pos), + merkle_path: Value::known(path.try_into().unwrap()), + }; + + let prover = MockProver::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())) + } + + #[cfg(feature = "test-dev-graph")] + #[test] + fn print_merkle_chip_4_5_b() { + use plotters::prelude::*; + + let root = BitMapBackend::new("merkle-path-layout.png", (1024, 7680)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); + + let circuit = MyCircuit45B::default(); + halo2_proofs::dev::CircuitLayout::default() + .show_labels(false) + .render(11, &circuit, &root) + .unwrap(); + } } diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index b8ea59ead7..24db41040f 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -9,6 +9,8 @@ use pasta_curves::pallas; use super::MerkleInstructions; +use crate::sinsemilla::chip::SinsemillaChipOptimized; +use crate::utilities::lookup_range_check::PallasLookupConfigOptimized; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, utilities::{ @@ -588,3 +590,183 @@ where SinsemillaChip::::extract(point) } } + +/// Chip implementing `MerkleInstructions`. +/// +/// This chip specifically implements `MerkleInstructions::hash_layer` as the `MerkleCRH` +/// function `hash = SinsemillaHash(Q, 𝑙⋆ || left⋆ || right⋆)`, where: +/// - `𝑙⋆ = I2LEBSP_10(l)` +/// - `left⋆ = I2LEBSP_255(left)` +/// - `right⋆ = I2LEBSP_255(right)` +/// +/// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of +/// `left` and `right`. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MerkleChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + base: MerkleChip, +} + +impl Chip for MerkleChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + type Config = MerkleConfig; + type Loaded = (); + + fn config(&self) -> &Self::Config { + &self.base.config + } + + fn loaded(&self) -> &Self::Loaded { + &() + } +} + +impl MerkleChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + /// Configures the [`MerkleChip`]. + pub fn configure( + meta: &mut ConstraintSystem, + sinsemilla_config: SinsemillaConfig, + ) -> MerkleConfig { + MerkleChip::configure(meta, sinsemilla_config) + } + + /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. + pub fn construct(config: MerkleConfig) -> Self { + MerkleChipOptimized { + base: MerkleChip { config }, + } + } +} + +impl MerkleSinsemillaInstructions + for MerkleChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ +} + +impl UtilitiesInstructions for MerkleChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + type Var = AssignedCell; +} + +impl CondSwapInstructions for MerkleChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + #[allow(clippy::type_complexity)] + fn swap( + &self, + layouter: impl Layouter, + pair: (Self::Var, Value), + swap: Value, + ) -> Result<(Self::Var, Self::Var), Error> { + self.base.swap(layouter, pair, swap) + } +} + +impl SinsemillaInstructions + for MerkleChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + type CellValue = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CellValue; + + type Message = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::Message; + type MessagePiece = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::MessagePiece; + type RunningSum = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::RunningSum; + + type X = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::X; + type NonIdentityPoint = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::NonIdentityPoint; + type FixedPoints = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::FixedPoints; + + type HashDomains = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::HashDomains; + type CommitDomains = as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CommitDomains; + + fn witness_message_piece( + &self, + layouter: impl Layouter, + value: Value, + num_words: usize, + ) -> Result { + let config = self.config().sinsemilla_config.clone(); + let chip = SinsemillaChipOptimized::::construct(config); + chip.witness_message_piece(layouter, value, num_words) + } + + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point( + &self, + layouter: impl Layouter, + Q: pallas::Affine, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { + let config = self.config().sinsemilla_config.clone(); + let chip = SinsemillaChipOptimized::::construct(config); + chip.hash_to_point(layouter, Q, message) + } + + fn extract(point: &Self::NonIdentityPoint) -> Self::X { + SinsemillaChipOptimized::::extract(point) + } +} diff --git a/halo2_gadgets/src/sinsemilla/primitives.rs b/halo2_gadgets/src/sinsemilla/primitives.rs index 9bf6a72332..ad9e397b5e 100644 --- a/halo2_gadgets/src/sinsemilla/primitives.rs +++ b/halo2_gadgets/src/sinsemilla/primitives.rs @@ -184,6 +184,7 @@ impl HashDomain { #[derive(Debug)] #[allow(non_snake_case)] pub struct CommitDomain { + /// A domain in which $\mathsf{SinsemillaHashToPoint}$ and $\mathsf{SinsemillaHash}$ can be used M: HashDomain, R: pallas::Point, } @@ -200,6 +201,17 @@ impl CommitDomain { } } + /// Constructs a new `CommitDomain` from different values for `hash_domain` and `blind_domain` + pub fn new_with_personalization(hash_domain: &str, blind_domain: &str) -> Self { + let m_prefix = format!("{}-M", hash_domain); + let r_prefix = format!("{}-r", blind_domain); + let hasher_r = pallas::Point::hash_to_curve(&r_prefix); + CommitDomain { + M: HashDomain::new(&m_prefix), + R: hasher_r(&[]), + } + } + /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit @@ -214,6 +226,26 @@ impl CommitDomain { .map(|p| p + Wnaf::new().scalar(r).base(self.R)) } + /// $\mathsf{SinsemillaHashToPoint}$ from [§ 5.4.1.9][concretesinsemillahash]. + /// + /// [concretesinsemillahash]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillahash + pub fn hash_to_point(&self, msg: impl Iterator) -> CtOption { + self.M.hash_to_point(msg) + } + + /// Returns `SinsemillaCommit_r(personalization, msg) = hash_point + [r]R` + /// where `SinsemillaHash(personalization, msg) = hash_point` + /// and `R` is derived from the `personalization`. + #[allow(non_snake_case)] + pub fn commit_from_hash_point( + &self, + hash_point: CtOption, + r: &pallas::Scalar, + ) -> CtOption { + // We use complete addition for the blinding factor. + hash_point.map(|p| p + Wnaf::new().scalar(r).base(self.R)) + } + /// $\mathsf{SinsemillaShortCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit @@ -305,4 +337,32 @@ mod tests { assert_eq!(computed, actual); } } + + #[test] + fn commit_in_several_steps() { + use rand::{rngs::OsRng, Rng}; + + use ff::Field; + + use crate::sinsemilla::primitives::CommitDomain; + + let domain = CommitDomain::new("z.cash:ZSA-NoteCommit"); + + let mut os_rng = OsRng::default(); + let msg: Vec = (0..36).map(|_| os_rng.gen::()).collect(); + + let rcm = pallas::Scalar::random(&mut os_rng); + + // Evaluate the commitment with commit function + let commit1 = domain.commit(msg.clone().into_iter(), &rcm); + + // Evaluate the commitment with the following steps + // 1. hash msg + // 2. evaluate the commitment from the hash point + let hash_point = domain.M.hash_to_point(msg.into_iter()); + let commit2 = domain.commit_from_hash_point(hash_point, &rcm); + + // Test equality + assert_eq!(commit1.unwrap(), commit2.unwrap()); + } } diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index d733e6c4fb..de25597d28 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -2,12 +2,15 @@ use super::{bool_check, ternary, UtilitiesInstructions}; +use crate::ecc::chip::{EccPoint, NonIdentityEccPoint}; use group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, + plonk, plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; +use pasta_curves::pallas; use std::marker::PhantomData; /// Instructions for a conditional swap gadget. @@ -192,10 +195,116 @@ impl CondSwapChip { } } +/// Instructions for a conditional swap gadget. +pub trait CondSwapInstructionsOptimized: CondSwapInstructions { + /// Given an input `(choice, left, right)` where `choice` is a boolean flag, + /// returns `left` if `choice` is not set and `right` if `choice` is set. + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result; +} + +impl CondSwapInstructionsOptimized for CondSwapChip { + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result { + let config = self.config(); + + layouter.assign_region( + || "mux", + |mut region| { + // Enable `q_swap` selector + config.q_swap.enable(&mut region, 0)?; + + // Copy in `a` value + let left = left.copy_advice(|| "copy left", &mut region, config.a, 0)?; + + // Copy in `b` value + let right = right.copy_advice(|| "copy right", &mut region, config.b, 0)?; + + // Copy `choice` value + let choice = choice.copy_advice(|| "copy choice", &mut region, config.swap, 0)?; + + let a_swapped = left + .value() + .zip(right.value()) + .zip(choice.value()) + .map(|((left, right), choice)| { + if *choice == F::from(0_u64) { + left + } else { + right + } + }) + .cloned(); + let b_swapped = left + .value() + .zip(right.value()) + .zip(choice.value()) + .map(|((left, right), choice)| { + if *choice == F::from(0_u64) { + right + } else { + left + } + }) + .cloned(); + + region.assign_advice(|| "out b_swap", self.config.b_swapped, 0, || b_swapped)?; + region.assign_advice(|| "out a_swap", self.config.a_swapped, 0, || a_swapped) + }, + ) + } +} + +impl CondSwapChip { + /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are `EccPoint`, + /// returns `left` if `choice` is not set and `right` if `choice` is set. + pub fn mux_on_points( + &self, + mut layouter: impl Layouter, + choice: &AssignedCell, + left: &EccPoint, + right: &EccPoint, + ) -> Result { + let x_cell = self.mux(&mut layouter, choice.clone(), left.x(), right.x())?; + let y_cell = self.mux(&mut layouter, choice.clone(), left.y(), right.y())?; + Ok(EccPoint::from_coordinates_unchecked( + x_cell.into(), + y_cell.into(), + )) + } + + /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are + /// `NonIdentityEccPoint`, returns `left` if `choice` is not set and `right` if `choice` is set. + pub fn mux_on_non_identity_points( + &self, + mut layouter: impl Layouter, + choice: &AssignedCell, + left: &NonIdentityEccPoint, + right: &NonIdentityEccPoint, + ) -> Result { + let x_cell = self.mux(&mut layouter, choice.clone(), left.x(), right.x())?; + let y_cell = self.mux(&mut layouter, choice.clone(), left.y(), right.y())?; + Ok(NonIdentityEccPoint::from_coordinates_unchecked( + x_cell.into(), + y_cell.into(), + )) + } +} #[cfg(test)] mod tests { use super::super::UtilitiesInstructions; use super::{CondSwapChip, CondSwapConfig, CondSwapInstructions}; + use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfigOptimized}; use group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, @@ -291,4 +400,228 @@ mod tests { assert_eq!(prover.verify(), Ok(())); } } + + #[test] + fn test_mux() { + use crate::ecc::{ + chip::{EccChip, EccConfig}, + tests::TestFixedBases, + NonIdentityPoint, Point, + }; + + use group::{cofactor::CofactorCurveAffine, Curve, Group}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, + }; + use pasta_curves::arithmetic::CurveAffine; + use pasta_curves::{pallas, EpAffine}; + + use rand::rngs::OsRng; + + #[derive(Clone, Debug)] + pub struct MyConfig { + primary: Column, + advice: Column, + cond_swap_config: CondSwapConfig, + ecc_config: EccConfig< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, + } + + #[derive(Default)] + struct MyCircuit { + left_point: Value, + right_point: Value, + choice: Value, + } + + impl Circuit for MyCircuit { + type Config = MyConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + let cond_swap_config = + CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); + + let table_idx = meta.lookup_table_column(); + + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + meta.enable_constant(lagrange_coeffs[0]); + + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], table_idx); + + let ecc_config = + EccChip::< + TestFixedBases, + LookupRangeCheckConfigOptimized< + pallas::Base, + { crate::sinsemilla::primitives::K }, + >, + >::configure(meta, advices, lagrange_coeffs, range_check); + + MyConfig { + primary, + advice: advices[0], + cond_swap_config, + ecc_config, + } + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Construct a CondSwap chip + let cond_swap_chip = CondSwapChip::construct(config.cond_swap_config); + + // Construct an ECC chip + let ecc_chip = EccChip::construct(config.ecc_config); + + // Assign choice + let choice = layouter.assign_region( + || "load private", + |mut region| { + region.assign_advice(|| "load private", config.advice, 0, || self.choice) + }, + )?; + + // Test mux on non identity points + // Assign left point + let left_non_identity_point = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "left point"), + self.left_point.map(|left_point| left_point), + )?; + + // Assign right point + let right_non_identity_point = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "right point"), + self.right_point.map(|right_point| right_point), + )?; + + // Apply mux + let result_non_identity_point = cond_swap_chip.mux_on_non_identity_points( + layouter.namespace(|| "MUX"), + &choice, + left_non_identity_point.inner(), + right_non_identity_point.inner(), + )?; + + // Check equality with instance + layouter.constrain_instance( + result_non_identity_point.x().cell(), + config.primary, + 0, + )?; + layouter.constrain_instance( + result_non_identity_point.y().cell(), + config.primary, + 1, + )?; + + // Test mux on points + // Assign left point + let left_point = Point::new( + ecc_chip.clone(), + layouter.namespace(|| "left point"), + self.left_point.map(|left_point| left_point), + )?; + + // Assign right point + let right_point = Point::new( + ecc_chip, + layouter.namespace(|| "right point"), + self.right_point.map(|right_point| right_point), + )?; + + // Apply mux + let result = cond_swap_chip.mux_on_points( + layouter.namespace(|| "MUX"), + &choice, + left_point.inner(), + right_point.inner(), + )?; + + // Check equality with instance + layouter.constrain_instance(result.x().cell(), config.primary, 0)?; + layouter.constrain_instance(result.y().cell(), config.primary, 1) + } + } + + // Test different circuits + let mut circuits = vec![]; + let mut instances = vec![]; + for choice in [false, true] { + let choice_value = if choice { + pallas::Base::one() + } else { + pallas::Base::zero() + }; + let left_point = pallas::Point::random(OsRng).to_affine(); + let right_point = pallas::Point::random(OsRng).to_affine(); + circuits.push(MyCircuit { + left_point: Value::known(left_point), + right_point: Value::known(right_point), + choice: Value::known(choice_value), + }); + let expected_output = if choice { right_point } else { left_point }; + let (expected_x, expected_y) = if bool::from(expected_output.is_identity()) { + (pallas::Base::zero(), pallas::Base::zero()) + } else { + let coords = expected_output.coordinates().unwrap(); + (*coords.x(), *coords.y()) + }; + instances.push([[expected_x, expected_y]]); + } + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + let prover = MockProver::::run( + 5, + circuit, + instance.iter().map(|p| p.to_vec()).collect(), + ) + .unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } } diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 10a302e82b..890cdf1136 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -456,9 +456,246 @@ pub type PallasLookupRCConfig = LookupRangeCheckConfig { + base: LookupRangeCheckConfig, + q_range_check_4: Selector, + q_range_check_5: Selector, + table_range_check_tag: TableColumn, +} + +impl LookupRangeCheckConfigOptimized { + /// The `running_sum` advice column breaks the field element into `K`-bit + /// words. It is used to construct the input expression to the lookup + /// argument. + /// + /// The `table_idx` fixed column contains values from [0..2^K). Looking up + /// a value in `table_idx` constrains it to be within this range. The table + /// can be loaded outside this helper. + /// + /// # Side-effects + /// + /// Both the `running_sum` and `constants` columns will be equality-enabled. + pub(crate) fn configure_with_tag( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + table_range_check_tag: TableColumn, + ) -> Self { + meta.enable_equality(running_sum); + + let q_lookup = meta.complex_selector(); + let q_running = meta.complex_selector(); + let q_bitshift = meta.selector(); + + let q_range_check_4 = meta.complex_selector(); + let q_range_check_5 = meta.complex_selector(); + + // if the order of the creation makes a difference + let config = LookupRangeCheckConfigOptimized { + base: LookupRangeCheckConfig { + q_lookup, + q_running, + q_bitshift, + running_sum, + table_idx, + _marker: PhantomData, + }, + q_range_check_4, + q_range_check_5, + table_range_check_tag, + }; + + // https://p.z.cash/halo2-0.1:decompose-combined-lookup + meta.lookup(|meta| { + let q_lookup = meta.query_selector(config.base.q_lookup); + let q_running = meta.query_selector(config.base.q_running); + // if the order of the creation makes a difference + let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); + let one = Expression::Constant(F::ONE); + + // In the case of a running sum decomposition, we recover the word from + // the difference of the running sums: + // z_i = 2^{K}⋅z_{i + 1} + a_i + // => a_i = z_i - 2^{K}⋅z_{i + 1} + let running_sum_lookup = { + let running_sum_word = { + let z_next = meta.query_advice(config.base.running_sum, Rotation::next()); + z_cur.clone() - z_next * F::from(1 << K) + }; + + q_running.clone() * running_sum_word + }; + + // In the short range check, the word is directly witnessed. + let short_lookup = { + let short_word = z_cur.clone(); + let q_short = one.clone() - q_running; + + q_short * short_word + }; + + let q_range_check_4 = meta.query_selector(config.q_range_check_4); + let q_range_check_5 = meta.query_selector(config.q_range_check_5); + + // q_range_check is equal to + // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 + // - 0 otherwise + let q_range_check = one.clone() + - (one.clone() - q_range_check_4.clone()) * (one.clone() - q_range_check_5.clone()); + + // num_bits is equal to + // - 5 if q_range_check_5 = 1 + // - 4 if q_range_check_4 = 1 and q_range_check_5 = 0 + // - 0 otherwise + let num_bits = q_range_check_5.clone() * Expression::Constant(F::from(5_u64)) + + (one.clone() - q_range_check_5) + * q_range_check_4 + * Expression::Constant(F::from(4_u64)); + + // Combine the running sum, short lookups and optimized range checks: + vec![ + ( + q_lookup.clone() + * ((one - q_range_check.clone()) * (running_sum_lookup + short_lookup) + + q_range_check.clone() * z_cur), + config.base.table_idx, + ), + ( + q_lookup * q_range_check * num_bits, + config.table_range_check_tag, + ), + ] + }); + + // For short lookups, check that the word has been shifted by the correct number of bits. + // https://p.z.cash/halo2-0.1:decompose-short-lookup + meta.create_gate("Short lookup bitshift", |meta| { + let q_bitshift = meta.query_selector(config.base.q_bitshift); + let word = meta.query_advice(config.base.running_sum, Rotation::prev()); + let shifted_word = meta.query_advice(config.base.running_sum, Rotation::cur()); + let inv_two_pow_s = meta.query_advice(config.base.running_sum, Rotation::next()); + + let two_pow_k = F::from(1 << K); + + // shifted_word = word * 2^{K-s} + // = word * 2^K * inv_two_pow_s + Constraints::with_selector( + q_bitshift, + Some(word * two_pow_k * inv_two_pow_s - shifted_word), + ) + }); + + config + } + + pub(crate) fn table_range_check_tag(&self) -> TableColumn { + self.table_range_check_tag + } +} + +impl LookupRangeCheck + for LookupRangeCheckConfigOptimized +{ + fn config(&self) -> &LookupRangeCheckConfig { + &self.base + } + + fn configure( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + ) -> Self { + let table_range_check_tag = meta.lookup_table_column(); + Self::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) + } + + #[cfg(test)] + // Fill `table_idx` and `table_range_check_tag`. + // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table + // in the Orchard context. + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table_idx", + |mut table| { + let mut assign_cells = + |offset: usize, table_size, value: u64| -> Result { + for index in 0..table_size { + let new_index = index + offset; + table.assign_cell( + || "table_idx", + self.base.table_idx, + new_index, + || Value::known(F::from(index as u64)), + )?; + table.assign_cell( + || "table_range_check_tag", + self.table_range_check_tag, + new_index, + || Value::known(F::from(value)), + )?; + } + Ok(offset + table_size) + }; + + // We generate the row values lazily (we only need them during keygen). + let mut offset = 0; + + //annotation: &'v (dyn Fn() -> String + 'v), + //column: TableColumn, + //offset: usize, + //to: &'v mut (dyn FnMut() -> Value> + 'v), + + offset = assign_cells(offset, 1 << K, 0)?; + offset = assign_cells(offset, 1 << 4, 4)?; + assign_cells(offset, 1 << 5, 5)?; + + Ok(()) + }, + ) + } + + /// Constrain `x` to be a NUM_BITS word. + /// + /// `element` must have been assigned to `self.running_sum` at offset 0. + fn short_range_check( + &self, + region: &mut Region<'_, F>, + element: AssignedCell, + num_bits: usize, + ) -> Result<(), Error> { + match num_bits { + 4 => { + self.base.q_lookup.enable(region, 0)?; + self.q_range_check_4.enable(region, 0)?; + Ok(()) + } + + 5 => { + self.base.q_lookup.enable(region, 0)?; + self.q_range_check_5.enable(region, 0)?; + Ok(()) + } + + _ => self.base.short_range_check(region, element, num_bits), + } + } +} + +/// In this crate, `LookupRangeCheckConfigOptimized` is always used with `pallas::Base` as the prime field +/// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, +/// we introduce this alias and use it instead of that long construction. +/// +///todo: rename PallasLookupConfig(?) and PallasLookupConfigOptimized, LookupRangeCheckConfigOptimized +pub type PallasLookupConfigOptimized = + LookupRangeCheckConfigOptimized; + +impl PallasLookupRC for PallasLookupConfigOptimized {} + #[cfg(test)] mod tests { - use super::{LookupRangeCheck, LookupRangeCheckConfig}; + use super::{LookupRangeCheck, LookupRangeCheckConfig, LookupRangeCheckConfigOptimized}; use super::super::lebs2ip; use crate::sinsemilla::primitives::K; @@ -739,4 +976,282 @@ mod tests { ); } } + + #[test] + fn lookup_range_check_4_5_b() { + #[derive(Clone, Copy)] + struct MyCircuit { + num_words: usize, + _marker: PhantomData, + } + + impl Circuit for MyCircuit { + type Config = LookupRangeCheckConfigOptimized; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + *self + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + LookupRangeCheckConfigOptimized::::configure(meta, running_sum, table_idx) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_words * K bits. + let elements_and_expected_final_zs = [ + (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long + (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long + ]; + + fn expected_zs( + element: F, + num_words: usize, + ) -> Vec { + let chunks = { + element + .to_le_bits() + .iter() + .by_vals() + .take(num_words * K) + .collect::>() + .chunks_exact(K) + .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) + .collect::>() + }; + let expected_zs = { + let inv_two_pow_k = F::from(1 << K).invert().unwrap(); + chunks.iter().fold(vec![element], |mut zs, a_i| { + // z_{i + 1} = (z_i - a_i) / 2^{K} + let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; + zs.push(z); + zs + }) + }; + expected_zs + } + + for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { + let expected_zs = expected_zs::(*element, self.num_words); + + let zs = config.witness_check( + layouter.namespace(|| format!("Lookup {:?}", self.num_words)), + Value::known(*element), + self.num_words, + *strict, + )?; + + assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); + + for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { + z.value().assert_if_known(|z| &&expected_z == z); + } + } + Ok(()) + } + } + + { + let circuit: MyCircuit = MyCircuit { + num_words: 6, + _marker: PhantomData, + }; + + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } + + #[test] + fn short_range_check_4_5_b() { + struct MyCircuit { + element: Value, + num_bits: usize, + } + + impl Circuit for MyCircuit { + type Config = LookupRangeCheckConfigOptimized; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + MyCircuit { + element: Value::unknown(), + num_bits: self.num_bits, + } + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + LookupRangeCheckConfigOptimized::::configure(meta, running_sum, table_idx) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_bits. + config.witness_short_check( + layouter.namespace(|| format!("Lookup {:?} bits", self.num_bits)), + self.element, + self.num_bits, + )?; + + Ok(()) + } + } + + // Edge case: zero bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::ZERO), + num_bits: 0, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Edge case: K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from((1 << K) - 1)), + num_bits: K, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Element within `num_bits` + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from((1 << 6) - 1)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Element larger than `num_bits` but within K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from(1 << 6)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }]) + ); + } + + // Element larger than K bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from(1 << K)), + num_bits: 6, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }, + VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }, + ]) + ); + } + + // Element which is not within `num_bits`, but which has a shifted value within + // num_bits + { + let num_bits = 6; + let shifted = pallas::Base::from((1 << num_bits) - 1); + // Recall that shifted = element * 2^{K-s} + // => element = shifted * 2^{s-K} + let element = shifted + * pallas::Base::from(1 << (K as u64 - num_bits)) + .invert() + .unwrap(); + let circuit: MyCircuit = MyCircuit { + element: Value::known(element), + num_bits: num_bits as usize, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }]) + ); + } + + // Element within 4 bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from((1 << 4) - 1)), + num_bits: 4, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + + // Element larger than 5 bits + { + let circuit: MyCircuit = MyCircuit { + element: Value::known(pallas::Base::from(1 << 5)), + num_bits: 5, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 5 bits").into(), + offset: 0, + }, + }]) + ); + } + } } diff --git a/halo2_proofs/src/circuit.rs b/halo2_proofs/src/circuit.rs index 0822d8d8aa..1083339fed 100644 --- a/halo2_proofs/src/circuit.rs +++ b/halo2_proofs/src/circuit.rs @@ -139,6 +139,16 @@ impl AssignedCell, F> { } } +impl From> for AssignedCell, F> { + fn from(ac: AssignedCell) -> Self { + AssignedCell { + value: ac.value.map(|a| a.into()), + cell: ac.cell, + _marker: Default::default(), + } + } +} + impl AssignedCell where for<'v> Assigned: From<&'v V>, From 8a8aca2dd6676d5bc787ad854e69637609ca4c39 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 3 Jun 2024 18:46:49 +0200 Subject: [PATCH 065/121] fix cargo clippy --- halo2_gadgets/src/ecc.rs | 68 ++++++++++++------- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 14 ++-- halo2_gadgets/src/ecc/chip/witness_point.rs | 2 +- halo2_gadgets/src/sinsemilla.rs | 2 +- 4 files changed, 53 insertions(+), 33 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 0bfb3fff5b..c597d90539 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -628,15 +628,6 @@ pub(crate) mod tests { use ff::PrimeField; use group::{prime::PrimeCurveAffine, Curve, Group}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use lazy_static::lazy_static; - use pasta_curves::pallas; - use pasta_curves::vesta::Affine; - use super::{ chip::{ find_zs_and_us, BaseFieldElem, EccChip, EccConfig, FixedPoint, FullScalar, ShortScalar, @@ -649,6 +640,13 @@ pub(crate) mod tests { tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, }; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use lazy_static::lazy_static; + use pasta_curves::pallas; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -953,7 +951,7 @@ pub(crate) mod tests { #[test] fn ecc_chip() { - let k = 13; + let k = 11; let circuit = MyCircuit { test_errors: true }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) @@ -986,12 +984,12 @@ pub(crate) mod tests { .unwrap(); } - struct MyCircuit_4_5_b { + struct MyCircuit45B { test_errors: bool, } #[allow(non_snake_case)] - impl Circuit for MyCircuit_4_5_b { + impl Circuit for MyCircuit45B { type Config = EccConfig< crate::ecc::tests::TestFixedBases, LookupRangeCheckConfigOptimized, @@ -999,7 +997,7 @@ pub(crate) mod tests { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit_4_5_b { test_errors: false } + MyCircuit45B { test_errors: false } } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -1083,7 +1081,7 @@ pub(crate) mod tests { Value::known(pallas::Affine::identity()), )?; - crate::ecc::NonIdentityPoint::new( + super::NonIdentityPoint::new( chip.clone(), layouter.namespace(|| "identity"), Value::known(pallas::Affine::identity()), @@ -1093,7 +1091,7 @@ pub(crate) mod tests { // Test witness non-identity point { - crate::ecc::chip::witness_point::tests::test_witness_non_id( + super::chip::witness_point::tests::test_witness_non_id( chip.clone(), layouter.namespace(|| "witness non-identity point"), ) @@ -1101,7 +1099,7 @@ pub(crate) mod tests { // Test complete addition { - crate::ecc::chip::add::tests::test_add( + super::chip::add::tests::test_add( chip.clone(), layouter.namespace(|| "complete addition"), p_val, @@ -1114,7 +1112,7 @@ pub(crate) mod tests { // Test incomplete addition { - crate::ecc::chip::add_incomplete::tests::test_add_incomplete( + super::chip::add_incomplete::tests::test_add_incomplete( chip.clone(), layouter.namespace(|| "incomplete addition"), p_val, @@ -1128,7 +1126,7 @@ pub(crate) mod tests { // Test variable-base scalar multiplication { - crate::ecc::chip::mul::tests::test_mul( + super::chip::mul::tests::test_mul( chip.clone(), layouter.namespace(|| "variable-base scalar mul"), &p, @@ -1138,34 +1136,58 @@ pub(crate) mod tests { // Test variable-base sign-scalar multiplication { - crate::ecc::chip::mul_fixed::short::tests::test_mul_sign( + super::chip::mul_fixed::short::tests::test_mul_sign( chip.clone(), layouter.namespace(|| "variable-base sign-scalar mul"), )?; } + // Test full-width fixed-base scalar multiplication + { + super::chip::mul_fixed::full_width::tests::test_mul_fixed( + chip.clone(), + layouter.namespace(|| "full-width fixed-base scalar mul"), + )?; + } + + // Test signed short fixed-base scalar multiplication + { + super::chip::mul_fixed::short::tests::test_mul_fixed_short( + chip.clone(), + layouter.namespace(|| "signed short fixed-base scalar mul"), + )?; + } + + // Test fixed-base scalar multiplication with a base field element + { + super::chip::mul_fixed::base_field_elem::tests::test_mul_fixed_base_field( + chip, + layouter.namespace(|| "fixed-base scalar mul with base field element"), + )?; + } + Ok(()) } } #[test] - fn ecc_chip() { + fn ecc_chip_4_5_b() { let k = 11; - let circuit = MyCircuit_4_5_b { test_errors: true }; + let circuit = MyCircuit45B { test_errors: true }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[cfg(feature = "test-dev-graph")] #[test] - fn print_ecc_chip() { + fn print_ecc_chip_4_5_b() { use plotters::prelude::*; let root = BitMapBackend::new("ecc-chip-layout.png", (1024, 7680)).into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit_4_5_b { test_errors: false }; + let circuit = MyCircuit45B { test_errors: false }; halo2_proofs::dev::CircuitLayout::default() .render(13, &circuit, &root) .unwrap(); diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index c618f0f801..124b50c2b9 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -999,7 +999,10 @@ pub mod tests { } pub(crate) fn test_mul_sign( - chip: EccChip, + chip: EccChip< + TestFixedBases, + LookupRangeCheckConfigOptimized, + >, mut layouter: impl Layouter, ) -> Result<(), Error> { // Generate a random non-identity point P @@ -1107,7 +1110,6 @@ pub mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -1123,12 +1125,8 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); EccChip::< TestFixedBases, LookupRangeCheckConfigOptimized< diff --git a/halo2_gadgets/src/ecc/chip/witness_point.rs b/halo2_gadgets/src/ecc/chip/witness_point.rs index e2cbba372f..98f865a6dc 100644 --- a/halo2_gadgets/src/ecc/chip/witness_point.rs +++ b/halo2_gadgets/src/ecc/chip/witness_point.rs @@ -142,7 +142,7 @@ impl Config { } /// Assigns a constant point that can be the identity. - pub(crate) fn constant_point( + pub(super) fn constant_point( &self, value: pallas::Affine, offset: usize, diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index aba408c8cd..f50c4702a0 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -78,7 +78,7 @@ pub trait SinsemillaInstructions Date: Mon, 3 Jun 2024 19:37:06 +0200 Subject: [PATCH 066/121] fix shrot test --- halo2_gadgets/src/ecc.rs | 28 +++++++++++-------- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 18 +++++++++--- halo2_gadgets/src/sinsemilla.rs | 12 ++++++-- halo2_gadgets/src/sinsemilla/merkle.rs | 10 +++++-- halo2_gadgets/src/utilities/cond_swap.rs | 9 ++++-- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index c597d90539..85033ee050 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -576,7 +576,8 @@ impl> FixedPointShort { } } -/// The set of circuit instructions required to use the ECC gadgets. +/// 'EccInstructionsOptimized' trait is an extension of the `EccInstructions` trait, +/// designed to enhance performance in specific cryptographic scenarios. pub trait EccInstructionsOptimized: EccInstructions { /// Witnesses the given constant point as a private input to the circuit. /// This allows the point to be the identity, mapped to (0, 0) in @@ -628,6 +629,14 @@ pub(crate) mod tests { use ff::PrimeField; use group::{prime::PrimeCurveAffine, Curve, Group}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use lazy_static::lazy_static; + use pasta_curves::pallas; + use super::{ chip::{ find_zs_and_us, BaseFieldElem, EccChip, EccConfig, FixedPoint, FullScalar, ShortScalar, @@ -640,13 +649,6 @@ pub(crate) mod tests { tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, }; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use lazy_static::lazy_static; - use pasta_curves::pallas; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -1014,7 +1016,7 @@ pub(crate) mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); - + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -1029,8 +1031,12 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup_table, + table_range_check_tag, + ); EccChip::< crate::ecc::tests::TestFixedBases, LookupRangeCheckConfigOptimized, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 124b50c2b9..fef5666632 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -779,6 +779,7 @@ pub mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -794,8 +795,12 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup_table, + table_range_check_tag, + ); EccChip::< TestFixedBases, LookupRangeCheckConfigOptimized< @@ -1110,6 +1115,7 @@ pub mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -1125,8 +1131,12 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup_table, + table_range_check_tag, + ); EccChip::< TestFixedBases, LookupRangeCheckConfigOptimized< diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index f50c4702a0..2f163bd7d2 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -951,6 +951,8 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -964,13 +966,17 @@ pub(crate) mod tests { // Fixed columns for the Sinsemilla generator lookup table let lookup = ( - meta.lookup_table_column(), + table_idx, meta.lookup_table_column(), meta.lookup_table_column(), ); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup.0); + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); let ecc_config = EccChip::< TestFixedBases, diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 13272e0141..dcca5aaa2d 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -478,8 +478,14 @@ pub mod tests { meta.lookup_table_column(), ); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup.0); + let table_range_check_tag = meta.lookup_table_column(); + + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + lookup.0, + table_range_check_tag, + ); let sinsemilla_config_1 = SinsemillaChipOptimized::configure( meta, diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index de25597d28..4572b1bd66 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -472,6 +472,7 @@ mod tests { CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), @@ -485,8 +486,12 @@ mod tests { ]; meta.enable_constant(lagrange_coeffs[0]); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], table_idx); + let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); let ecc_config = EccChip::< From 1c694c665a1880eae7838b34d2ba54457658652c Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Mon, 3 Jun 2024 20:24:29 +0200 Subject: [PATCH 067/121] add some docs --- halo2_gadgets/src/ecc.rs | 9 +++--- halo2_gadgets/src/ecc/chip/mul.rs | 3 +- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 3 +- halo2_gadgets/src/sinsemilla/chip.rs | 7 ++-- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 32 +++++++++++++------ halo2_gadgets/src/utilities/cond_swap.rs | 4 +-- .../src/utilities/lookup_range_check.rs | 4 +-- 7 files changed, 36 insertions(+), 26 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 85033ee050..0dbce3df68 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -2,10 +2,9 @@ use std::fmt::Debug; -use halo2_proofs::circuit::AssignedCell; use halo2_proofs::{ arithmetic::CurveAffine, - circuit::{Chip, Layouter, Value}, + circuit::{AssignedCell, Chip, Layouter, Value}, plonk::Error, }; @@ -1056,13 +1055,13 @@ pub(crate) mod tests { // Generate a random non-identity point P let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P - let p = crate::ecc::NonIdentityPoint::new( + let p = super::NonIdentityPoint::new( chip.clone(), layouter.namespace(|| "P"), Value::known(p_val), )?; let p_neg = -p_val; - let p_neg = crate::ecc::NonIdentityPoint::new( + let p_neg = super::NonIdentityPoint::new( chip.clone(), layouter.namespace(|| "-P"), Value::known(p_neg), @@ -1070,7 +1069,7 @@ pub(crate) mod tests { // Generate a random non-identity point Q let q_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // Q - let q = crate::ecc::NonIdentityPoint::new( + let q = super::NonIdentityPoint::new( chip.clone(), layouter.namespace(|| "Q"), Value::known(q_val), diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index e4e2004882..6ce49aaa35 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -460,9 +460,8 @@ pub mod tests { ff::{Field, PrimeField}, Curve, }; - use halo2_proofs::circuit::Chip; use halo2_proofs::{ - circuit::{Layouter, Value}, + circuit::{Chip, Layouter, Value}, plonk::Error, }; use pasta_curves::pallas; diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index fef5666632..b84c21ea25 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -3,9 +3,8 @@ use std::convert::TryInto; use super::super::{EccPoint, EccScalarFixedShort, FixedPoints, L_SCALAR_SHORT, NUM_WINDOWS_SHORT}; use crate::{ecc::chip::MagnitudeSign, utilities::bool_check}; -use halo2_proofs::circuit::AssignedCell; use halo2_proofs::{ - circuit::{Layouter, Region}, + circuit::{AssignedCell, Layouter, Region}, plonk::{ConstraintSystem, Constraints, Error, Expression, Selector}, poly::Rotation, }; diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index ffe2bcc35a..6e2a54edef 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -381,9 +381,9 @@ where } } -/// A chip that implements 10-bit Sinsemilla using a lookup table and 5 advice columns. -/// -/// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). +/// 'SinsemillaChipOptimized' is an extended version of the SinsemillaChip. +/// The corresponding lookup table support optimized range check for 4 and 5 bits. +/// It also implements methods for hash optimization. #[derive(Eq, PartialEq, Clone, Debug)] pub struct SinsemillaChipOptimized where @@ -440,6 +440,7 @@ where ) } + /// Assign y_q to an advice column #[allow(non_snake_case)] fn create_initial_y_q_gate( meta: &mut ConstraintSystem, diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 24db41040f..7df70b5eb4 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -10,6 +10,7 @@ use pasta_curves::pallas; use super::MerkleInstructions; use crate::sinsemilla::chip::SinsemillaChipOptimized; +use crate::utilities::cond_swap::CondSwapInstructionsOptimized; use crate::utilities::lookup_range_check::PallasLookupConfigOptimized; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, @@ -591,16 +592,7 @@ where } } -/// Chip implementing `MerkleInstructions`. -/// -/// This chip specifically implements `MerkleInstructions::hash_layer` as the `MerkleCRH` -/// function `hash = SinsemillaHash(Q, 𝑙⋆ || left⋆ || right⋆)`, where: -/// - `𝑙⋆ = I2LEBSP_10(l)` -/// - `left⋆ = I2LEBSP_255(left)` -/// - `right⋆ = I2LEBSP_255(right)` -/// -/// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of -/// `left` and `right`. +/// 'MerkleChipOptimized' Chip extends 'MerkleChip', supporting new methods #[derive(Clone, Debug, PartialEq, Eq)] pub struct MerkleChipOptimized where @@ -686,6 +678,26 @@ where } } +impl CondSwapInstructionsOptimized + for MerkleChipOptimized +where + Hash: HashDomains, + F: FixedPoints, + Commit: CommitDomains, +{ + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result { + let config = self.config().cond_swap_config.clone(); + let chip = CondSwapChip::::construct(config); + chip.mux(layouter, choice, left, right) + } +} + impl SinsemillaInstructions for MerkleChipOptimized where diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 4572b1bd66..09a18f9c97 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -195,7 +195,7 @@ impl CondSwapChip { } } -/// Instructions for a conditional swap gadget. +/// 'CondSwapInstructionsOptimized' extends 'CondSwapInstructions', provides new method 'mux'. pub trait CondSwapInstructionsOptimized: CondSwapInstructions { /// Given an input `(choice, left, right)` where `choice` is a boolean flag, /// returns `left` if `choice` is not set and `right` if `choice` is set. @@ -304,7 +304,7 @@ impl CondSwapChip { mod tests { use super::super::UtilitiesInstructions; use super::{CondSwapChip, CondSwapConfig, CondSwapInstructions}; - use crate::utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfigOptimized}; + use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 890cdf1136..e124a0ab53 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -58,7 +58,7 @@ impl RangeConstrained> { } } -/// Configuration that provides methods for a lookup range check. +/// Configuration that provides methods for a 10-bit lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] pub struct LookupRangeCheckConfig { q_lookup: Selector, @@ -456,7 +456,7 @@ pub type PallasLookupRCConfig = LookupRangeCheckConfig { base: LookupRangeCheckConfig, From aedcc548d48f60ac408804c039ec3e86d95bdef9 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 09:37:20 +0200 Subject: [PATCH 068/121] Fix error in ci.yml --- .github/workflows/ci.yml | 59 ++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce5cafc981..d2876a4688 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,8 +52,10 @@ jobs: with: beta-features: ${{ matrix.stage == 'beta' }} nightly-features: ${{ matrix.stage == 'nightly' }} + - name: Update apt + run: sudo apt-get update - name: Install cross-platform support dependencies - run: sudo apt install gcc-multilib + run: sudo apt-get install gcc-multilib - run: rustup target add i686-unknown-linux-gnu - name: Run tests run: > @@ -125,34 +127,33 @@ jobs: - name: Test halo2 book run: mdbook test -L target/debug/deps book/ - codecov: - name: Code coverage - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - # Use stable for this to ensure that cargo-tarpaulin can be built. - - id: prepare - uses: ./.github/actions/prepare - with: - toolchain: stable - nightly-features: true - - name: Install cargo-tarpaulin - uses: actions-rs/cargo@v1 - with: - command: install - args: cargo-tarpaulin - - name: Generate coverage report - uses: actions-rs/cargo@v1 - with: - command: tarpaulin - # Extend the timeout to 3600 to ensure the code coverage test pass - args: > - ${{ steps.prepare.outputs.feature-flags }} - --timeout 3600 - --out Xml - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3.1.4 + # codecov: + # name: Code coverage + # runs-on: ubuntu-latest + # + # steps: + # - uses: actions/checkout@v3 + # # Use stable for this to ensure that cargo-tarpaulin can be built. + # - id: prepare + # uses: ./.github/actions/prepare + # with: + # toolchain: stable + # nightly-features: true + # - name: Install cargo-tarpaulin + # uses: actions-rs/cargo@v1 + # with: + # command: install + # args: cargo-tarpaulin + # - name: Generate coverage report + # uses: actions-rs/cargo@v1 + # with: + # command: tarpaulin + # args: > + # ${{ steps.prepare.outputs.feature-flags }} + # --timeout 600 + # --out Xml + # - name: Upload coverage to Codecov + # uses: codecov/codecov-action@v3.1.4 doc-links: name: Intra-doc links From b25257998b4be8386ae297cf19052ecaad5e136e Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 10:06:49 +0200 Subject: [PATCH 069/121] remove space in ci.yml --- .github/workflows/ci.yml | 54 ++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2876a4688..a182c0f209 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -127,33 +127,33 @@ jobs: - name: Test halo2 book run: mdbook test -L target/debug/deps book/ - # codecov: - # name: Code coverage - # runs-on: ubuntu-latest - # - # steps: - # - uses: actions/checkout@v3 - # # Use stable for this to ensure that cargo-tarpaulin can be built. - # - id: prepare - # uses: ./.github/actions/prepare - # with: - # toolchain: stable - # nightly-features: true - # - name: Install cargo-tarpaulin - # uses: actions-rs/cargo@v1 - # with: - # command: install - # args: cargo-tarpaulin - # - name: Generate coverage report - # uses: actions-rs/cargo@v1 - # with: - # command: tarpaulin - # args: > - # ${{ steps.prepare.outputs.feature-flags }} - # --timeout 600 - # --out Xml - # - name: Upload coverage to Codecov - # uses: codecov/codecov-action@v3.1.4 +# codecov: +# name: Code coverage +# runs-on: ubuntu-latest +# +# steps: +# - uses: actions/checkout@v3 +# # Use stable for this to ensure that cargo-tarpaulin can be built. +# - id: prepare +# uses: ./.github/actions/prepare +# with: +# toolchain: stable +# nightly-features: true +# - name: Install cargo-tarpaulin +# uses: actions-rs/cargo@v1 +# with: +# command: install +# args: cargo-tarpaulin +# - name: Generate coverage report +# uses: actions-rs/cargo@v1 +# with: +# command: tarpaulin +# args: > +# ${{ steps.prepare.outputs.feature-flags }} +# --timeout 600 +# --out Xml +# - name: Upload coverage to Codecov +# uses: codecov/codecov-action@v3.1.4 doc-links: name: Intra-doc links From ce24e86b624dcb3277d11781d59484aaa6daa7ff Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 11:45:20 +0200 Subject: [PATCH 070/121] order functions in hash_to_point --- .../src/sinsemilla/chip/hash_to_point.rs | 148 +++++++++--------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index fc4567974c..74a3d113a0 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -58,6 +58,80 @@ where self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum) } + #[allow(unused_variables)] + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn check_hash_result( + &self, + Q: EccPointQ, + message: &>::Message, + x_a: X, + y_a: AssignedCell, pallas::Base>, + zs_sum: Vec>>, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + #[cfg(test)] + // Check equivalence to result from primitives::sinsemilla::hash_to_point + { + use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; + + use group::{prime::PrimeCurveAffine, Curve}; + use pasta_curves::arithmetic::CurveExt; + + let field_elems: Value> = message + .iter() + .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) + .collect(); + + let value_Q = match Q { + EccPointQ::PublicPoint(p) => Value::known(p), + EccPointQ::PrivatePoint(p) => p.point(), + }; + + field_elems + .zip(x_a.value().zip(y_a.value())) + .zip(value_Q) + .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { + // Get message as a bitstring. + let bitstring: Vec = field_elems + .iter() + .flat_map(|(elem, num_words)| { + elem.to_le_bits().into_iter().take(K * num_words) + }) + .collect(); + + let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); + let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); + + // We can use complete addition here because it differs from + // incomplete addition with negligible probability. + let expected_point = bitstring + .chunks(K) + .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); + let actual_point = + pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); + expected_point.to_affine() == actual_point + }); + } + + x_a.value() + .zip(y_a.value()) + .error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?; + Ok(( + NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a), + zs_sum, + )) + } + #[allow(non_snake_case)] /// Assign the coordinates of the initial public point `Q`, /// y_Q to a fixed column @@ -179,80 +253,6 @@ where Ok((x_a, y_a, zs_sum)) } - #[allow(unused_variables)] - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn check_hash_result( - &self, - Q: EccPointQ, - message: &>::Message, - x_a: X, - y_a: AssignedCell, pallas::Base>, - zs_sum: Vec>>, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - #[cfg(test)] - // Check equivalence to result from primitives::sinsemilla::hash_to_point - { - use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; - - use group::{prime::PrimeCurveAffine, Curve}; - use pasta_curves::arithmetic::CurveExt; - - let field_elems: Value> = message - .iter() - .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) - .collect(); - - let value_Q = match Q { - EccPointQ::PublicPoint(p) => Value::known(p), - EccPointQ::PrivatePoint(p) => p.point(), - }; - - field_elems - .zip(x_a.value().zip(y_a.value())) - .zip(value_Q) - .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { - // Get message as a bitstring. - let bitstring: Vec = field_elems - .iter() - .flat_map(|(elem, num_words)| { - elem.to_le_bits().into_iter().take(K * num_words) - }) - .collect(); - - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - - // We can use complete addition here because it differs from - // incomplete addition with negligible probability. - let expected_point = bitstring - .chunks(K) - .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); - let actual_point = - pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); - expected_point.to_affine() == actual_point - }); - } - - x_a.value() - .zip(y_a.value()) - .error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?; - Ok(( - NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a), - zs_sum, - )) - } - #[allow(clippy::type_complexity)] /// Hashes a message piece containing `piece.length` number of `K`-bit words. /// From 5474c7c26912f448ce2706e343b37ef600175a4a Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 11:47:43 +0200 Subject: [PATCH 071/121] order functions in hash_to_point --- .../src/sinsemilla/chip/hash_to_point.rs | 326 +++++++++--------- 1 file changed, 163 insertions(+), 163 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 74a3d113a0..f8fdc45ad7 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -25,6 +25,169 @@ pub enum EccPointQ<'a> { PrivatePoint(&'a NonIdentityEccPoint), } +impl SinsemillaChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(crate) fn hash_message( + &self, + region: &mut Region<'_, pallas::Base>, + Q: pallas::Affine, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + // Coordinates of the initial point `Q` are assigned to advice columns + let (offset, x_a, y_a) = self.public_initialization(region, Q)?; + + let (x_a, y_a, zs_sum) = + SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; + + SinsemillaChip::check_hash_result( + &self.inner, + EccPointQ::PublicPoint(Q), + message, + x_a, + y_a, + zs_sum, + ) + } + /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(crate) fn hash_message_with_private_init( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + let (offset, x_a, y_a) = self.private_initialization(region, Q)?; + + let (x_a, y_a, zs_sum) = + SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; + + SinsemillaChip::check_hash_result( + &self.inner, + EccPointQ::PrivatePoint(Q), + message, + x_a, + y_a, + zs_sum, + ) + } + + #[allow(non_snake_case)] + /// Assign the coordinates of the initial public point `Q` to advice columns + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + fn public_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: pallas::Affine, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + let mut offset = 0; + + // Get the `x`- and `y`-coordinates of the starting `Q` base. + let x_q = *Q.coordinates().unwrap().x(); + let y_q = *Q.coordinates().unwrap().y(); + + // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 + // selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, offset + 1)?; + let y_a: AssignedCell, pallas::Base> = region + .assign_advice_from_constant( + || "fixed y_q", + config.double_and_add.x_p, + offset, + y_q.into(), + )?; + + y_a.value_field().into() + }; + offset += 1; + + // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. + let x_a: X = { + let x_a = region.assign_advice_from_constant( + || "fixed x_q", + config.double_and_add.x_a, + offset, + x_q.into(), + )?; + + x_a.into() + }; + + Ok((offset, x_a, y_a)) + } + + #[allow(non_snake_case)] + /// Assign the coordinates of the initial private point `Q` + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + fn private_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + let mut offset = 0; + + // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, + // x_p, y_Q using the q_sinsemilla4 selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, offset + 1)?; + let q_y: AssignedCell, pallas::Base> = Q.y().into(); + let y_a: AssignedCell, pallas::Base> = + q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, offset)?; + + y_a.value_field().into() + }; + offset += 1; + + let x_a: X = { + let q_x: AssignedCell, pallas::Base> = Q.x().into(); + let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, offset)?; + + x_a.into() + }; + + Ok((offset, x_a, y_a)) + } +} + impl SinsemillaChip where Hash: HashDomains, @@ -460,169 +623,6 @@ where } } -impl SinsemillaChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(crate) fn hash_message( - &self, - region: &mut Region<'_, pallas::Base>, - Q: pallas::Affine, - message: &>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - // Coordinates of the initial point `Q` are assigned to advice columns - let (offset, x_a, y_a) = self.public_initialization(region, Q)?; - - let (x_a, y_a, zs_sum) = - SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; - - SinsemillaChip::check_hash_result( - &self.inner, - EccPointQ::PublicPoint(Q), - message, - x_a, - y_a, - zs_sum, - ) - } - /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(crate) fn hash_message_with_private_init( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - message: &>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - let (offset, x_a, y_a) = self.private_initialization(region, Q)?; - - let (x_a, y_a, zs_sum) = - SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; - - SinsemillaChip::check_hash_result( - &self.inner, - EccPointQ::PrivatePoint(Q), - message, - x_a, - y_a, - zs_sum, - ) - } - - #[allow(non_snake_case)] - /// Assign the coordinates of the initial public point `Q` to advice columns - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn public_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: pallas::Affine, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - let mut offset = 0; - - // Get the `x`- and `y`-coordinates of the starting `Q` base. - let x_q = *Q.coordinates().unwrap().x(); - let y_q = *Q.coordinates().unwrap().y(); - - // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 - // selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, offset + 1)?; - let y_a: AssignedCell, pallas::Base> = region - .assign_advice_from_constant( - || "fixed y_q", - config.double_and_add.x_p, - offset, - y_q.into(), - )?; - - y_a.value_field().into() - }; - offset += 1; - - // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. - let x_a: X = { - let x_a = region.assign_advice_from_constant( - || "fixed x_q", - config.double_and_add.x_a, - offset, - x_q.into(), - )?; - - x_a.into() - }; - - Ok((offset, x_a, y_a)) - } - - #[allow(non_snake_case)] - /// Assign the coordinates of the initial private point `Q` - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn private_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - let mut offset = 0; - - // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, - // x_p, y_Q using the q_sinsemilla4 selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, offset + 1)?; - let q_y: AssignedCell, pallas::Base> = Q.y().into(); - let y_a: AssignedCell, pallas::Base> = - q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, offset)?; - - y_a.value_field().into() - }; - offset += 1; - - let x_a: X = { - let q_x: AssignedCell, pallas::Base> = Q.x().into(); - let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, offset)?; - - x_a.into() - }; - - Ok((offset, x_a, y_a)) - } -} - /// The x-coordinate of the accumulator in a Sinsemilla hash instance. struct X(AssignedCell, F>); From 1cac5b70fdf7e1d976a66153d4532394ad5d2cb9 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 11:50:27 +0200 Subject: [PATCH 072/121] crate -> super --- halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index f8fdc45ad7..06b7fbb3b3 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -33,7 +33,7 @@ where { #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - pub(crate) fn hash_message( + pub(super) fn hash_message( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, @@ -67,7 +67,7 @@ where /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - pub(crate) fn hash_message_with_private_init( + pub(super) fn hash_message_with_private_init( &self, region: &mut Region<'_, pallas::Base>, Q: &NonIdentityEccPoint, From ddee3edc211803857d85887451534bc66e2cad73 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 12:02:12 +0200 Subject: [PATCH 073/121] re-order cond_swap and lookup --- halo2_gadgets/src/utilities/cond_swap.rs | 26 +- .../src/utilities/lookup_range_check.rs | 474 +++++++++--------- 2 files changed, 250 insertions(+), 250 deletions(-) diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 09a18f9c97..06bc318919 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -126,6 +126,19 @@ impl CondSwapInstructions for CondSwapChip { } } +/// 'CondSwapInstructionsOptimized' extends 'CondSwapInstructions', provides new method 'mux'. +pub trait CondSwapInstructionsOptimized: CondSwapInstructions { + /// Given an input `(choice, left, right)` where `choice` is a boolean flag, + /// returns `left` if `choice` is not set and `right` if `choice` is set. + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result; +} + impl CondSwapChip { /// Configures this chip for use in a circuit. /// @@ -195,19 +208,6 @@ impl CondSwapChip { } } -/// 'CondSwapInstructionsOptimized' extends 'CondSwapInstructions', provides new method 'mux'. -pub trait CondSwapInstructionsOptimized: CondSwapInstructions { - /// Given an input `(choice, left, right)` where `choice` is a boolean flag, - /// returns `left` if `choice` is not set and `right` if `choice` is set. - fn mux( - &self, - layouter: &mut impl Layouter, - choice: Self::Var, - left: Self::Var, - right: Self::Var, - ) -> Result; -} - impl CondSwapInstructionsOptimized for CondSwapChip { fn mux( &self, diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index e124a0ab53..2cb525f874 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -58,6 +58,243 @@ impl RangeConstrained> { } } +/// Configuration that provides methods for an efficient 4, 5, and 10-bit lookup range check. +#[derive(Eq, PartialEq, Debug, Clone, Copy)] +pub struct LookupRangeCheckConfigOptimized { + base: LookupRangeCheckConfig, + q_range_check_4: Selector, + q_range_check_5: Selector, + table_range_check_tag: TableColumn, +} + +impl LookupRangeCheckConfigOptimized { + /// The `running_sum` advice column breaks the field element into `K`-bit + /// words. It is used to construct the input expression to the lookup + /// argument. + /// + /// The `table_idx` fixed column contains values from [0..2^K). Looking up + /// a value in `table_idx` constrains it to be within this range. The table + /// can be loaded outside this helper. + /// + /// # Side-effects + /// + /// Both the `running_sum` and `constants` columns will be equality-enabled. + pub(crate) fn configure_with_tag( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + table_range_check_tag: TableColumn, + ) -> Self { + meta.enable_equality(running_sum); + + let q_lookup = meta.complex_selector(); + let q_running = meta.complex_selector(); + let q_bitshift = meta.selector(); + + let q_range_check_4 = meta.complex_selector(); + let q_range_check_5 = meta.complex_selector(); + + // if the order of the creation makes a difference + let config = LookupRangeCheckConfigOptimized { + base: LookupRangeCheckConfig { + q_lookup, + q_running, + q_bitshift, + running_sum, + table_idx, + _marker: PhantomData, + }, + q_range_check_4, + q_range_check_5, + table_range_check_tag, + }; + + // https://p.z.cash/halo2-0.1:decompose-combined-lookup + meta.lookup(|meta| { + let q_lookup = meta.query_selector(config.base.q_lookup); + let q_running = meta.query_selector(config.base.q_running); + // if the order of the creation makes a difference + let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); + let one = Expression::Constant(F::ONE); + + // In the case of a running sum decomposition, we recover the word from + // the difference of the running sums: + // z_i = 2^{K}⋅z_{i + 1} + a_i + // => a_i = z_i - 2^{K}⋅z_{i + 1} + let running_sum_lookup = { + let running_sum_word = { + let z_next = meta.query_advice(config.base.running_sum, Rotation::next()); + z_cur.clone() - z_next * F::from(1 << K) + }; + + q_running.clone() * running_sum_word + }; + + // In the short range check, the word is directly witnessed. + let short_lookup = { + let short_word = z_cur.clone(); + let q_short = one.clone() - q_running; + + q_short * short_word + }; + + let q_range_check_4 = meta.query_selector(config.q_range_check_4); + let q_range_check_5 = meta.query_selector(config.q_range_check_5); + + // q_range_check is equal to + // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 + // - 0 otherwise + let q_range_check = one.clone() + - (one.clone() - q_range_check_4.clone()) * (one.clone() - q_range_check_5.clone()); + + // num_bits is equal to + // - 5 if q_range_check_5 = 1 + // - 4 if q_range_check_4 = 1 and q_range_check_5 = 0 + // - 0 otherwise + let num_bits = q_range_check_5.clone() * Expression::Constant(F::from(5_u64)) + + (one.clone() - q_range_check_5) + * q_range_check_4 + * Expression::Constant(F::from(4_u64)); + + // Combine the running sum, short lookups and optimized range checks: + vec![ + ( + q_lookup.clone() + * ((one - q_range_check.clone()) * (running_sum_lookup + short_lookup) + + q_range_check.clone() * z_cur), + config.base.table_idx, + ), + ( + q_lookup * q_range_check * num_bits, + config.table_range_check_tag, + ), + ] + }); + + // For short lookups, check that the word has been shifted by the correct number of bits. + // https://p.z.cash/halo2-0.1:decompose-short-lookup + meta.create_gate("Short lookup bitshift", |meta| { + let q_bitshift = meta.query_selector(config.base.q_bitshift); + let word = meta.query_advice(config.base.running_sum, Rotation::prev()); + let shifted_word = meta.query_advice(config.base.running_sum, Rotation::cur()); + let inv_two_pow_s = meta.query_advice(config.base.running_sum, Rotation::next()); + + let two_pow_k = F::from(1 << K); + + // shifted_word = word * 2^{K-s} + // = word * 2^K * inv_two_pow_s + Constraints::with_selector( + q_bitshift, + Some(word * two_pow_k * inv_two_pow_s - shifted_word), + ) + }); + + config + } + + pub(crate) fn table_range_check_tag(&self) -> TableColumn { + self.table_range_check_tag + } +} + +impl LookupRangeCheck + for LookupRangeCheckConfigOptimized +{ + fn config(&self) -> &LookupRangeCheckConfig { + &self.base + } + + fn configure( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + ) -> Self { + let table_range_check_tag = meta.lookup_table_column(); + Self::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) + } + + #[cfg(test)] + // Fill `table_idx` and `table_range_check_tag`. + // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table + // in the Orchard context. + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table_idx", + |mut table| { + let mut assign_cells = + |offset: usize, table_size, value: u64| -> Result { + for index in 0..table_size { + let new_index = index + offset; + table.assign_cell( + || "table_idx", + self.base.table_idx, + new_index, + || Value::known(F::from(index as u64)), + )?; + table.assign_cell( + || "table_range_check_tag", + self.table_range_check_tag, + new_index, + || Value::known(F::from(value)), + )?; + } + Ok(offset + table_size) + }; + + // We generate the row values lazily (we only need them during keygen). + let mut offset = 0; + + //annotation: &'v (dyn Fn() -> String + 'v), + //column: TableColumn, + //offset: usize, + //to: &'v mut (dyn FnMut() -> Value> + 'v), + + offset = assign_cells(offset, 1 << K, 0)?; + offset = assign_cells(offset, 1 << 4, 4)?; + assign_cells(offset, 1 << 5, 5)?; + + Ok(()) + }, + ) + } + + /// Constrain `x` to be a NUM_BITS word. + /// + /// `element` must have been assigned to `self.running_sum` at offset 0. + fn short_range_check( + &self, + region: &mut Region<'_, F>, + element: AssignedCell, + num_bits: usize, + ) -> Result<(), Error> { + match num_bits { + 4 => { + self.base.q_lookup.enable(region, 0)?; + self.q_range_check_4.enable(region, 0)?; + Ok(()) + } + + 5 => { + self.base.q_lookup.enable(region, 0)?; + self.q_range_check_5.enable(region, 0)?; + Ok(()) + } + + _ => self.base.short_range_check(region, element, num_bits), + } + } +} + +/// In this crate, `LookupRangeCheckConfigOptimized` is always used with `pallas::Base` as the prime field +/// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, +/// we introduce this alias and use it instead of that long construction. +/// +///todo: rename PallasLookupConfig(?) and PallasLookupConfigOptimized, LookupRangeCheckConfigOptimized +pub type PallasLookupConfigOptimized = + LookupRangeCheckConfigOptimized; + +impl PallasLookupRC for PallasLookupConfigOptimized {} + /// Configuration that provides methods for a 10-bit lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] pub struct LookupRangeCheckConfig { @@ -456,243 +693,6 @@ pub type PallasLookupRCConfig = LookupRangeCheckConfig { - base: LookupRangeCheckConfig, - q_range_check_4: Selector, - q_range_check_5: Selector, - table_range_check_tag: TableColumn, -} - -impl LookupRangeCheckConfigOptimized { - /// The `running_sum` advice column breaks the field element into `K`-bit - /// words. It is used to construct the input expression to the lookup - /// argument. - /// - /// The `table_idx` fixed column contains values from [0..2^K). Looking up - /// a value in `table_idx` constrains it to be within this range. The table - /// can be loaded outside this helper. - /// - /// # Side-effects - /// - /// Both the `running_sum` and `constants` columns will be equality-enabled. - pub(crate) fn configure_with_tag( - meta: &mut ConstraintSystem, - running_sum: Column, - table_idx: TableColumn, - table_range_check_tag: TableColumn, - ) -> Self { - meta.enable_equality(running_sum); - - let q_lookup = meta.complex_selector(); - let q_running = meta.complex_selector(); - let q_bitshift = meta.selector(); - - let q_range_check_4 = meta.complex_selector(); - let q_range_check_5 = meta.complex_selector(); - - // if the order of the creation makes a difference - let config = LookupRangeCheckConfigOptimized { - base: LookupRangeCheckConfig { - q_lookup, - q_running, - q_bitshift, - running_sum, - table_idx, - _marker: PhantomData, - }, - q_range_check_4, - q_range_check_5, - table_range_check_tag, - }; - - // https://p.z.cash/halo2-0.1:decompose-combined-lookup - meta.lookup(|meta| { - let q_lookup = meta.query_selector(config.base.q_lookup); - let q_running = meta.query_selector(config.base.q_running); - // if the order of the creation makes a difference - let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); - let one = Expression::Constant(F::ONE); - - // In the case of a running sum decomposition, we recover the word from - // the difference of the running sums: - // z_i = 2^{K}⋅z_{i + 1} + a_i - // => a_i = z_i - 2^{K}⋅z_{i + 1} - let running_sum_lookup = { - let running_sum_word = { - let z_next = meta.query_advice(config.base.running_sum, Rotation::next()); - z_cur.clone() - z_next * F::from(1 << K) - }; - - q_running.clone() * running_sum_word - }; - - // In the short range check, the word is directly witnessed. - let short_lookup = { - let short_word = z_cur.clone(); - let q_short = one.clone() - q_running; - - q_short * short_word - }; - - let q_range_check_4 = meta.query_selector(config.q_range_check_4); - let q_range_check_5 = meta.query_selector(config.q_range_check_5); - - // q_range_check is equal to - // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 - // - 0 otherwise - let q_range_check = one.clone() - - (one.clone() - q_range_check_4.clone()) * (one.clone() - q_range_check_5.clone()); - - // num_bits is equal to - // - 5 if q_range_check_5 = 1 - // - 4 if q_range_check_4 = 1 and q_range_check_5 = 0 - // - 0 otherwise - let num_bits = q_range_check_5.clone() * Expression::Constant(F::from(5_u64)) - + (one.clone() - q_range_check_5) - * q_range_check_4 - * Expression::Constant(F::from(4_u64)); - - // Combine the running sum, short lookups and optimized range checks: - vec![ - ( - q_lookup.clone() - * ((one - q_range_check.clone()) * (running_sum_lookup + short_lookup) - + q_range_check.clone() * z_cur), - config.base.table_idx, - ), - ( - q_lookup * q_range_check * num_bits, - config.table_range_check_tag, - ), - ] - }); - - // For short lookups, check that the word has been shifted by the correct number of bits. - // https://p.z.cash/halo2-0.1:decompose-short-lookup - meta.create_gate("Short lookup bitshift", |meta| { - let q_bitshift = meta.query_selector(config.base.q_bitshift); - let word = meta.query_advice(config.base.running_sum, Rotation::prev()); - let shifted_word = meta.query_advice(config.base.running_sum, Rotation::cur()); - let inv_two_pow_s = meta.query_advice(config.base.running_sum, Rotation::next()); - - let two_pow_k = F::from(1 << K); - - // shifted_word = word * 2^{K-s} - // = word * 2^K * inv_two_pow_s - Constraints::with_selector( - q_bitshift, - Some(word * two_pow_k * inv_two_pow_s - shifted_word), - ) - }); - - config - } - - pub(crate) fn table_range_check_tag(&self) -> TableColumn { - self.table_range_check_tag - } -} - -impl LookupRangeCheck - for LookupRangeCheckConfigOptimized -{ - fn config(&self) -> &LookupRangeCheckConfig { - &self.base - } - - fn configure( - meta: &mut ConstraintSystem, - running_sum: Column, - table_idx: TableColumn, - ) -> Self { - let table_range_check_tag = meta.lookup_table_column(); - Self::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) - } - - #[cfg(test)] - // Fill `table_idx` and `table_range_check_tag`. - // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table - // in the Orchard context. - fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { - layouter.assign_table( - || "table_idx", - |mut table| { - let mut assign_cells = - |offset: usize, table_size, value: u64| -> Result { - for index in 0..table_size { - let new_index = index + offset; - table.assign_cell( - || "table_idx", - self.base.table_idx, - new_index, - || Value::known(F::from(index as u64)), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(F::from(value)), - )?; - } - Ok(offset + table_size) - }; - - // We generate the row values lazily (we only need them during keygen). - let mut offset = 0; - - //annotation: &'v (dyn Fn() -> String + 'v), - //column: TableColumn, - //offset: usize, - //to: &'v mut (dyn FnMut() -> Value> + 'v), - - offset = assign_cells(offset, 1 << K, 0)?; - offset = assign_cells(offset, 1 << 4, 4)?; - assign_cells(offset, 1 << 5, 5)?; - - Ok(()) - }, - ) - } - - /// Constrain `x` to be a NUM_BITS word. - /// - /// `element` must have been assigned to `self.running_sum` at offset 0. - fn short_range_check( - &self, - region: &mut Region<'_, F>, - element: AssignedCell, - num_bits: usize, - ) -> Result<(), Error> { - match num_bits { - 4 => { - self.base.q_lookup.enable(region, 0)?; - self.q_range_check_4.enable(region, 0)?; - Ok(()) - } - - 5 => { - self.base.q_lookup.enable(region, 0)?; - self.q_range_check_5.enable(region, 0)?; - Ok(()) - } - - _ => self.base.short_range_check(region, element, num_bits), - } - } -} - -/// In this crate, `LookupRangeCheckConfigOptimized` is always used with `pallas::Base` as the prime field -/// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, -/// we introduce this alias and use it instead of that long construction. -/// -///todo: rename PallasLookupConfig(?) and PallasLookupConfigOptimized, LookupRangeCheckConfigOptimized -pub type PallasLookupConfigOptimized = - LookupRangeCheckConfigOptimized; - -impl PallasLookupRC for PallasLookupConfigOptimized {} - #[cfg(test)] mod tests { use super::{LookupRangeCheck, LookupRangeCheckConfig, LookupRangeCheckConfigOptimized}; From 637abbc1a514eb2249d16fc95a06d2bf11824b74 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 12:12:33 +0200 Subject: [PATCH 074/121] re-order cond_swap --- halo2_gadgets/src/utilities/cond_swap.rs | 166 +++++++++--------- .../src/utilities/lookup_range_check.rs | 7 +- 2 files changed, 87 insertions(+), 86 deletions(-) diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 06bc318919..1db4d8d92c 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -29,6 +29,19 @@ pub trait CondSwapInstructions: UtilitiesInstructions { ) -> Result<(Self::Var, Self::Var), Error>; } +/// 'CondSwapInstructionsOptimized' extends 'CondSwapInstructions', provides new method 'mux'. +pub trait CondSwapInstructionsOptimized: CondSwapInstructions { + /// Given an input `(choice, left, right)` where `choice` is a boolean flag, + /// returns `left` if `choice` is not set and `right` if `choice` is set. + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result; +} + /// A chip implementing a conditional swap. #[derive(Clone, Debug)] pub struct CondSwapChip { @@ -126,88 +139,6 @@ impl CondSwapInstructions for CondSwapChip { } } -/// 'CondSwapInstructionsOptimized' extends 'CondSwapInstructions', provides new method 'mux'. -pub trait CondSwapInstructionsOptimized: CondSwapInstructions { - /// Given an input `(choice, left, right)` where `choice` is a boolean flag, - /// returns `left` if `choice` is not set and `right` if `choice` is set. - fn mux( - &self, - layouter: &mut impl Layouter, - choice: Self::Var, - left: Self::Var, - right: Self::Var, - ) -> Result; -} - -impl CondSwapChip { - /// Configures this chip for use in a circuit. - /// - /// # Side-effects - /// - /// `advices[0]` will be equality-enabled. - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 5], - ) -> CondSwapConfig { - let a = advices[0]; - // Only column a is used in an equality constraint directly by this chip. - meta.enable_equality(a); - - let q_swap = meta.selector(); - - let config = CondSwapConfig { - q_swap, - a, - b: advices[1], - a_swapped: advices[2], - b_swapped: advices[3], - swap: advices[4], - }; - - // TODO: optimise shape of gate for Merkle path validation - - meta.create_gate("a' = b ⋅ swap + a ⋅ (1-swap)", |meta| { - let q_swap = meta.query_selector(q_swap); - - let a = meta.query_advice(config.a, Rotation::cur()); - let b = meta.query_advice(config.b, Rotation::cur()); - let a_swapped = meta.query_advice(config.a_swapped, Rotation::cur()); - let b_swapped = meta.query_advice(config.b_swapped, Rotation::cur()); - let swap = meta.query_advice(config.swap, Rotation::cur()); - - // This checks that `a_swapped` is equal to `b` when `swap` is set, - // but remains as `a` when `swap` is not set. - let a_check = a_swapped - ternary(swap.clone(), b.clone(), a.clone()); - - // This checks that `b_swapped` is equal to `a` when `swap` is set, - // but remains as `b` when `swap` is not set. - let b_check = b_swapped - ternary(swap.clone(), a, b); - - // Check `swap` is boolean. - let bool_check = bool_check(swap); - - Constraints::with_selector( - q_swap, - [ - ("a check", a_check), - ("b check", b_check), - ("swap is bool", bool_check), - ], - ) - }); - - config - } - - /// Constructs a [`CondSwapChip`] given a [`CondSwapConfig`]. - pub fn construct(config: CondSwapConfig) -> Self { - CondSwapChip { - config, - _marker: PhantomData, - } - } -} - impl CondSwapInstructionsOptimized for CondSwapChip { fn mux( &self, @@ -265,6 +196,7 @@ impl CondSwapInstructionsOptimized for CondSwapChip { } } + impl CondSwapChip { /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are `EccPoint`, /// returns `left` if `choice` is not set and `right` if `choice` is set. @@ -300,6 +232,76 @@ impl CondSwapChip { )) } } + +impl CondSwapChip { + /// Configures this chip for use in a circuit. + /// + /// # Side-effects + /// + /// `advices[0]` will be equality-enabled. + pub fn configure( + meta: &mut ConstraintSystem, + advices: [Column; 5], + ) -> CondSwapConfig { + let a = advices[0]; + // Only column a is used in an equality constraint directly by this chip. + meta.enable_equality(a); + + let q_swap = meta.selector(); + + let config = CondSwapConfig { + q_swap, + a, + b: advices[1], + a_swapped: advices[2], + b_swapped: advices[3], + swap: advices[4], + }; + + // TODO: optimise shape of gate for Merkle path validation + + meta.create_gate("a' = b ⋅ swap + a ⋅ (1-swap)", |meta| { + let q_swap = meta.query_selector(q_swap); + + let a = meta.query_advice(config.a, Rotation::cur()); + let b = meta.query_advice(config.b, Rotation::cur()); + let a_swapped = meta.query_advice(config.a_swapped, Rotation::cur()); + let b_swapped = meta.query_advice(config.b_swapped, Rotation::cur()); + let swap = meta.query_advice(config.swap, Rotation::cur()); + + // This checks that `a_swapped` is equal to `b` when `swap` is set, + // but remains as `a` when `swap` is not set. + let a_check = a_swapped - ternary(swap.clone(), b.clone(), a.clone()); + + // This checks that `b_swapped` is equal to `a` when `swap` is set, + // but remains as `b` when `swap` is not set. + let b_check = b_swapped - ternary(swap.clone(), a, b); + + // Check `swap` is boolean. + let bool_check = bool_check(swap); + + Constraints::with_selector( + q_swap, + [ + ("a check", a_check), + ("b check", b_check), + ("swap is bool", bool_check), + ], + ) + }); + + config + } + + /// Constructs a [`CondSwapChip`] given a [`CondSwapConfig`]. + pub fn construct(config: CondSwapConfig) -> Self { + CondSwapChip { + config, + _marker: PhantomData, + } + } +} + #[cfg(test)] mod tests { use super::super::UtilitiesInstructions; diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 2cb525f874..71c7da3641 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -113,7 +113,9 @@ impl LookupRangeCheckConfigOptimized { meta.lookup(|meta| { let q_lookup = meta.query_selector(config.base.q_lookup); let q_running = meta.query_selector(config.base.q_running); - // if the order of the creation makes a difference + let q_range_check_4 = meta.query_selector(config.q_range_check_4); + let q_range_check_5 = meta.query_selector(config.q_range_check_5); + let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); let one = Expression::Constant(F::ONE); @@ -138,9 +140,6 @@ impl LookupRangeCheckConfigOptimized { q_short * short_word }; - let q_range_check_4 = meta.query_selector(config.q_range_check_4); - let q_range_check_5 = meta.query_selector(config.q_range_check_5); - // q_range_check is equal to // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 // - 0 otherwise From 9cef0b0d6f22e3ebecbd3dd8cc08a1f8373ecb1b Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 12:27:21 +0200 Subject: [PATCH 075/121] remove crate for configure_with_tag --- halo2_gadgets/src/utilities/cond_swap.rs | 1 - halo2_gadgets/src/utilities/lookup_range_check.rs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 1db4d8d92c..17c144eb5b 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -196,7 +196,6 @@ impl CondSwapInstructionsOptimized for CondSwapChip { } } - impl CondSwapChip { /// Given an input `(choice, left, right)` where `choice` is a boolean flag and `left` and `right` are `EccPoint`, /// returns `left` if `choice` is not set and `right` if `choice` is set. diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 71c7da3641..a1d9b41ad7 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -79,7 +79,7 @@ impl LookupRangeCheckConfigOptimized { /// # Side-effects /// /// Both the `running_sum` and `constants` columns will be equality-enabled. - pub(crate) fn configure_with_tag( + pub fn configure_with_tag( meta: &mut ConstraintSystem, running_sum: Column, table_idx: TableColumn, @@ -90,7 +90,6 @@ impl LookupRangeCheckConfigOptimized { let q_lookup = meta.complex_selector(); let q_running = meta.complex_selector(); let q_bitshift = meta.selector(); - let q_range_check_4 = meta.complex_selector(); let q_range_check_5 = meta.complex_selector(); From f69907b7416acece9a767e5c57a5e7df05837d5a Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 13:36:41 +0200 Subject: [PATCH 076/121] lookup tests update --- halo2_gadgets/src/utilities/lookup_range_check.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index a1d9b41ad7..bfc270045a 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -994,10 +994,11 @@ mod tests { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let running_sum = meta.advice_column(); let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let constants = meta.fixed_column(); meta.enable_constant(constants); - LookupRangeCheckConfigOptimized::::configure(meta, running_sum, table_idx) + LookupRangeCheckConfigOptimized::::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) } fn synthesize( @@ -1093,10 +1094,11 @@ mod tests { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let running_sum = meta.advice_column(); let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let constants = meta.fixed_column(); meta.enable_constant(constants); - LookupRangeCheckConfigOptimized::::configure(meta, running_sum, table_idx) + LookupRangeCheckConfigOptimized::::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) } fn synthesize( From 9b4c51ff017b5514e6580899851a8c96f6ee2779 Mon Sep 17 00:00:00 2001 From: YaoGalteland Date: Tue, 4 Jun 2024 15:10:27 +0200 Subject: [PATCH 077/121] change sinsemillachip to sinsemillachipOptimized --- halo2_gadgets/src/sinsemilla.rs | 8 ++++---- halo2_gadgets/src/utilities/lookup_range_check.rs | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 2f163bd7d2..6b3ef9ae96 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -983,7 +983,7 @@ pub(crate) mod tests { LookupRangeCheckConfigOptimized, >::configure(meta, advices, lagrange_coeffs, range_check); - let config1 = SinsemillaChip::configure( + let config1 = SinsemillaChipOptimized::configure( meta, advices[..5].try_into().unwrap(), advices[2], @@ -991,7 +991,7 @@ pub(crate) mod tests { lookup, range_check, ); - let config2 = SinsemillaChip::configure( + let config2 = SinsemillaChipOptimized::configure( meta, advices[5..].try_into().unwrap(), advices[7], @@ -1020,7 +1020,7 @@ pub(crate) mod tests { // This MerkleCRH example is purely for illustrative purposes. // It is not an implementation of the Orchard protocol spec. { - let chip1 = SinsemillaChip::construct(config.1); + let chip1 = SinsemillaChipOptimized::construct(config.1); let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); @@ -1092,7 +1092,7 @@ pub(crate) mod tests { } { - let chip2 = SinsemillaChip::construct(config.2); + let chip2 = SinsemillaChipOptimized::construct(config.2); let test_commit = CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index bfc270045a..effdc14939 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -998,7 +998,12 @@ mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - LookupRangeCheckConfigOptimized::::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) + LookupRangeCheckConfigOptimized::::configure_with_tag( + meta, + running_sum, + table_idx, + table_range_check_tag, + ) } fn synthesize( @@ -1098,7 +1103,12 @@ mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - LookupRangeCheckConfigOptimized::::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) + LookupRangeCheckConfigOptimized::::configure_with_tag( + meta, + running_sum, + table_idx, + table_range_check_tag, + ) } fn synthesize( From 2069bd11482656303f581ffa191c26d5cf5c37db Mon Sep 17 00:00:00 2001 From: Constance Date: Tue, 11 Jun 2024 20:52:47 +0200 Subject: [PATCH 078/121] Cleanup code and some renamings --- halo2_gadgets/src/ecc/chip/mul.rs | 3 +- .../src/sinsemilla/chip/hash_to_point.rs | 11 ++-- halo2_gadgets/src/sinsemilla/merkle.rs | 1 + halo2_gadgets/src/tests/test_utils.rs | 65 ++++++++----------- 4 files changed, 36 insertions(+), 44 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 6ce49aaa35..9cf8391dc5 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -467,14 +467,13 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::PallasLookupRC; use crate::{ ecc::{ chip::{EccChip, EccPoint}, tests::TestFixedBases, EccInstructions, NonIdentityPoint, Point, ScalarVar, }, - utilities::UtilitiesInstructions, + utilities::{lookup_range_check::PallasLookupRC, UtilitiesInstructions}, }; pub(crate) fn test_mul( diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 06b7fbb3b3..34c4253110 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -17,7 +17,7 @@ use pasta_curves::{arithmetic::CurveAffine, pallas}; use std::ops::Deref; -/// Define an enum that can hold either type +/// Define an enum that can hold either a public or a private ECC Point #[derive(Debug, Clone)] #[allow(dead_code)] pub enum EccPointQ<'a> { @@ -214,7 +214,7 @@ where ), Error, > { - let (offset, x_a, y_a) = self.public_initialization(region, Q)?; + let (offset, x_a, y_a) = self.public_q_initialization(region, Q)?; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; @@ -296,13 +296,14 @@ where } #[allow(non_snake_case)] - /// Assign the coordinates of the initial public point `Q`, - /// y_Q to a fixed column + /// Assign the coordinates of the initial public point `Q` + /// - `x_Q` in a advice column, and + /// - `y_Q` in a fixed column. /// /// | offset | x_A | q_sinsemilla4 | fixed_y_q | /// -------------------------------------- /// | 0 | x_Q | 1 | y_Q | - fn public_initialization( + fn public_q_initialization( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index dcca5aaa2d..7d6f3e2ca1 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -364,6 +364,7 @@ pub mod tests { Ok(()) } } + fn generate_circuit() -> MyCircuit { let mut rng = OsRng; diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index ed73cc3c17..085f695f08 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -1,9 +1,6 @@ -//! functions used for circuit test +//! Functions used for circuit test. -use std::{ - env, fs, - path::{Path, PathBuf}, -}; +use std::{env, fs, path::Path}; use rand::rngs::OsRng; @@ -33,14 +30,14 @@ impl AsRef<[u8]> for Proof { } impl Proof { - /// Creates a proof for the given circuits and instances. + /// Creates a proof for the given circuit and instances. pub fn create( vk: &VerifyingKey, params: &Params, circuit: C, ) -> Result - where - C: Circuit, + where + C: Circuit, { let pk = plonk::keygen_pk(params, vk.clone(), &circuit).unwrap(); @@ -69,8 +66,10 @@ impl Proof { } /// Test the generated vk against the stored vk. +/// +/// If the env variable GEN_ENV_VAR is set, save `vk` into a file. pub(crate) fn test_against_stored_vk>(circuit: &C, circuit_name: &str) { - let full_file_name = Path::new(TEST_DATA_DIR) + let file_path = Path::new(TEST_DATA_DIR) .join(format!("vk_{circuit_name}")) .with_extension("rdata"); @@ -81,39 +80,26 @@ pub(crate) fn test_against_stored_vk>(circuit: &C, circ let vk_text = format!("{:#?}\n", vk.pinned()); if env::var_os(GEN_ENV_VAR).is_some() { - fs::write(&full_file_name, &vk_text).expect("Unable to write vk test file") - } - - assert_eq!( - vk_text, - fs::read_to_string(full_file_name) - .expect("Unable to read vk test file") - .replace("\r\n", "\n") - ); -} - -/// If the env variable GEN_ENV_VAR is set, write the `Proof` to a file -fn conditionally_save_proof_to_disk>( - vk: &VerifyingKey, - params: &Params, - circuit: C, - full_file_name: &PathBuf, -) { - if env::var_os(GEN_ENV_VAR).is_some() { - let proof = Proof::create(vk, params, circuit).unwrap(); - assert!(proof.verify(vk, params).is_ok()); - - fs::write(full_file_name, proof.as_ref()).expect("Unable to write proof test file"); + fs::write(&file_path, &vk_text).expect("Unable to write vk test file"); + } else { + assert_eq!( + vk_text, + fs::read_to_string(file_path) + .expect("Unable to read vk test file") + .replace("\r\n", "\n") + ); } } /// Test the generated circuit against the stored proof. +/// +/// If the env variable GEN_ENV_VAR is set, save `vk` into a file. pub(crate) fn test_against_stored_proof>( circuit: C, circuit_name: &str, index: usize, ) { - let full_file_name = Path::new(TEST_DATA_DIR) + let file_path = Path::new(TEST_DATA_DIR) .join(format!("proof_{circuit_name}_{index}")) .with_extension("bin"); @@ -121,10 +107,15 @@ pub(crate) fn test_against_stored_proof>( let params: Params = Params::new(11); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - conditionally_save_proof_to_disk(&vk, ¶ms, circuit, &full_file_name); - - // Read the proof from storage - let proof = Proof::new(fs::read(full_file_name).expect("Unable to read proof test file")); + let proof = if env::var_os(GEN_ENV_VAR).is_some() { + // Create the proof and save it into a file + let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); + fs::write(&file_path, proof.as_ref()).expect("Unable to write proof test file"); + proof + } else { + // Read the proof from storage + Proof::new(fs::read(file_path).expect("Unable to read proof test file")) + }; // Verify the stored proof with the generated vk assert!(proof.verify(&vk, ¶ms).is_ok()); From 1a2141395a1f4011d4551c9a80d51d63635cf551 Mon Sep 17 00:00:00 2001 From: Constance Date: Tue, 11 Jun 2024 21:01:21 +0200 Subject: [PATCH 079/121] rust fmt --- halo2_gadgets/src/tests/test_utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index 085f695f08..33ad75670f 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -36,8 +36,8 @@ impl Proof { params: &Params, circuit: C, ) -> Result - where - C: Circuit, + where + C: Circuit, { let pk = plonk::keygen_pk(params, vk.clone(), &circuit).unwrap(); From de562019455e9bae842fd40fdaedad02384033aa Mon Sep 17 00:00:00 2001 From: Constance Date: Fri, 14 Jun 2024 09:40:06 +0200 Subject: [PATCH 080/121] Remove EccInstructionsOptimized --- halo2_gadgets/src/ecc.rs | 91 +++++++++++++++++------------------ halo2_gadgets/src/ecc/chip.rs | 54 +++++++++------------ 2 files changed, 66 insertions(+), 79 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 0dbce3df68..5cd4d78be9 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -145,6 +145,24 @@ pub trait EccInstructions: base_field_elem: Self::Var, base: &>::Base, ) -> Result; + + /// Witnesses the given constant point as a private input to the circuit. + /// This allows the point to be the identity, mapped to (0, 0) in + /// affine coordinates. + fn witness_point_from_constant( + &self, + layouter: &mut impl Layouter, + value: C, + ) -> Result; + + /// Performs variable-base sign-scalar multiplication, returning `[sign] point` + /// `sign` must be in {-1, 1}. + fn mul_sign( + &self, + layouter: &mut impl Layouter, + sign: &AssignedCell, + point: &Self::Point, + ) -> Result; } /// Instructions that can be implemented for a curve whose base field fits into @@ -432,6 +450,31 @@ impl + Clone + Debug + Eq> Point, + value: C, + ) -> Result { + let point = chip.witness_point_from_constant(&mut layouter, value); + point.map(|inner| Point { chip, inner }) + } + + /// Returns `[sign] self`. + /// `sign` must be in {-1, 1}. + pub fn mul_sign( + &self, + mut layouter: impl Layouter, + sign: &AssignedCell, + ) -> Result, Error> { + self.chip + .mul_sign(&mut layouter, sign, &self.inner) + .map(|point| Point { + chip: self.chip.clone(), + inner: point, + }) + } } /// The affine short Weierstrass x-coordinate of a point on a specific elliptic curve. @@ -575,54 +618,6 @@ impl> FixedPointShort { } } -/// 'EccInstructionsOptimized' trait is an extension of the `EccInstructions` trait, -/// designed to enhance performance in specific cryptographic scenarios. -pub trait EccInstructionsOptimized: EccInstructions { - /// Witnesses the given constant point as a private input to the circuit. - /// This allows the point to be the identity, mapped to (0, 0) in - /// affine coordinates. - fn witness_point_from_constant( - &self, - layouter: &mut impl Layouter, - value: C, - ) -> Result; - - /// Performs variable-base sign-scalar multiplication, returning `[sign] point` - /// `sign` must be in {-1, 1}. - fn mul_sign( - &self, - layouter: &mut impl Layouter, - sign: &AssignedCell, - point: &Self::Point, - ) -> Result; -} - -impl + Clone + Debug + Eq> Point { - /// Constructs a new point with the given fixed value. - pub fn new_from_constant( - chip: EccChip, - mut layouter: impl Layouter, - value: C, - ) -> Result { - let point = chip.witness_point_from_constant(&mut layouter, value); - point.map(|inner| Point { chip, inner }) - } - - /// Returns `[sign] self`. - /// `sign` must be in {-1, 1}. - pub fn mul_sign( - &self, - mut layouter: impl Layouter, - sign: &AssignedCell, - ) -> Result, Error> { - self.chip - .mul_sign(&mut layouter, sign, &self.inner) - .map(|point| Point { - chip: self.chip.clone(), - inner: point, - }) - } -} #[cfg(test)] pub(crate) mod tests { use ff::PrimeField; diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 34186c4a49..704abdc76a 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -1,6 +1,6 @@ //! Chip implementations for the ECC gadgets. -use super::{BaseFitsInScalarInstructions, EccInstructions, EccInstructionsOptimized, FixedPoints}; +use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; use crate::utilities::{ lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, UtilitiesInstructions, @@ -604,37 +604,10 @@ where base, ) } -} - -impl, Lookup: PallasLookupRC> - BaseFitsInScalarInstructions for EccChip -where - >::Base: - FixedPoint, - >::FullScalar: - FixedPoint, - >::ShortScalar: - FixedPoint, -{ - fn scalar_var_from_base( - &self, - _layouter: &mut impl Layouter, - base: &Self::Var, - ) -> Result { - Ok(ScalarVar::BaseFieldElem(base.clone())) - } -} -impl, Lookup: PallasLookupRC> - EccInstructionsOptimized for EccChip -where - >::Base: - FixedPoint, - >::FullScalar: - FixedPoint, - >::ShortScalar: - FixedPoint, -{ + /// Witnesses the given constant point as a private input to the circuit. + /// This allows the point to be the identity, mapped to (0, 0) in + /// affine coordinates. fn witness_point_from_constant( &self, layouter: &mut impl Layouter, @@ -665,3 +638,22 @@ where ) } } + +impl, Lookup: PallasLookupRC> + BaseFitsInScalarInstructions for EccChip +where + >::Base: + FixedPoint, + >::FullScalar: + FixedPoint, + >::ShortScalar: + FixedPoint, +{ + fn scalar_var_from_base( + &self, + _layouter: &mut impl Layouter, + base: &Self::Var, + ) -> Result { + Ok(ScalarVar::BaseFieldElem(base.clone())) + } +} From 52e6fbb90c18b25eb690235f54d52d1805f03617 Mon Sep 17 00:00:00 2001 From: Constance Date: Fri, 14 Jun 2024 10:07:19 +0200 Subject: [PATCH 081/121] Remove dead_code flag on EccPointQ --- halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 34c4253110..03dc204f1e 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -19,7 +19,6 @@ use std::ops::Deref; /// Define an enum that can hold either a public or a private ECC Point #[derive(Debug, Clone)] -#[allow(dead_code)] pub enum EccPointQ<'a> { PublicPoint(pallas::Affine), PrivatePoint(&'a NonIdentityEccPoint), From 8d13e7a29bc6ac47a82d89f58b218169c55b2131 Mon Sep 17 00:00:00 2001 From: Constance Date: Fri, 14 Jun 2024 10:16:37 +0200 Subject: [PATCH 082/121] Remove CondSwapInstructionsOptimized --- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 27 +++++++++++---------- halo2_gadgets/src/utilities/cond_swap.rs | 5 ---- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 7df70b5eb4..3b5d1d839c 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -9,19 +9,16 @@ use pasta_curves::pallas; use super::MerkleInstructions; -use crate::sinsemilla::chip::SinsemillaChipOptimized; -use crate::utilities::cond_swap::CondSwapInstructionsOptimized; -use crate::utilities::lookup_range_check::PallasLookupConfigOptimized; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, utilities::{ - lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, + lookup_range_check::{PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig}, RangeConstrained, }, { ecc::FixedPoints, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, + chip::{SinsemillaChip, SinsemillaChipOptimized, SinsemillaConfig}, CommitDomains, HashDomains, SinsemillaInstructions, }, utilities::{ @@ -503,6 +500,18 @@ where let chip = CondSwapChip::::construct(config); chip.swap(layouter, pair, swap) } + + fn mux( + &self, + layouter: &mut impl Layouter, + choice: Self::Var, + left: Self::Var, + right: Self::Var, + ) -> Result { + let config = self.config().cond_swap_config.clone(); + let chip = CondSwapChip::::construct(config); + chip.mux(layouter, choice, left, right) + } } impl @@ -676,15 +685,7 @@ where ) -> Result<(Self::Var, Self::Var), Error> { self.base.swap(layouter, pair, swap) } -} -impl CondSwapInstructionsOptimized - for MerkleChipOptimized -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, -{ fn mux( &self, layouter: &mut impl Layouter, diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 17c144eb5b..ebc18ea77d 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -27,10 +27,7 @@ pub trait CondSwapInstructions: UtilitiesInstructions { pair: (Self::Var, Value), swap: Value, ) -> Result<(Self::Var, Self::Var), Error>; -} -/// 'CondSwapInstructionsOptimized' extends 'CondSwapInstructions', provides new method 'mux'. -pub trait CondSwapInstructionsOptimized: CondSwapInstructions { /// Given an input `(choice, left, right)` where `choice` is a boolean flag, /// returns `left` if `choice` is not set and `right` if `choice` is set. fn mux( @@ -137,9 +134,7 @@ impl CondSwapInstructions for CondSwapChip { }, ) } -} -impl CondSwapInstructionsOptimized for CondSwapChip { fn mux( &self, layouter: &mut impl Layouter, From 36a9319487008110aa5f49706917377e405c26c2 Mon Sep 17 00:00:00 2001 From: Constance Date: Mon, 17 Jun 2024 11:01:25 +0200 Subject: [PATCH 083/121] Clean imports --- halo2_gadgets/src/ecc.rs | 9 +++++---- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 3 +-- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 6 ++++-- halo2_gadgets/src/sinsemilla.rs | 11 +++++++---- halo2_gadgets/src/sinsemilla/chip.rs | 5 +++-- halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs | 2 +- halo2_gadgets/src/utilities/cond_swap.rs | 3 +-- halo2_gadgets/src/utilities/lookup_range_check.rs | 11 +++++++---- 8 files changed, 29 insertions(+), 21 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 5cd4d78be9..a2a7ec5602 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -638,10 +638,11 @@ pub(crate) mod tests { }, FixedPoints, }; - use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, - utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, + utilities::lookup_range_check::{ + LookupRangeCheck, LookupRangeCheckConfigOptimized, PallasLookupRCConfig, + }, }; #[derive(Debug, Eq, PartialEq, Clone)] @@ -987,7 +988,7 @@ pub(crate) mod tests { #[allow(non_snake_case)] impl Circuit for MyCircuit45B { type Config = EccConfig< - crate::ecc::tests::TestFixedBases, + TestFixedBases, LookupRangeCheckConfigOptimized, >; type FloorPlanner = SimpleFloorPlanner; @@ -1032,7 +1033,7 @@ pub(crate) mod tests { table_range_check_tag, ); EccChip::< - crate::ecc::tests::TestFixedBases, + TestFixedBases, LookupRangeCheckConfigOptimized, >::configure(meta, advices, lagrange_coeffs, range_check) } diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index e6060ec426..a4a6ee08df 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -389,14 +389,13 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::utilities::lookup_range_check::PallasLookupRC; use crate::{ ecc::{ chip::{EccChip, FixedPoint, H}, tests::{BaseField, TestFixedBases}, FixedPointBaseField, NonIdentityPoint, Point, }, - utilities::UtilitiesInstructions, + utilities::{lookup_range_check::PallasLookupRC, UtilitiesInstructions}, }; pub(crate) fn test_mul_fixed_base_field( diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index b84c21ea25..4dfda94b7e 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -315,7 +315,6 @@ pub mod tests { }; use pasta_curves::pallas; - use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use crate::{ ecc::{ chip::{EccChip, FixedPoint, MagnitudeSign}, @@ -323,7 +322,10 @@ pub mod tests { FixedPointShort, NonIdentityPoint, Point, ScalarFixedShort, }, utilities::{ - lookup_range_check::{LookupRangeCheck, PallasLookupRC, PallasLookupRCConfig}, + lookup_range_check::{ + LookupRangeCheck, LookupRangeCheckConfigOptimized, PallasLookupRC, + PallasLookupRCConfig, + }, UtilitiesInstructions, }, }; diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 6b3ef9ae96..d301d6a55d 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -593,17 +593,20 @@ pub(crate) mod tests { tests::{FullWidth, TestFixedBases}, NonIdentityPoint, ScalarFixed, }, - sinsemilla::primitives::{self as sinsemilla, K}, + sinsemilla::{ + chip::SinsemillaChipOptimized, + primitives::{self as sinsemilla, K}, + }, tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, - utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, + utilities::lookup_range_check::{ + LookupRangeCheck, LookupRangeCheckConfigOptimized, PallasLookupRCConfig, + }, }; use group::{ff::Field, Curve}; use lazy_static::lazy_static; use pasta_curves::pallas; - use crate::sinsemilla::chip::SinsemillaChipOptimized; - use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use std::convert::TryInto; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 6e2a54edef..41214f2d22 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -10,7 +10,9 @@ use crate::{ chip::{DoubleAndAdd, NonIdentityEccPoint}, FixedPoints, }, - utilities::lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, + utilities::lookup_range_check::{ + PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig, + }, }; use std::marker::PhantomData; @@ -25,7 +27,6 @@ use halo2_proofs::{ use pasta_curves::pallas; mod generator_table; -use crate::utilities::lookup_range_check::PallasLookupConfigOptimized; use generator_table::GeneratorTableConfig; mod hash_to_point; diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 03dc204f1e..ef30a4e9d6 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -1,7 +1,7 @@ use super::super::{CommitDomains, HashDomains, SinsemillaInstructions}; -use super::{NonIdentityEccPoint, SinsemillaChip, SinsemillaChipOptimized}; use crate::{ ecc::FixedPoints, + sinsemilla::chip::{NonIdentityEccPoint, SinsemillaChip, SinsemillaChipOptimized}, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, utilities::lookup_range_check::PallasLookupRC, }; diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index ebc18ea77d..ced0b9a296 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -411,8 +411,7 @@ mod tests { dev::MockProver, plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, }; - use pasta_curves::arithmetic::CurveAffine; - use pasta_curves::{pallas, EpAffine}; + use pasta_curves::{arithmetic::CurveAffine, pallas, EpAffine}; use rand::rngs::OsRng; diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index effdc14939..4afbabb624 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -693,10 +693,7 @@ impl PallasLookupRC for PallasLookupRCConfig {} #[cfg(test)] mod tests { - use super::{LookupRangeCheck, LookupRangeCheckConfig, LookupRangeCheckConfigOptimized}; - use super::super::lebs2ip; - use crate::sinsemilla::primitives::K; use ff::{Field, PrimeFieldBits}; use halo2_proofs::{ @@ -706,7 +703,13 @@ mod tests { }; use pasta_curves::pallas; - use crate::tests::test_utils::{test_against_stored_proof, test_against_stored_vk}; + use crate::{ + sinsemilla::primitives::K, + tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, + utilities::lookup_range_check::{ + LookupRangeCheck, LookupRangeCheckConfig, LookupRangeCheckConfigOptimized, + }, + }; use std::{convert::TryInto, marker::PhantomData}; #[test] From 6cab338f0c9074cc8f6421d11538182e6a45d9d6 Mon Sep 17 00:00:00 2001 From: Constance Date: Tue, 18 Jun 2024 09:18:19 +0200 Subject: [PATCH 084/121] Remove redundancy in lookup_range_check tests --- .../proof_lookup_range_check_4_5_b_0.bin | Bin 0 -> 2048 bytes .../proof_short_range_check_4_5_b_case0_0.bin | Bin 0 -> 2048 bytes .../proof_short_range_check_4_5_b_case1_0.bin | Bin 0 -> 2048 bytes .../proof_short_range_check_4_5_b_case2_0.bin | Bin 0 -> 2048 bytes .../proof_short_range_check_4_5_b_case3_0.bin | Bin 0 -> 2048 bytes .../vk_lookup_range_check_4_5_b.rdata | 465 +++++++++ .../vk_short_range_check_4_5_b_case0.rdata | 465 +++++++++ .../vk_short_range_check_4_5_b_case1.rdata | 465 +++++++++ .../vk_short_range_check_4_5_b_case2.rdata | 465 +++++++++ .../vk_short_range_check_4_5_b_case3.rdata | 465 +++++++++ .../src/utilities/lookup_range_check.rs | 905 +++++++++--------- 11 files changed, 2752 insertions(+), 478 deletions(-) create mode 100644 halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata create mode 100644 halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata create mode 100644 halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata create mode 100644 halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata create mode 100644 halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b_0.bin new file mode 100644 index 0000000000000000000000000000000000000000..976409570e71c45d7f67e95a087372b6455a8f9b GIT binary patch literal 2048 zcmbu(`6Ckw0KoBOLc&~I$=b{v!W?Ot+uU+gtPn-6iG=m07<1%q_DJNIYmTCa-q1`V z7517VM?{XK$nspxwY)!}AKv%Z&oAEx$wkbpO){r6PK8C8)6~)gmHYaHi4`|-;Mhdt z>xfSO^i|nmG5x1UM~BcL!e=aZ!58xJ$bQ2&!+>JzBzSQA8WiAxr$M*&pE_diNArG8 zdl)=#!^6&Gp7j_8s1imVp88=~8Q7>3#3#TRjl62c(h-MON>6O@`&*adtH$laQ#b}j zQiDQ8^PaS>6o`eMF8h+Oab)OW*TCW&lY3bko5{pdhp(-VZqHCk9B4QS^QT_=S2Ch2 z{i#Ir(YVa3W>y-Q@fHQjBl=%)F^%`I7N1YDaON6txpT)fYnsS=wGKWHuCBVEscp3) zNyS|5>8rcN@_gE-5<1i%@3HPQULm5jj%_%w#|)D6gtRN)wVN0ZHk-zr&7~Jew~#8M zeNKT3Zp2kRzcr?u_pi3344z8B*9#B+#6CAEZWJzY;Q$SrU5z)_kx^;tLNFsTxQRz? zSRBLQBHc-$TFMvxq*x1dz#Y+%a>~&4jR52ozV23k)Y_Kw0Dz&5anE64aYDp-nxgo! zmK893<3PYRDcN6DZFZf#TaUhZ@S*Nx%r)YrVTqj{sh<-8IlBwNqC5JRuzYBnn*zIr zqC`SPjRsphMhN`r_g3~-#bP5 z*_AcW4BqB@CBSbwsuu#x4!aiveYRO*S@h54-alAHFZbub0a}?whi6L!oKKMehl5IHJt z9?~!MJO9nz|K=HiJ0bwmi?t2vy6K4wwqRb_jP3BNJ7WK)qkF8sl1yjkb;A~Ed{9-- z#5k{HQe9kn%8QZP$DYK#Ll^C#R`*dN zat0ys=O&sho73McGyL>yb$_@!F;~$~>Ic3(pDfDAmYL)#e(i{si>?aj;>U2j>4{W& zb)ALZHA^d+fAppw#L-#}+GXFN&Ga7W9fZv$1e=+=ycahSL&K})+w)R1_Jby<`qz2R z*^-*v3e++ng9O9|g?eqD`LuMGa~yOy9C_Yu8(a*3f5_5B`;eSRv)sZKw88B7x9uG} zXXqmd73Ym_UwZIvCtO%7`pu>xF*Gn|@2p{X%epZ>h9ob>Y4i75jTTbpd7t6Otz3tX zg70okDmZ0PF>Qo^ZiM0yTMR0>8ux^Gkkwu^5}~2cg-l3H5n0yT-RxLXkur%)trrmh zzj|hPt50w#PX%VFcE`9A8s)Pbu+rdDMg#kQ`T{RKzHg?>fBmZ(R#&;#Pl26_-}TsIaG;7Tr=dvy)Z4e-P8UUUf{y9f zOPNS+qizmiD(Q5Q;FRXFLSAkbO21#?t2YRqS7S`ZswV{06l!wKSgs)-1~H-TV#9@9OQ(TZp)grWF$Lr_dC-e5pV* z>ap*Ts^v}X`lzr@4rgh2;Zd$vo38`-B}G&Qp3QSn+fid3R1^-8t+2{wO%U?H!`*Mwq8!qNr1MN-9PhgBEn_F1Zhi kSQ`Wt?AMGvNYB}}#c19Vlb*#H0l literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0_0.bin new file mode 100644 index 0000000000000000000000000000000000000000..9b160e77ba5b4056841c9a0cc2712ba3ad239e00 GIT binary patch literal 2048 zcmcJ+i9Ztz0{~#Rks~d~nry@zb4F;6k$bK!cdnc-OiSA5UI)E~b*^IzTWsd56dArI4$%R^@SqQJhCt;>ARy)xb?&PyIs zYF_pXS%xV~p*NO8f;JaLM{Qphq!Vww%k&d4wX@Hu|0rSo)?rF7WV)usnQzgPU1_JU z#vMrb-BG29|J43$?%cf^D6UfcVj_aWwiBL72p7Cr1oSa!3;m2wAVa(_-Kd^-v@+ER zRJk15pZa6P(QTY-qRkbz47^ifx5AX}{>l-FKc$o#Y0N!hgqmX8na%p&&6cB>%npG7 zVS{z3BC>s(p}$O_8&>NL)(R8bTy3hm3ZHZ%i{FR!`TU7x9dHZ_Awtw^Q35Ba0fh$+ zs@YPAaE66O6z|4}>w&EzDRf>6XR>fE__XtU&@cWAc0yuM(-%9mp$ar>lEo(i^&SAU z!uaiN0mHFlp;wImBTS~u4%R2?m(c_jUz8#JoBR+U(#p%ASt4ma3xlVx@eHp)9Xg0b zL#6hoAWc0AW5_!zTI{nH`K;eOKeFWvt)hjA6q;VnmjcJg>^V4jQ)yZUp>DoY*Tg{f z?Zy_LX#G3H8K)LED63&Zijg6A!ixLP1UQKxsGALY!vkHheWQytZY}cXNCb}vA3Z^W zR-H?*WF=NzPr#yzayO^?%9-xkTX$ru2)`x=M!dC6y;;mG369y2bB?o4%=3x3W8VHk z7z>faelem?ByQY(@KAeXADo%ADcS>dt~)psRWLLN;(^1g|6U55dor{uPTA|1Ax2Hq zc2K>~ywp*tw*IN}*haOxFQR~*1epui30{{u)KEx>{i1$p2Qsz2l995(S~98#{h+jc zbFU+@j~@i|Sn!Jr>dX*Y%B$xEE$cm@lY_YWvGpQW zD=)AQzKL;H5n6xA+zv$vpRb=v)U!!m4B}=>tv+|RZ@7|50CsDE=@L}s${eR1*C>22 z#G~5qpNi3D@AcaQph_pPSa_=riXV$?KN7r2&{noKF(<^@Q;Jq)jCj85SjuU=5jTcK zCh%Y)jxJoolqoQY{Flz}VWfOg$CU~JK909a-{*3bqyiN%X8pd8Lv@sjP{uN&(WBXM zeXTgCn2=rShCHutyTc$d*-EcwUDYt1B`bE}=)JoKCnT*s zV-;GZ=r2k>aW>>vaJjw!GY~R4KC3#pkW9vjfd{i@m!BZqc8Q+0rK$|7=j4-p|* z0U3c61Mc`~KaHkbb`61umn!2h#?A33YJhQc*J-QH%o&hD*^rUziYliPZ3Acm)mIoSr_NJfKwnP~DKGA~{CvExMU z=~U%~R!p%t-_L_L+Ai&yOe0!Xrf7Uq0rw0S^-!A2B;o|A(}TqDEGoeLRIr0lK&iJUHb&YOj8cnusNyI6?OvlwML>y~T#_bw*3}&+Almt=-9{zp zv^+yn(DO0YA}`yra_ob4#4P!&jj>?KG+0vzW+q2pJJM`#r@|VXeO(a z`l(_Naa+ZH(zRfGRJK3bsQ+mg9U)R@jngWuU{V=23op`pM0Z(<{JT%`x@qOt+ICLT zbaDW3KcO`i<@ZGzKn1xp>poKrDHEhVGVlx5uffZ+)?U13ztk#iPLvxqHrTOEa;XG$ z{nT&+ofrp}$q&XD1p9i=v`E!c9GbpsZl0#(dKKNBX2;%& z4tKk!o?GZ1I897PW4%mVgBeAevC3EBF@f#2!iq}1ynyszX!)8>WD-1}=R9f6|9hLu zpo394H6^hA^|GC4^{9j--y}KMjMe)PnVA2VTXWFn@J`2Y!~g{Mu!ynZb_F zT{BZBfK&2a!I}026ggzt5-7l8VwPE@1W6RRnC@1L3BVnb#67+}0n#pbpF^4SdEGAW zt(yC|e<1QG*Re>zBX~E{VthRXn!s2?HTKYpT%MYJi;#U0_UU~nkzc>lb^3-+B=b>y zE}jD2dQ|oKYLmEZo73>;h!6A!)-#{-wLRpAnu4)0p|}h4o4PsINMvDiW*gr~HA$#& zjcjHUzB4>*DblR@yhuhm9frwxlm_lv26jYBJy|_09%nziSRPMm_{sF#&tO5S~F#aE&TdgVp literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1_0.bin new file mode 100644 index 0000000000000000000000000000000000000000..b928aa178f35bb006582f5008cd5006953af8e0b GIT binary patch literal 2048 zcmcJ+2_q8<003Y~Y~~t;x#kQl%!J%$TaJV|l2MDNgp%7juw-ndw%jp8Bc6zcVTc?# zBR3^i?z6>2^nS(rKFEAYlGtL-iK2I3PSl-5zRwzw0H@eh4aJ0l>A?V7?bVuF&y>l% zv^IXU_LD2Ry*s#?kmxk9^00f}hcOd>Q32Iw(me|~{S%?Q zI+wFM@+aX!ScTAnLR4s|zL$#K&~iiJqGLbm24r8}#VM%7wW(%F z<7ZAJvy+a)zpvQ^K3mp}VwHALg>3CI;V|gAGKzjlqEdvj@b1Z}2l>Ag+zNcu{OJqFs~?E^?(Ws&og(gJ#L-D`i!5KP~08Jdv=R9TehP zkz765-;&aG`n4J1`9PE<&uO158pTwo6vF1mHkw6(18byd5vI6TCd{Mg|a9V1WE z32viUnyBn7h7Wnyb<^#+i44SYz{VdEJsaGleHZA0_QUtMp6s?1j78O1uEtHS4%b?H zbqogH%Js)}*UsBX@X9X%1QN`zt~#SDznF_*8kw&=ysP*udn(V~U6u9WdW3gyI$LnT z_lBL!zWg-EG0~jUPc(#tqYQMgOXDlK^OP;HM!?){kFENB1rpaNqA_f7oLyF49EplG zyK38e{-CDAXz~3n-c7DJ&#IvTHDzM|`%?A?sG(8112SI_K5KYS>9Nc|f6^m>vRIT? zmwHKtmsadARFf!ASE58<@XZ8It&>-ja>LOl0=bOCc}0$m2=LpdF533RjB# ziyq`9FLx_)hT_{aE0uN#wyEZIb(=A4m;c=F8fP=j0enhANmH z3ZRELX_IK9dMN)!SUOUt{F{(;*=$6<)sE!t-&>ke#M>Va+Rt%e);HJur^>|%;S@c2 z{Zs*(p~wYS01~vVmN@;?z5eR~KRhsm*V>O5i7gVjH?s$Q$z`PBT- z*z?gDI8U)bEQX6aUUkh8;6L`|K*M6d^#c_>2vL|L?bs%Kj{Hik!zm&d)wj`jvmuf4 zt`5(Dg)g1oGC2ma8t2z@CoUS^jEgrpn>aZ>G|}@s{$HH%+l?M#M$WL1-*zhdlhY+d z4^^oFCST^3O}z;0ksE)a?HVC-2UpSuJ$pQw?|{w0g3saLbxcC!#qmxY_C%6&06wG(W1Iizjb$h-cl7fxU zLO|v?49S;c!&W&nH9f*YObTC1cDcg8XRw-ZIA+c|94fqXsM`_bkA6boWK=qJek2{B zf8VCffI5cJY&JBWaAd1JX79EIlN?hi$h#I+teFf2UhK0ed@_?)PvZ?39n5rF2I(>! z9krABS0*U@N0f7E4zfazE!FN!{!elhz)Xrit g6Q$|5ewjm9p!6J1)DZ>q5^1+@?QL3;4Nw*T5AkZUng9R* literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2_0.bin new file mode 100644 index 0000000000000000000000000000000000000000..d3d71dc54d0843136e0283b185d74c093b95b2b5 GIT binary patch literal 2048 zcmcJ+i6aw=0{~zwLfU3i$$hQdv5k?1oD(XsT)h?%hNP&yEN9LL!_%W8_puc=T13kn zGt5!$@LV%TlB+q=@2~iMU+ke!{ zP2=!NE4L#%o2pld23ny=!HlNdEab=I*8(d)>9R3mcI^?ha)ZW(p&&_FMzmqR$6?XW zmsMBCBlOD?bX20IyN&Em9dg(riFv~mbu9GR9~Ls>HXKDRChQey421DFgx;@hbn3ZO z(2vs96Bcrxt{G?53yo_m__UJyVhK~EzwJjb!V5DZ22K;obDUf4qYjWDfA;OXs)nopVvh*rcukjQ)^cS`%>cN!@N%hX)0&-U3ZgyK?z~!>z#h}?w zsQGVCHBS7iV((><73i?=ni5LnG zZZUkwQeHWRm^SlQRm>jV%f&VW7Lz{+qUhqD*o^o~eAfU)xfj;}^D7Ho67)N?=RiML zP=&2snZ1Pr&;^q$50l*d5Xg)S_LQ`M3jCk_r}IRorvvDWqnPpXs4ZQ$8oHFL(*cgY zwY(EE8sl(ti=8Q-BNcfCHlkhB_IU1ITy;c3%DvjGD$+=)rUm4BJDNqg8@=*#Xb9l; znWaix0uimEY9r>1qH|K?SXeLz71i-4qj0cU&Rg*@Ms6(giK5*WIsDtnrJkG=?5PS%NJ{IS z=Qm+)=303TB03Kl(qqQ>lqG++pq~D*Ctdol>ZIeZYv&d8Q2~3nXdS==FojR3n&_jn z2lOG}r-PC>?%7Bc1=rI(7Oq2!5W3PU}NT)RH_Q7V7+$m74eq^{IB4^IKjo<~14&V&|J?7qU zqj`>mOTh6TDyh>5?g#D7CoO)vv`9F7kD; zB~h|A?{=~AtIIs;E#`XbW5Ur7V>|^E+MI+wqp0l8Y+IT)D^fiWzZoNwR(kYaAa~~5 z->G2<#spg*+;l=#X1A*~X*b&Yb^+I=pu641Bxm8W1a-y3n3=+rp&JXEw6PQ+-qgEF zuiej!cr;Z>+%#4#E0Nn-ok-bl|5B$7x^%msE_vGMFk~&>%9LRT{q>ueXtgfaO@0*7 zh)cW3wuhPZ>kF1;k?!45PAIsP9r+eNG|~%;a~yl(b)z}a(MfHsb=o^^IjJ`qDGhJ! zeD}s=#R=&@#2o-{p~!Bc9?#HQXWTWUOG8hcz0mKedz}GgZ1mlF$-SZ`Tm$snVlL;x zVLH31^^|q&T(75L0K@x>|wKI)B5+UmOOGA-=PYq-{&Sku?sP{VE2JRCD}x6nDhRo(~;TfUz_~l`|;*e`C%*Jkn+us z8R-3Gs9-|8+J#(9pMbKn+m0E6TR&OSb^Pmh^10dNPZl#AgLmh021ef(u6j~u(o1Ft zYKy!cTIhtpxU9BCn!(1|8CjD!6R^A|ZV3kQ8gd}EvZl0s&RaPqSLYJ@c~yZYwphs% zF~HgRhsufBcm3VuvHVQWPxV|=2B-8hha-#S2i-oJ$i9tcVIBH>m{ kVbE>AVyqnXr4tT2zBWWfGWx-OJbixjkX?FispOIW0jtowJOSxTJdRJ z@eRhEM>DlMM(I(Zp7EHE27;StZ8r47?$e0(=_8RQg4}s36d13=s8+*{P8`ZGomEi9 zfffG@F-`cxk7IbP;{(cR3E~E-5BcX^mU8kJr^&8%FdXU|xg^~u3>RD>j zUrJ0A>?fwoJU^Uv5Oeef}vo&wFc2k*--C52Z=YsZpUoE<(l|37>? zwP{Y2$RTB$b}40g@hXCdmL~Bod;L~25c8}uw8To&7nH18609P09KMWhU!ELmTp1W8 zGSx15gp_qy9xPq;@LFKIy?yWkr@i*UFS*id$&Vu=EB638{pw}&*gm0J92vhWgyR^% zMgFn}{J;L+`q+k{+1B%(gamjiD6M8Da9ESJU)|=f7TBvlOO? zof)v=Zw{P|)--iLUzlVnJ%>&B`r7#^zUjUVN+F@a=rYtGxbk*bdJO4V1~LwTz5!m2 z>N(sHMum#9d_Y(LVSOfc8ZkX*9c`UgZ&6|~D8V(%44P5uwcgmkl%UidS-Nfqw>^$C zVSNs!6rXU0Mcwp^#)>?USW)WKF5YmWlYEo-j`Yk-`-?tMy;#k-o26 zot@};e@FUv_j7Eny{)S5Wrb7e-&{v>-dPplT7esg92dT|sEGE-NC!xwW8+C=)fIM8 zw#Z@@`}(hJJ=Nao9;#P1rMR)H@ja}EKM1~B5E#$zWfV>z+gw{(m+vc3INi_m(mpOE z4%bolOQjAz-+`v_-VqIKhvyq^g|J$96J;+TK+2Ot2eT34ChCt=Gl#e!cZ~__QwC)2 z@VI_<(MBA{aiqoss4g)Dm7#2Eyag1V#B3)9hS;?CwxP;u>l%y8wd}t1T6+6ML#o<< z=GxqK)jOPApCALdVxRf+_?EoobgKv@2df~7meyCmJWB6Li-F5+CQETYUpf^Fzr&^E zqv3fm_CGy`lDGNx9-#AWByIp{5_h4`rG$6<;m(Vz;7@zD>I}L7QpZssZ3;j>eZ4F# zRBqyb4xNFsRBeXq7P2-!2v!1lU?gy~MRFt6R zv8i1b88hr-1F)aFa~HNf*YcTp_J=ORc!x(j#*TRX=+*v09K2*MWB5YTKv;8Da(|79 z%Q@X%{P5N69IR!jEHcicVAsiP>I+9=)=Rs*dtLnLd|~+?Eq8xguGIwT;;lN0eiCo+ zGBuRn&B$z%&}<>rz}9kz)zV$dECNYwzA}D&FAFr^^KJi^<~UkMe%jqO(2CMYH-wE@ zom=B;H?MVc`(r7Sh=?bkpDc;r_(Q00706W%Km$c5B%_i>Ma6QRZ<@~({gf+hy(Tof z23Uy*)@yzulC4-zP@S%pOOxJQy(bVIIb1nVm(!rfJcvzzJMc$KiD_k@E8;FIS;1r2 zEkil_Sibbs0wdYtZWm-ug@)@>VL!En5FQ-enXEJAwhRK_idOT=17`;p4lCY$6Xrh>*~XHs;>`a~yKc8K(^CVhwPnpSPZ zw-t2Zkayuf`jwbvh9GRki1}SIqp~0BzjaOXV!3Z4I3vF)+^Ra|){7eS5wF3@$LqCR z!2Tt!WQVH?_-@HfpzVt+4f4y5X}-*h!q?<)64P9hZHdUeJQ4gcjOO}==l7v0-1))7 mv*KhLm`=KActFVTuIC>KmDUbEU`aP$?YwFh1Olo#8vPG`qM{Z6 literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata new file mode 100644 index 0000000000..7f228e6244 --- /dev/null +++ b/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata @@ -0,0 +1,465 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 8, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 5, + gates: [ + Product( + Fixed { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 2, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 2, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 2, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x1e8ad0c6992851e2d92d368088d79e3326cd63e2a12bb086407dc3dbe0691fb0, 0x0895d1133a5889cf2a52bf5a7ac48502ac399a0088625be4db7aaec534ee8576), + (0x1e8ad0c6992851e2d92d368088d79e3326cd63e2a12bb086407dc3dbe0691fb0, 0x0895d1133a5889cf2a52bf5a7ac48502ac399a0088625be4db7aaec534ee8576), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + ], + permutation: VerifyingKey { + commitments: [ + (0x2477ff33a8671d640d752567c99805c0dda68328ddfff306b085f13be1fd9079, 0x3f7c0fa2ae0b1b7683c39103509711d525eb2dfb73ed21458b77b9d0de222923), + (0x1c85783d2128c72103589576bf9d4ed2a509202944a52b48db13848f9431439f, 0x0c363acac4903e6907846abb10920dcf7a2b8c7462ac37f64d0da5cf7f9a643e), + ], + }, +} diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata new file mode 100644 index 0000000000..6f2d4066cd --- /dev/null +++ b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata @@ -0,0 +1,465 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 8, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 5, + gates: [ + Product( + Fixed { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 2, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 2, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 2, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x27c2b8ac34f64d4d18eada2b41dc9d8c30409eb866c7e4d539204fadcb696826, 0x0881a9c2e2e4a577b5a951254bd508dedafa5f1c7be905aaf4fbac60971bc9f7), + (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x28d1c924953bc53f232465943d25fd085f85727ae4e2d26249207da1e59559e2, 0x184d19e00f109c4dacf8026c6e0fc4181178b32a236828047c46d9d61eab90fa), + ], + permutation: VerifyingKey { + commitments: [ + (0x3b7b93d7540327328791a14933d8f3345abd943eb35b67a8a4bd2eb72e2a707a, 0x26fff57a6fa3c01dd0d739fc56479303b4302d6baa6f1da06f4013419c40e10c), + (0x3fdf7a15a0d2378accc11f704f4ba4a487b542ace83c7f5a8551b569a3b9a380, 0x34253920878d15d6fe1b5198c31bdd670d32e81621e9fcd569d582e596ed0af5), + ], + }, +} diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata new file mode 100644 index 0000000000..754fc559c7 --- /dev/null +++ b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata @@ -0,0 +1,465 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 8, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 5, + gates: [ + Product( + Fixed { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 2, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 2, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 2, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x369f0b3422178fecf6e9a4fc7224622da26e8b5c74fb9aca5864c9f72e30bd5c, 0x2d7892875c06c460c9c9f66449103e7b6ef2871fb0a4e39b9af90e938c8e291b), + (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x28d1c924953bc53f232465943d25fd085f85727ae4e2d26249207da1e59559e2, 0x184d19e00f109c4dacf8026c6e0fc4181178b32a236828047c46d9d61eab90fa), + ], + permutation: VerifyingKey { + commitments: [ + (0x3b7b93d7540327328791a14933d8f3345abd943eb35b67a8a4bd2eb72e2a707a, 0x26fff57a6fa3c01dd0d739fc56479303b4302d6baa6f1da06f4013419c40e10c), + (0x3fdf7a15a0d2378accc11f704f4ba4a487b542ace83c7f5a8551b569a3b9a380, 0x34253920878d15d6fe1b5198c31bdd670d32e81621e9fcd569d582e596ed0af5), + ], + }, +} diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata new file mode 100644 index 0000000000..0a3f3a30fe --- /dev/null +++ b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata @@ -0,0 +1,465 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 8, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 5, + gates: [ + Product( + Fixed { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 2, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 2, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 2, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x2ca6650c6fcad471c1c9d29e9115516064a1fe096af3b13821cf1fe7fee088eb, 0x18e61f68d5978b837a3e2295fe7ae7ca672268a519394f41aabd085aadc1221d), + (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x28d1c924953bc53f232465943d25fd085f85727ae4e2d26249207da1e59559e2, 0x184d19e00f109c4dacf8026c6e0fc4181178b32a236828047c46d9d61eab90fa), + ], + permutation: VerifyingKey { + commitments: [ + (0x3b7b93d7540327328791a14933d8f3345abd943eb35b67a8a4bd2eb72e2a707a, 0x26fff57a6fa3c01dd0d739fc56479303b4302d6baa6f1da06f4013419c40e10c), + (0x3fdf7a15a0d2378accc11f704f4ba4a487b542ace83c7f5a8551b569a3b9a380, 0x34253920878d15d6fe1b5198c31bdd670d32e81621e9fcd569d582e596ed0af5), + ], + }, +} diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata new file mode 100644 index 0000000000..a3969f9746 --- /dev/null +++ b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata @@ -0,0 +1,465 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 8, + num_advice_columns: 1, + num_instance_columns: 0, + num_selectors: 5, + gates: [ + Product( + Fixed { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 0, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 2, + column_type: Fixed, + }, + Column { + index: 0, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 2, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 2, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x27c2b8ac34f64d4d18eada2b41dc9d8c30409eb866c7e4d539204fadcb696826, 0x0881a9c2e2e4a577b5a951254bd508dedafa5f1c7be905aaf4fbac60971bc9f7), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x27c2b8ac34f64d4d18eada2b41dc9d8c30409eb866c7e4d539204fadcb696826, 0x0881a9c2e2e4a577b5a951254bd508dedafa5f1c7be905aaf4fbac60971bc9f7), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + ], + permutation: VerifyingKey { + commitments: [ + (0x0c1d926ba62fa64dd3783396092fe2cd7fd98a5d79d8c3fead299d41ba82807c, 0x387da97a34f98c3cee781c2cfba0fd46c20d1e11907c6995b4ee46c0028ed391), + (0x34015e25137a9a8ea4feb8af77f10d27fc6a04e952823f7e2343a749419df2ce, 0x2c6589a5343037dd14d33821800626bba96354283fb05011f27dcda6a6b860fb), + ], + }, +} diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 4afbabb624..eb79d504ba 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -708,563 +708,512 @@ mod tests { tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, utilities::lookup_range_check::{ LookupRangeCheck, LookupRangeCheckConfig, LookupRangeCheckConfigOptimized, + PallasLookupConfigOptimized, PallasLookupRCConfig, }, }; use std::{convert::TryInto, marker::PhantomData}; - #[test] - fn lookup_range_check() { - #[derive(Clone, Copy)] - struct MyCircuit { - num_words: usize, - _marker: PhantomData, - } - - impl Circuit for MyCircuit { - type Config = LookupRangeCheckConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - *self - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); + fn configure_optimized( + meta: &mut ConstraintSystem, + ) -> LookupRangeCheckConfigOptimized { + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); - LookupRangeCheckConfig::::configure(meta, running_sum, table_idx) - } + LookupRangeCheckConfigOptimized::::configure_with_tag( + meta, + running_sum, + table_idx, + table_range_check_tag, + ) + } - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_words * K bits. - let elements_and_expected_final_zs = [ - (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long - (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long - ]; - - fn expected_zs( - element: F, - num_words: usize, - ) -> Vec { - let chunks = { - element - .to_le_bits() - .iter() - .by_vals() - .take(num_words * K) - .collect::>() - .chunks_exact(K) - .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) - .collect::>() - }; - let expected_zs = { - let inv_two_pow_k = F::from(1 << K).invert().unwrap(); - chunks.iter().fold(vec![element], |mut zs, a_i| { - // z_{i + 1} = (z_i - a_i) / 2^{K} - let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; - zs.push(z); - zs - }) - }; - expected_zs - } + fn configure_non_optimized( + meta: &mut ConstraintSystem, + ) -> LookupRangeCheckConfig { + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); - for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { - let expected_zs = expected_zs::(*element, self.num_words); + LookupRangeCheckConfig::::configure(meta, running_sum, table_idx) + } - let zs = config.witness_check( - layouter.namespace(|| format!("Lookup {:?}", self.num_words)), - Value::known(*element), - self.num_words, - *strict, - )?; + #[derive(Clone, Copy)] + struct MyLookupCircuit> { + num_words: usize, + _field_marker: PhantomData, + _lookup_marker: PhantomData, + } - assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); + fn lookup_synthesize>( + circuit: &MyLookupCircuit, + config: Lookup, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load table_idx + config.load(&mut layouter)?; - for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { - z.value().assert_if_known(|z| &&expected_z == z); - } - } - Ok(()) - } - } + // Lookup constraining element to be no longer than num_words * K bits. + let elements_and_expected_final_zs = [ + (F::from((1 << (circuit.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long + (F::from(1 << (circuit.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long + ]; - { - let circuit: MyCircuit = MyCircuit { - num_words: 6, - _marker: PhantomData, + fn expected_zs(element: F, num_words: usize) -> Vec { + let chunks = { + element + .to_le_bits() + .iter() + .by_vals() + .take(num_words * K) + .collect::>() + .chunks_exact(K) + .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) + .collect::>() }; - - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - - test_against_stored_vk(&circuit, "lookup_range_check"); - - test_against_stored_proof(circuit, "lookup_range_check", 0); - } - } - - #[test] - fn short_range_check() { - #[derive(Clone, Copy)] - struct MyCircuit { - element: Value, - num_bits: usize, + let expected_zs = { + let inv_two_pow_k = F::from(1 << K).invert().unwrap(); + chunks.iter().fold(vec![element], |mut zs, a_i| { + // z_{i + 1} = (z_i - a_i) / 2^{K} + let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; + zs.push(z); + zs + }) + }; + expected_zs } - impl Circuit for MyCircuit { - type Config = LookupRangeCheckConfig; - type FloorPlanner = SimpleFloorPlanner; + for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { + let expected_zs = expected_zs::(*element, circuit.num_words); - fn without_witnesses(&self) -> Self { - MyCircuit { - element: Value::unknown(), - num_bits: self.num_bits, - } - } + let zs = config.witness_check( + layouter.namespace(|| format!("Lookup {:?}", circuit.num_words)), + Value::known(*element), + circuit.num_words, + *strict, + )?; - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); + assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); - LookupRangeCheckConfig::::configure(meta, running_sum, table_idx) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_bits. - config.witness_short_check( - layouter.namespace(|| format!("Lookup {:?} bits", self.num_bits)), - self.element, - self.num_bits, - )?; - - Ok(()) + for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { + z.value().assert_if_known(|z| &&expected_z == z); } } + Ok(()) + } - // Edge case: zero bits (case 0) - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::ZERO), - num_bits: 0, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - - test_against_stored_vk(&circuit, "short_range_check_case0"); + impl Circuit for MyLookupCircuit> { + type Config = LookupRangeCheckConfig; + type FloorPlanner = SimpleFloorPlanner; - test_against_stored_proof(circuit, "short_range_check_case0", 0); + fn without_witnesses(&self) -> Self { + *self } - // Edge case: K bits (case 1) - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << K) - 1)), - num_bits: K, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - - test_against_stored_vk(&circuit, "short_range_check_case1"); - - test_against_stored_proof(circuit, "short_range_check_case1", 0); + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + configure_non_optimized(meta) } - // Element within `num_bits` (case 2) - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << 6) - 1)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); + fn synthesize( + &self, + config: Self::Config, + layouter: impl Layouter, + ) -> Result<(), Error> { + lookup_synthesize(self, config, layouter) + } + } - test_against_stored_vk(&circuit, "short_range_check_case2"); + impl Circuit for MyLookupCircuit> { + type Config = LookupRangeCheckConfigOptimized; + type FloorPlanner = SimpleFloorPlanner; - test_against_stored_proof(circuit, "short_range_check_case2", 0); + fn without_witnesses(&self) -> Self { + *self } - // Element larger than `num_bits` but within K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << 6)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }]) - ); + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + configure_optimized(meta) } - // Element larger than K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << K)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }, - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }, - ]) - ); + fn synthesize( + &self, + config: Self::Config, + layouter: impl Layouter, + ) -> Result<(), Error> { + lookup_synthesize(self, config, layouter) } + } - // Element which is not within `num_bits`, but which has a shifted value within - // num_bits - { - let num_bits = 6; - let shifted = pallas::Base::from((1 << num_bits) - 1); - // Recall that shifted = element * 2^{K-s} - // => element = shifted * 2^{s-K} - let element = shifted - * pallas::Base::from(1 << (K as u64 - num_bits)) - .invert() - .unwrap(); - let circuit: MyCircuit = MyCircuit { - element: Value::known(element), - num_bits: num_bits as usize, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }]) - ); - } + #[test] + fn lookup_range_check() { + let circuit: MyLookupCircuit = MyLookupCircuit { + num_words: 6, + _field_marker: PhantomData, + _lookup_marker: PhantomData, + }; + + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + + test_against_stored_vk(&circuit, "lookup_range_check"); + test_against_stored_proof(circuit, "lookup_range_check", 0); } #[test] fn lookup_range_check_4_5_b() { - #[derive(Clone, Copy)] - struct MyCircuit { - num_words: usize, - _marker: PhantomData, - } - - impl Circuit for MyCircuit { - type Config = LookupRangeCheckConfigOptimized; - type FloorPlanner = SimpleFloorPlanner; + let circuit: MyLookupCircuit = MyLookupCircuit { + num_words: 6, + _field_marker: PhantomData, + _lookup_marker: PhantomData, + }; - fn without_witnesses(&self) -> Self { - *self - } + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - LookupRangeCheckConfigOptimized::::configure_with_tag( - meta, - running_sum, - table_idx, - table_range_check_tag, - ) - } + test_against_stored_vk(&circuit, "lookup_range_check_4_5_b"); + test_against_stored_proof(circuit, "lookup_range_check_4_5_b", 0); + } - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_words * K bits. - let elements_and_expected_final_zs = [ - (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long - (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long - ]; - - fn expected_zs( - element: F, - num_words: usize, - ) -> Vec { - let chunks = { - element - .to_le_bits() - .iter() - .by_vals() - .take(num_words * K) - .collect::>() - .chunks_exact(K) - .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) - .collect::>() - }; - let expected_zs = { - let inv_two_pow_k = F::from(1 << K).invert().unwrap(); - chunks.iter().fold(vec![element], |mut zs, a_i| { - // z_{i + 1} = (z_i - a_i) / 2^{K} - let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; - zs.push(z); - zs - }) - }; - expected_zs - } + #[derive(Clone, Copy)] + struct MyShortRangeCheckCircuit> { + element: Value, + num_bits: usize, + _lookup_marker: PhantomData, + } - for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { - let expected_zs = expected_zs::(*element, self.num_words); + fn short_range_synthesize>( + circuit: &MyShortRangeCheckCircuit, + config: Lookup, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_bits. + config.witness_short_check( + layouter.namespace(|| format!("Lookup {:?} bits", circuit.num_bits)), + circuit.element, + circuit.num_bits, + )?; - let zs = config.witness_check( - layouter.namespace(|| format!("Lookup {:?}", self.num_words)), - Value::known(*element), - self.num_words, - *strict, - )?; + Ok(()) + } - assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); + impl Circuit for MyShortRangeCheckCircuit> { + type Config = LookupRangeCheckConfig; + type FloorPlanner = SimpleFloorPlanner; - for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { - z.value().assert_if_known(|z| &&expected_z == z); - } - } - Ok(()) + fn without_witnesses(&self) -> Self { + MyShortRangeCheckCircuit { + element: Value::unknown(), + num_bits: self.num_bits, + _lookup_marker: PhantomData, } } - { - let circuit: MyCircuit = MyCircuit { - num_words: 6, - _marker: PhantomData, - }; + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + configure_non_optimized(meta) + } - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); + fn synthesize( + &self, + config: Self::Config, + layouter: impl Layouter, + ) -> Result<(), Error> { + short_range_synthesize(self, config, layouter) } } - #[test] - fn short_range_check_4_5_b() { - struct MyCircuit { - element: Value, - num_bits: usize, + impl Circuit + for MyShortRangeCheckCircuit> + { + type Config = LookupRangeCheckConfigOptimized; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + MyShortRangeCheckCircuit { + element: Value::unknown(), + num_bits: self.num_bits, + _lookup_marker: PhantomData, + } } - impl Circuit for MyCircuit { - type Config = LookupRangeCheckConfigOptimized; - type FloorPlanner = SimpleFloorPlanner; + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + configure_optimized(meta) + } - fn without_witnesses(&self) -> Self { - MyCircuit { - element: Value::unknown(), - num_bits: self.num_bits, - } - } + fn synthesize( + &self, + config: Self::Config, + layouter: impl Layouter, + ) -> Result<(), Error> { + short_range_synthesize(self, config, layouter) + } + } - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - LookupRangeCheckConfigOptimized::::configure_with_tag( - meta, - running_sum, - table_idx, - table_range_check_tag, - ) - } + fn test_short_range_check( + element: pallas::Base, + num_bits: usize, + proof_result: Result<(), Vec>, + optimized: bool, + circuit_name: &str, + index: usize, + ) { + if optimized { + let circuit: MyShortRangeCheckCircuit = + MyShortRangeCheckCircuit { + element: Value::known(element), + num_bits, + _lookup_marker: PhantomData, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), proof_result); - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_bits. - config.witness_short_check( - layouter.namespace(|| format!("Lookup {:?} bits", self.num_bits)), - self.element, - self.num_bits, - )?; + if proof_result.is_ok() { + test_against_stored_vk(&circuit, circuit_name); + test_against_stored_proof(circuit, circuit_name, index); + } + } else { + let circuit: MyShortRangeCheckCircuit = + MyShortRangeCheckCircuit { + element: Value::known(element), + num_bits, + _lookup_marker: PhantomData, + }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), proof_result); - Ok(()) + if proof_result.is_ok() { + test_against_stored_vk(&circuit, circuit_name); + test_against_stored_proof(circuit, circuit_name, index); } - } + }; + } - // Edge case: zero bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::ZERO), - num_bits: 0, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + #[test] + fn short_range_check() { + // Edge case: zero bits (case 0) + test_short_range_check( + pallas::Base::ZERO, + 0, + Ok(()), + false, + "short_range_check_case0", + 0, + ); - // Edge case: K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << K) - 1)), - num_bits: K, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + // Edge case: K bits (case 1) + test_short_range_check( + pallas::Base::from((1 << K) - 1), + K, + Ok(()), + false, + "short_range_check_case1", + 0, + ); - // Element within `num_bits` - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << 6) - 1)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + // Element within `num_bits` (case 2) + test_short_range_check( + pallas::Base::from((1 << 6) - 1), + 6, + Ok(()), + false, + "short_range_check_case2", + 0, + ); // Element larger than `num_bits` but within K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << 6)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { + test_short_range_check( + pallas::Base::from(1 << 6), + 6, + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }]), + false, + "not_saved", + 0, + ); + + // Element larger than K bits + test_short_range_check( + pallas::Base::from(1 << K), + 6, + Err(vec![ + VerifyFailure::Lookup { lookup_index: 0, location: FailureLocation::InRegion { region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }]) - ); - } - - // Element larger than K bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << K)), - num_bits: 6, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, + offset: 0, }, - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, + }, + VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, }, - ]) - ); - } + }, + ]), + false, + "not_saved", + 0, + ); // Element which is not within `num_bits`, but which has a shifted value within // num_bits - { - let num_bits = 6; - let shifted = pallas::Base::from((1 << num_bits) - 1); - // Recall that shifted = element * 2^{K-s} - // => element = shifted * 2^{s-K} - let element = shifted - * pallas::Base::from(1 << (K as u64 - num_bits)) - .invert() - .unwrap(); - let circuit: MyCircuit = MyCircuit { - element: Value::known(element), - num_bits: num_bits as usize, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { + let num_bits = 6; + let shifted = pallas::Base::from((1 << num_bits) - 1); + // Recall that shifted = element * 2^{K-s} + // => element = shifted * 2^{s-K} + let element = shifted + * pallas::Base::from(1 << (K as u64 - num_bits)) + .invert() + .unwrap(); + test_short_range_check( + element, + num_bits as usize, + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }]), + false, + "not_saved", + 0, + ); + } + + #[test] + fn short_range_check_4_5_b() { + // Edge case: zero bits + test_short_range_check( + pallas::Base::ZERO, + 0, + Ok(()), + true, + "short_range_check_4_5_b_case0", + 0, + ); + + // Edge case: K bits + test_short_range_check( + pallas::Base::from((1 << K) - 1), + K, + Ok(()), + true, + "short_range_check_4_5_b_case1", + 0, + ); + + // Element within `num_bits` + test_short_range_check( + pallas::Base::from((1 << 6) - 1), + 6, + Ok(()), + true, + "short_range_check_4_5_b_case2", + 0, + ); + + // Element larger than `num_bits` but within K bits + test_short_range_check( + pallas::Base::from(1 << 6), + 6, + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }]), + true, + "not_saved", + 0, + ); + + // Element larger than K bits + test_short_range_check( + pallas::Base::from(1 << K), + 6, + Err(vec![ + VerifyFailure::Lookup { lookup_index: 0, location: FailureLocation::InRegion { region: (1, "Range check 6 bits").into(), offset: 0, }, - }]) - ); - } + }, + VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }, + ]), + true, + "not_saved", + 0, + ); + + // Element which is not within `num_bits`, but which has a shifted value within + // num_bits + let num_bits = 6; + let shifted = pallas::Base::from((1 << num_bits) - 1); + // Recall that shifted = element * 2^{K-s} + // => element = shifted * 2^{s-K} + let element = shifted + * pallas::Base::from(1 << (K as u64 - num_bits)) + .invert() + .unwrap(); + test_short_range_check( + element, + num_bits as usize, + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }]), + true, + "not_saved", + 0, + ); // Element within 4 bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from((1 << 4) - 1)), - num_bits: 4, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } + test_short_range_check( + pallas::Base::from((1 << 4) - 1), + 4, + Ok(()), + true, + "short_range_check_4_5_b_case3", + 0, + ); // Element larger than 5 bits - { - let circuit: MyCircuit = MyCircuit { - element: Value::known(pallas::Base::from(1 << 5)), - num_bits: 5, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 5 bits").into(), - offset: 0, - }, - }]) - ); - } + test_short_range_check( + pallas::Base::from(1 << 5), + 5, + Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 5 bits").into(), + offset: 0, + }, + }]), + true, + "not_saved", + 0, + ); } } From 474cfac100d35fe43cfc59c355e08884e506d4d6 Mon Sep 17 00:00:00 2001 From: Constance Date: Fri, 21 Jun 2024 10:47:50 +0200 Subject: [PATCH 085/121] Save test files for optimized lookup range check --- halo2_gadgets/src/ecc.rs | 15 +- halo2_gadgets/src/sinsemilla.rs | 16 +- halo2_gadgets/src/sinsemilla/merkle.rs | 27 +- .../circuit_data/proof_ecc_chip_4_5_b_0.bin | Bin 0 -> 3872 bytes .../proof_merkle_chip_4_5_b_0.bin | Bin 0 -> 4160 bytes .../proof_sinsemilla_chip_4_5_b_0.bin | Bin 0 -> 4672 bytes .../circuit_data/vk_ecc_chip_4_5_b.rdata | 9915 +++++++++++++ .../circuit_data/vk_merkle_chip_4_5_b.rdata | 3556 +++++ .../vk_sinsemilla_chip_4_5_b.rdata | 12042 ++++++++++++++++ 9 files changed, 25547 insertions(+), 24 deletions(-) create mode 100644 halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b_0.bin create mode 100644 halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata create mode 100644 halo2_gadgets/src/tests/circuit_data/vk_merkle_chip_4_5_b.rdata create mode 100644 halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_chip_4_5_b.rdata diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index a2a7ec5602..618fca2c01 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -955,14 +955,9 @@ pub(crate) mod tests { } #[test] - fn fixed_verification_key_test() { + fn test_against_stored_ecc_chip() { let circuit = MyCircuit { test_errors: false }; test_against_stored_vk(&circuit, "ecc_chip"); - } - - #[test] - fn serialized_proof_test_case() { - let circuit = MyCircuit { test_errors: false }; test_against_stored_proof(circuit, "ecc_chip", 0); } @@ -1179,6 +1174,14 @@ pub(crate) mod tests { assert_eq!(prover.verify(), Ok(())) } + + #[test] + fn test_against_stored_ecc_chip_4_5_b() { + let circuit = MyCircuit { test_errors: false }; + test_against_stored_vk(&circuit, "ecc_chip_4_5_b"); + test_against_stored_proof(circuit, "ecc_chip_4_5_b", 0); + } + #[cfg(feature = "test-dev-graph")] #[test] fn print_ecc_chip_4_5_b() { diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index d301d6a55d..90ca0e22d9 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -455,7 +455,6 @@ where /// for implementing the Sinsemilla hash function and commitment scheme /// on elliptic curves. This trait is an extension of the `SinsemillaInstructions` trait, /// designed to enhance performance in specific cryptographic scenarios.ld - pub trait SinsemillaInstructionsOptimized: SinsemillaInstructions { @@ -880,14 +879,9 @@ pub(crate) mod tests { } #[test] - fn fixed_verification_key_test() { + fn test_against_stored_sinsemilla_chip() { let circuit = MyCircuit {}; test_against_stored_vk(&circuit, "sinsemilla_chip"); - } - - #[test] - fn serialized_proof_test_case() { - let circuit = MyCircuit {}; test_against_stored_proof(circuit, "sinsemilla_chip", 0); } @@ -1150,6 +1144,14 @@ pub(crate) mod tests { assert_eq!(prover.verify(), Ok(())) } + #[test] + fn test_against_stored_sinsemilla_chip_4_5_b() { + let circuit = MyCircuit45B {}; + + test_against_stored_vk(&circuit, "sinsemilla_chip_4_5_b"); + test_against_stored_proof(circuit, "sinsemilla_chip_4_5_b", 0); + } + #[cfg(feature = "test-dev-graph")] #[test] fn print_sinsemilla_chip_4_5_b() { diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 7d6f3e2ca1..552b727f8a 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -394,14 +394,9 @@ pub mod tests { } #[test] - fn fixed_verification_key_test() { + fn test_against_stored_merkle_chip() { let circuit = generate_circuit(); test_against_stored_vk(&circuit, "merkle_chip"); - } - - #[test] - fn serialized_proof_test_case() { - let circuit = generate_circuit(); test_against_stored_proof(circuit, "merkle_chip", 0); } @@ -593,8 +588,7 @@ pub mod tests { } } - #[test] - fn merkle_chip_4_5_b() { + fn generate_circuit_4_5_b() -> MyCircuit45B { let mut rng = OsRng; // Choose a random leaf and position @@ -607,17 +601,28 @@ pub mod tests { .collect(); // The root is provided as a public input in the Orchard circuit. - - let circuit = MyCircuit45B { + MyCircuit45B { leaf: Value::known(leaf), leaf_pos: Value::known(pos), merkle_path: Value::known(path.try_into().unwrap()), - }; + } + } + #[test] + fn merkle_chip_4_5_b() { + let circuit = generate_circuit_4_5_b(); let prover = MockProver::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } + #[test] + fn test_against_stored_merkle_chip_4_5_b() { + let circuit = generate_circuit_4_5_b(); + + test_against_stored_vk(&circuit, "merkle_chip_4_5_b"); + test_against_stored_proof(circuit, "merkle_chip_4_5_b", 0); + } + #[cfg(feature = "test-dev-graph")] #[test] fn print_merkle_chip_4_5_b() { diff --git a/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b_0.bin new file mode 100644 index 0000000000000000000000000000000000000000..36bd1595fc62763d63bd07b9a43b70f23075e313 GIT binary patch literal 3872 zcmajU^&=b%0{~!oy1U~r-R2y|Y~s~1PHdWqX~rE6r{l$R9gY*5oQa9yon|{7!?a;K zP9NW&@IAjikIOOxy`W|BC}8fsHb!m;|F>p4+uq^?7fCbDdBL#?GHzW@prUoeAvskm zXP!vbF_=)MLD~yx6zW{yifj zrh{8+Ekrz5k9|R>G3+^4yneC4xB&Sad?{X%#)>pR?@O;B@UKCr^V{SfauPi&Vw4`A zlUQq}m!nRp9dN?H<^$H^me5Twu2-=aWZ2^wE*}cEnZQ95WfObd)Hfj7!b|1Q8>=<`|J**ls$FmM zw+ptCzS%csKPj5^X-%eh+`RADyBVr*_g>e!l>d%MFb+5R>ORIXObAA5`b z8at*Da*A;>;v4Ko?z78{R`PeD&X&*2MBj(z!v3y8Q1&Txi<{~&+Uk#bOw{djXIl9c z=d`RLQZbUG`Xxy(V<~8y3KW&*AvD6v z3#%FN2o1=X@al|Ki-qfHn^JVp*UWQCR{t*YJdCu~vHc!f!7CruSR?&(>yT_2pVi(O zlpaXYowG-q?LpPwOX>(&u$dHdC9>x zhb=M6%jI5`tZ5`<{Bs>!G}R)`#Mb+7t@sL=*e3f+v?27H3(YYkyYM z&~HgG%%xQ4+-6yG7k@!#B+oK-4~Y`G9ysF4d|uoDbozPGcV>K|USybqK31<4T$Aku z)1{_eS`(|3LLLE-)Faa~fi?FCOZjix+K&;KlSi9uF$?=z?owerzp9iyo~;*ZwigZr z5_yYBhBNOEuD?{{-~H-wm)4@QZm9ngMFAJT$0=*<2(ddAMa<8|>|8K#{phvXx+Nxh z+|D)0LWFPzn$W7avypXL#Em{DzwL{_Aa`1*lgFhJ9Jy^5gTPpr|JVZCH9a6b#y%l= zq-cdHpRJEtW*CI`f3#&d^4E_|7M5vS-*Q?z1axk{J0wbY$gvFUqir-jBB_{+sotlO zW|&Fv%`{~l?~?3fO2d?g!{CFD$0`<2@vG@5mEjPdSi%oaQ(8fFPPjN<1~^c zgL`L1i2=G*EaDwt1@Vd3kp@g{ z`({BG7rs>|DS0o{jN6YALYwWp5LuF~{N8mh7xgGx<9m})ZAMD;!Z`osBja7gF9#X% z|7mX<9}TGpTTYhT4B~rsq!x#lZVtX*J47J)%jvafHp=Cw-f}2r8DVlIYW_5~>x6*U z_zT{pflwdvqlu_Zyerkcs=26SS8+ z*r~`7)*6)e1l17?#UA)Wyn1t4VpYy}??S8lZ}q@X)IiddxH#}+qxWwJWySb;7`IgKbs;KC(Q*dli?`1leUW$aV_SG{!Fa!D!=U z2Fb0_k<;XQ7x5Da?{c;#fXG~_SA{Shiz?RQ2*{MDJ<1m>m4VCB_rr>L$ec;*>pUgV1HFP^6^ z6yF14^Dg|VUZ-VEIoJne3YF-ot$2>{sInLT>zndPTkp7e_xjRfaDev~0uv1uN6ZTMON}=eDWFf8&cOq*G)t?Y5-H6XDVuxQ>|8!k9*o?Q~h+ zsh@n#-cgx9{fgB52?nxjOKy=FN%%lrUfu(_yfwTjmx8O^ce9UTn;tFo&17r2e-+%r z$GRiSBzAg0Q^##mp-1D@G`%`+tQk1Lx9RlJcTBuTHa-8t@{S< zo)Jh626w1+rA~+FA*aAS`~w3Cr59%S6r0vgYGT67=l>)bPZTineiPnVn_oWZFL@*s z$(DEE!FaW#xpKC%iyYVoM5$KuhOj%M^G6H`y})Zk41yrMUsOgyqsomgJbvaCmQjUD z69)cfjz78(CLKFtjUihki3qk?EwlEiyxtGzO}m`;qnNk#J=~X_Ee`0GY~vZ_x5k*t zY@+!O&?}QSeaf_`8cwqy_Z~<4w~ET0?OFgKVcV)eG>I_(zG#^}e;5L77Z-cREI zqJXtcn5^GZmR#VZU(_X=v%{}Uh_odDZlb=8Hx*C{2Wo+-ir2JNmKKQX`mFCz> zaGVwX29H0On_&#WWQ|VTDazf?IVAL8h6ePHC)hoDRQlGzydCmf-c&bN>E!Suf}ai`YmQ2TGMwKxhfuw1Arg(zGzO1|m5Lw*SrVHMh!`AQcM{?t)Z*&MzV1dA~` zAWpRO_$;rL|Gj=#E4YeX@zX7tfLpqMNJm`pXg)9W#ho#>V{lVq_0%e=UwY@K0tHXE zmHz8p_76i*4SrcFqn(693@s-yUxgf2gaOQsz^a$Cac4Lw} zx!hf$bSLbhLe>HVe&yo~7$;3m8+I>o!RnFmeh)#Q$eLdU2Q=|!9@7Tcgj%fT7|0U= z#-9-kx0@+QdF0AiQyL$nY<$t5fCWq3VTsvpJdV5??ngOfIgz@B0Y z&~5keo8!%VH>zzP%2Zz4KYxf|FBEI1Rd)?jCf#o=Z?{u25Ep!P&B+5(C6K0;`U1O! z6nOp&fhssKJ6hN_!Urcb9hYAT4*iB)_bB0F%Zg^`GpL`i80>F_1S{e4nZ}O>YUx`R*R6ZifT2aa9TjPKl+W4Ab1@2cO%~9@}?Sm4Eu*mHz2mb+1R_ z^3eUrNm8Vdm{ByPsvr2_c&fBC1KAfCg*1A8lJ=*^mSPRy-05NyI?s4exD*52<|xN< zjM%sw?W&$H^Ua8YtrwSpe3y|HN#_-(cjZR$H898eC}2^6&#i!yd!8KDIF6TH5NSBp zPeZS%3bvSUqD0FRw+JUc_4c@`w@Ct}Jndl|BRBy6^Q|7ff=))sbGGrBcKx-Gk>G)c zA$>$_yUS-rTb(C|JqZ)sgel7!g{L5eZv*4BvyR7%d1H>n%bF+k-e}6)c~|F!(lJ2b zdZMu#w2axr8a^2P>wzYVLs@yolR`qQSS4>X9DO3*_ zt(#XWL$^pm!re*z_DRuV&U;JV;3xX=>(3Z&cq>^_lUaQvPYCUsb4gZYzoefgNvqie zuP#~wZu*_e<4hPr{S1(oz!qBHTsD#gvDUuHCH8~+G`zhT8+WhltP`J0;j*4J!DoH1 z2y%ko0B#oqsvnq#db;E)$WOCo=^&1nIVm3w<*+OT!S SQl;V4R98V^kwR@n(EkAA9&U;N literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b_0.bin new file mode 100644 index 0000000000000000000000000000000000000000..f1c89256adc0f89c9425531c186e880405fee375 GIT binary patch literal 4160 zcmbu-)j|`10)S!0$k8DsAq?qe#5TG^N>}z2IX>*2Lul$#TxG`-C7-`dF2@&+2NXNkFb8KPANS~ z+eKb=aKGdMjU-Z+LHImPGFztCWP$55(28slmnZmySm;XyOMnst$+6;EDYZx5j9b=_ z&;L}qtSwd>r5lou*H<6Ah?Io@V~E+mh%`^ZAB=4S!RX5nLoERJH;1foA-VV6(PYpr z4Xrb|z9lTcY%;7`&!;jejdT-K`)d9#v{a~y5;K27o~wTmT(*PyiL!n9;^LB_kqA%9 zd4H<{!u0M~I2~oHzNyOo>2|~vx&g?u#j=Y()j8%6$^%(}Uds5b=KDegM+$Myr*354 zVH8Bcw8~u9fUAg>Oty!(v+}9_8o9)v`h7-F_@4EtBx#6?r9FF6=rFlzH$G*R7V z1J>)0uHT2><9F(nIEEzuCVkPnFoplkXdKbLGX%COYpNjAWR_&*UJ=l8ZNb~iJPDZ2 z(|g@2|0i_1PDC6!^uxGV-7*XDsLH^!D%zM%@tA}*3%{k%XUco?YKk-YdmM&g2G+SZ zN6LD*3>E>=6pN}^JpXwiY|6apq_k&iDDPx-LwU4g zB>j-%-r*rf;+Y}7%uIMz^9Zy#F&nISyU`y!jkLzD3Bc!W;tD;&^{%7;i z)oCl^;Oy|JW-(u(GY_&d#~%CUnY8}YrKE?&(to>9l- z?GolU!V}5kbZGXSFj)N?KcvVTpWMV30ajikw2-naie~lBM@ZK;;Ll9 zn*?`_S^Ns@;>^~GSOVI0JA4frGr+q%s@M~cCT_&O0u7!o@PuRQ(g;92riTp8yqBqj zBpoUl^IrP%m$6``L(!71=rK_@(Ia>A+h3E$)VN<{9{_?s&EuDNTf{U4l5i@_;O2uG z1LjhjwwlJCz5rE~8rmrND80$omJexNwX2x_IF|a>I+QZ~`%wbcyze;*yzum`eM+F< zoyXtK8J8yEQ4Tv)O^~9oi(QTsh*SeT@V+8iRa&`2B~g8gw=o-HplW|k4t^^ruFSXe z>qt`mntAZ3fdZg)=O8w-S2|c2<^9i2PLBN$7ny#IqvK$|6wBgY^HLG}xGZpkpF{!5 z5Bi8mH1gh>GoFZfY&8FmNQ)}Bc&0R_j9#`OIxg?8AqPb>Zyo8cN2ohFRoSeR-%53C zN2bDf;jZHPtMgzgEc_#NqukppfE;`-+63+Q8#t0=ejg{NPfw7zFB>e<9X^9zV;;;L=f>n(XOoeGGQ=)b zUZ;409=m#}g1^{3pUi;lps0kAX~7M-qe+gxePV6*7VCe{k~6 zG-^)j^d`))LeidV%;CRzmv2ZVp0}iyaKjkZ2I%$~#J+t4!7u(z?15TDyK%W)-7maM z&eQ4jhb^wxhcUwLVbSFO4j&u61dz(eE%%)=efuP=`Rtgw@(bS{O~F&hmCJlQOH=WS zGdqDm9$CgF)4>Zg$>D;(sr5}5+E{KF55eX&wT}uxv64!lj@a0B3^)#VE1RG`(|?x- zFU`~pQj{SMd8rTGv{)x=kfFqeyL!`m%Wr-d26euDQUM!x9zBC&W|GlX0o-3x@P(!A z^q*EgdE!1}@BSINsfNovcnMs}w?_x+6@eGSHzHcZ-ZUZC;+MAro+d&f>1klIM6 zLbBW>*30`*StlY&X_YRnEko>M2q*}1WYL{cQI?gN7fU;NN$yGoi4w68rauxtvl%7kf1sX~AzHM{>q-&tzo3yWQaK=X!dwNvR%J4VLyJ#6y1% zr>_W;v4o(OZdS^CYgM(5$sL;0d}5}b4hc&|hFtG}I%IVPgw%gD9a8pn%IpMaiEkLw z4vVb!^xV;($>|eoRoe{hy|%|8(w4fy9g~UncqwXu(ah-EeTKvwCu(bNEky8`?}_LG zwiEw35B3Sboo~+W#`RpVVxyM|n4xk~CiaY#y;u&b`%(EGk>-+sewSh7Q1?mPD6j&L zo;gCg=G+9ARVQSSRwJHb2|mVb3VtRt_FY9<`rRX`7VyWXe4XvHxOfia&Go@9M3}~K z-m!`ZhwJW+xM2#l#5WCNKQ&^j*r4Y+jCDW0lws3(6L{GR#uZtW8>J$WIDElyx=xd< za7C8`l+fRC*#$8R&j*JlL>80qe-J(*R3G}GCYi-!4-`OY{1ouwwRl=Q z7Et&%VIgc}9;sTV?$-;X-tu61_r~AFFP5KAksxqn<|;+kD-zzeD`<=`Du0{ znwKe0yn;bfLBzG(wy1rUzg2NoLJejmJYm|v&UZuexi&{+7#SunMc$LG%6HKAZjsXYhv_Z>wu^umYb|Z zja#!M4ddZHkXQD7;j1kR`XQkr7OmThMVMHit2Vn^;&s(_5JUqKK<4C}(xkrwmT`Uc5*Z9hdu<-Mv7 z@xxc+ICv)u=O8$^;5=@;Sb=yYMaA}5vSk>b@dIXoNZYT-RsPG+t;J`do;p|u2{^>JI!H8+oW2SuH+7$EC)cqF41X9seJk+ zN!RXW|9TnreNF6#i%a|z=T7!GQaTN4;c){UB7!WFh8z8~86T!k^*>z2_zf21ROxvr z<`n+%q*(WAZBsj5ev`zb&>UDVPN)Av;p$MMUYdFBdCQKR^Pce$a^B6T7Yw~?O)5Y% z7D`<(&Te|yBqMN`5wZ}7WU;y%W;jYdK_VGqojV`KwIDgjOO>y20^f{U=k@x_%EV?4 z*>}7t$zIU?;UpsdHE*YnVKvf(b2oRokKl<`O>m^v;1i>$AU&y=O#XJ7g>^1>^VL^S z*_|_WGh+CxpBpFpj#ncWFd5UMa@k0xR>xJ-IXw&MlY40Zgyd;kRC!N=u`^KY;(K~k z&ooSb1+3kNCoeAZT-q6H+_q}ZT`!U`Uh!o^SAK{$J6xAPhGkS-bV4&qk}~;1NKk2K zo6}=g*P8?Q{`_7|O8_z82C)6e<@tKwsFP+hjwug&-A-LcTqI)?rz+85=ptMD+&(W9 zKakMI0LHnrLJaqT3ggn>G|wH#w}(to%i3uuXxXwU*s9tX3GPQIU3<6c?FJEJ?#+du zsO|N$eK#p3IQdkJ*DDrHONgabBpV~kpg93SrB6_feeqh!1Se-TrJNsZwH-qL!5&M{ zENolmFkUuNY7P=G5QI95IQq$Xw5w5;G+X*vKL)0i@2m=@4!?R4`l=Fk`>}0QBulG$ z(mzusiy>Kq(f82|3inrpV#|d(H{rie9<56ZZiY+4uDKfW^hT8(m7jSB9ypFk8jKLJ zqw7_>y8{vrY)a_&FU9I#olL5bf^RJCb)Xv{GXj^z(o_Ft2;mhW(&LU&1tMpMvivX= z7R2l7$4HZ-AL)`rwia*ZL5FyD;`5cj1lGh$m`LuzuL^e(s<3uG1RaPrDq@eB!M{iz z3k)E00FvLthmL5mf)0R7LtAuPaIOSV4Kq?Oa!tq*u`4~9k}6VqwcGv{OT*b$~MW<3lG=B0yU$z0>jQqtTn+Ou_|+LVBb5~vvK&AN6`s}EW8 zPXn^dlp;fH!U5|sh42T)FO+lW=>Kx6bv?;j!ctk_I6J=&;`6l_j>X;OWBfKf28ER* zc3gfp8{A`1)dU`H+y0gXx5p1e(QMx|OkjthOYW%?5)_$RaY}sQFRAzGYG+pPnLRdm z3ftWqdNnY9B{-g>y!?aBLc*Mod(T;u;q1^y1zcvnJ<=3A0ylAF#r_gBLH0lyhv}WJV+jdJN@MukkdVM1f>tsDSe_$S`wTMqLjmlTth7xXZ0BrvcGh&QnrFTj+lPOChr~ literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b_0.bin new file mode 100644 index 0000000000000000000000000000000000000000..2ad627e536ee98edda76c2f25f04383360cae100 GIT binary patch literal 4672 zcmc(fC<&iclS0NrsHrrZ`zn{(`^$Ir(+nV+l}dt4bz<1;isGT{U6>B z@ADr#AD)MuG2cZVd(lvo&3t%S0XkT$G#%f@2PBlPsTs!|C6OG{(sk3!itB1G73RAu zmIR~=(~)|iC?FI-?sbf$t4u&vK9g*xEI})B)`fOlmftl{L2ANP5bbn!RJ}C+dk2|i zJ5bq#zKX;8QkbQw-CllvfXuY9%BfI}BHd?AMkvNcE)vv*+_@(kO&YZU{y3|qZi4)% zJ6`!^>%@LA-#jReb4D)rTpMMTfQ1Q>maUo>Npv5nxx~-k+-dkbO>ceB)xuYi7iBkL zEiW(^uFbUCBTw4!JWV8#xE3B`oKH|P+1VloFy3Lh9#;1u+uakK>ZZf_6hbzT=VkaQ zDUwLDLkV$%mPh)e;pRQz7(d91PW`aB)mO1FjzL?`AAhee0ir9%ea%9WB84d#|-K_5^){eT}|9t4oz$C zfBOz?;7QM!IH+%2IQ=-Rak{>sa>Q#bgY%VaXTI!I-@VO0G<8-r&S`p0#KMHg4fWq9 zE0nLie*9g49iQKKs-%=@orBZcuBOym9fOhua&hogacfwoe5Q#Q1P&-6|Lk%`J;xpw z$V-qoWKVY54Gx@kfsIR;TNjEf3?&*xUyH0y&ai|Flnv zEj&-F-WMk6C!z{huxiWK;r8pTamzBvuw5fiO%0icTl07|O=IyGNL`0zhjh_?cFvER zsIaBE5jAE{b0P1iIJa{-kVhN|&7>aIIP7#IPA73Ar~=fxPOELG#dD|Z$33|u(*ymQ17 zc3x9R4gBCuZc$KX<0&F(R8Jk`p7;GCByq7Pm+1i6N)!LhUEBdcnPso;`>#u*($Y+n zxPlAXcR9+y{YM;Z!9?+yXzi~$S zS-j)VR&!5HdA+UCkh*Rgckmc>7)_--xG}+pc%5-Jb;;++BKp1bku@Yti5FR?k5+*B z*T|{K!{|dOF8(W|b(Ef8i=QiDRz)u%1s(}Tx4R%UQ(YN8opWKujGJ3Y&2OXZxa_5f z!u*#UCH%<~F|S7q8rK`N-`el*-Ce2VRNkM0--UKEr3!v@j6R;6Y;OcJ-iSN*cVke_ z4CwW1WRR1aj_eZ$u+?6-8Z~7e4HV1}bp-nVt}pa}NNUXcJ*sr4=AU>-p?aSJF!PwB z9k@qujaBq3R(U3q-#lxv*jXN(FJb`DVf@Vcv#U!tH4~d4FQ`Y{gi`lA4}Al5fL>Xm zicp%J6T{S1?xC4+%Al11V=z3h>P|3bbJn__0dw(bwVWiA%m zQRsJk6N=V)E;qOZ{nTo0%doZ-27jEs{qZC3*F;V#w%K{R-Enw|kP~rW%5uS{AOcHL zKQ(3=TZ8G-v0F)^7I3ra8)@V|o-I;+XD;M_gE~7rvHya5VS#7At}Vr*vbsI`CXMd% z4G-)}O)f@ZBE1SFbolt?nJjM2dIF@+)VdSE>HqYp^Ko_!P3TLdTk_VRp9FAVI&rny zzd~*pb1L^bDye`LIEm5z@k)&9#~uEcVn-jaRcTDnzzws6dtuFH(L)jFoaQ-kBOWdR z3H^DwroI#|*Xx%8{>_-1YWaOw4q{qc#;o{nrqmY(12l=9jVYzKYX??|wh^ry@nN4k zp1-7&BM!DOFAAGHuv_&KppI13j_^%Q9x=S&o!I=fr1t>bo{I(oiiR;oh&ae(tz04K0(PaiU#?W#Lv$#&kZ$Ty z8@iZvl3;dy=U)>&o?BtR7n={{me985bpfy+}@W1$E@O+JU^GW_!_9c!z)IylD$vtpN6_6?=mB>ksYCGbjMEVA0oV|2ISUGXI0-noTnar*wp8?MDH?gPn4IY%$eHy3&8&(;AYExUWgUB|?3P_jYo09| zz1JC_Sr6bySW4rEqG?dmhhlaxheeJ_VFeKADI3eScOv_8AD_%O@l+k+EN9Nx_qdPW zd8>ElKPY_S3;4h4a{y}iNls8@-d(#3%xzG|(ruwe5aOvGf_%477slgoTr9EF1cz(?3NSz84S-}tc-A<L5IBze}l3g_1e&Egi2zB1efcB~wPoED{V-cxlW?TS2q$<{Bgyaxxs;$aY~Ei&0I! z-7yM(Qz9TEV#+p}eGy*%3ZtssI-;M)<=-7080QF1t&5dQ>b-=MF)UuG{U{7%ejpWM7T%Z#MyTgdYi(E5=o(%9Q>lySKt5yrs{EN4w z=~BZQIt9%Y-ccU`M^FAr;rR$;XUT7J#M+NwTww6A`C_*)J>JG4gJ!6M0-M=L>#|3D zlz=WB#K7z-EX*EhE1T2vh~ZL#)U;c|M@Y8K_iHc5g#W z@G44*7KLt5)Ata4_2-XEFyQ5&B8+s_;{E~kE!Kik?oTC=qJ+ZbId}e5!iJF4I6sFP z?$Js6{bzY+o40avOrpS&u5F zs?x41EvNh{u6{1yL*>JP+E=#|!s@>@W*~i>uYAl_QkYJ@P-WN*`@3)8zL#W)OnCEw zqSi_51C%;Z2>#_JS{LryGM09drclIv`d1X55@RbyD*Ft+F!xYqMx;wJ7BrWWj%^M9lKFVeJIm3{ zQxB-HXT|xBsNB=IPQ|0S!dIuK3|ZRyr9~ESK+P~33O2hW$iY%;OQOEXrA)4qew7Gm*@};hJgSnVa+7 zUod)W6sgb}Vk~`*=e=Soh$HGh2%si}Ma+8j>E3G4r_g&p#DSHtgJ>0RK*Uo59~G!Gj~cB@9?m=o(A-L@OPv4!eO zw}O=!)24HWXMZrM$V?%+{nmV+w-8H#pqhb)y3lfw>kW$HK~wS-n1*mW}ijHnbMZkwe&|UM+T}?FO0ek zB~y?AOZMkk4?wStSZ?ydD7~v6g1K3y#62o0t(s-t*7ul1Le0X@?nrA>W=)Fg>r=L7 zkNI2pgGSWvOmQ+BsG}7}F_u*#97de@Z|(w;86puT+TY@Tj5a?CGK_Bp^`^@%w0Qab z+#yn`2<%_R{f`G`dZ?rRiP*X&@<{+KKE1?!ffwd-pAqKO^7(#9rZey3*j|7EU^+!v zn8BVSpm%lzZ@&S@&>9vI$UHFE3&__QsWn%}B(OT9;gja!a21+ef`g)x`aE#Z399oL zk6Ci6Y?p;o_pM-EPnK zESvhZ$*u7Ujhz3d%Hhn_9Os5|;Rvki9@|_#8sTQ;-G9BXjaYPT*j8! z7dWlRq9PRs7JIQVbTf$WiZs`kkr^itD1A}VpXrPIch2mEb8|GavPaQpW4R$eF`#ETcMOOf4 zKSK;$W`MO94mBTk0dt7zL^Dn|dl~Vsn+Nl*3&Tvq^%{@S+&y%{&_cxvwso7&?qf@> zYcQP5iaXXh*b0vQFz~G?p@WESn&Gs)N#1dWCStOF7UjqC2#z6f4tPFVIjEfe&m^=N zPh{VWn`9^2M+GltgzHF^G!zheQT8@D*(F}}W#GXlmDi3-t&f#x8)fXcWa!d4Vb6Y^C^ySZXM0~_--5^Y=s{s+SJgmVA@ literal 0 HcmV?d00001 diff --git a/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata new file mode 100644 index 0000000000..5eb13f31e1 --- /dev/null +++ b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata @@ -0,0 +1,9915 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 19, + num_advice_columns: 10, + num_instance_columns: 0, + num_selectors: 20, + gates: [ + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Product( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 3, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 4, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 5, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 6, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 7, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 8, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 9, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 10, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 2, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 3, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 4, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 5, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 6, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 7, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 8, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 9, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 10, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 2, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Constant( + 0x0000000000000000000000000000000001000000000000000000000000000000, + ), + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + 0x1000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 9, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 10, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 11, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 12, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 13, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 14, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 15, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 16, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 17, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 18, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 9, + column_type: Fixed, + }, + Column { + index: 9, + column_type: Advice, + }, + Column { + index: 0, + column_type: Advice, + }, + Column { + index: 1, + column_type: Advice, + }, + Column { + index: 2, + column_type: Advice, + }, + Column { + index: 3, + column_type: Advice, + }, + Column { + index: 4, + column_type: Advice, + }, + Column { + index: 6, + column_type: Advice, + }, + Column { + index: 8, + column_type: Advice, + }, + Column { + index: 7, + column_type: Advice, + }, + Column { + index: 5, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 11, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 9, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x15e9797cbf96b3ab5f2a21595a5ede5becc665dbf113ae1bd93c5fdd577b3fdd, 0x2276c102a90057ccaac390724cd3e8032eaa0d5c7630b979e2f86354d46044fe), + (0x0a3757ecd8df677c56dd731a5988940130dc69375d09185120348b4c24f23f9a, 0x209e7e273d9d9254893a220d7329114fa83eda5d483437612cf638275b4d97f2), + (0x337f1898449ead1933c764ae23b48d20f646e528b079ac5cd0743d9ac8e8f063, 0x144e28d47be3a5d90eab8ec65a10b965fd83c7b34f8e4b387154f126efbbf7a7), + (0x1ba31dfd22b785ba6080c0a1378f14d104f571d6ab2ac6e650865b27296773db, 0x3c49108055aa494775123cb379dbee7ae628e193cba15827df962722a9a47367), + (0x0fdf7430975fbf9361ee6a0eef8e811b838cf64cb042d5988c669010329a8e8c, 0x1292f817500e4ef166ccf48483d061b41372ac7e44ed52b04fbf03da5b04fc79), + (0x145d45d803dfd99569e689c02583b2a63f004e25ba23bf9acc17148b42267480, 0x230efff0cad7a66c33eb7462b4b60237619e1287a6c23a122057ef0359d324a6), + (0x0ce14fcd6eef4247d75df3d38a918bd8d8c66362629ca8ca697254bf703f1dc9, 0x3cc92942c824cad0a3f16828a29dd42785485b878e459a289db7c377973f2aee), + (0x0bd58593a2e2657cd0a228b678a4a7ec04492e20768108383cfdae26613da0b9, 0x090c75a86508be75f6f57e33946c5f9170f40d08e058eb33c8370311fed2868c), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x1676bb18498c153055ba927b909ef96c5edf8108be253d7a86663f57cd815cd1, 0x0ca79754ab892586fe9df1ae7a23e527bbae042eb89e96747f3befe88c493446), + (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), + (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), + (0x11ee40a7ae1d9b3bc41a88dd50a69661de280c85222c5567ea3fc06c606558a5, 0x0c6ad5f6fb00347486477aededc92f686f6d079737fd2ca147b7db5ea7381061), + (0x33be67428155b1361122a6eddf7e24a7cbeddcce8166dead5d9d5ec6714b25f2, 0x3ec742ac0f64c3ffc4d47bbdeaba0603c55ef74d40065b84b7d738c95f473c79), + (0x11c136f6ea303c5630240788e7a4db6c3aa321aaeaebecbd473af5ace4d05248, 0x0afe33d04a38bae95c2ec4c4372b2d766369c4c5b10f82dcbd4375a41f838d79), + (0x320eb135936ed226a108ccc06bea1ce3ea57dfc2d708fc2ea868ee90330fe22b, 0x15f1174d43608cb597ad1708d2c15e6fcb399219662c75a476b34d51d7ef8f09), + (0x2157882bf836df0d37c2fe7b4c03c099712bf0f1f70475cf79a47a269cd05d6e, 0x2b21b30255ccaa0152b483916b033c38c54edaf1ae8987df41d4812affd004fa), + (0x0bb1ce75e6be204e3d006a0dd70adbc82e9babae94be0a0fcd0eba958bf78d95, 0x25af91a42e58455509f322ab700f45210e369a79cfc3635db30fa5298d46475b), + ], + permutation: VerifyingKey { + commitments: [ + (0x2dfdfeda0fc01492b0884d17870ef7c30a6a59502ead966bb6c072b216ef7b33, 0x206d9ce95f9c1bfb675cd14130a877aa70650b7d1bb5cbf82f3fbfa517c2a19a), + (0x001deacc3520d2f07b82695befedaee3c62c595d80d0f406f473ab3e8c362213, 0x316bcc3ef777e42b96c36bbb95b41654dc91b4fbf264e3796267716917e0b63f), + (0x142095bd2f3ceed4e0ee7eaae4952488aa314d89f4755b81bc4f4df5e849947a, 0x0e6b8ab5b49069d21ea86f1d320c2959f144a3b1f284231312ea776f337b00b6), + (0x20bdfa7afff8a496620db915f9323e348b0ea52ccb0e5ef2a26cc5edfb4a3490, 0x033516b53f25239682efb9f0b6865a1841a2f80e88c08c9431f08906bf2ece95), + (0x3b3d22054a70b22ab2f4daabb0671df492f8ae365372d34f9ed9cbf053f77560, 0x386d905cc46f526544a620c7251d661cf09ec673efafce3bd36f59295e8c8e10), + (0x23bdd78c87775077ce68d63f15349c6851d18cef963e714fad7c182172539964, 0x36df72f765faa06fdc6e79e9b71557043f1b3c32677cbe852bfb89b9ff2adf73), + (0x1f058e8d0ce9494143e267f9190d4a8a0f4fc18cee14b9cbb00fd4324d028d2f, 0x053c9574cfa8f32a4795152eb742f40752011ad9704a6b7a05fdf2d660948eca), + (0x0c116eea00a8888c4a5917f514f323b993c732ad08d9655cbcfb3ea57645c1d3, 0x1811bf498434bba922e2eb1b1dfc3025bedd7fe7aecb3837a561c1e78ee56b05), + (0x1317f5890e3c536bc205f7ecc9e286414f7abcd160903ba663f33cd37821a1ac, 0x39d386ba96759c162f980de92743c908b4808e252d04309fc5c10fb48c8f5f17), + (0x05aa4e237c2775c8105b736664b7b873a3a0a35cda546e29439fdcd87c844afc, 0x36129c33ee883439d98e23d4fb625a22df4b8b62d41702d82b59eb264c649832), + (0x2e48423c28c290a75feb9d431f59ec36e48d9e88c3ff46a9e1dfb04ed894d88d, 0x00d3bb38bca1ec15ac2e79c8e9c093fb496cca52c58f2947b51537ce718d9060), + ], + }, +} diff --git a/halo2_gadgets/src/tests/circuit_data/vk_merkle_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_merkle_chip_4_5_b.rdata new file mode 100644 index 0000000000..54d213c0ae --- /dev/null +++ b/halo2_gadgets/src/tests/circuit_data/vk_merkle_chip_4_5_b.rdata @@ -0,0 +1,3556 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 17, + num_advice_columns: 10, + num_instance_columns: 0, + num_selectors: 13, + gates: [ + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Advice { + query_index: 8, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 3, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 3, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 9, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 3, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 3, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 9, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 9, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 5, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 9, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 13, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Advice { + query_index: 18, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 20, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 20, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 19, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 21, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 20, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 20, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 22, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 19, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 14, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 21, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 20, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 22, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 17, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 19, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 14, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 22, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 17, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 19, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 10, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 11, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 12, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 13, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 14, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 15, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 16, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 0, + column_type: Fixed, + }, + Column { + index: 9, + column_type: Advice, + }, + Column { + index: 5, + column_type: Advice, + }, + Column { + index: 6, + column_type: Advice, + }, + Column { + index: 7, + column_type: Advice, + }, + Column { + index: 8, + column_type: Advice, + }, + Column { + index: 0, + column_type: Advice, + }, + Column { + index: 1, + column_type: Advice, + }, + Column { + index: 2, + column_type: Advice, + }, + Column { + index: 3, + column_type: Advice, + }, + Column { + index: 4, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 7, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 9, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 8, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 8, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 9, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 7, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 9, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 9, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 2, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 5, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 3, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 3, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 3, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 11, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 14, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 6, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 17, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 16, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 15, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 13, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 0, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x249fbac2ba4de5583a815cbd8b910c508d3c8471e095d10200319f6602a934a2, 0x1c1efe5b72b19e20d97d5250950473fa70a1e76e1a39dc7ee92dc85155a42db2), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x285e16cead69d5fef9441d4d4ac695fe8880120d209e1e631d8a4bc5f55e90e6, 0x3700fd2dfcfac5b2cb6d33c60ac79dfac3fb95518cd0aa97c75a51d62281f2c1), + (0x2dc11f4f0000da15c59cd395ea5f32b4e79783d958c290c821c89e0bcb50eaf1, 0x2c53e12ce0a2022516ef31f0224b0bc1b119861078358f78d245ba5d2f180099), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x090bd25cdb6d94445abb0e0725b39d9ddf81f52e25b9498b899337909f632e1f, 0x14d931683e644cb249223f6f48e4d06d87967206ad72749f0d1e9c3a19093300), + (0x2deefb04be65a9065b35f1a1df2d574771b7a2a3ada6ef400518861651bdac47, 0x267ea152faf5a64734664e21e4bd714522b5d9834d063baa1228f8886cb08d67), + (0x0274af29c9eeba93aa3aa9638ea66a151027dd56de2ff7ec7d4f053967bab5a9, 0x35396f0f27eac3e5714c265d4b960d5a09b60046a716a1023d61ba24b1b66798), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x0274af29c9eeba93aa3aa9638ea66a151027dd56de2ff7ec7d4f053967bab5a9, 0x35396f0f27eac3e5714c265d4b960d5a09b60046a716a1023d61ba24b1b66798), + (0x242e515d0c247f0325e9290699210c561b393979218abf784f78ff3ed8cc9844, 0x051963b7b298e4201fd2d8a11096e758726675c740fa0262710b51be2bf6f88f), + (0x071acaca7c01c1cce3358b2aed6248bd72e2a6361b564ca9e7f7e4bae53cda04, 0x2ce822c9848da7a2af1572933ebd8f97955b389bdf12da84692b6846c8eb40ca), + (0x111742d100329820af821bfd47af29d0757c9178b0333694b2c03127033d7f2a, 0x0234ec5001d0d2f2116c10414abba4bff0955151d60db379c529bc9c5f1380d6), + (0x171e04e53efcb8d89d355756d04ad508d889605f5657d71fbd21345103ee0c0f, 0x1d0e14532cf6a20ffac8815827506247ccb2f2f9a9f39b79b8d16c88758a25ab), + ], + permutation: VerifyingKey { + commitments: [ + (0x27d6e6e33d79d434b55e51a491b141ede5ecc4eb0c161a981ada1c2600c5bb71, 0x13ce7840b2a4a9845b5f6907fc4b83c7ee9c55c243861d0291cecf5c1f971d0d), + (0x04f6d28e6cdf93f68052a9a02dd64328b3906a730a82e84dbbfb161992b2e335, 0x3972e3c82d8fa20b99a98fd97483cf6236ce7202959107bfb1ad3cac29834141), + (0x00a8a177f35c265a5389f8762c37ba10b693648e27de734bf4d1d0b85d468fa4, 0x1c8e0913f09647fd23722719a8ee6e0ad88063162974df03a6f143478afeeeea), + (0x1f383528e8ad7b0bef57816d2b69f86a903920305d54ed4db0cb9f60e86c6570, 0x0ab31e4091e544be4d0b533dc084701111abc0b80b4234cee0f62807eb8954f8), + (0x32e2a0a9a45ac27fef75f34af5db629ec5b6948eee6f89466f293f621222146e, 0x09116815944e5fbb66eee196cb9dbb4eed79343eca1e8a70057574f0b99ad9e3), + (0x044d5a85c9f195e1be81dceb88e22c4513176482da2091a2c8be54414eb16c06, 0x0949f75659baae8328fa34f32d3bf1557a759f202dc5e14562439092acffbf9a), + (0x2ef67a4cc9101882c47dad1f0a48589406de8c8e4c4affb1c6fdfe575dd93540, 0x26bf1fe779fb01a54b46b3cf6f548aec904a2dcf841fcec0ac87f3109800c46d), + (0x27920d52e14715e3cf90f71901d4506eb5ff8ce823a6ec553d15c73dce1c12d6, 0x33cbceb19a235530d09a3caa72473618bbedb2b075551da1b67b3ad6f2e4ad99), + (0x02346520bb3508a53e299ec6a8c3843de3ac95c7c8eb01965f5aefe42226361a, 0x254d36cecf44efb7f70e655c144716fe7418c6c7698bb7419e66d9f34f916a4c), + (0x2c5949c614ab0738119a4881ad5a3f8d8a6c4e23d11d7dc82e145dcc9e9ad967, 0x0fb23cec4fe3480016fa82a7ce5e3338e81edd25e8c277289d869fa4067fcb4a), + (0x12a957011628382875af60bc012654739784a349c0ab2e213324d08ab686664d, 0x1ec4612e46a373400b1861c04a996b00f19d094dbd834fffbc5a36e5d77ff064), + ], + }, +} diff --git a/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_chip_4_5_b.rdata new file mode 100644 index 0000000000..467fa7830c --- /dev/null +++ b/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_chip_4_5_b.rdata @@ -0,0 +1,12042 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 28, + num_advice_columns: 10, + num_instance_columns: 0, + num_selectors: 26, + gates: [ + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 2, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Product( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 4, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 5, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 6, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 7, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 8, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 9, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 10, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 11, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 3, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 4, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 5, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 6, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 7, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 8, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 9, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 10, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 11, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 3, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Constant( + 0x0000000000000000000000000000000001000000000000000000000000000000, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + 0x1000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 8, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ], + advice_queries: [ + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [], + fixed_queries: [ + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 13, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 10, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 14, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 11, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 12, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 15, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 16, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 17, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 18, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 19, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 20, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 21, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 22, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 23, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 24, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 25, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 26, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 27, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 0, + column_type: Fixed, + }, + Column { + index: 9, + column_type: Advice, + }, + Column { + index: 0, + column_type: Advice, + }, + Column { + index: 1, + column_type: Advice, + }, + Column { + index: 2, + column_type: Advice, + }, + Column { + index: 3, + column_type: Advice, + }, + Column { + index: 4, + column_type: Advice, + }, + Column { + index: 6, + column_type: Advice, + }, + Column { + index: 8, + column_type: Advice, + }, + Column { + index: 7, + column_type: Advice, + }, + Column { + index: 5, + column_type: Advice, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 5, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 12, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 7, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 6, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 4, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 13, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 14, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 12, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 13, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 10, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 11, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 13, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 14, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 0, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x1f52e1e5a4228f86b85706beb3a38f9b8f83178b92572875e97e5d57526e59df, 0x2415bfeebebfed5e1766260161912596cc82afd7e6f6906257ae5ebb3b0ff1ef), + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x06f460c587c896f1f8284619af6d9cd7ed55ed416c6777336afab0facd2d9125, 0x0132b10308dfc29176a0ac2fd00846e89b4b098238b2f743d048460e5a853b07), + (0x30e332088e023adfd8d0a9c54ca15a08d83f6e0d5516cb51f32e9bb956bbc3a7, 0x15bef2896e132c2c52ab59d768d48d3cf7dde3e2b643953823edc4bd9977b287), + (0x3480efa9a7eaa4b42dfb9b2ce4dd7bc0a1e65ce9d04ac0b3471fcd6d5be7fdc8, 0x322895945a2c9b6fa91a2de6641244b71edeca0b11e324c086cc6fab3095c5b2), + (0x0a8b0aee714c5d0e341b1eaad1433658b97c1c2c832f6655b9646995394606cb, 0x0bb14512ec0b828353d9ce1b9c77c1a0fc8e2175a8c8ddfdaa8d8f217e90c72e), + (0x3b9a1e88e1b3fe02332edb76470b277083fc874c7b6f655b304fb6b8d5e008dd, 0x0f5cfb93dc67d5bc1e09e5ee6899e9ded07c7ab77524af9d0c438863453ff9b2), + (0x1cb469f53e7ebad3a3b9ecc6462d33c2463b02e1284ad8bdbaeb72727dce51c8, 0x0bdd0b9dd063b882e3ece64aa7235a7d77cae8233899da13fe9dd3028d7aadce), + (0x34be76efca554fa14ceb1a064ccddee241100284831edcef978f45c1e56550e4, 0x2d298f9126ea0bc22d54dd408f09e1c8f70287c13b95f2825a314e3be43078b6), + (0x1076db76ed054a8ea26563331cfb04eb688169c04ca370d09f1aae0e6fbc8787, 0x0c87eca3dec43f90e5a64cbb22c1d38de880e1e8b7156fc378ffdc99e09f7c1f), + (0x285e16cead69d5fef9441d4d4ac695fe8880120d209e1e631d8a4bc5f55e90e6, 0x3700fd2dfcfac5b2cb6d33c60ac79dfac3fb95518cd0aa97c75a51d62281f2c1), + (0x2dc11f4f0000da15c59cd395ea5f32b4e79783d958c290c821c89e0bcb50eaf1, 0x2c53e12ce0a2022516ef31f0224b0bc1b119861078358f78d245ba5d2f180099), + (0x21f3275c835d322344502eedaf3c1e2ca34db968c3353b7de0eecff447a21be8, 0x278a7d6512910d39b926c80e89400e99255b5d587e2471107a88b24cc7c4ee6f), + (0x3965d4503e0eed848f7c7ad1ae773a7de6b370bf62d4df90a6c058e2a476492c, 0x0e9b5713800ebced2820c9361a0c4640e79e3631a52952f76b479bc0f31883e7), + (0x38a3ca5237cf04483e05dff22994bd83e45eb713563584f198750f1da538eeab, 0x38f39efa2eaa6dd41a613671e7801f703b210c66ef4fb7ede78e27ebf08bb9c1), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x17049dd198dc17b5b2aeb7cd09b1c0ad03c7ca0689fb99a926139386d1f4e000, 0x391ede5a3a78c7f62e3a129a98aabe4db8380688d687518c65b64371df756402), + (0x105bbc575ca99f6c075ab242b699f535debf8f03e0e833025157bc35ab44af77, 0x0a922af92400d875e7f8c90d4ae1f8be8563f81ad28a5f6ffef820d59bc70833), + (0x3eed4304a320487e0b521e143d01ed5922c314321155b047e53b45a70a072213, 0x35f2e91b7ce9721484ee1c8e72bbcb8977fd14be04f8d49455e4c92f74393f09), + (0x027700746c221118d0eb0485be60557dbc62dc43af198036bc252de8066279ac, 0x3267381e56b1d520243f38c64f4c053f821c2ad41db7a800d8677eb3c028d5af), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x22c9b6e0b62b7775054fa64071365d777431be72465060c054703f84c5c32de3, 0x15c1ad5239edd6e2633e684b843008ccda0192ae2f66e20833125790b02a1678), + (0x3c7076b9739b9cea554d62821bfa67a54c7dd3979f9417c3114c0263782d5c89, 0x2df85200c36ffbe48f8d8b54a6efca4927f6b5817035a7237809551b4467e046), + ], + permutation: VerifyingKey { + commitments: [ + (0x3d1e00a1c0981547bb7438092484560637f53d3103c4f66a03bda4af4cddddcc, 0x13c17470d54d91215fbe83820094e338c9a014b7dd81081edcb5403dc7edefce), + (0x34015e25137a9a8ea4feb8af77f10d27fc6a04e952823f7e2343a749419df2ce, 0x2c6589a5343037dd14d33821800626bba96354283fb05011f27dcda6a6b860fb), + (0x3d8021f09ab26b5fa92940f17f6a3ffd249a13d7371339270160dd507e3ec47a, 0x357c17b35411a2576fe6d0ebfaae899c1dec623ec4612e7431b4e9244e16eee3), + (0x3b81a179faa15892c0ed66bf1cf419deabd4f8798e3a0ed8f51ec89041c95307, 0x22cd77db9da943d2cea2407ad4c7f8650d2397d2d37f88e0a3f58f842496d1a7), + (0x05712c1b5b9e1c9a059b060fde47ced732935f9892983116d73c48623d6545f7, 0x25ff6fc718c7cb5b141601930356df691c76ec71e4b7a1ea6edcbe76ef2851c8), + (0x21edbe5a41ef39292b9aaf767a6426dcbf948cd24fcbe5a637afa0622a5227ac, 0x1e1c4594ce213b7f358587417c410dadf716f673edd6f1c6ab083f08e8db88e8), + (0x053904bdde8cfead3b517bb4f6ded3e699f8b94ca6156a9dd2f92a2a05a7ec5a, 0x16753ff97c0d82ff586bb7a07bf7f27a92df90b3617fa5e75d4f55c3b0ef8711), + (0x2b7676e04e415972383e37be8fab18cf38185a04adc2693593defc741ed9489a, 0x02e764be452909551da84a24e3da0b2dfa97b6b2d141621d45c347a67f325dc2), + (0x2e69a4ecbac635b206d31d1353a1afd24cc01b280767cde458d60d256a92205a, 0x31e620808b4ce9af3cc60b5e28110aed182e4933b8296eb735ce75b2d11981ae), + (0x290d388d6512a677de8ac781b2eb99537b723088687c110ec58d633d79e3d0f0, 0x12a2bfbce2d31213582d68ff7b3a82782fa1319af0dddcaa4a44a7110d1c0fe1), + (0x313658b9ba4845eff11f69955b2b2e75721d00dbe81c333e1d6dd463df87a7ba, 0x162f9a55a73e2d8c7bee4f765ecea5d1dbacdc5b5810f938250c2ec2c6cd83c6), + ], + }, +} From ce807eaa8fbcad52be9e46bff8e09ed4c9b0bf30 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 21 Jun 2024 17:34:10 +0200 Subject: [PATCH 086/121] Fix test_against_stored_ecc_chip_4_5_b --- halo2_gadgets/src/ecc.rs | 2 +- .../circuit_data/proof_ecc_chip_4_5_b_0.bin | Bin 3872 -> 3968 bytes .../circuit_data/vk_ecc_chip_4_5_b.rdata | 1449 ++++++++++------- 3 files changed, 836 insertions(+), 615 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 618fca2c01..359013b927 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -1177,7 +1177,7 @@ pub(crate) mod tests { #[test] fn test_against_stored_ecc_chip_4_5_b() { - let circuit = MyCircuit { test_errors: false }; + let circuit = MyCircuit45B { test_errors: false }; test_against_stored_vk(&circuit, "ecc_chip_4_5_b"); test_against_stored_proof(circuit, "ecc_chip_4_5_b", 0); } diff --git a/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b_0.bin index 36bd1595fc62763d63bd07b9a43b70f23075e313..06c2f6c05fb998a2bf8de3ebed1f966f92412ef2 100644 GIT binary patch literal 3968 zcmajc=OYvh0Dy6OZ;7*$J$sz{_bxMZcet#qh_a)z z;*$OT3Gegu_wjj^VGwuvqbfFK!o12wozWZliX&1Uq&Q7XWJ10B<=+c@^`soV-^Cn7 zxA|{*+pTx`>mAq79RH}erU6B=xmM)n)%P%N^@1}+jX0}H@C;NC&8-U0O4#k@mmFE9 zRP4G~wcvq<*9-P%aQcW0h%(!4R@=`W>YS$N>ZsR3hh76WZhJoMG00!@Drzx1zDvl= zpq5Od1eMD>NV`quT#JEBFKe9yLDMnCDrLzZ29MIe za`#;w&{HQ)|HA)^g^E!z8u$Zr+hLMRm|(K3^IaY^8T>6Fbc%5Ka$2H=5~vL3XJ@0$eknuFO0cUgBJgz{&}g(dM}1W zu{t9YjicAL`r;#5jev>qsNo|yP}UcxL%w>xP~OEs;e5-QXKp=)tF-AGB3mC4%82aF z7j^;)*Tb!8dIBlZhm`dqC020k`hl$@FJUbr*Jr2WF3~X)6}%~I$J#! z7*zxOOoE~fQ@4v5&MX;lY$^9#<+y*Am79rqPRiow$JSq#+vf|lyA}KzL~~w_-b25O za$OuZKY+Hfh&d-LIm1`E<_O)&qZyj%O8^?T~GayFkgfs1H#PjnPyj}21@4jkHV zJh(OD&V6kfc7LP%UQbE)#?)@b*=3iOSH~Zy9qS)~PRARsZ`kNa%F$sn8Zy6(z|4?*>(J6xR0V4AjX|2YLoBV|J&J)gXOdf(G|zDH<8x zvw?8Af|98(IQiDC4ZP;{rW&zYX9N0reu`N{GPt+PjiV;bZU1ix!;ru4W!s-G@4bC2 z=Vm(_bi6%rMbOS1%zbR~)1AkPgG7cP6&9^S^JY?{O?b}imc!&H6f7BxI z{V{8eZkyS!<1O#+6n-xwc4qEftQ985M#oW=aZAro#QOfW;t}{Yb&q@oQqZg;fVY=~ z&>H1q^Pjg@vgv~*5>mEye5{L1SXX8SDDl)hYqxzyXULu+C$t0xjUE`t^0n#%0r240&V{r{JPNRrg zty4KE^`kX5GI%fWAEr54SQEubMlK=SOvHx%ZO3kZvqTEO5+pT5d}{G>u?|3%n7)(D z6%VIP8BHc@sGJhzv$CZv+1iYRs$S9|w6-xFd&&Xj)$gR013WC#P17(x6>pJVI8 zB<#%|y)f2p=8ZXwqdEjAM)p5VPI&aJL^$)jF6Q70Qn!)5KObOd^c#0Lyk@jz+L1!X z0y=7-ufF|OIOp5wr-vfRGG2||M-OM`V3@RNF!;G*K{SOBAbTo$G#%7ie%^l8`?K&@ zHOd4OIcLBo+-6JB*92$C@1l_tm|#A?F?_paYCmYIX1u;h@IJUco{&SC=b^mK*c23S z^oG9AyF`qs5uPWZO05@Y=xU|zR`mm1?@ZFG!HPwSkNL{ZB6J`4z>)_ou9dO% zgypDZctRvRcV}D*p(dIK_DVGA@K@fGH2>3_s7A)2i_!aSZ4kIQ5w}?m^I|hO*qe)A zTDS|e-Vk%^JA@_m`%CO58Lywbd8;l)Ap=-Jd4z#K=N|iLU0yun6XHt}=G2){&yL@exCE&!skm?z0uUolg_QG_<>z$IY`z!VqUENaecZ53A8t5mI$c(W|27-_ ztG{J>{wXiAiu4SX`=)N_OP8A+k9M8Z#OR4#G_B`&kyu6VdfHxcO00tHo#2Go9S8q4 z@<*VR`#KtYG#d*`Csh+wwp;{7{vQT=;_|P!cSZNdK@HSdpX=Py4y)TOtc=I_|FpVF z^*jyUaaq)okL)V!(IgPaVpHbDn}r&mvUNPFn-h3fADMA0h(gy@5&t9@36jA^xqE4Z zL^2Z9%zP_uQ} z2!R{%@*xHyu(vUxL1D`@(k3anesHGoWg(vo8n2ta?vLXOT0WUS+0fRs7xpJGQ z=(`m!(J&ALtR1NC$gRmkg?~VWU$T6$iJzU@O}8>(V142P z##2M8Er`d=`S>mPjp!g(J0W3Rpwa@kG$*i=uq^Mx06neb7o@C=^~0*YrL3jzGS;CK z*8TvgUF0qjx+kG8d?R05BrOzBlc-4|tr>@FBv3AktXTqz6Jb?LK6u%tZPoa+G>>HW z_T48@hEdU9kJO80wY7E(a}C4uSUcfs)YBfvj=9|)~!Xm-CL$m z&YgJ~F`=!9QbPX48&tzBabtVI)5zta+HmW`_8~q4-Ui-_7Ap5QZ{-HWA62;3ev_n2TZSi<2e?5*5k`=ky$`E@A{Ae^8hEdlB}coKlLS4%Z^gd zk!R&^d;4^sG2AamN-ZM~bqcD3saZv6T#87A7TP6thSi3(HCFER#VPsq#wRCz^8#i4 zz9~SYF?LfZ&b}XrBXqzA|7CqD%U$_1ywfRmf@ip>q_>h4CT?C=f6T?BS8^=4Krb%C zaXFHSB3Dsd=6%TFPs>}3fdR;&5Gp8Pj0s4+momZf*x_9={c2$R@vRJkJl#d9!NQleF`~Toku}VX4XB*zh(eHsr*moiKk9m^c~gb=i;VoRabo^Phi zpA49AGi^nY3RMtu<*nKsBhdVsb=4T<5U$Gr@t_2Fse)O}>hrg>)sxAlfB2EOG^%=v zm*Y^^dYCI~RFOfj85bzp^)$Hu1<_tSx14J}E`L8a9N|FkEh!V4WX zEWKq)APz!Qq;~n{_S|rICUArwk8vuqvPN}q#;M0h!`c~-n_^fPC^S3Y4_*;S>{+vl zhT4~@^z0x6_ZwT=?E+9JOQ5UVriNbm$@xf0Rs2>Pw~P#MJ3@ z;dKxUrU8A@Q&2JHI4E}KDzqJcV2uI+v|+)$6vRr_GipdoXr+7ysqIa{HNxz3aAXwisY0DK-;v!EepZVjiom? zk{wl_*HFQaHq^8({3~>cQ@vQLfTSYf+Xid}M{Xg9EQ+G-*#edJ5GY3VF+*czSFt!w zNtz%2S3{A?bMc4H`OhiQ*?;mBgaRZ^QfC3iHfC!IenwzMkNsW{I}~Yb+=ckZ%qsi` D^HYH~ literal 3872 zcmajU^&=b%0{~!oy1U~r-R2y|Y~s~1PHdWqX~rE6r{l$R9gY*5oQa9yon|{7!?a;K zP9NW&@IAjikIOOxy`W|BC}8fsHb!m;|F>p4+uq^?7fCbDdBL#?GHzW@prUoeAvskm zXP!vbF_=)MLD~yx6zW{yifj zrh{8+Ekrz5k9|R>G3+^4yneC4xB&Sad?{X%#)>pR?@O;B@UKCr^V{SfauPi&Vw4`A zlUQq}m!nRp9dN?H<^$H^me5Twu2-=aWZ2^wE*}cEnZQ95WfObd)Hfj7!b|1Q8>=<`|J**ls$FmM zw+ptCzS%csKPj5^X-%eh+`RADyBVr*_g>e!l>d%MFb+5R>ORIXObAA5`b z8at*Da*A;>;v4Ko?z78{R`PeD&X&*2MBj(z!v3y8Q1&Txi<{~&+Uk#bOw{djXIl9c z=d`RLQZbUG`Xxy(V<~8y3KW&*AvD6v z3#%FN2o1=X@al|Ki-qfHn^JVp*UWQCR{t*YJdCu~vHc!f!7CruSR?&(>yT_2pVi(O zlpaXYowG-q?LpPwOX>(&u$dHdC9>x zhb=M6%jI5`tZ5`<{Bs>!G}R)`#Mb+7t@sL=*e3f+v?27H3(YYkyYM z&~HgG%%xQ4+-6yG7k@!#B+oK-4~Y`G9ysF4d|uoDbozPGcV>K|USybqK31<4T$Aku z)1{_eS`(|3LLLE-)Faa~fi?FCOZjix+K&;KlSi9uF$?=z?owerzp9iyo~;*ZwigZr z5_yYBhBNOEuD?{{-~H-wm)4@QZm9ngMFAJT$0=*<2(ddAMa<8|>|8K#{phvXx+Nxh z+|D)0LWFPzn$W7avypXL#Em{DzwL{_Aa`1*lgFhJ9Jy^5gTPpr|JVZCH9a6b#y%l= zq-cdHpRJEtW*CI`f3#&d^4E_|7M5vS-*Q?z1axk{J0wbY$gvFUqir-jBB_{+sotlO zW|&Fv%`{~l?~?3fO2d?g!{CFD$0`<2@vG@5mEjPdSi%oaQ(8fFPPjN<1~^c zgL`L1i2=G*EaDwt1@Vd3kp@g{ z`({BG7rs>|DS0o{jN6YALYwWp5LuF~{N8mh7xgGx<9m})ZAMD;!Z`osBja7gF9#X% z|7mX<9}TGpTTYhT4B~rsq!x#lZVtX*J47J)%jvafHp=Cw-f}2r8DVlIYW_5~>x6*U z_zT{pflwdvqlu_Zyerkcs=26SS8+ z*r~`7)*6)e1l17?#UA)Wyn1t4VpYy}??S8lZ}q@X)IiddxH#}+qxWwJWySb;7`IgKbs;KC(Q*dli?`1leUW$aV_SG{!Fa!D!=U z2Fb0_k<;XQ7x5Da?{c;#fXG~_SA{Shiz?RQ2*{MDJ<1m>m4VCB_rr>L$ec;*>pUgV1HFP^6^ z6yF14^Dg|VUZ-VEIoJne3YF-ot$2>{sInLT>zndPTkp7e_xjRfaDev~0uv1uN6ZTMON}=eDWFf8&cOq*G)t?Y5-H6XDVuxQ>|8!k9*o?Q~h+ zsh@n#-cgx9{fgB52?nxjOKy=FN%%lrUfu(_yfwTjmx8O^ce9UTn;tFo&17r2e-+%r z$GRiSBzAg0Q^##mp-1D@G`%`+tQk1Lx9RlJcTBuTHa-8t@{S< zo)Jh626w1+rA~+FA*aAS`~w3Cr59%S6r0vgYGT67=l>)bPZTineiPnVn_oWZFL@*s z$(DEE!FaW#xpKC%iyYVoM5$KuhOj%M^G6H`y})Zk41yrMUsOgyqsomgJbvaCmQjUD z69)cfjz78(CLKFtjUihki3qk?EwlEiyxtGzO}m`;qnNk#J=~X_Ee`0GY~vZ_x5k*t zY@+!O&?}QSeaf_`8cwqy_Z~<4w~ET0?OFgKVcV)eG>I_(zG#^}e;5L77Z-cREI zqJXtcn5^GZmR#VZU(_X=v%{}Uh_odDZlb=8Hx*C{2Wo+-ir2JNmKKQX`mFCz> zaGVwX29H0On_&#WWQ|VTDazf?IVAL8h6ePHC)hoDRQlGzydCmf-c&bN>E!Suf}ai`YmQ2TGMwKxhfuw1Arg(zGzO1|m5Lw*SrVHMh!`AQcM{?t)Z*&MzV1dA~` zAWpRO_$;rL|Gj=#E4YeX@zX7tfLpqMNJm`pXg)9W#ho#>V{lVq_0%e=UwY@K0tHXE zmHz8p_76i*4SrcFqn(693@s-yUxgf2gaOQsz^a$Cac4Lw} zx!hf$bSLbhLe>HVe&yo~7$;3m8+I>o!RnFmeh)#Q$eLdU2Q=|!9@7Tcgj%fT7|0U= z#-9-kx0@+QdF0AiQyL$nY<$t5fCWq3VTsvpJdV5??ngOfIgz@B0Y z&~5keo8!%VH>zzP%2Zz4KYxf|FBEI1Rd)?jCf#o=Z?{u25Ep!P&B+5(C6K0;`U1O! z6nOp&fhssKJ6hN_!Urcb9hYAT4*iB)_bB0F%Zg^`GpL`i80>F_1S{e4nZ}O>YUx`R*R6ZifT2aa9TjPKl+W4Ab1@2cO%~9@}?Sm4Eu*mHz2mb+1R_ z^3eUrNm8Vdm{ByPsvr2_c&fBC1KAfCg*1A8lJ=*^mSPRy-05NyI?s4exD*52<|xN< zjM%sw?W&$H^Ua8YtrwSpe3y|HN#_-(cjZR$H898eC}2^6&#i!yd!8KDIF6TH5NSBp zPeZS%3bvSUqD0FRw+JUc_4c@`w@Ct}Jndl|BRBy6^Q|7ff=))sbGGrBcKx-Gk>G)c zA$>$_yUS-rTb(C|JqZ)sgel7!g{L5eZv*4BvyR7%d1H>n%bF+k-e}6)c~|F!(lJ2b zdZMu#w2axr8a^2P>wzYVLs@yolR`qQSS4>X9DO3*_ zt(#XWL$^pm!re*z_DRuV&U;JV;3xX=>(3Z&cq>^_lUaQvPYCUsb4gZYzoefgNvqie zuP#~wZu*_e<4hPr{S1(oz!qBHTsD#gvDUuHCH8~+G`zhT8+WhltP`J0;j*4J!DoH1 z2y%ko0B#oqsvnq#db;E)$WOCo=^&1nIVm3w<*+OT!S SQl;V4R98V^kwR@n(EkAA9&U;N diff --git a/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata index 5eb13f31e1..5005d3dafe 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata @@ -7,10 +7,10 @@ PinnedVerificationKey { omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, }, cs: PinnedConstraintSystem { - num_fixed_columns: 19, + num_fixed_columns: 22, num_advice_columns: 10, num_instance_columns: 0, - num_selectors: 20, + num_selectors: 22, gates: [ Product( Product( @@ -18,8 +18,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -30,8 +30,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -45,8 +45,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -60,8 +60,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -75,8 +75,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -122,8 +122,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -134,8 +134,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -149,8 +149,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -164,8 +164,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -179,8 +179,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -256,8 +256,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -268,8 +268,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -283,8 +283,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -298,8 +298,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -313,8 +313,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -389,8 +389,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -401,8 +401,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -416,8 +416,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -431,8 +431,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -446,8 +446,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -514,8 +514,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -526,8 +526,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -541,8 +541,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -556,8 +556,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -571,8 +571,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -694,8 +694,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -706,8 +706,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -721,8 +721,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -736,8 +736,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -751,8 +751,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -844,8 +844,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -856,8 +856,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -871,8 +871,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -886,8 +886,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -970,8 +970,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -982,8 +982,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -997,8 +997,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1012,8 +1012,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1109,8 +1109,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1121,8 +1121,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1136,8 +1136,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1151,8 +1151,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1253,8 +1253,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1265,8 +1265,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1280,8 +1280,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1295,8 +1295,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1397,8 +1397,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1409,8 +1409,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1424,8 +1424,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1439,8 +1439,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1539,8 +1539,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1551,8 +1551,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1566,8 +1566,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1581,8 +1581,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1681,8 +1681,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1693,8 +1693,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1708,8 +1708,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1723,8 +1723,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1781,8 +1781,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1793,8 +1793,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1808,8 +1808,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1823,8 +1823,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1881,8 +1881,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1893,8 +1893,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1908,8 +1908,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1923,8 +1923,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1981,8 +1981,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -1993,8 +1993,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2008,8 +2008,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2023,8 +2023,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2081,8 +2081,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2093,8 +2093,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2108,8 +2108,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2123,8 +2123,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2210,8 +2210,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2222,8 +2222,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2237,8 +2237,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2252,8 +2252,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2340,8 +2340,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -2352,8 +2352,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -2367,8 +2367,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -2382,8 +2382,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -2397,8 +2397,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 16, + column_index: 16, rotation: Rotation( 0, ), @@ -2493,8 +2493,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2505,8 +2505,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2520,8 +2520,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2535,8 +2535,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2568,8 +2568,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2580,8 +2580,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2595,8 +2595,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2610,8 +2610,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2643,8 +2643,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2655,8 +2655,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2670,8 +2670,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2685,8 +2685,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2751,8 +2751,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2763,8 +2763,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2778,8 +2778,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2793,8 +2793,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2951,8 +2951,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2963,8 +2963,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2978,8 +2978,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -2993,8 +2993,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3088,8 +3088,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3100,8 +3100,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3115,8 +3115,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3130,8 +3130,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3320,8 +3320,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3332,8 +3332,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3347,8 +3347,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3362,8 +3362,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3428,8 +3428,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3440,8 +3440,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3455,8 +3455,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3470,8 +3470,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3628,8 +3628,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3640,8 +3640,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3655,8 +3655,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3670,8 +3670,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3765,8 +3765,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3777,8 +3777,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3792,8 +3792,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3807,8 +3807,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3934,8 +3934,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3946,8 +3946,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3961,8 +3961,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -3976,8 +3976,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 14, - column_index: 14, + query_index: 17, + column_index: 17, rotation: Rotation( 0, ), @@ -4073,8 +4073,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4085,8 +4085,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4100,8 +4100,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4115,8 +4115,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4130,8 +4130,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4164,8 +4164,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4176,8 +4176,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4191,8 +4191,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4206,8 +4206,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4221,8 +4221,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4255,8 +4255,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4267,8 +4267,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4282,8 +4282,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4297,8 +4297,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4312,8 +4312,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4379,8 +4379,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4391,8 +4391,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4406,8 +4406,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4421,8 +4421,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4436,8 +4436,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4595,8 +4595,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4607,8 +4607,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4622,8 +4622,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4637,8 +4637,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4652,8 +4652,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4748,8 +4748,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4760,8 +4760,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4775,8 +4775,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4790,8 +4790,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4805,8 +4805,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -4996,8 +4996,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5008,8 +5008,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5023,8 +5023,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5038,8 +5038,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5053,8 +5053,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5120,8 +5120,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5132,8 +5132,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5147,8 +5147,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5162,8 +5162,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5177,8 +5177,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5336,8 +5336,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5348,8 +5348,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5363,8 +5363,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5378,8 +5378,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5393,8 +5393,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5489,8 +5489,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5501,8 +5501,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5516,8 +5516,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5531,8 +5531,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5546,8 +5546,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5674,8 +5674,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5686,8 +5686,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5701,8 +5701,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5716,8 +5716,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5731,8 +5731,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5802,8 +5802,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5814,8 +5814,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5829,8 +5829,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5844,8 +5844,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5859,8 +5859,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5968,8 +5968,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5980,8 +5980,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -5995,8 +5995,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6010,8 +6010,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6025,8 +6025,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6078,8 +6078,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6090,8 +6090,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6105,8 +6105,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6120,8 +6120,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6135,8 +6135,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6176,8 +6176,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6188,8 +6188,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6203,8 +6203,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6218,8 +6218,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6233,8 +6233,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6272,8 +6272,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6284,8 +6284,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6299,8 +6299,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6314,8 +6314,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6329,8 +6329,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6361,8 +6361,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6373,8 +6373,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6388,8 +6388,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6403,8 +6403,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6418,8 +6418,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6482,8 +6482,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6494,8 +6494,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6509,8 +6509,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6524,8 +6524,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6539,8 +6539,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6606,8 +6606,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6618,8 +6618,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6633,8 +6633,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6648,8 +6648,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6663,8 +6663,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6759,8 +6759,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6771,8 +6771,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6786,8 +6786,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6801,8 +6801,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6816,8 +6816,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 15, - column_index: 15, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -6906,8 +6906,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -7146,8 +7146,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -7169,8 +7169,8 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000001, ), Fixed { - query_index: 3, - column_index: 1, + query_index: 4, + column_index: 2, rotation: Rotation( 0, ), @@ -7205,8 +7205,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 4, - column_index: 2, + query_index: 5, + column_index: 3, rotation: Rotation( 0, ), @@ -7264,8 +7264,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 5, - column_index: 3, + query_index: 6, + column_index: 4, rotation: Rotation( 0, ), @@ -7346,8 +7346,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 6, - column_index: 4, + query_index: 7, + column_index: 5, rotation: Rotation( 0, ), @@ -7451,8 +7451,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 7, - column_index: 5, + query_index: 8, + column_index: 6, rotation: Rotation( 0, ), @@ -7579,8 +7579,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 8, - column_index: 6, + query_index: 9, + column_index: 7, rotation: Rotation( 0, ), @@ -7730,8 +7730,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 9, - column_index: 7, + query_index: 10, + column_index: 8, rotation: Rotation( 0, ), @@ -7904,8 +7904,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 10, - column_index: 8, + query_index: 11, + column_index: 9, rotation: Rotation( 0, ), @@ -7925,8 +7925,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -7961,8 +7961,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 2, - column_index: 10, + query_index: 3, + column_index: 11, rotation: Rotation( 0, ), @@ -7972,8 +7972,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -8033,8 +8033,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -8056,8 +8056,8 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000001, ), Fixed { - query_index: 3, - column_index: 1, + query_index: 4, + column_index: 2, rotation: Rotation( 0, ), @@ -8078,8 +8078,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 4, - column_index: 2, + query_index: 5, + column_index: 3, rotation: Rotation( 0, ), @@ -8109,8 +8109,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 5, - column_index: 3, + query_index: 6, + column_index: 4, rotation: Rotation( 0, ), @@ -8149,8 +8149,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 6, - column_index: 4, + query_index: 7, + column_index: 5, rotation: Rotation( 0, ), @@ -8198,8 +8198,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 7, - column_index: 5, + query_index: 8, + column_index: 6, rotation: Rotation( 0, ), @@ -8256,8 +8256,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 8, - column_index: 6, + query_index: 9, + column_index: 7, rotation: Rotation( 0, ), @@ -8323,8 +8323,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 9, - column_index: 7, + query_index: 10, + column_index: 8, rotation: Rotation( 0, ), @@ -8399,8 +8399,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 10, - column_index: 8, + query_index: 11, + column_index: 9, rotation: Rotation( 0, ), @@ -8420,8 +8420,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -8456,8 +8456,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 2, - column_index: 10, + query_index: 3, + column_index: 11, rotation: Rotation( 0, ), @@ -8467,8 +8467,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -8528,8 +8528,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -8657,8 +8657,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8669,8 +8669,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8705,8 +8705,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8717,8 +8717,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8753,8 +8753,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8765,8 +8765,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8814,8 +8814,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8826,8 +8826,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8866,8 +8866,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8878,8 +8878,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8907,8 +8907,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8919,8 +8919,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8964,8 +8964,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8976,8 +8976,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9049,8 +9049,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9061,8 +9061,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9090,8 +9090,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9102,8 +9102,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9170,8 +9170,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9182,8 +9182,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9218,8 +9218,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9230,8 +9230,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9273,8 +9273,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9285,8 +9285,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9571,7 +9571,7 @@ PinnedVerificationKey { fixed_queries: [ ( Column { - index: 9, + index: 10, column_type: Fixed, }, Rotation( @@ -9589,7 +9589,7 @@ PinnedVerificationKey { ), ( Column { - index: 10, + index: 1, column_type: Fixed, }, Rotation( @@ -9598,7 +9598,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 11, column_type: Fixed, }, Rotation( @@ -9670,7 +9670,7 @@ PinnedVerificationKey { ), ( Column { - index: 11, + index: 9, column_type: Fixed, }, Rotation( @@ -9740,11 +9740,38 @@ PinnedVerificationKey { 0, ), ), + ( + Column { + index: 19, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 20, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 21, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), ], permutation: Argument { columns: [ Column { - index: 9, + index: 10, column_type: Fixed, }, Column { @@ -9794,40 +9821,111 @@ PinnedVerificationKey { input_expressions: [ Product( Fixed { - query_index: 11, - column_index: 11, + query_index: 12, + column_index: 12, rotation: Rotation( 0, ), }, Sum( Product( - Fixed { - query_index: 12, - column_index: 12, - rotation: Rotation( - 0, - ), - }, Sum( - Advice { - query_index: 0, - column_index: 9, - rotation: Rotation( - 0, - ), - }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), Negated( - Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( Advice { - query_index: 1, + query_index: 0, column_index: 9, rotation: Rotation( - 1, + 0, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000400, + Negated( + Scaled( + Advice { + query_index: 1, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + ), ), + Advice { + query_index: 0, + column_index: 9, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -9837,13 +9935,36 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Fixed { - query_index: 12, - column_index: 12, - rotation: Rotation( - 0, + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), ), ), Advice { @@ -9856,6 +9977,96 @@ PinnedVerificationKey { ), ), ), + Product( + Product( + Fixed { + query_index: 12, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), ], table_expressions: [ Fixed { @@ -9865,51 +10076,61 @@ PinnedVerificationKey { 0, ), }, + Fixed { + query_index: 2, + column_index: 1, + rotation: Rotation( + 0, + ), + }, ], }, ], constants: [ Column { - index: 9, + index: 10, column_type: Fixed, }, ], minimum_degree: None, }, fixed_commitments: [ - (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), - (0x15e9797cbf96b3ab5f2a21595a5ede5becc665dbf113ae1bd93c5fdd577b3fdd, 0x2276c102a90057ccaac390724cd3e8032eaa0d5c7630b979e2f86354d46044fe), - (0x0a3757ecd8df677c56dd731a5988940130dc69375d09185120348b4c24f23f9a, 0x209e7e273d9d9254893a220d7329114fa83eda5d483437612cf638275b4d97f2), - (0x337f1898449ead1933c764ae23b48d20f646e528b079ac5cd0743d9ac8e8f063, 0x144e28d47be3a5d90eab8ec65a10b965fd83c7b34f8e4b387154f126efbbf7a7), - (0x1ba31dfd22b785ba6080c0a1378f14d104f571d6ab2ac6e650865b27296773db, 0x3c49108055aa494775123cb379dbee7ae628e193cba15827df962722a9a47367), - (0x0fdf7430975fbf9361ee6a0eef8e811b838cf64cb042d5988c669010329a8e8c, 0x1292f817500e4ef166ccf48483d061b41372ac7e44ed52b04fbf03da5b04fc79), - (0x145d45d803dfd99569e689c02583b2a63f004e25ba23bf9acc17148b42267480, 0x230efff0cad7a66c33eb7462b4b60237619e1287a6c23a122057ef0359d324a6), - (0x0ce14fcd6eef4247d75df3d38a918bd8d8c66362629ca8ca697254bf703f1dc9, 0x3cc92942c824cad0a3f16828a29dd42785485b878e459a289db7c377973f2aee), - (0x0bd58593a2e2657cd0a228b678a4a7ec04492e20768108383cfdae26613da0b9, 0x090c75a86508be75f6f57e33946c5f9170f40d08e058eb33c8370311fed2868c), + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x0b70f6f89e88131bb5ab28571ca837a4160b51998c6ced04328991a5c3bdcae9, 0x2cee3ef6523c2d36e01981c4794271d53fb47e9c5480b982a2ff3a869144d648), + (0x0299c2272092ebe4e08c73d7261afea742a7dc29ddf73ffb941a1c9c19dcf4a1, 0x1f002552d6af287e66e3e9706ecc2a5523f256bf2c6eeb995b4233f80c8c4eeb), + (0x28fb28941b09f9878eab1ce7923578b332ca794e3036789016fc6f832e820a37, 0x0e1fa37a3b4298c8df50b830e32ed5ff0ea40a0f8fbb1f9bb4620b8cfdcacf12), + (0x37de994248cd221c19cc8a5f354769ecc7e3ac253a4387dbdb8a25934d602225, 0x1c3d47b5ba1cc80af1666afaa42c97043c2b793e48a9c362a398adbf4cbfea78), + (0x0f2ff7cc3b300b9e92d481dfc01b84968a21937691ef5bb84cf7b7ac4bb56f8c, 0x010616d33ce6482c9958f2678cea622493de8477527fea737feb8fad11fc2ad6), + (0x2c40aa103ee1123360d1e47947f6ebc13ecddfc679514202b33f02a45ede862f, 0x2988d36fc6be72b80ac26c8253f72452e0db13387ab35c86d97cc03991cd9bb2), + (0x02fb26d5aa81b4fd2ba3324ae48a27a3e89a90005e4daebfb8004697379f235d, 0x0b484b92ea252f7a58c5bd41cbcdcd9efb932482c902abb4ae3ccb2c90912173), + (0x22e2076fb8f40364e7c733c89be2039af2d0976a5a240ef6f05d9b67f5861b8a, 0x1b9f2382c80f971341343fbfd1cfa3a3fa84d70310e7a8fda21a21e20fe9b0a2), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), - (0x1676bb18498c153055ba927b909ef96c5edf8108be253d7a86663f57cd815cd1, 0x0ca79754ab892586fe9df1ae7a23e527bbae042eb89e96747f3befe88c493446), + (0x2cec31b1d071d872bd6b1e0660840e27bc6247398c917d5dcb09354d3175fd68, 0x0812dfd78e8ec30827f658cfb64f4f253458d0fcac102af2639295659aaa75a6), (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), - (0x11ee40a7ae1d9b3bc41a88dd50a69661de280c85222c5567ea3fc06c606558a5, 0x0c6ad5f6fb00347486477aededc92f686f6d079737fd2ca147b7db5ea7381061), - (0x33be67428155b1361122a6eddf7e24a7cbeddcce8166dead5d9d5ec6714b25f2, 0x3ec742ac0f64c3ffc4d47bbdeaba0603c55ef74d40065b84b7d738c95f473c79), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x0a7b6a62e3771fea1024172f8fa5ae0a8b6b63d96dc2cd5794a0d61be93c5230, 0x2664583fab5a71ea152a5dc10512917a6b927ca607008db40abdd06dbbb0aedf), + (0x149ab89afd559c4dab808f183828cac2c3c20ce9311ecf7280e03bc9881fd783, 0x2ffd5de1303205066fd7a1540ed79a47baad27532dfc1de2fb708cfde51be867), (0x11c136f6ea303c5630240788e7a4db6c3aa321aaeaebecbd473af5ace4d05248, 0x0afe33d04a38bae95c2ec4c4372b2d766369c4c5b10f82dcbd4375a41f838d79), - (0x320eb135936ed226a108ccc06bea1ce3ea57dfc2d708fc2ea868ee90330fe22b, 0x15f1174d43608cb597ad1708d2c15e6fcb399219662c75a476b34d51d7ef8f09), - (0x2157882bf836df0d37c2fe7b4c03c099712bf0f1f70475cf79a47a269cd05d6e, 0x2b21b30255ccaa0152b483916b033c38c54edaf1ae8987df41d4812affd004fa), - (0x0bb1ce75e6be204e3d006a0dd70adbc82e9babae94be0a0fcd0eba958bf78d95, 0x25af91a42e58455509f322ab700f45210e369a79cfc3635db30fa5298d46475b), + (0x3e360352e498a60f895216359624fcb58372ea0c8acf99c7ffd5678eb018fbec, 0x2821347d5fbae5e9ef8ea16c9b1014b44916bb73ad287ba747ade3c636dcc4e5), + (0x0a3b507e0fe0189f45a2eff60e8fc488da60ce3550391e82f7ec7a1941898c24, 0x3bf48f50d5987b0740eba87e833abb6327c3017dfa065777f3a4f06a555fd12b), + (0x11d043ef781774cb85fa85951ad4acfc4e8de1f4c551cfc677e3f8ac6490224c, 0x239a09984bfe5441f05d454b7da0cacc0797978b17bab820cfe538e748053022), ], permutation: VerifyingKey { commitments: [ - (0x2dfdfeda0fc01492b0884d17870ef7c30a6a59502ead966bb6c072b216ef7b33, 0x206d9ce95f9c1bfb675cd14130a877aa70650b7d1bb5cbf82f3fbfa517c2a19a), - (0x001deacc3520d2f07b82695befedaee3c62c595d80d0f406f473ab3e8c362213, 0x316bcc3ef777e42b96c36bbb95b41654dc91b4fbf264e3796267716917e0b63f), - (0x142095bd2f3ceed4e0ee7eaae4952488aa314d89f4755b81bc4f4df5e849947a, 0x0e6b8ab5b49069d21ea86f1d320c2959f144a3b1f284231312ea776f337b00b6), - (0x20bdfa7afff8a496620db915f9323e348b0ea52ccb0e5ef2a26cc5edfb4a3490, 0x033516b53f25239682efb9f0b6865a1841a2f80e88c08c9431f08906bf2ece95), - (0x3b3d22054a70b22ab2f4daabb0671df492f8ae365372d34f9ed9cbf053f77560, 0x386d905cc46f526544a620c7251d661cf09ec673efafce3bd36f59295e8c8e10), - (0x23bdd78c87775077ce68d63f15349c6851d18cef963e714fad7c182172539964, 0x36df72f765faa06fdc6e79e9b71557043f1b3c32677cbe852bfb89b9ff2adf73), - (0x1f058e8d0ce9494143e267f9190d4a8a0f4fc18cee14b9cbb00fd4324d028d2f, 0x053c9574cfa8f32a4795152eb742f40752011ad9704a6b7a05fdf2d660948eca), - (0x0c116eea00a8888c4a5917f514f323b993c732ad08d9655cbcfb3ea57645c1d3, 0x1811bf498434bba922e2eb1b1dfc3025bedd7fe7aecb3837a561c1e78ee56b05), - (0x1317f5890e3c536bc205f7ecc9e286414f7abcd160903ba663f33cd37821a1ac, 0x39d386ba96759c162f980de92743c908b4808e252d04309fc5c10fb48c8f5f17), - (0x05aa4e237c2775c8105b736664b7b873a3a0a35cda546e29439fdcd87c844afc, 0x36129c33ee883439d98e23d4fb625a22df4b8b62d41702d82b59eb264c649832), - (0x2e48423c28c290a75feb9d431f59ec36e48d9e88c3ff46a9e1dfb04ed894d88d, 0x00d3bb38bca1ec15ac2e79c8e9c093fb496cca52c58f2947b51537ce718d9060), + (0x207caa09d3dac116acbb172db321e7f61bc484712e630410052c9065265e2fea, 0x01e1f679fed31ace260648de20aa1fecfa49a86883d7816da5610ce877af90e8), + (0x116b8a5b5779b94dc005494d7149a52fb7335e33109c0ffd2592ce36d8eb05ab, 0x2d8fbe17a8f044ae2e1f96c23ee266dc573afd0f57e51c0099510a81c7092e3e), + (0x2bcf89c0aad7686c3d2fe6941cca5ef1618ba5782b318fa03c2d0ded11e1562f, 0x199ddac71a22d6d0ee7ce48d81f22c97bd5e457e0a943424f190d961a978a929), + (0x2a25812521943a2e1efabfbc6c25673444ef448672695083ff756fcd208038b4, 0x2995c0e58a1158e6a36829ebe87e80adbe76e2393e0df579b623a3a247d533d8), + (0x29b4d4a14eb4471725dca90eb7867a1dec10f8942529b5cc1416e574bd9a9ab5, 0x14989bc5b00b80d38bbddae6513a8af3b4eeb2cc329db76cddec618b23df3289), + (0x32df58319d2d09dbb1fee48d3527d363073cd64c83bbde5b03c8fcb4ce911b31, 0x3b90f39ea943accfa63415c093154f964b63abfa2b0e7858f1b4cf64025600ed), + (0x023eb33622c0edabcb91ddf416ae92d24c7cb92507ca21a8b1402aaf528186ec, 0x2ca49fd21b69c9bc981e5fe64896fc237c501cca77cd2cbd843337084738e0c6), + (0x1c26136061e77adca28c3cbba70a24e47b8a3927a5756fc5dbfed16bde4908f4, 0x3e6d79c18b45835803e8a30aa51dae0ee615a0727d902afa11ac144459902641), + (0x1d140d091fff23e0d54048c8ba62096aba0bc38ac86ae071c54f09186ea22686, 0x19aebca6f2256d1e7f412a00f2bfbfda587e39c49baaac1cc61ff4672f51930d), + (0x1ab03409dc7f5fb7f1f8b5e3c54859db1b8a61eba30de1196145b07243170034, 0x2f139218f6fa6a266e846721b4c6f2ac03ebfefa35cdcdd2ba7f713677e58d74), + (0x07d62e5d650fddae400848ae7eec6073f5a9a032d163f5f24603460404197d4b, 0x0cce86359cc5e284c1427c2c8d65e4f93a26f8757746943497a4dcaaa7e8459c), ], }, } From 8c55c6f0b97dc4c7386516c4513cb3d23b24abd4 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 21 Jun 2024 21:31:47 +0200 Subject: [PATCH 087/121] Put together test_against_stored_vk/proof into test_against_stored_circuit Previously, the functions test_against_stored_vk and test_against_stored_proof each generated a verification key (vk). This operation can be quite slow. We are combining these two tests to generate the vk only once. --- halo2_gadgets/src/ecc.rs | 8 ++-- halo2_gadgets/src/sinsemilla.rs | 8 ++-- halo2_gadgets/src/sinsemilla/merkle.rs | 8 ++-- ...roof_ecc_chip_0.bin => proof_ecc_chip.bin} | Bin ...p_4_5_b_0.bin => proof_ecc_chip_4_5_b.bin} | Bin ...eck_0.bin => proof_lookup_range_check.bin} | Bin ...bin => proof_lookup_range_check_4_5_b.bin} | Bin ...erkle_chip_0.bin => proof_merkle_chip.bin} | Bin ..._5_b_0.bin => proof_merkle_chip_4_5_b.bin} | Bin ...> proof_short_range_check_4_5_b_case0.bin} | Bin ...> proof_short_range_check_4_5_b_case1.bin} | Bin ...> proof_short_range_check_4_5_b_case2.bin} | Bin ...> proof_short_range_check_4_5_b_case3.bin} | Bin ....bin => proof_short_range_check_case0.bin} | Bin ....bin => proof_short_range_check_case1.bin} | Bin ....bin => proof_short_range_check_case2.bin} | Bin ...a_chip_0.bin => proof_sinsemilla_chip.bin} | Bin ..._0.bin => proof_sinsemilla_chip_4_5_b.bin} | Bin halo2_gadgets/src/tests/test_utils.rs | 40 +++++++----------- .../src/utilities/lookup_range_check.rs | 29 +++---------- 20 files changed, 29 insertions(+), 64 deletions(-) rename halo2_gadgets/src/tests/circuit_data/{proof_ecc_chip_0.bin => proof_ecc_chip.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_ecc_chip_4_5_b_0.bin => proof_ecc_chip_4_5_b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_lookup_range_check_0.bin => proof_lookup_range_check.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_lookup_range_check_4_5_b_0.bin => proof_lookup_range_check_4_5_b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_merkle_chip_0.bin => proof_merkle_chip.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_merkle_chip_4_5_b_0.bin => proof_merkle_chip_4_5_b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_4_5_b_case0_0.bin => proof_short_range_check_4_5_b_case0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_4_5_b_case1_0.bin => proof_short_range_check_4_5_b_case1.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_4_5_b_case2_0.bin => proof_short_range_check_4_5_b_case2.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_4_5_b_case3_0.bin => proof_short_range_check_4_5_b_case3.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_case0_0.bin => proof_short_range_check_case0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_case1_0.bin => proof_short_range_check_case1.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_case2_0.bin => proof_short_range_check_case2.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_sinsemilla_chip_0.bin => proof_sinsemilla_chip.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_sinsemilla_chip_4_5_b_0.bin => proof_sinsemilla_chip_4_5_b.bin} (100%) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 359013b927..87f7e2f366 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -639,7 +639,7 @@ pub(crate) mod tests { FixedPoints, }; use crate::{ - tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, + tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ LookupRangeCheck, LookupRangeCheckConfigOptimized, PallasLookupRCConfig, }, @@ -957,8 +957,7 @@ pub(crate) mod tests { #[test] fn test_against_stored_ecc_chip() { let circuit = MyCircuit { test_errors: false }; - test_against_stored_vk(&circuit, "ecc_chip"); - test_against_stored_proof(circuit, "ecc_chip", 0); + test_against_stored_circuit(circuit, "ecc_chip"); } #[cfg(feature = "test-dev-graph")] @@ -1178,8 +1177,7 @@ pub(crate) mod tests { #[test] fn test_against_stored_ecc_chip_4_5_b() { let circuit = MyCircuit45B { test_errors: false }; - test_against_stored_vk(&circuit, "ecc_chip_4_5_b"); - test_against_stored_proof(circuit, "ecc_chip_4_5_b", 0); + test_against_stored_circuit(circuit, "ecc_chip_4_5_b"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 90ca0e22d9..0952825740 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -596,7 +596,7 @@ pub(crate) mod tests { chip::SinsemillaChipOptimized, primitives::{self as sinsemilla, K}, }, - tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, + tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ LookupRangeCheck, LookupRangeCheckConfigOptimized, PallasLookupRCConfig, }, @@ -881,8 +881,7 @@ pub(crate) mod tests { #[test] fn test_against_stored_sinsemilla_chip() { let circuit = MyCircuit {}; - test_against_stored_vk(&circuit, "sinsemilla_chip"); - test_against_stored_proof(circuit, "sinsemilla_chip", 0); + test_against_stored_circuit(circuit, "sinsemilla_chip"); } #[cfg(feature = "test-dev-graph")] @@ -1148,8 +1147,7 @@ pub(crate) mod tests { fn test_against_stored_sinsemilla_chip_4_5_b() { let circuit = MyCircuit45B {}; - test_against_stored_vk(&circuit, "sinsemilla_chip_4_5_b"); - test_against_stored_proof(circuit, "sinsemilla_chip_4_5_b", 0); + test_against_stored_circuit(circuit, "sinsemilla_chip_4_5_b"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 552b727f8a..482cea4deb 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -184,7 +184,7 @@ pub mod tests { tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, - tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, + tests::test_utils::test_against_stored_circuit, utilities::{ i2lebsp, lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, @@ -396,8 +396,7 @@ pub mod tests { #[test] fn test_against_stored_merkle_chip() { let circuit = generate_circuit(); - test_against_stored_vk(&circuit, "merkle_chip"); - test_against_stored_proof(circuit, "merkle_chip", 0); + test_against_stored_circuit(circuit, "merkle_chip"); } #[cfg(feature = "test-dev-graph")] @@ -619,8 +618,7 @@ pub mod tests { fn test_against_stored_merkle_chip_4_5_b() { let circuit = generate_circuit_4_5_b(); - test_against_stored_vk(&circuit, "merkle_chip_4_5_b"); - test_against_stored_proof(circuit, "merkle_chip_4_5_b", 0); + test_against_stored_circuit(circuit, "merkle_chip_4_5_b"); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_ecc_chip.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_merkle_chip.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case0_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case0_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case1_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case1.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case1_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case1.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case2_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case2.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case2_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_case2.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b_0.bin b/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b_0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b.bin diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index 33ad75670f..d6f6317e4f 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -65,58 +65,48 @@ impl Proof { } } -/// Test the generated vk against the stored vk. +/// Test the generated vk and the generated proof against the stored vk and the stored proof. /// -/// If the env variable GEN_ENV_VAR is set, save `vk` into a file. -pub(crate) fn test_against_stored_vk>(circuit: &C, circuit_name: &str) { - let file_path = Path::new(TEST_DATA_DIR) +/// If the env variable GEN_ENV_VAR is set, save `vk` and `proof` into a file. +pub(crate) fn test_against_stored_circuit>( + circuit: C, + circuit_name: &str, +) { + let vk_file_path = Path::new(TEST_DATA_DIR) .join(format!("vk_{circuit_name}")) .with_extension("rdata"); // Setup phase: generate parameters, vk for the circuit. let params: Params = Params::new(11); - let vk = plonk::keygen_vk(¶ms, circuit).unwrap(); + let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); let vk_text = format!("{:#?}\n", vk.pinned()); if env::var_os(GEN_ENV_VAR).is_some() { - fs::write(&file_path, &vk_text).expect("Unable to write vk test file"); + fs::write(&vk_file_path, &vk_text).expect("Unable to write vk test file"); } else { assert_eq!( vk_text, - fs::read_to_string(file_path) + fs::read_to_string(vk_file_path) .expect("Unable to read vk test file") .replace("\r\n", "\n") ); } -} -/// Test the generated circuit against the stored proof. -/// -/// If the env variable GEN_ENV_VAR is set, save `vk` into a file. -pub(crate) fn test_against_stored_proof>( - circuit: C, - circuit_name: &str, - index: usize, -) { - let file_path = Path::new(TEST_DATA_DIR) - .join(format!("proof_{circuit_name}_{index}")) + let proof_file_path = Path::new(TEST_DATA_DIR) + .join(format!("proof_{circuit_name}")) .with_extension("bin"); - // Setup phase: generate parameters, vk for the circuit. - let params: Params = Params::new(11); - let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); - let proof = if env::var_os(GEN_ENV_VAR).is_some() { // Create the proof and save it into a file let proof = Proof::create(&vk, ¶ms, circuit).unwrap(); - fs::write(&file_path, proof.as_ref()).expect("Unable to write proof test file"); + fs::write(&proof_file_path, proof.as_ref()).expect("Unable to write proof test file"); proof } else { // Read the proof from storage - Proof::new(fs::read(file_path).expect("Unable to read proof test file")) + Proof::new(fs::read(proof_file_path).expect("Unable to read proof test file")) }; - // Verify the stored proof with the generated vk + // Verify the stored proof with the generated or stored vk. assert!(proof.verify(&vk, ¶ms).is_ok()); } diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index eb79d504ba..8c6ca33216 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -705,7 +705,7 @@ mod tests { use crate::{ sinsemilla::primitives::K, - tests::test_utils::{test_against_stored_proof, test_against_stored_vk}, + tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ LookupRangeCheck, LookupRangeCheckConfig, LookupRangeCheckConfigOptimized, PallasLookupConfigOptimized, PallasLookupRCConfig, @@ -858,8 +858,7 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - test_against_stored_vk(&circuit, "lookup_range_check"); - test_against_stored_proof(circuit, "lookup_range_check", 0); + test_against_stored_circuit(circuit, "lookup_range_check"); } #[test] @@ -873,8 +872,7 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - test_against_stored_vk(&circuit, "lookup_range_check_4_5_b"); - test_against_stored_proof(circuit, "lookup_range_check_4_5_b", 0); + test_against_stored_circuit(circuit, "lookup_range_check_4_5_b"); } #[derive(Clone, Copy)] @@ -960,7 +958,6 @@ mod tests { proof_result: Result<(), Vec>, optimized: bool, circuit_name: &str, - index: usize, ) { if optimized { let circuit: MyShortRangeCheckCircuit = @@ -973,8 +970,7 @@ mod tests { assert_eq!(prover.verify(), proof_result); if proof_result.is_ok() { - test_against_stored_vk(&circuit, circuit_name); - test_against_stored_proof(circuit, circuit_name, index); + test_against_stored_circuit(circuit, circuit_name); } } else { let circuit: MyShortRangeCheckCircuit = @@ -987,8 +983,7 @@ mod tests { assert_eq!(prover.verify(), proof_result); if proof_result.is_ok() { - test_against_stored_vk(&circuit, circuit_name); - test_against_stored_proof(circuit, circuit_name, index); + test_against_stored_circuit(circuit, circuit_name); } }; } @@ -1002,7 +997,6 @@ mod tests { Ok(()), false, "short_range_check_case0", - 0, ); // Edge case: K bits (case 1) @@ -1012,7 +1006,6 @@ mod tests { Ok(()), false, "short_range_check_case1", - 0, ); // Element within `num_bits` (case 2) @@ -1022,7 +1015,6 @@ mod tests { Ok(()), false, "short_range_check_case2", - 0, ); // Element larger than `num_bits` but within K bits @@ -1038,7 +1030,6 @@ mod tests { }]), false, "not_saved", - 0, ); // Element larger than K bits @@ -1063,7 +1054,6 @@ mod tests { ]), false, "not_saved", - 0, ); // Element which is not within `num_bits`, but which has a shifted value within @@ -1088,7 +1078,6 @@ mod tests { }]), false, "not_saved", - 0, ); } @@ -1101,7 +1090,6 @@ mod tests { Ok(()), true, "short_range_check_4_5_b_case0", - 0, ); // Edge case: K bits @@ -1111,7 +1099,6 @@ mod tests { Ok(()), true, "short_range_check_4_5_b_case1", - 0, ); // Element within `num_bits` @@ -1121,7 +1108,6 @@ mod tests { Ok(()), true, "short_range_check_4_5_b_case2", - 0, ); // Element larger than `num_bits` but within K bits @@ -1137,7 +1123,6 @@ mod tests { }]), true, "not_saved", - 0, ); // Element larger than K bits @@ -1162,7 +1147,6 @@ mod tests { ]), true, "not_saved", - 0, ); // Element which is not within `num_bits`, but which has a shifted value within @@ -1187,7 +1171,6 @@ mod tests { }]), true, "not_saved", - 0, ); // Element within 4 bits @@ -1197,7 +1180,6 @@ mod tests { Ok(()), true, "short_range_check_4_5_b_case3", - 0, ); // Element larger than 5 bits @@ -1213,7 +1195,6 @@ mod tests { }]), true, "not_saved", - 0, ); } } From c9d800609a49d3e76cf279c12de40f828f5a062e Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Sat, 22 Jun 2024 11:47:35 +0200 Subject: [PATCH 088/121] Add test on mul_sign for non optimized lookup --- halo2_gadgets/src/ecc.rs | 17 +++-- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 7 +- .../src/tests/circuit_data/proof_ecc_chip.bin | Bin 3872 -> 3872 bytes .../circuit_data/proof_ecc_chip_4_5_b.bin | Bin 3968 -> 3968 bytes .../src/tests/circuit_data/vk_ecc_chip.rdata | 50 +++++++-------- .../circuit_data/vk_ecc_chip_4_5_b.rdata | 60 +++++++++--------- 6 files changed, 67 insertions(+), 67 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 87f7e2f366..ec436ef5fe 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -918,6 +918,14 @@ pub(crate) mod tests { )?; } + // Test variable-base sign-scalar multiplication + { + super::chip::mul_fixed::short::tests::test_mul_sign( + chip.clone(), + layouter.namespace(|| "variable-base sign-scalar mul"), + )?; + } + // Test full-width fixed-base scalar multiplication { super::chip::mul_fixed::full_width::tests::test_mul_fixed( @@ -1005,7 +1013,6 @@ pub(crate) mod tests { meta.advice_column(), ]; let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), meta.fixed_column(), @@ -1020,12 +1027,8 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); EccChip::< TestFixedBases, LookupRangeCheckConfigOptimized, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 4dfda94b7e..9153571893 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -1004,11 +1004,8 @@ pub mod tests { } } - pub(crate) fn test_mul_sign( - chip: EccChip< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, + pub(crate) fn test_mul_sign( + chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { // Generate a random non-identity point P diff --git a/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip.bin b/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip.bin index 1565f2935cce5a184ba1b5fff88f3c95b78b319d..e30d156d18c7303f0f7ed7e7b2f91b89522fcbbd 100644 GIT binary patch literal 3872 zcmajU$W12a+!_?WdGqq`^ z#``C{&(|kM^`=3HL}i~gk2~q|2TteKn^-;k^ZPZB=e*Psnld|B_hFZd?1K>`L3rOY z(A{f`sVeCCOlTrru-BKFJMy<`0GY`bwpGsI%l9Jom{%a4Kyv-YQUaq4*Hj`WTlM(j zRS-G-j_zgEii}VPm*nkE4lg=PNwBEIBM3sH#+gTF&jOU5ThNG(T$YI#?|OS|8F$cr zVq_^+*eb{q<3}5rU~#!Lfb}hCSVBC*U^csUIC@y~PUk5Icei?r9%Xn!$6;h5jvp5a zSgB>>=I0c{e0)Ay`Sd^T0K#Ct^$=cPqYu=6t>Go+mD)|8Zx|h{{|Ua-WP0rfG`$Oa zBq>bl+zsa^g$1A@sC`o#qW8u_PP>}tQ~M|V0ZK{tNJ2*qFs;U*>Z@q+pXgccrtN8l z2w-nyP)v420dY=ID&;#~Z5k2JSkWf-rz6n~?zEjj77|&1Q&*nWXZMz6Fa) z42Off3I5VP$uHwQZ0%C~JEEG9B{={Fu*y#YnTc~8I`t5l;%ucTJ9QGG`-UJ^=S@`N z1_ALAxd@xr?Czd+*YS?-&Y_hP4S&1+J`^;I_j=F84R>08UvVW_6CSAW)Y8>&i!qMY zuoPWKX85d+%QA$f#sD~f!Ip3#*GtS`b_psvk(UXPQqT*i`jGV_7Akv+`Qg^}Q-s!Y zlPMQ|!JR5%bSsf{)T8ey(w2RIp;0hJ$f*ghafIlv?wUqnh1*KO>Nz1)I%muDv5)Pd zv+5eDj*cy%N)c#g`4h0P4GDI0)8@s>ooS4UzuY@>-6XE@04=|YBKpQ$1BWP5sQ72| zX|aPAJS^z29Gdc&#+t_^K+5X!vy2y!drC5kztit3(;RMEn|7wi;dqCjsO)=AODnAs z(CwS8W`MStL{o7MP(ay_c-o}1vg}NRAuP;0Pv26aIE>$U zjtb9}%gNPjippY(+iJS^LF;#8GhZcKJmDsOw_E~IS|lETE1|=_<uo;MS>PIjZyeqI}IW@xw3a-?jn_g47>7;I=VrCK6i5xMVT(QE^6%L(QN# zD)G-ll8h;6xLJ&;l2=iI`ZUONS=|WQ@9xx zfCUHsPv^1 zzzkMaU>T{V9HIkvUWe+h*MA*1a^D3Rvz`;J0s}M~V}1Wi)Xt&h*InxC_=gP_x!=v(pL*Vq7)NQSH+Kt*{xWdl3MC1`2L}P4{J?* z#Vb*C=_=ugeF)gq$VbWr#xRQ2U?u(M=!*G_ z^C{IF`jp49WZIrYVOviyecDa<#8(5b944g(Hr7aLgU0Fm!g6wv3vnPOVo0nqQ{C(T z^5;qUiiKK)z!mRDU!ID{OImLD@kju?s1Z2tQk78%N<1B)@Hl;~6tpkgGM4vLhaaJ= zaH_?%=o3NnQ=tqfziTxJe{$qe&`z7^2ARZ%bKpH}uilFu6v>E>5uBrV=s?;(L{HN) zJX|c$#Qc#wDlee7Hg;-gTByON%}LDH)wZB@03O@*lD&oFku3BRvY+RZb59YaB>*u)8Yu>HI1*C#M^ku)k-5mAhD>D8}G_*5u?xlllL)6sDoi(mVV{2KX6 z{wwuD^12J2_5-@*P>b+NS8^w~`knnc%rs=n5=qE~{ZgON*XRPD!o%f}e~%+QCEV z$9fw_{uJK#PGyaqP|t;*ssQlk$@BdjRqi5WzVeL7U$)CIKLn+`c60^Lc78&2W&J&1 zdLC5xOwp^*sj}sJ1oxO2PqJt+0Ur+DpHBS*qL;YWrLwb~EL>i>n< zv1z{RtTwbZwAj!jB4Iy~8ynG8duYbz?1(-57cXXZNmto>F+*l-8roAV?vH|TpN3ri z@C=A>)!2G7N458Sc4H z6uxrkH-&y39iP7qkLPV+zk|_g5q(Xtw91n1933c}%^g~w<`?;!H))zHZ$8v4?J8;q zQ2_ojVgpylc1=-^>*j=e@T(r=*F}`w(|wv1HH5mQUq7kU=GTC`YMYrKikhh_E2mVS zIQ1XEpKo~yNU;Uf594=)v$)-g`~5@|7TR+BO2>nE9pRR!H0ugzza@k1EE+zEv+veM z)d!1wiQ`O)WXwpU;u5lTvsK)XqGMjBA7vmQOkp?@i3}VJ)C2rS{<&RWQ&z(aS|nhv zLZLcz3&BGc`g0CBYt`Ca@R7yUo!}gDc3dI%zwi+XM0*`>?IF(*Fy!Uj`#;%V@SWfp z)S?=k=!+Y!p7R`n@mfw_?0j`Ag{@ zl0BCH8$LmN-F@3lI?^W-n@t*sNGGdU$P-=G;>9aD)@uTu8;kcuT79I1m6QJdSMwl( zTf8=UI&c@#X5ePvoWZ8@J*ZAUrfD7Cu@cQgCTMeTK9|@Y2XUED(X{Tje(fs20sfoe zU9r4{s-KwgD6VVywl^L4UkCdloh6~BM=UFCSM7r&aqb-Sr!^6a!;(NQ&+bBWx*Yc( zT*diOcP32Q&y>^uo@cacLff(4sVBhEW{c!~sR>1wQ-%3_P3Q?zX^vv=Z;RdfMb9jPEO0m*vI+mVu3ff*H#t*TC7FMG zpZ@rQduz$OEVmf6UH-=3XLiU*rffqSbp!H|I zaYOg&M%`2$VxP!hw~~qECUJQy367n%1w*gOdS3l16WL^KIRYvSsJ4uld@KMlNrc$< zz8EeZO%v_A)LL-fyb(gDeZxlKgsMX}I7Z3{s@^#dY1^jVL|7(g7rxjM$oa0ut~Fhs zHQmZv8*eNKq2!3NbT+TN*j&600}xA6`(2h_uThZq{p~v(T9!tcbRqcG3Um7&@Z*uI8l|rx7{m~pJOn$Cu zaTzL@wsA0O@`C0KvN)Q;(JL{+ge%TeBHmo+EpKV@BB666GZ}rF4HsvLoi0(j=_`1k z?B0rc&oO?&MX;OOju4gZNEW-{xqLHS!oEySDYJ(xP`~!=to^bwRhZMkzo2EOt*r58 z1sJ0cz=ec(k6q;I_x%aSO|JHkbN@l@{I+85nJu2sbQFY3tLm}kN}nxb>XgV*uV9H3 zq~~EW_?E8CYh?1;-Gr`5+U$A4zAAorEv~AST+sos8lHSR_i>SW#jz zK!i|P)m}s~-ifo}6F)(u?OT*Qi$Ll;laE-%)R+?6J zviQ?iA6!IjQkZ&mFEW9AYYU51DQ_8=J#|sPN9>0Km%B+i!pLZg$aHCGjL4Mj1~$&S zv#J8|$2U1R^nK3tknQ}YTQ$P?^d_Mon8gQtP03KjV;?ELB_aEyCzVn^iZG08Dx^Jr z1?=DXlcgVM4RRG<);O*fxV^G@KxFbWt*^ zP=}>mC2_5{QfEU2or&ms^hESBUn2k7#N*;SDS}15+j~g<%DLM{d~RJK3A z>;D9Y)$;7uIi@juI2ZzZGMi5}M|+d+t$7ekLWMoz^0PSz6^X$YIoVrd8G*xv#<3nr zY^f@H0d@K{2PDf(o*j!LCT74D*Ve-Ls292EIbXdhDiQdk&!U6fUpVmDVk!tTp+95& U#Yof-=`sHpn@*oOR2n}1A4u0i1ONa4 literal 3872 zcmajf^&=dP!@%)#hI6{R>on6bZ8+VN6Z^<99AlW7c1)j+VRAYqrn|eDIC0u^jPpGI z!T0^^>-V?q_e8w4C}4ICqTXr}J5QJp_da;Q#I^XElH-0UN|>ruwQzKx(`ZJP8<}@odUSts!Z zt`{UP6O#CamZaWlRM>mFheBT^+ZAw{1I5S^;}Rt{ZaVYB)IF}3f+|X9;wcti^qlCl z7jg<=nx#jxV8(-zQVk8~-1xuYGUd+1uK{2`*U8Xx<{2vZHu9Fr_UEI!-YzTlc?w%A(46cLB74M&_(OvFd*43Fe4mN6XU)Z%1j(IJ#qg zpD9}Cs)DONgSZ^D#VUsXGT(;^i8ES!@*)iM)1`dTlD)7CIKrQ)l*ZPclXH15wVNW z%;&%W6xZxx>vVLam0u~m=nwNVax?uihswcjYdPtY?<5!QWVP4X!>5Ir$iJ;`ARP3# z>I7>GQC|kLx+|vLkQf5ihL6@=yT+OV>|Z>aXQ5&rtxm zhaM)Q_4&E0F8fk*)+tYP}Hyq`bV2s zA5HSCDxpLVQTzBX%jd4Xy$?qZL!xD{veWqF9NysV$2jyC-Ii`XMPqnrrD|1qe5;KZ z8b8+GtxxIl61toDv-R1BEkLALC1UJ{Yg{4xl2O-_) z6b!5S?u~_IN7azd--iR+S_$||)H;2P~;YpK1Ao45* zxOuLeDf<%2$aT2a!(arg?#bx50>Lj^@A;?oS%iCF+biKUt?VvvRz5OBhP|v8&tU?f z&RhX!jMT!-AL;8|{DC|dWQ`fxl@11qWejMykjXFzWOmr+xc46|OZ+@hBOSEYWfmjD zh-#OWro}6^N@nYv60O#&k3rQ%D7n;{{+4-dM>hO$m1@L>BXvdmVvgcF^|?zN9RcAV zCtQrDf%j^s$@G2yp?a}YT22|qYJeU4kiZ&?uNczd_M!xCNs_Y3DKdktHS6q}2%qoa zl=Ku;A_;Lv)i(t+DU6hRIMPH3e<@*Js7v<9WrRsa(Z?vRr4P78GU(>CF$QuN(BI^C z8G`LoN%3V(K^OOCH#MX;P<;$^!h1neWurNHk7Lr=2p=in zY3@xAz0PMg496A-6))SA5@7lAZL+AOY)ttSG^+sU*c>Hxy;AKP2ef?!0W~t9w`Wz~ zc!+wbmlgB{*m3_Vu(?j- zRpAO!em9)aOv=^mO`%5Z9`%WMA#sLJFCVCv-bj1oKt61Zlx4pEYlja;s(m_QX}X~Z z>1?|=j=djZdd$Nu813VXzf`2<%B;&v)cD{Gn8XZF2bh1mw7eLBrTse}m*(JMyeYa- z99WZ5AQqZaI5?)rHX>GHFuSi9R61bE(3Wvx!SG-@)m>@u9Bu!dmfnoB7h+MpYothH&C|;j4WqRMnO^0Uu>QYQWWm{bc6R{AmjMe+ zJ;kDaNUZ;ArR|lr7P?f9Ju^aN8QP2Q1`I_$rY)*bAZTeL?m*%n6hApVcnwc-=4ER% z0_*52{5{+X4=XbuH(L92t=y2pJ!X8Fn%4CMMI2&JP;DbnP$~8io4e&owjVN$C{~T@_gvVO+C)vAH7nWpGe5z1XnE zzaQQcjI2A$rZcl1O#M<^mXu8<23I`0rmGC}n93DTSFx4bS+W3wBW~|1?Qk=>*$ljx zB*Ckx);{WI6Zz=12ZzSVDTBfE>55x1e(9M?EvKwtO6KvS_)mny8@vX;ffD>DlKFa@ z`y(HhaHUqS%PBcnt%)xKMaQu>th|~caEdnu8jy+_{5& z{o;a!nQ_BE&zF0Ia>+yFbklGKEFR?l_k&4ileR@H&e%xvaDN0 zSzL}1Ni+%VE$1Wr3xsBdJ%;eOeV< zS;_UkJcUPaqRV?{VWSO|GCc_~7J@ku1}Z_IFk-wV38J{Qrc-8?H>P`CSZb~=Yhd7v?`IN{K3m4@YRT))!;B#x6gW zo6wQEeR5gdLt{KG2=6)-t;5X~Zr}~lPsk>xZ7W*q6KKYX9xBg+-YG@aue%?4u<{Zn zrC$~AOr|uA>?m}jRVLCNFi#7*`0iJIdV;mOqPcMcn(lnxlxB^2t^sidBt-)h7&UHT z*|WC<#(cCFJ~CdH?yP1Ghgf|Jg_I9Qa6{+qa^Cv2&i+-`SCWR+Gz>+?D4zR&Ri}Q6 zIDvZ(KiE1Wu_VXKb|Jp-+oxWP@4#P`^F8eP``cD+*8B);uBEq%{F0l>!YUUJC;xuF z$tBdv;zID&OKkV;$+KE>@G_c;>6=dygU%8Ck%v1gRd|SgPfx)WO^@9J7fZ6v+c6lC zFN-|x#F)1~?a6=NPx;!^?AYdm7~Go)4J<-#Xg3??y1L z2_#DCku6Yy zkF6+dlMVkmG8GjmA7pb>nD>Wzc~z(1bTNQoL$hLdWvM{rlDGvB?0()9adyTFCXsS; zS-G3Qs?m!JTCrxe+1eu5AmiBJ$n8nwACV>S9;fN)<27JBV#XmV%3Y=Z51CR~O%El` z)9l$doR6gBkqkL;&PGqCLTw8n!yt~RzXLgS;L?`v6w%ZwY9NJ%aK;BVT7r?<&e1Hy7zYXJg-If#%p z3KtQbP>gI{EL9traegG!Q%;w6p#mbD{~Ay+|Nkq%>?9vZtjg==N3LSnlBaN%A9JKq-8q>Z@{(e_7=G6jT~vSO(i%lt45nuR<;6hy zS_ICSWb0BSJtR%z&TJ#R#NP_1nFRul={QqD${ewa)81?Vr{+;oY*khD+%(cgJ7qs|tJM1Ebo zlS`GBnoE|)W!J>t233fb_G5Xh>8~ac0ZL|&S+{a9|CVj#1=s7d8(Cd=WNG^^J4;v9 z^k)8uryXq;3(Vq6BK%;=f&jpf(AS9fB2YzZ!pElbr(Xxxo4PPr0RAFe#`!bU=G3X4 zrin0tf+i3>U@?~~D#TfxPb2Xw>W8WlQKCYA@GI(K$EhT;+mui)!5o-U;~HH@L%s9w z<~UYSHQj(i55#5^OEpJgz_|TJtpZ+@d?{nq-d>Z)M6UmR{iZ!?h@mHKejZyLk?;#% zeNd-E==MCtGcwxj$l20sbaGyd(;D3SiI1jd8dupr0o+;hm7=~0XGhot- zHwd=r6-eaByj-cQ4l#+Jd0RX4dabTD}qxyI|=v zYj01+bff=smrSUcGnl3Xsk4?hQcWB7a&3ycZrIt+jCx*6-Yj^%+x90+xfvwzXurB1 zp4R3~(71!wAXpPsa>?etil*eJ9{htN3VccHKg_+8rN@dt^tB{QVl|>9F|7e_u=7MzBoRsH8b0WyPCd z;u7vY^<7_L#1Zl4aFSMaPqeMzJwali-uqh{Hb5?h0pz|F4uq-OHTv!)YDvTH{3EBv zUW{7!#GcSbSi%yJDvy56zlYHqBwOUhn#Yw}2J?6sob&nwbabKoN3TjP4oC*HH)R;~ znZ|6;60Pwi^)I7Ivmx0P5j>>=9fT!mFzr@eyFo=S8?nLWOSHA)_1mG{28kz5V>gL} z9w8iH&pGow9`H94%0n(y1S+(CMRy(-EeLplhZLJHx_g z12%ipv`4`vt)Np;ZqmqCsoS!*r8zllVXz|No}kA2A_#ugY^3-m^g?yLCEEJKyX&s1 zF~ns-*zgtJC=noMfKRt&l{}X0dT9aToOMI{6Nl*M3Bxpk=+_XFXg=gbXOs&m;E(3(Fey1X8{t$ZFjI96hEUaU8M1Vl ztsh;eDb^s^ErdGtB+5+#vF;1vk}qlCZsyK?g_;thgEOsMhneWRwp^BA)+UQJ*9O&N z$Cbm&)_!B$jQ8F9L0aI?d4H4*a}W`SHM-xegCZ)Q4i3=TUH}h{dd(sHhTf_zZbSS| z!o2Q@_#U@tbeXjJx-oB4W#mQzp`^PPsCO#wZL*$x!M|;I*STY0bK8Nw?8(f*21buEu%|q?sa^o*N(G23aV^h0u*sWZHh2-2YUIm;HXFKC z7>&0Vw;%tAQXMJWHcV{yA10@A4LU6?hOs9`2V7bmZLBwxtu^ibTNmmj!a<$&k9eVvv_wR$~tTrnju%OXk%v7Z$6Ek-$6 zho_W}Yi)UcLl}V@+1IdbW7`!y-*%{fd6=|3Zt^mfJMV`1oBmjgLgU8Qe%kpf{tA}U zDVb`SK;}fJkX`h8zgLfLqEF5?9TnidPmT7P_1P2?g9&p+=MxF1Msp6%AxnBn^~a5U zOPqTDT1HSaw?Ak^;@7ht9V1@zJO$O~T>DFuQ3Q*>ok@0>BU z#UD~u#ZxC*?qE~R5*2-uTNG&wFjuALC(th7sheIXu72=iu=GlWTfAqLNN7@>!wI?_ zT=ApW;~cox!Sxc)<$GFf4_p5b;BB-h-vNa+)IYP_F>CxFZjfi#?ddgq8|O(?t9*|! z*4}ECjbsArZmt5@nR{c}yWz%M@!6&u=7QC#lZ6W5v1s;`v}{zQwlN>Jnuc2Uuy1D! zYBzcGk!kIu`Z~}4Vf^{XK`hN;mq*|R7Yf|n3LZRntOr%2hn>p}E=bSGW_1*c0EfUR z;ulGHB!z+KGRU{8w7DZ3TJ0SuS)iEd<`Yt^uRCTC`8^r5X@X85fS!xMGz`1?E16e81t{%?FWZ8rFNm7(;(LVpS5T*{f7`15A^gZ1nTC2-plQkM?rY{}X z8fwGaKMhYvL8DRmyORg_{maBqE;K6x^TokO62w7ObNE%Du@}yak2{B3g1A=B^<3Va z&3571tF6HuhVt05mKWR@-Rn0tiVvv6PEN7$+A9b)iFT0&~RIkGNkp_TB$h=>?ekQ2F)%qoA2kNR}-YB?GHuApDV=C*1l#f zP&4VFsX*7U9}42>RM3En_T&_OtS2Njw(`-Xlp3ZxtW``UA-XP&dwDfelPS~$Vd+%?5%@fWXrWW9q#wC_pzl{~Yxg(es1TU8ttbHC z^~~L(j8hRMddaWc?F!%+#T#xs@rue;FMa6_cWTr>SRsn$2vhz-zRDZIi32bYyM+XITNC$|cYo%pZseY} z9MJEqDyG>Qpb)-dVJ4<8c9afc+?+9pC;ElpHh-IiJkOBDsVP3DO z?ZnK*F;Plm`fo$IodI9He?(M9SByC5Zw(h19^v{0j2np`C3)x?A3l^acua|c zcg{RQ@QNUsxERu{ry1UeCNU9OGiU4MPFq!maV7FBd@ZNIm)?s4Q+!r7=1%K{Ir#dc zyb6)JSndxjHe|%Mcr_zNAS#3qh^2JGLoT#*j#L!g$%Lx-KXsf2FUObw!@+Ym(Oo@ zc%AT&3R9~#c@;v^C+f~Q4Q;YDjWxi=*qvonivCMep1Z{OjE^hHh}W5AEF{8i`RJ0u z>2|05FI;FXM+L^HB44=Hp`EX-%#H6L!OYb!ViUxx6a2#V6g^x>i%Z~)EgU4ojg$=8 ziw62zP-^{~#;kyk4C-~+kp3=zsKgES-kv97%luj+#=b%f!Eb|N(Xfw1hvfefMr-45 zrTSE|&bm0|SL{~nW^ogbdNWwpbOJK7=C6r^7C0f8s+$_SO@3qSzp(SVpJnC zM4XLpl=56QGsH(}?v+Y7@fXl<)wMhR4LezV;eT6}8I%evjd4(dwM4k=Xd9b7`ldd% zxEmSfyb*#f5hsT*?8G4L>W?sOz;7Q%=g;zK{7cmR%c$E=V1~*t#v|r~L=gZEcd*5r zE+0oc`}mJ*6CStdlIEk^pD?Rr)>1O=hNvfea^>ZVt?2YW0lKkV$q&_8j-GSseVs~Twf7QH=8xto?^WG>$ICZdP)-i{St^&pI%Vy%+3|M#^_A49i1AsW(c140gN z7_~tlBLsTqivI#%$H9}zjag^Vki^`;GS0J8(vn?(uUB@Y_#Cze(&&l+9sw9l-3M+V z*qUe}S+ca?-9cVx-{NpX+g>T|pYdK>Hq-*;f8R5?ma(!^2N<17;dc3)rMifi@s{xb z2!O3HQDpsZycyI>9|82U_Cv=Ztl~IzD30QHL7A-x(06E7a1#@<(k+{IM3-nJT1R4i zUS?fWg{=9ST!;`|jvfsC+%1Qy@@q^_n zgM9|7N%FeNt*2L} z2_g}0&P=HN!V6PkOzo|fq+eZe$G+nyT39sA-gtK++O zs?gd}sq^U(xJ&1UO`5iPYm^28af z;{L=vlfKCju{3K47yPc7yhPMF6cPHUne*E#(ZPGp&>M&cUuNTFizAzLV%h0)C*7oO(%1 zWg_9;!ikVfim+63`eqkSO2L3@@!Yx#ad(z1Vq3_R5;r1Ag$&W{8*!wL=@;p#f7?4@ z!H5#JosP75@;E6GnkT=wY9rbz=Hmre27~-G*0C}?Mt&)!lj5!o!@ttRP8PXLpm7~W zCWcwoFg^(-`{F8M=cR{#Co;hIH?N{^fYW<2cYVa`u0&!E94Y(ec+sj=oAYa0uTv!x z#JM+$4w8f7io8GV^SjgTu0uQ>jXh;hQP6d;#lEn`pGRVlH`c`A9s`!sQR2Px;11wv zaJWH2!ZqaRVM~TzayHsQgMrrrTHn_j_gu*#O486-*Us~-jttW03fbT^W)~%-Ghf(E z$sz{_bxMZcet#qh_a)z z;*$OT3Gegu_wjj^VGwuvqbfFK!o12wozWZliX&1Uq&Q7XWJ10B<=+c@^`soV-^Cn7 zxA|{*+pTx`>mAq79RH}erU6B=xmM)n)%P%N^@1}+jX0}H@C;NC&8-U0O4#k@mmFE9 zRP4G~wcvq<*9-P%aQcW0h%(!4R@=`W>YS$N>ZsR3hh76WZhJoMG00!@Drzx1zDvl= zpq5Od1eMD>NV`quT#JEBFKe9yLDMnCDrLzZ29MIe za`#;w&{HQ)|HA)^g^E!z8u$Zr+hLMRm|(K3^IaY^8T>6Fbc%5Ka$2H=5~vL3XJ@0$eknuFO0cUgBJgz{&}g(dM}1W zu{t9YjicAL`r;#5jev>qsNo|yP}UcxL%w>xP~OEs;e5-QXKp=)tF-AGB3mC4%82aF z7j^;)*Tb!8dIBlZhm`dqC020k`hl$@FJUbr*Jr2WF3~X)6}%~I$J#! z7*zxOOoE~fQ@4v5&MX;lY$^9#<+y*Am79rqPRiow$JSq#+vf|lyA}KzL~~w_-b25O za$OuZKY+Hfh&d-LIm1`E<_O)&qZyj%O8^?T~GayFkgfs1H#PjnPyj}21@4jkHV zJh(OD&V6kfc7LP%UQbE)#?)@b*=3iOSH~Zy9qS)~PRARsZ`kNa%F$sn8Zy6(z|4?*>(J6xR0V4AjX|2YLoBV|J&J)gXOdf(G|zDH<8x zvw?8Af|98(IQiDC4ZP;{rW&zYX9N0reu`N{GPt+PjiV;bZU1ix!;ru4W!s-G@4bC2 z=Vm(_bi6%rMbOS1%zbR~)1AkPgG7cP6&9^S^JY?{O?b}imc!&H6f7BxI z{V{8eZkyS!<1O#+6n-xwc4qEftQ985M#oW=aZAro#QOfW;t}{Yb&q@oQqZg;fVY=~ z&>H1q^Pjg@vgv~*5>mEye5{L1SXX8SDDl)hYqxzyXULu+C$t0xjUE`t^0n#%0r240&V{r{JPNRrg zty4KE^`kX5GI%fWAEr54SQEubMlK=SOvHx%ZO3kZvqTEO5+pT5d}{G>u?|3%n7)(D z6%VIP8BHc@sGJhzv$CZv+1iYRs$S9|w6-xFd&&Xj)$gR013WC#P17(x6>pJVI8 zB<#%|y)f2p=8ZXwqdEjAM)p5VPI&aJL^$)jF6Q70Qn!)5KObOd^c#0Lyk@jz+L1!X z0y=7-ufF|OIOp5wr-vfRGG2||M-OM`V3@RNF!;G*K{SOBAbTo$G#%7ie%^l8`?K&@ zHOd4OIcLBo+-6JB*92$C@1l_tm|#A?F?_paYCmYIX1u;h@IJUco{&SC=b^mK*c23S z^oG9AyF`qs5uPWZO05@Y=xU|zR`mm1?@ZFG!HPwSkNL{ZB6J`4z>)_ou9dO% zgypDZctRvRcV}D*p(dIK_DVGA@K@fGH2>3_s7A)2i_!aSZ4kIQ5w}?m^I|hO*qe)A zTDS|e-Vk%^JA@_m`%CO58Lywbd8;l)Ap=-Jd4z#K=N|iLU0yun6XHt}=G2){&yL@exCE&!skm?z0uUolg_QG_<>z$IY`z!VqUENaecZ53A8t5mI$c(W|27-_ ztG{J>{wXiAiu4SX`=)N_OP8A+k9M8Z#OR4#G_B`&kyu6VdfHxcO00tHo#2Go9S8q4 z@<*VR`#KtYG#d*`Csh+wwp;{7{vQT=;_|P!cSZNdK@HSdpX=Py4y)TOtc=I_|FpVF z^*jyUaaq)okL)V!(IgPaVpHbDn}r&mvUNPFn-h3fADMA0h(gy@5&t9@36jA^xqE4Z zL^2Z9%zP_uQ} z2!R{%@*xHyu(vUxL1D`@(k3anesHGoWg(vo8n2ta?vLXOT0WUS+0fRs7xpJGQ z=(`m!(J&ALtR1NC$gRmkg?~VWU$T6$iJzU@O}8>(V142P z##2M8Er`d=`S>mPjp!g(J0W3Rpwa@kG$*i=uq^Mx06neb7o@C=^~0*YrL3jzGS;CK z*8TvgUF0qjx+kG8d?R05BrOzBlc-4|tr>@FBv3AktXTqz6Jb?LK6u%tZPoa+G>>HW z_T48@hEdU9kJO80wY7E(a}C4uSUcfs)YBfvj=9|)~!Xm-CL$m z&YgJ~F`=!9QbPX48&tzBabtVI)5zta+HmW`_8~q4-Ui-_7Ap5QZ{-HWA62;3ev_n2TZSi<2e?5*5k`=ky$`E@A{Ae^8hEdlB}coKlLS4%Z^gd zk!R&^d;4^sG2AamN-ZM~bqcD3saZv6T#87A7TP6thSi3(HCFER#VPsq#wRCz^8#i4 zz9~SYF?LfZ&b}XrBXqzA|7CqD%U$_1ywfRmf@ip>q_>h4CT?C=f6T?BS8^=4Krb%C zaXFHSB3Dsd=6%TFPs>}3fdR;&5Gp8Pj0s4+momZf*x_9={c2$R@vRJkJl#d9!NQleF`~Toku}VX4XB*zh(eHsr*moiKk9m^c~gb=i;VoRabo^Phi zpA49AGi^nY3RMtu<*nKsBhdVsb=4T<5U$Gr@t_2Fse)O}>hrg>)sxAlfB2EOG^%=v zm*Y^^dYCI~RFOfj85bzp^)$Hu1<_tSx14J}E`L8a9N|FkEh!V4WX zEWKq)APz!Qq;~n{_S|rICUArwk8vuqvPN}q#;M0h!`c~-n_^fPC^S3Y4_*;S>{+vl zhT4~@^z0x6_ZwT=?E+9JOQ5UVriNbm$@xf0Rs2>Pw~P#MJ3@ z;dKxUrU8A@Q&2JHI4E}KDzqJcV2uI+v|+)$6vRr_GipdoXr+7ysqIa{HNxz3aAXwisY0DK-;v!EepZVjiom? zk{wl_*HFQaHq^8({3~>cQ@vQLfTSYf+Xid}M{Xg9EQ+G-*#edJ5GY3VF+*czSFt!w zNtz%2S3{A?bMc4H`OhiQ*?;mBgaRZ^QfC3iHfC!IenwzMkNsW{I}~Yb+=ckZ%qsi` D^HYH~ diff --git a/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip.rdata b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip.rdata index 5eb13f31e1..295db7c9ce 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip.rdata @@ -9878,38 +9878,38 @@ PinnedVerificationKey { }, fixed_commitments: [ (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), - (0x15e9797cbf96b3ab5f2a21595a5ede5becc665dbf113ae1bd93c5fdd577b3fdd, 0x2276c102a90057ccaac390724cd3e8032eaa0d5c7630b979e2f86354d46044fe), - (0x0a3757ecd8df677c56dd731a5988940130dc69375d09185120348b4c24f23f9a, 0x209e7e273d9d9254893a220d7329114fa83eda5d483437612cf638275b4d97f2), - (0x337f1898449ead1933c764ae23b48d20f646e528b079ac5cd0743d9ac8e8f063, 0x144e28d47be3a5d90eab8ec65a10b965fd83c7b34f8e4b387154f126efbbf7a7), - (0x1ba31dfd22b785ba6080c0a1378f14d104f571d6ab2ac6e650865b27296773db, 0x3c49108055aa494775123cb379dbee7ae628e193cba15827df962722a9a47367), - (0x0fdf7430975fbf9361ee6a0eef8e811b838cf64cb042d5988c669010329a8e8c, 0x1292f817500e4ef166ccf48483d061b41372ac7e44ed52b04fbf03da5b04fc79), - (0x145d45d803dfd99569e689c02583b2a63f004e25ba23bf9acc17148b42267480, 0x230efff0cad7a66c33eb7462b4b60237619e1287a6c23a122057ef0359d324a6), - (0x0ce14fcd6eef4247d75df3d38a918bd8d8c66362629ca8ca697254bf703f1dc9, 0x3cc92942c824cad0a3f16828a29dd42785485b878e459a289db7c377973f2aee), - (0x0bd58593a2e2657cd0a228b678a4a7ec04492e20768108383cfdae26613da0b9, 0x090c75a86508be75f6f57e33946c5f9170f40d08e058eb33c8370311fed2868c), + (0x0b70f6f89e88131bb5ab28571ca837a4160b51998c6ced04328991a5c3bdcae9, 0x2cee3ef6523c2d36e01981c4794271d53fb47e9c5480b982a2ff3a869144d648), + (0x0299c2272092ebe4e08c73d7261afea742a7dc29ddf73ffb941a1c9c19dcf4a1, 0x1f002552d6af287e66e3e9706ecc2a5523f256bf2c6eeb995b4233f80c8c4eeb), + (0x28fb28941b09f9878eab1ce7923578b332ca794e3036789016fc6f832e820a37, 0x0e1fa37a3b4298c8df50b830e32ed5ff0ea40a0f8fbb1f9bb4620b8cfdcacf12), + (0x37de994248cd221c19cc8a5f354769ecc7e3ac253a4387dbdb8a25934d602225, 0x1c3d47b5ba1cc80af1666afaa42c97043c2b793e48a9c362a398adbf4cbfea78), + (0x0f2ff7cc3b300b9e92d481dfc01b84968a21937691ef5bb84cf7b7ac4bb56f8c, 0x010616d33ce6482c9958f2678cea622493de8477527fea737feb8fad11fc2ad6), + (0x2c40aa103ee1123360d1e47947f6ebc13ecddfc679514202b33f02a45ede862f, 0x2988d36fc6be72b80ac26c8253f72452e0db13387ab35c86d97cc03991cd9bb2), + (0x02fb26d5aa81b4fd2ba3324ae48a27a3e89a90005e4daebfb8004697379f235d, 0x0b484b92ea252f7a58c5bd41cbcdcd9efb932482c902abb4ae3ccb2c90912173), + (0x22e2076fb8f40364e7c733c89be2039af2d0976a5a240ef6f05d9b67f5861b8a, 0x1b9f2382c80f971341343fbfd1cfa3a3fa84d70310e7a8fda21a21e20fe9b0a2), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), - (0x1676bb18498c153055ba927b909ef96c5edf8108be253d7a86663f57cd815cd1, 0x0ca79754ab892586fe9df1ae7a23e527bbae042eb89e96747f3befe88c493446), + (0x2cec31b1d071d872bd6b1e0660840e27bc6247398c917d5dcb09354d3175fd68, 0x0812dfd78e8ec30827f658cfb64f4f253458d0fcac102af2639295659aaa75a6), (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), - (0x11ee40a7ae1d9b3bc41a88dd50a69661de280c85222c5567ea3fc06c606558a5, 0x0c6ad5f6fb00347486477aededc92f686f6d079737fd2ca147b7db5ea7381061), - (0x33be67428155b1361122a6eddf7e24a7cbeddcce8166dead5d9d5ec6714b25f2, 0x3ec742ac0f64c3ffc4d47bbdeaba0603c55ef74d40065b84b7d738c95f473c79), + (0x0a7b6a62e3771fea1024172f8fa5ae0a8b6b63d96dc2cd5794a0d61be93c5230, 0x2664583fab5a71ea152a5dc10512917a6b927ca607008db40abdd06dbbb0aedf), + (0x149ab89afd559c4dab808f183828cac2c3c20ce9311ecf7280e03bc9881fd783, 0x2ffd5de1303205066fd7a1540ed79a47baad27532dfc1de2fb708cfde51be867), (0x11c136f6ea303c5630240788e7a4db6c3aa321aaeaebecbd473af5ace4d05248, 0x0afe33d04a38bae95c2ec4c4372b2d766369c4c5b10f82dcbd4375a41f838d79), - (0x320eb135936ed226a108ccc06bea1ce3ea57dfc2d708fc2ea868ee90330fe22b, 0x15f1174d43608cb597ad1708d2c15e6fcb399219662c75a476b34d51d7ef8f09), - (0x2157882bf836df0d37c2fe7b4c03c099712bf0f1f70475cf79a47a269cd05d6e, 0x2b21b30255ccaa0152b483916b033c38c54edaf1ae8987df41d4812affd004fa), - (0x0bb1ce75e6be204e3d006a0dd70adbc82e9babae94be0a0fcd0eba958bf78d95, 0x25af91a42e58455509f322ab700f45210e369a79cfc3635db30fa5298d46475b), + (0x3e360352e498a60f895216359624fcb58372ea0c8acf99c7ffd5678eb018fbec, 0x2821347d5fbae5e9ef8ea16c9b1014b44916bb73ad287ba747ade3c636dcc4e5), + (0x0a3b507e0fe0189f45a2eff60e8fc488da60ce3550391e82f7ec7a1941898c24, 0x3bf48f50d5987b0740eba87e833abb6327c3017dfa065777f3a4f06a555fd12b), + (0x11d043ef781774cb85fa85951ad4acfc4e8de1f4c551cfc677e3f8ac6490224c, 0x239a09984bfe5441f05d454b7da0cacc0797978b17bab820cfe538e748053022), ], permutation: VerifyingKey { commitments: [ - (0x2dfdfeda0fc01492b0884d17870ef7c30a6a59502ead966bb6c072b216ef7b33, 0x206d9ce95f9c1bfb675cd14130a877aa70650b7d1bb5cbf82f3fbfa517c2a19a), - (0x001deacc3520d2f07b82695befedaee3c62c595d80d0f406f473ab3e8c362213, 0x316bcc3ef777e42b96c36bbb95b41654dc91b4fbf264e3796267716917e0b63f), - (0x142095bd2f3ceed4e0ee7eaae4952488aa314d89f4755b81bc4f4df5e849947a, 0x0e6b8ab5b49069d21ea86f1d320c2959f144a3b1f284231312ea776f337b00b6), - (0x20bdfa7afff8a496620db915f9323e348b0ea52ccb0e5ef2a26cc5edfb4a3490, 0x033516b53f25239682efb9f0b6865a1841a2f80e88c08c9431f08906bf2ece95), - (0x3b3d22054a70b22ab2f4daabb0671df492f8ae365372d34f9ed9cbf053f77560, 0x386d905cc46f526544a620c7251d661cf09ec673efafce3bd36f59295e8c8e10), - (0x23bdd78c87775077ce68d63f15349c6851d18cef963e714fad7c182172539964, 0x36df72f765faa06fdc6e79e9b71557043f1b3c32677cbe852bfb89b9ff2adf73), - (0x1f058e8d0ce9494143e267f9190d4a8a0f4fc18cee14b9cbb00fd4324d028d2f, 0x053c9574cfa8f32a4795152eb742f40752011ad9704a6b7a05fdf2d660948eca), - (0x0c116eea00a8888c4a5917f514f323b993c732ad08d9655cbcfb3ea57645c1d3, 0x1811bf498434bba922e2eb1b1dfc3025bedd7fe7aecb3837a561c1e78ee56b05), - (0x1317f5890e3c536bc205f7ecc9e286414f7abcd160903ba663f33cd37821a1ac, 0x39d386ba96759c162f980de92743c908b4808e252d04309fc5c10fb48c8f5f17), - (0x05aa4e237c2775c8105b736664b7b873a3a0a35cda546e29439fdcd87c844afc, 0x36129c33ee883439d98e23d4fb625a22df4b8b62d41702d82b59eb264c649832), - (0x2e48423c28c290a75feb9d431f59ec36e48d9e88c3ff46a9e1dfb04ed894d88d, 0x00d3bb38bca1ec15ac2e79c8e9c093fb496cca52c58f2947b51537ce718d9060), + (0x207caa09d3dac116acbb172db321e7f61bc484712e630410052c9065265e2fea, 0x01e1f679fed31ace260648de20aa1fecfa49a86883d7816da5610ce877af90e8), + (0x116b8a5b5779b94dc005494d7149a52fb7335e33109c0ffd2592ce36d8eb05ab, 0x2d8fbe17a8f044ae2e1f96c23ee266dc573afd0f57e51c0099510a81c7092e3e), + (0x2bcf89c0aad7686c3d2fe6941cca5ef1618ba5782b318fa03c2d0ded11e1562f, 0x199ddac71a22d6d0ee7ce48d81f22c97bd5e457e0a943424f190d961a978a929), + (0x2a25812521943a2e1efabfbc6c25673444ef448672695083ff756fcd208038b4, 0x2995c0e58a1158e6a36829ebe87e80adbe76e2393e0df579b623a3a247d533d8), + (0x29b4d4a14eb4471725dca90eb7867a1dec10f8942529b5cc1416e574bd9a9ab5, 0x14989bc5b00b80d38bbddae6513a8af3b4eeb2cc329db76cddec618b23df3289), + (0x32df58319d2d09dbb1fee48d3527d363073cd64c83bbde5b03c8fcb4ce911b31, 0x3b90f39ea943accfa63415c093154f964b63abfa2b0e7858f1b4cf64025600ed), + (0x023eb33622c0edabcb91ddf416ae92d24c7cb92507ca21a8b1402aaf528186ec, 0x2ca49fd21b69c9bc981e5fe64896fc237c501cca77cd2cbd843337084738e0c6), + (0x1c26136061e77adca28c3cbba70a24e47b8a3927a5756fc5dbfed16bde4908f4, 0x3e6d79c18b45835803e8a30aa51dae0ee615a0727d902afa11ac144459902641), + (0x1d140d091fff23e0d54048c8ba62096aba0bc38ac86ae071c54f09186ea22686, 0x19aebca6f2256d1e7f412a00f2bfbfda587e39c49baaac1cc61ff4672f51930d), + (0x1ab03409dc7f5fb7f1f8b5e3c54859db1b8a61eba30de1196145b07243170034, 0x2f139218f6fa6a266e846721b4c6f2ac03ebfefa35cdcdd2ba7f713677e58d74), + (0x07d62e5d650fddae400848ae7eec6073f5a9a032d163f5f24603460404197d4b, 0x0cce86359cc5e284c1427c2c8d65e4f93a26f8757746943497a4dcaaa7e8459c), ], }, } diff --git a/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata index 5005d3dafe..7214d57d45 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata @@ -7170,7 +7170,7 @@ PinnedVerificationKey { ), Fixed { query_index: 4, - column_index: 2, + column_index: 1, rotation: Rotation( 0, ), @@ -7206,7 +7206,7 @@ PinnedVerificationKey { ), Fixed { query_index: 5, - column_index: 3, + column_index: 2, rotation: Rotation( 0, ), @@ -7265,7 +7265,7 @@ PinnedVerificationKey { ), Fixed { query_index: 6, - column_index: 4, + column_index: 3, rotation: Rotation( 0, ), @@ -7347,7 +7347,7 @@ PinnedVerificationKey { ), Fixed { query_index: 7, - column_index: 5, + column_index: 4, rotation: Rotation( 0, ), @@ -7452,7 +7452,7 @@ PinnedVerificationKey { ), Fixed { query_index: 8, - column_index: 6, + column_index: 5, rotation: Rotation( 0, ), @@ -7580,7 +7580,7 @@ PinnedVerificationKey { ), Fixed { query_index: 9, - column_index: 7, + column_index: 6, rotation: Rotation( 0, ), @@ -7731,7 +7731,7 @@ PinnedVerificationKey { ), Fixed { query_index: 10, - column_index: 8, + column_index: 7, rotation: Rotation( 0, ), @@ -7905,7 +7905,7 @@ PinnedVerificationKey { ), Fixed { query_index: 11, - column_index: 9, + column_index: 8, rotation: Rotation( 0, ), @@ -8057,7 +8057,7 @@ PinnedVerificationKey { ), Fixed { query_index: 4, - column_index: 2, + column_index: 1, rotation: Rotation( 0, ), @@ -8079,7 +8079,7 @@ PinnedVerificationKey { ), Fixed { query_index: 5, - column_index: 3, + column_index: 2, rotation: Rotation( 0, ), @@ -8110,7 +8110,7 @@ PinnedVerificationKey { ), Fixed { query_index: 6, - column_index: 4, + column_index: 3, rotation: Rotation( 0, ), @@ -8150,7 +8150,7 @@ PinnedVerificationKey { ), Fixed { query_index: 7, - column_index: 5, + column_index: 4, rotation: Rotation( 0, ), @@ -8199,7 +8199,7 @@ PinnedVerificationKey { ), Fixed { query_index: 8, - column_index: 6, + column_index: 5, rotation: Rotation( 0, ), @@ -8257,7 +8257,7 @@ PinnedVerificationKey { ), Fixed { query_index: 9, - column_index: 7, + column_index: 6, rotation: Rotation( 0, ), @@ -8324,7 +8324,7 @@ PinnedVerificationKey { ), Fixed { query_index: 10, - column_index: 8, + column_index: 7, rotation: Rotation( 0, ), @@ -8400,7 +8400,7 @@ PinnedVerificationKey { ), Fixed { query_index: 11, - column_index: 9, + column_index: 8, rotation: Rotation( 0, ), @@ -9571,7 +9571,7 @@ PinnedVerificationKey { fixed_queries: [ ( Column { - index: 10, + index: 9, column_type: Fixed, }, Rotation( @@ -9589,7 +9589,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 10, column_type: Fixed, }, Rotation( @@ -9607,7 +9607,7 @@ PinnedVerificationKey { ), ( Column { - index: 2, + index: 1, column_type: Fixed, }, Rotation( @@ -9616,7 +9616,7 @@ PinnedVerificationKey { ), ( Column { - index: 3, + index: 2, column_type: Fixed, }, Rotation( @@ -9625,7 +9625,7 @@ PinnedVerificationKey { ), ( Column { - index: 4, + index: 3, column_type: Fixed, }, Rotation( @@ -9634,7 +9634,7 @@ PinnedVerificationKey { ), ( Column { - index: 5, + index: 4, column_type: Fixed, }, Rotation( @@ -9643,7 +9643,7 @@ PinnedVerificationKey { ), ( Column { - index: 6, + index: 5, column_type: Fixed, }, Rotation( @@ -9652,7 +9652,7 @@ PinnedVerificationKey { ), ( Column { - index: 7, + index: 6, column_type: Fixed, }, Rotation( @@ -9661,7 +9661,7 @@ PinnedVerificationKey { ), ( Column { - index: 8, + index: 7, column_type: Fixed, }, Rotation( @@ -9670,7 +9670,7 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 8, column_type: Fixed, }, Rotation( @@ -9771,7 +9771,7 @@ PinnedVerificationKey { permutation: Argument { columns: [ Column { - index: 10, + index: 9, column_type: Fixed, }, Column { @@ -10078,7 +10078,7 @@ PinnedVerificationKey { }, Fixed { query_index: 2, - column_index: 1, + column_index: 10, rotation: Rotation( 0, ), @@ -10088,7 +10088,7 @@ PinnedVerificationKey { ], constants: [ Column { - index: 10, + index: 9, column_type: Fixed, }, ], @@ -10096,7 +10096,6 @@ PinnedVerificationKey { }, fixed_commitments: [ (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), - (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x0b70f6f89e88131bb5ab28571ca837a4160b51998c6ced04328991a5c3bdcae9, 0x2cee3ef6523c2d36e01981c4794271d53fb47e9c5480b982a2ff3a869144d648), (0x0299c2272092ebe4e08c73d7261afea742a7dc29ddf73ffb941a1c9c19dcf4a1, 0x1f002552d6af287e66e3e9706ecc2a5523f256bf2c6eeb995b4233f80c8c4eeb), (0x28fb28941b09f9878eab1ce7923578b332ca794e3036789016fc6f832e820a37, 0x0e1fa37a3b4298c8df50b830e32ed5ff0ea40a0f8fbb1f9bb4620b8cfdcacf12), @@ -10106,6 +10105,7 @@ PinnedVerificationKey { (0x02fb26d5aa81b4fd2ba3324ae48a27a3e89a90005e4daebfb8004697379f235d, 0x0b484b92ea252f7a58c5bd41cbcdcd9efb932482c902abb4ae3ccb2c90912173), (0x22e2076fb8f40364e7c733c89be2039af2d0976a5a240ef6f05d9b67f5861b8a, 0x1b9f2382c80f971341343fbfd1cfa3a3fa84d70310e7a8fda21a21e20fe9b0a2), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x2cec31b1d071d872bd6b1e0660840e27bc6247398c917d5dcb09354d3175fd68, 0x0812dfd78e8ec30827f658cfb64f4f253458d0fcac102af2639295659aaa75a6), (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), (0x2e0cad5df5c23f42086784fd79c09b1dff1718dd1700e5157a1592dec21306a8, 0x01cd2a585d4dacd1c4ebb7eccc804a7284792641900d383e9f6f496482c01144), From 06746f72dda5fd14b72363612c965b12d0f5b849 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Sat, 22 Jun 2024 15:25:54 +0200 Subject: [PATCH 089/121] Remove redundancy in ecc tests --- halo2_gadgets/src/ecc.rs | 234 ++++++--------------------------------- 1 file changed, 36 insertions(+), 198 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index ec436ef5fe..9b7201ce9f 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -622,6 +622,7 @@ impl> FixedPointShort { pub(crate) mod tests { use ff::PrimeField; use group::{prime::PrimeCurveAffine, Curve, Group}; + use std::marker::PhantomData; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, @@ -641,7 +642,7 @@ pub(crate) mod tests { use crate::{ tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - LookupRangeCheck, LookupRangeCheckConfigOptimized, PallasLookupRCConfig, + PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig, }, }; @@ -771,17 +772,21 @@ pub(crate) mod tests { type Base = BaseField; } - struct MyCircuit { + struct MyCircuit { test_errors: bool, + _lookup_marker: PhantomData, } #[allow(non_snake_case)] - impl Circuit for MyCircuit { - type Config = EccConfig; + impl Circuit for MyCircuit { + type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit { test_errors: false } + MyCircuit { + test_errors: false, + _lookup_marker: PhantomData, + } } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -812,8 +817,8 @@ pub(crate) mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - let range_check = PallasLookupRCConfig::configure(meta, advices[9], lookup_table); - EccChip::::configure( + let range_check = Lookup::configure(meta, advices[9], lookup_table); + EccChip::::configure( meta, advices, lagrange_coeffs, @@ -957,14 +962,20 @@ pub(crate) mod tests { #[test] fn ecc_chip() { let k = 11; - let circuit = MyCircuit { test_errors: true }; + let circuit: MyCircuit = MyCircuit { + test_errors: true, + _lookup_marker: PhantomData, + }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] fn test_against_stored_ecc_chip() { - let circuit = MyCircuit { test_errors: false }; + let circuit: MyCircuit = MyCircuit { + test_errors: false, + _lookup_marker: PhantomData, + }; test_against_stored_circuit(circuit, "ecc_chip"); } @@ -977,201 +988,22 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit { test_errors: false }; + let circuit: MyCircuit = MyCircuit { + test_errors: false, + _lookup_marker: PhantomData, + }; halo2_proofs::dev::CircuitLayout::default() .render(13, &circuit, &root) .unwrap(); } - struct MyCircuit45B { - test_errors: bool, - } - - #[allow(non_snake_case)] - impl Circuit for MyCircuit45B { - type Config = EccConfig< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - MyCircuit45B { test_errors: false } - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - let lookup_table = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup_table); - EccChip::< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >::configure(meta, advices, lagrange_coeffs, range_check) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let chip = EccChip::construct(config.clone()); - - // Load 10-bit lookup table. In the Action circuit, this will be - // provided by the Sinsemilla chip. - config.lookup_config.load(&mut layouter)?; - - // Generate a random non-identity point P - let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P - let p = super::NonIdentityPoint::new( - chip.clone(), - layouter.namespace(|| "P"), - Value::known(p_val), - )?; - let p_neg = -p_val; - let p_neg = super::NonIdentityPoint::new( - chip.clone(), - layouter.namespace(|| "-P"), - Value::known(p_neg), - )?; - - // Generate a random non-identity point Q - let q_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // Q - let q = super::NonIdentityPoint::new( - chip.clone(), - layouter.namespace(|| "Q"), - Value::known(q_val), - )?; - - // Make sure P and Q are not the same point. - assert_ne!(p_val, q_val); - - // Test that we can witness the identity as a point, but not as a non-identity point. - { - let _ = super::Point::new( - chip.clone(), - layouter.namespace(|| "identity"), - Value::known(pallas::Affine::identity()), - )?; - - super::NonIdentityPoint::new( - chip.clone(), - layouter.namespace(|| "identity"), - Value::known(pallas::Affine::identity()), - ) - .expect_err("Trying to witness the identity should return an error"); - } - - // Test witness non-identity point - { - super::chip::witness_point::tests::test_witness_non_id( - chip.clone(), - layouter.namespace(|| "witness non-identity point"), - ) - } - - // Test complete addition - { - super::chip::add::tests::test_add( - chip.clone(), - layouter.namespace(|| "complete addition"), - p_val, - &p, - q_val, - &q, - &p_neg, - )?; - } - - // Test incomplete addition - { - super::chip::add_incomplete::tests::test_add_incomplete( - chip.clone(), - layouter.namespace(|| "incomplete addition"), - p_val, - &p, - q_val, - &q, - &p_neg, - self.test_errors, - )?; - } - - // Test variable-base scalar multiplication - { - super::chip::mul::tests::test_mul( - chip.clone(), - layouter.namespace(|| "variable-base scalar mul"), - &p, - p_val, - )?; - } - - // Test variable-base sign-scalar multiplication - { - super::chip::mul_fixed::short::tests::test_mul_sign( - chip.clone(), - layouter.namespace(|| "variable-base sign-scalar mul"), - )?; - } - - // Test full-width fixed-base scalar multiplication - { - super::chip::mul_fixed::full_width::tests::test_mul_fixed( - chip.clone(), - layouter.namespace(|| "full-width fixed-base scalar mul"), - )?; - } - - // Test signed short fixed-base scalar multiplication - { - super::chip::mul_fixed::short::tests::test_mul_fixed_short( - chip.clone(), - layouter.namespace(|| "signed short fixed-base scalar mul"), - )?; - } - - // Test fixed-base scalar multiplication with a base field element - { - super::chip::mul_fixed::base_field_elem::tests::test_mul_fixed_base_field( - chip, - layouter.namespace(|| "fixed-base scalar mul with base field element"), - )?; - } - - Ok(()) - } - } - #[test] fn ecc_chip_4_5_b() { let k = 11; - let circuit = MyCircuit45B { test_errors: true }; + let circuit: MyCircuit = MyCircuit { + test_errors: true, + _lookup_marker: PhantomData, + }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) @@ -1179,7 +1011,10 @@ pub(crate) mod tests { #[test] fn test_against_stored_ecc_chip_4_5_b() { - let circuit = MyCircuit45B { test_errors: false }; + let circuit: MyCircuit = MyCircuit { + test_errors: false, + _lookup_marker: PhantomData, + }; test_against_stored_circuit(circuit, "ecc_chip_4_5_b"); } @@ -1192,7 +1027,10 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit45B { test_errors: false }; + let circuit: MyCircuit = MyCircuit { + test_errors: false, + _lookup_marker: PhantomData, + }; halo2_proofs::dev::CircuitLayout::default() .render(13, &circuit, &root) .unwrap(); From 36e03e3ca76f633964e5db148295fecb15397e52 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Sun, 23 Jun 2024 14:56:38 +0200 Subject: [PATCH 090/121] Add expected_proof_size in test_against_stored_circuit --- halo2_gadgets/src/ecc.rs | 4 ++-- halo2_gadgets/src/sinsemilla.rs | 4 ++-- halo2_gadgets/src/sinsemilla/merkle.rs | 4 ++-- halo2_gadgets/src/tests/test_utils.rs | 2 ++ .../src/utilities/lookup_range_check.rs | 23 +++++++++++++++---- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 9b7201ce9f..de2d003098 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -976,7 +976,7 @@ pub(crate) mod tests { test_errors: false, _lookup_marker: PhantomData, }; - test_against_stored_circuit(circuit, "ecc_chip"); + test_against_stored_circuit(circuit, "ecc_chip", 3872); } #[cfg(feature = "test-dev-graph")] @@ -1015,7 +1015,7 @@ pub(crate) mod tests { test_errors: false, _lookup_marker: PhantomData, }; - test_against_stored_circuit(circuit, "ecc_chip_4_5_b"); + test_against_stored_circuit(circuit, "ecc_chip_4_5_b", 3968); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 0952825740..49bb2fb4d0 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -881,7 +881,7 @@ pub(crate) mod tests { #[test] fn test_against_stored_sinsemilla_chip() { let circuit = MyCircuit {}; - test_against_stored_circuit(circuit, "sinsemilla_chip"); + test_against_stored_circuit(circuit, "sinsemilla_chip", 4576); } #[cfg(feature = "test-dev-graph")] @@ -1147,7 +1147,7 @@ pub(crate) mod tests { fn test_against_stored_sinsemilla_chip_4_5_b() { let circuit = MyCircuit45B {}; - test_against_stored_circuit(circuit, "sinsemilla_chip_4_5_b"); + test_against_stored_circuit(circuit, "sinsemilla_chip_4_5_b", 4672); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 482cea4deb..180d2651a6 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -396,7 +396,7 @@ pub mod tests { #[test] fn test_against_stored_merkle_chip() { let circuit = generate_circuit(); - test_against_stored_circuit(circuit, "merkle_chip"); + test_against_stored_circuit(circuit, "merkle_chip", 4160); } #[cfg(feature = "test-dev-graph")] @@ -618,7 +618,7 @@ pub mod tests { fn test_against_stored_merkle_chip_4_5_b() { let circuit = generate_circuit_4_5_b(); - test_against_stored_circuit(circuit, "merkle_chip_4_5_b"); + test_against_stored_circuit(circuit, "merkle_chip_4_5_b", 4160); } #[cfg(feature = "test-dev-graph")] diff --git a/halo2_gadgets/src/tests/test_utils.rs b/halo2_gadgets/src/tests/test_utils.rs index d6f6317e4f..8ee5224cd5 100644 --- a/halo2_gadgets/src/tests/test_utils.rs +++ b/halo2_gadgets/src/tests/test_utils.rs @@ -71,6 +71,7 @@ impl Proof { pub(crate) fn test_against_stored_circuit>( circuit: C, circuit_name: &str, + expected_proof_size: usize, ) { let vk_file_path = Path::new(TEST_DATA_DIR) .join(format!("vk_{circuit_name}")) @@ -109,4 +110,5 @@ pub(crate) fn test_against_stored_circuit>( // Verify the stored proof with the generated or stored vk. assert!(proof.verify(&vk, ¶ms).is_ok()); + assert_eq!(proof.0.len(), expected_proof_size); } diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 8c6ca33216..2eb20862c7 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -858,7 +858,7 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - test_against_stored_circuit(circuit, "lookup_range_check"); + test_against_stored_circuit(circuit, "lookup_range_check", 1888); } #[test] @@ -872,7 +872,7 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); - test_against_stored_circuit(circuit, "lookup_range_check_4_5_b"); + test_against_stored_circuit(circuit, "lookup_range_check_4_5_b", 2048); } #[derive(Clone, Copy)] @@ -958,6 +958,7 @@ mod tests { proof_result: Result<(), Vec>, optimized: bool, circuit_name: &str, + expected_proof_size: usize, ) { if optimized { let circuit: MyShortRangeCheckCircuit = @@ -970,7 +971,7 @@ mod tests { assert_eq!(prover.verify(), proof_result); if proof_result.is_ok() { - test_against_stored_circuit(circuit, circuit_name); + test_against_stored_circuit(circuit, circuit_name, expected_proof_size); } } else { let circuit: MyShortRangeCheckCircuit = @@ -983,7 +984,7 @@ mod tests { assert_eq!(prover.verify(), proof_result); if proof_result.is_ok() { - test_against_stored_circuit(circuit, circuit_name); + test_against_stored_circuit(circuit, circuit_name, expected_proof_size); } }; } @@ -997,6 +998,7 @@ mod tests { Ok(()), false, "short_range_check_case0", + 1888, ); // Edge case: K bits (case 1) @@ -1006,6 +1008,7 @@ mod tests { Ok(()), false, "short_range_check_case1", + 1888, ); // Element within `num_bits` (case 2) @@ -1015,6 +1018,7 @@ mod tests { Ok(()), false, "short_range_check_case2", + 1888, ); // Element larger than `num_bits` but within K bits @@ -1030,6 +1034,7 @@ mod tests { }]), false, "not_saved", + 0, ); // Element larger than K bits @@ -1054,6 +1059,7 @@ mod tests { ]), false, "not_saved", + 0, ); // Element which is not within `num_bits`, but which has a shifted value within @@ -1078,6 +1084,7 @@ mod tests { }]), false, "not_saved", + 0, ); } @@ -1090,6 +1097,7 @@ mod tests { Ok(()), true, "short_range_check_4_5_b_case0", + 2048, ); // Edge case: K bits @@ -1099,6 +1107,7 @@ mod tests { Ok(()), true, "short_range_check_4_5_b_case1", + 2048, ); // Element within `num_bits` @@ -1108,6 +1117,7 @@ mod tests { Ok(()), true, "short_range_check_4_5_b_case2", + 2048, ); // Element larger than `num_bits` but within K bits @@ -1123,6 +1133,7 @@ mod tests { }]), true, "not_saved", + 0, ); // Element larger than K bits @@ -1147,6 +1158,7 @@ mod tests { ]), true, "not_saved", + 0, ); // Element which is not within `num_bits`, but which has a shifted value within @@ -1171,6 +1183,7 @@ mod tests { }]), true, "not_saved", + 0, ); // Element within 4 bits @@ -1180,6 +1193,7 @@ mod tests { Ok(()), true, "short_range_check_4_5_b_case3", + 2048, ); // Element larger than 5 bits @@ -1195,6 +1209,7 @@ mod tests { }]), true, "not_saved", + 0, ); } } From 5623a78f8e001990cbb85ebc594444c20c2e3f01 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Sun, 23 Jun 2024 15:56:14 +0200 Subject: [PATCH 091/121] Fix Merkle tests with optimized lookup --- halo2_gadgets/src/sinsemilla/merkle.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 180d2651a6..46de641bf6 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -473,14 +473,8 @@ pub mod tests { meta.lookup_table_column(), ); - let table_range_check_tag = meta.lookup_table_column(); - - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup.0, - table_range_check_tag, - ); + let range_check = + LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup.0); let sinsemilla_config_1 = SinsemillaChipOptimized::configure( meta, @@ -490,7 +484,7 @@ pub mod tests { lookup, range_check, ); - let config1 = MerkleChip::configure(meta, sinsemilla_config_1); + let config1 = MerkleChipOptimized::configure(meta, sinsemilla_config_1); let sinsemilla_config_2 = SinsemillaChipOptimized::configure( meta, @@ -500,7 +494,7 @@ pub mod tests { lookup, range_check, ); - let config2 = MerkleChip::configure(meta, sinsemilla_config_2); + let config2 = MerkleChipOptimized::configure(meta, sinsemilla_config_2); (config1, config2) } From 2c1f636a8f9de188a0bdb50d3cba6d8a81bb040b Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Sun, 23 Jun 2024 17:11:51 +0200 Subject: [PATCH 092/121] Rename layout images for circuits with optimized lookup --- halo2_gadgets/src/ecc.rs | 3 ++- halo2_gadgets/src/sinsemilla.rs | 4 ++-- halo2_gadgets/src/sinsemilla/merkle.rs | 7 ++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index de2d003098..1c33fe5400 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -1023,7 +1023,8 @@ pub(crate) mod tests { fn print_ecc_chip_4_5_b() { use plotters::prelude::*; - let root = BitMapBackend::new("ecc-chip-layout.png", (1024, 7680)).into_drawing_area(); + let root = + BitMapBackend::new("ecc-chip-4-5-b-layout.png", (1024, 7680)).into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 49bb2fb4d0..7454cefcdb 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -1155,8 +1155,8 @@ pub(crate) mod tests { fn print_sinsemilla_chip_4_5_b() { use plotters::prelude::*; - let root = - BitMapBackend::new("sinsemilla-hash-layout.png", (1024, 7680)).into_drawing_area(); + let root = BitMapBackend::new("sinsemilla-hash-4-5-b-layout.png", (1024, 7680)) + .into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 46de641bf6..7c548f8511 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -410,7 +410,7 @@ pub mod tests { let circuit = MyCircuit::default(); halo2_proofs::dev::CircuitLayout::default() - .show_labels(false) + .show_labels(true) .render(11, &circuit, &root) .unwrap(); } @@ -620,13 +620,14 @@ pub mod tests { fn print_merkle_chip_4_5_b() { use plotters::prelude::*; - let root = BitMapBackend::new("merkle-path-layout.png", (1024, 7680)).into_drawing_area(); + let root = + BitMapBackend::new("merkle-path-4-5-b-layout.png", (1024, 7680)).into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); let circuit = MyCircuit45B::default(); halo2_proofs::dev::CircuitLayout::default() - .show_labels(false) + .show_labels(true) .render(11, &circuit, &root) .unwrap(); } From ac7109751b80632f8676c3807de03568c0122380 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 24 Jun 2024 15:17:32 +0200 Subject: [PATCH 093/121] Remove redundancy in mul_fixed short tests --- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 1027 ++++++----------- 1 file changed, 377 insertions(+), 650 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 9153571893..9827274d7d 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -310,21 +310,22 @@ pub mod tests { use group::{ff::PrimeField, Curve, Group}; use halo2_proofs::{ arithmetic::CurveAffine, - circuit::{AssignedCell, Chip, Layouter, Value}, - plonk::{Any, Error}, + circuit::{AssignedCell, Chip, Layouter, SimpleFloorPlanner, Value}, + dev::{FailureLocation, MockProver, VerifyFailure}, + plonk::{Any, Circuit, ConstraintSystem, Error}, }; use pasta_curves::pallas; + use std::marker::PhantomData; use crate::{ ecc::{ - chip::{EccChip, FixedPoint, MagnitudeSign}, + chip::{EccChip, EccConfig, FixedPoint, MagnitudeSign}, tests::{Short, TestFixedBases}, FixedPointShort, NonIdentityPoint, Point, ScalarFixedShort, }, utilities::{ lookup_range_check::{ - LookupRangeCheck, LookupRangeCheckConfigOptimized, PallasLookupRC, - PallasLookupRCConfig, + PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig, }, UtilitiesInstructions, }, @@ -468,540 +469,285 @@ pub mod tests { Ok(()) } - #[test] - fn invalid_magnitude_sign() { - use crate::{ - ecc::chip::{EccConfig, FixedPoint}, - utilities::UtilitiesInstructions, - }; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::{FailureLocation, MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - - #[derive(Default)] - struct MyCircuit { - magnitude: Value, - sign: Value, - // For test checking - magnitude_error: Value, - } - - impl UtilitiesInstructions for MyCircuit { - type Var = AssignedCell; - } - - impl Circuit for MyCircuit { - type Config = EccConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - let lookup_table = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let range_check = PallasLookupRCConfig::configure(meta, advices[9], lookup_table); - EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let column = config.advices[0]; - - let short_config = config.mul_fixed_short.clone(); - let magnitude_sign = { - let magnitude = self.load_private( - layouter.namespace(|| "load magnitude"), - column, - self.magnitude, - )?; - let sign = - self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; - ScalarFixedShort::new( - EccChip::construct(config), - layouter.namespace(|| "signed short scalar"), - (magnitude, sign), - )? - }; + #[derive(Default)] + struct MyCircuit { + magnitude: Value, + sign: Value, + // For test checking + magnitude_error: Value, + _lookup_marker: PhantomData, + } - short_config.assign(layouter, &magnitude_sign.inner, &Short)?; + impl UtilitiesInstructions for MyCircuit { + type Var = AssignedCell; + } - Ok(()) - } - } + impl Circuit for MyCircuit { + type Config = EccConfig; + type FloorPlanner = SimpleFloorPlanner; - // Copied from halo2_proofs::dev::util - fn format_value(v: pallas::Base) -> String { - use ff::Field; - if v.is_zero_vartime() { - "0".into() - } else if v == pallas::Base::one() { - "1".into() - } else if v == -pallas::Base::one() { - "-1".into() - } else { - // Format value as hex. - let s = format!("{:?}", v); - // Remove leading zeroes. - let s = s.strip_prefix("0x").unwrap(); - let s = s.trim_start_matches('0'); - format!("0x{}", s) + fn without_witnesses(&self) -> Self { + MyCircuit { + magnitude: Value::unknown(), + sign: Value::unknown(), + magnitude_error: Value::unknown(), + _lookup_marker: PhantomData, } } - // Magnitude larger than 64 bits should fail - { - let circuits = [ - // 2^64 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 64)), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 1)), - }, - // -2^64 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 64)), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 1)), - }, - // 2^66 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 66)), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 3)), - }, - // -2^66 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 66)), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 3)), - }, - // 2^254 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known( - pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), - ), - }, - // -2^254 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known( - pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), - ), - }, + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let lookup_table = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), ]; - for circuit in circuits.iter() { - let prover = MockProver::::run(11, circuit, vec![]).unwrap(); - circuit.magnitude_error.assert_if_known(|magnitude_error| { - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 0, - "last_window_check", - ) - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)") - .into(), - offset: 1, - }, - cell_values: vec![( - ((Any::Advice, 5).into(), 0).into(), - format_value(*magnitude_error), - )], - }, - VerifyFailure::Permutation { - column: (Any::Fixed, 9).into(), - location: FailureLocation::OutsideRegion { row: 0 }, - }, - VerifyFailure::Permutation { - column: (Any::Advice, 4).into(), - location: FailureLocation::InRegion { - region: (2, "Short fixed-base mul (incomplete addition)") - .into(), - offset: 22, - }, - }, - ]) - ); - true - }); - } + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let range_check = Lookup::configure(meta, advices[9], lookup_table); + EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ) } - // Sign that is not +/- 1 should fail - { - let magnitude_u64 = rand::random::(); - let circuit = MyCircuit { - magnitude: Value::known(pallas::Base::from(magnitude_u64)), - sign: Value::known(pallas::Base::zero()), - magnitude_error: Value::unknown(), + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let column = config.advices[0]; + + let short_config = config.mul_fixed_short.clone(); + let magnitude_sign = { + let magnitude = self.load_private( + layouter.namespace(|| "load magnitude"), + column, + self.magnitude, + )?; + let sign = + self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; + ScalarFixedShort::new( + EccChip::construct(config), + layouter.namespace(|| "signed short scalar"), + (magnitude, sign), + )? }; - let negation_check_y = { - *(Short.generator() * pallas::Scalar::from(magnitude_u64)) - .to_affine() - .coordinates() - .unwrap() - .y() - }; + short_config.assign(layouter, &magnitude_sign.inner, &Short)?; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check") - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)").into(), - offset: 1, - }, - cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], - }, - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 3, - "negation_check" - ) - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)").into(), - offset: 1, - }, - cell_values: vec![ - ( - ((Any::Advice, 1).into(), 0).into(), - format_value(negation_check_y), - ), - ( - ((Any::Advice, 3).into(), 0).into(), - format_value(negation_check_y), - ), - (((Any::Advice, 4).into(), 0).into(), "0".to_string()), - ], - } - ]) - ); + Ok(()) } } - #[test] - fn invalid_magnitude_sign_4_5_b() { - use crate::{ - ecc::chip::{EccConfig, FixedPoint}, - utilities::UtilitiesInstructions, - }; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::{FailureLocation, MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - - #[derive(Default)] - struct MyCircuit { - magnitude: Value, - sign: Value, - // For test checking - magnitude_error: Value, - } - - impl UtilitiesInstructions for MyCircuit { - type Var = AssignedCell; + // Copied from halo2_proofs::dev::util + fn format_value(v: pallas::Base) -> String { + use ff::Field; + if v.is_zero_vartime() { + "0".into() + } else if v == pallas::Base::one() { + "1".into() + } else if v == -pallas::Base::one() { + "-1".into() + } else { + // Format value as hex. + let s = format!("{:?}", v); + // Remove leading zeroes. + let s = s.strip_prefix("0x").unwrap(); + let s = s.trim_start_matches('0'); + format!("0x{}", s) } + } - impl Circuit for MyCircuit { - type Config = EccConfig< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), + impl MyCircuit { + fn test_invalid_magnitude_sign() { + // Magnitude larger than 64 bits should fail + { + let circuits: Vec> = vec![ + // 2^64 + MyCircuit:: { + magnitude: Value::known(pallas::Base::from_u128(1 << 64)), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 1)), + _lookup_marker: PhantomData, + }, + // -2^64 + MyCircuit:: { + magnitude: Value::known(pallas::Base::from_u128(1 << 64)), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 1)), + _lookup_marker: PhantomData, + }, + // 2^66 + MyCircuit:: { + magnitude: Value::known(pallas::Base::from_u128(1 << 66)), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 3)), + _lookup_marker: PhantomData, + }, + // -2^66 + MyCircuit:: { + magnitude: Value::known(pallas::Base::from_u128(1 << 66)), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known(pallas::Base::from(1 << 3)), + _lookup_marker: PhantomData, + }, + // 2^254 + MyCircuit:: { + magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), + sign: Value::known(pallas::Base::one()), + magnitude_error: Value::known( + pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), + ), + _lookup_marker: PhantomData, + }, + // -2^254 + MyCircuit:: { + magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), + sign: Value::known(-pallas::Base::one()), + magnitude_error: Value::known( + pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), + ), + _lookup_marker: PhantomData, + }, ]; - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); - EccChip::< - TestFixedBases, - LookupRangeCheckConfigOptimized< - pallas::Base, - { crate::sinsemilla::primitives::K }, - >, - >::configure(meta, advices, lagrange_coeffs, range_check) + for circuit in circuits.iter() { + let prover = MockProver::::run(11, circuit, vec![]).unwrap(); + circuit.magnitude_error.assert_if_known(|magnitude_error| { + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 0, + "last_window_check", + ) + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)") + .into(), + offset: 1, + }, + cell_values: vec![( + ((Any::Advice, 5).into(), 0).into(), + format_value(*magnitude_error), + )], + }, + VerifyFailure::Permutation { + column: (Any::Fixed, 9).into(), + location: FailureLocation::OutsideRegion { row: 0 }, + }, + VerifyFailure::Permutation { + column: (Any::Advice, 4).into(), + location: FailureLocation::InRegion { + region: (2, "Short fixed-base mul (incomplete addition)") + .into(), + offset: 22, + }, + }, + ]) + ); + true + }); + } } - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let column = config.advices[0]; - - let short_config = config.mul_fixed_short.clone(); - let magnitude_sign = { - let magnitude = self.load_private( - layouter.namespace(|| "load magnitude"), - column, - self.magnitude, - )?; - let sign = - self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; - ScalarFixedShort::new( - EccChip::construct(config), - layouter.namespace(|| "signed short scalar"), - (magnitude, sign), - )? + // Sign that is not +/- 1 should fail + { + let magnitude_u64 = rand::random::(); + let circuit: MyCircuit = MyCircuit { + magnitude: Value::known(pallas::Base::from(magnitude_u64)), + sign: Value::known(pallas::Base::zero()), + magnitude_error: Value::unknown(), + _lookup_marker: PhantomData, }; - short_config.assign(layouter, &magnitude_sign.inner, &Short)?; - - Ok(()) - } - } - - // Copied from halo2_proofs::dev::util - fn format_value(v: pallas::Base) -> String { - use ff::Field; - if v.is_zero_vartime() { - "0".into() - } else if v == pallas::Base::one() { - "1".into() - } else if v == -pallas::Base::one() { - "-1".into() - } else { - // Format value as hex. - let s = format!("{:?}", v); - // Remove leading zeroes. - let s = s.strip_prefix("0x").unwrap(); - let s = s.trim_start_matches('0'); - format!("0x{}", s) - } - } - - // Magnitude larger than 64 bits should fail - { - let circuits = [ - // 2^64 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 64)), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 1)), - }, - // -2^64 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 64)), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 1)), - }, - // 2^66 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 66)), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 3)), - }, - // -2^66 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 66)), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known(pallas::Base::from(1 << 3)), - }, - // 2^254 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), - sign: Value::known(pallas::Base::one()), - magnitude_error: Value::known( - pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), - ), - }, - // -2^254 - MyCircuit { - magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), - sign: Value::known(-pallas::Base::one()), - magnitude_error: Value::known( - pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), - ), - }, - ]; + let negation_check_y = { + *(Short.generator() * pallas::Scalar::from(magnitude_u64)) + .to_affine() + .coordinates() + .unwrap() + .y() + }; - for circuit in circuits.iter() { - let prover = MockProver::::run(11, circuit, vec![]).unwrap(); - circuit.magnitude_error.assert_if_known(|magnitude_error| { - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 0, - "last_window_check", - ) - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)") - .into(), - offset: 1, - }, - cell_values: vec![( - ((Any::Advice, 5).into(), 0).into(), - format_value(*magnitude_error), - )], - }, - VerifyFailure::Permutation { - column: (Any::Fixed, 10).into(), - location: FailureLocation::OutsideRegion { row: 0 }, + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check") + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)").into(), + offset: 1, }, - VerifyFailure::Permutation { - column: (Any::Advice, 4).into(), - location: FailureLocation::InRegion { - region: (2, "Short fixed-base mul (incomplete addition)") - .into(), - offset: 22, - }, + cell_values: vec![( + ((Any::Advice, 4).into(), 0).into(), + "0".to_string() + )], + }, + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 3, + "negation_check" + ) + .into(), + location: FailureLocation::InRegion { + region: (3, "Short fixed-base mul (most significant word)").into(), + offset: 1, }, - ]) - ); - true - }); + cell_values: vec![ + ( + ((Any::Advice, 1).into(), 0).into(), + format_value(negation_check_y), + ), + ( + ((Any::Advice, 3).into(), 0).into(), + format_value(negation_check_y), + ), + (((Any::Advice, 4).into(), 0).into(), "0".to_string()), + ], + } + ]) + ); } } + } - // Sign that is not +/- 1 should fail - { - let magnitude_u64 = rand::random::(); - let circuit = MyCircuit { - magnitude: Value::known(pallas::Base::from(magnitude_u64)), - sign: Value::known(pallas::Base::zero()), - magnitude_error: Value::unknown(), - }; - - let negation_check_y = { - *(Short.generator() * pallas::Scalar::from(magnitude_u64)) - .to_affine() - .coordinates() - .unwrap() - .y() - }; + #[cfg(feature = "test-dev-graph")] + #[test] + fn invalid_magnitude_sign() { + MyCircuit::::test_invalid_magnitude_sign(); + } - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check") - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)").into(), - offset: 1, - }, - cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], - }, - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 3, - "negation_check" - ) - .into(), - location: FailureLocation::InRegion { - region: (3, "Short fixed-base mul (most significant word)").into(), - offset: 1, - }, - cell_values: vec![ - ( - ((Any::Advice, 1).into(), 0).into(), - format_value(negation_check_y), - ), - ( - ((Any::Advice, 3).into(), 0).into(), - format_value(negation_check_y), - ), - (((Any::Advice, 4).into(), 0).into(), "0".to_string()), - ], - } - ]) - ); - } + #[test] + fn invalid_magnitude_sign_4_5_b() { + MyCircuit::::test_invalid_magnitude_sign(); } pub(crate) fn test_mul_sign( @@ -1069,165 +815,146 @@ pub mod tests { Ok(()) } - #[test] - fn invalid_sign_in_mul_sign() { - use crate::{ecc::chip::EccConfig, utilities::UtilitiesInstructions}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::{FailureLocation, MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - #[derive(Default)] - struct MyCircuit { - base: Value, - sign: Value, - } + #[derive(Default)] + struct MyMulSignCircuit { + base: Value, + sign: Value, + _lookup_marker: PhantomData, + } - impl UtilitiesInstructions for MyCircuit { - type Var = AssignedCell; - } + impl UtilitiesInstructions for MyMulSignCircuit { + type Var = AssignedCell; + } - impl Circuit for MyCircuit { - type Config = EccConfig< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >; - type FloorPlanner = SimpleFloorPlanner; + impl Circuit for MyMulSignCircuit { + type Config = EccConfig; + type FloorPlanner = SimpleFloorPlanner; - fn without_witnesses(&self) -> Self { - Self::default() + fn without_witnesses(&self) -> Self { + MyMulSignCircuit { + base: Value::unknown(), + sign: Value::unknown(), + _lookup_marker: PhantomData, } + } - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - let lookup_table = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let lookup_table = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( - meta, - advices[9], - lookup_table, - table_range_check_tag, - ); - EccChip::< - TestFixedBases, - LookupRangeCheckConfigOptimized< - pallas::Base, - { crate::sinsemilla::primitives::K }, - >, - >::configure(meta, advices, lagrange_coeffs, range_check) - } + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let chip = EccChip::construct(config.clone()); + let range_check = Lookup::configure(meta, advices[9], lookup_table); + EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ) + } - let column = config.advices[0]; + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = EccChip::::construct(config.clone()); - //let short_config = config.mul_fixed_short.clone(); - let base = Point::new(chip, layouter.namespace(|| "load base"), self.base)?; + let column = config.advices[0]; - let sign = - self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; + //let short_config = config.mul_fixed_short.clone(); + let base = Point::new(chip, layouter.namespace(|| "load base"), self.base)?; - base.mul_sign(layouter.namespace(|| "[sign] base"), &sign)?; + let sign = self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; - Ok(()) - } - } + base.mul_sign(layouter.namespace(|| "[sign] base"), &sign)?; - // Copied from halo2_proofs::dev::util - fn format_value(v: pallas::Base) -> String { - use ff::Field; - if v.is_zero_vartime() { - "0".into() - } else if v == pallas::Base::one() { - "1".into() - } else if v == -pallas::Base::one() { - "-1".into() - } else { - // Format value as hex. - let s = format!("{:?}", v); - // Remove leading zeroes. - let s = s.strip_prefix("0x").unwrap(); - let s = s.trim_start_matches('0'); - format!("0x{}", s) - } + Ok(()) } + } - // Sign that is not +/- 1 should fail - // Generate a random non-identity point - let point = pallas::Point::random(rand::rngs::OsRng); - let circuit = MyCircuit { - base: Value::known(point.to_affine()), - sign: Value::known(pallas::Base::zero()), - }; + impl MyMulSignCircuit { + fn test_invalid_magnitude_sign() { + // Sign that is not +/- 1 should fail + // Generate a random non-identity point + let point = pallas::Point::random(rand::rngs::OsRng); + let circuit: MyMulSignCircuit = MyMulSignCircuit { + base: Value::known(point.to_affine()), + sign: Value::known(pallas::Base::zero()), + _lookup_marker: PhantomData, + }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![ - VerifyFailure::ConstraintNotSatisfied { - constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check").into(), - location: FailureLocation::InRegion { - region: (2, "Signed point").into(), - offset: 0, - }, - cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], - }, - VerifyFailure::ConstraintNotSatisfied { - constraint: ( - (17, "Short fixed-base mul gate").into(), - 3, - "negation_check" - ) - .into(), - location: FailureLocation::InRegion { - region: (2, "Signed point").into(), - offset: 0, + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!( + prover.verify(), + Err(vec![ + VerifyFailure::ConstraintNotSatisfied { + constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check") + .into(), + location: FailureLocation::InRegion { + region: (2, "Signed point").into(), + offset: 0, + }, + cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], }, - cell_values: vec![ - ( - ((Any::Advice, 1).into(), 0).into(), - format_value(*point.to_affine().coordinates().unwrap().y()), - ), - ( - ((Any::Advice, 3).into(), 0).into(), - format_value(*point.to_affine().coordinates().unwrap().y()), - ), - (((Any::Advice, 4).into(), 0).into(), "0".to_string()), - ], - } - ]) - ); + VerifyFailure::ConstraintNotSatisfied { + constraint: ( + (17, "Short fixed-base mul gate").into(), + 3, + "negation_check" + ) + .into(), + location: FailureLocation::InRegion { + region: (2, "Signed point").into(), + offset: 0, + }, + cell_values: vec![ + ( + ((Any::Advice, 1).into(), 0).into(), + format_value(*point.to_affine().coordinates().unwrap().y()), + ), + ( + ((Any::Advice, 3).into(), 0).into(), + format_value(*point.to_affine().coordinates().unwrap().y()), + ), + (((Any::Advice, 4).into(), 0).into(), "0".to_string()), + ], + } + ]) + ); + } + } + + #[test] + fn invalid_sign_in_mul_sign() { + MyMulSignCircuit::::test_invalid_magnitude_sign(); + } + #[test] + fn invalid_sign_in_mul_sign_4_5_b() { + MyMulSignCircuit::::test_invalid_magnitude_sign(); } } From 61d223ec122d8376ce35249f9809a51465186ffc Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 24 Jun 2024 15:48:14 +0200 Subject: [PATCH 094/121] Move load_with_tag --- halo2_gadgets/src/sinsemilla/chip.rs | 8 +- .../src/sinsemilla/chip/generator_table.rs | 180 +++++++++--------- 2 files changed, 93 insertions(+), 95 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 41214f2d22..03438d9e58 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -434,11 +434,9 @@ where layouter: &mut impl Layouter, ) -> Result<>::Loaded, Error> { // Load the lookup table. - generator_table::load_with_tag( - &config.generator_table, - config.lookup_config.table_range_check_tag(), - layouter, - ) + config + .generator_table + .load_with_tag(config.lookup_config.table_range_check_tag(), layouter) } /// Assign y_q to an advice column diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index f01bb6766f..8d052cfb34 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -100,104 +100,104 @@ impl GeneratorTableConfig { }, ) } -} - -/// Load the generator table into the circuit. -/// -/// | table_idx | table_x | table_y | table_range_check_tag | -/// ------------------------------------------------------------------- -/// | 0 | X(S\[0\]) | Y(S\[0\]) | 0 | -/// | 1 | X(S\[1\]) | Y(S\[1\]) | 0 | -/// | ... | ... | ... | 0 | -/// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | 0 | -/// | 0 | X(S\[0\]) | Y(S\[0\]) | 4 | -/// | 1 | X(S\[1\]) | Y(S\[1\]) | 4 | -/// | ... | ... | ... | 4 | -/// | 2^4-1 | X(S\[2^4-1\]) | Y(S\[2^4-1\]) | 4 | -/// | 0 | X(S\[0\]) | Y(S\[0\]) | 5 | -/// | 1 | X(S\[1\]) | Y(S\[1\]) | 5 | -/// | ... | ... | ... | 5 | -/// | 2^5-1 | X(S\[2^5-1\]) | Y(S\[2^5-1\]) | 5 | -pub fn load_with_tag( - config: &GeneratorTableConfig, - table_range_check_tag: TableColumn, - layouter: &mut impl Layouter, -) -> Result<(), Error> { - layouter.assign_table( - || "generator_table", - |mut table| { - for (index, (x, y)) in SINSEMILLA_S.iter().enumerate() { - table.assign_cell( - || "table_idx", - config.table_idx, - index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell(|| "table_x", config.table_x, index, || Value::known(*x))?; - table.assign_cell(|| "table_y", config.table_y, index, || Value::known(*y))?; - table.assign_cell( - || "table_range_check_tag", - table_range_check_tag, - index, - || Value::known(pallas::Base::zero()), - )?; - if index < (1 << 4) { - let new_index = index + (1 << K); - table.assign_cell( - || "table_idx", - config.table_idx, - new_index, - || Value::known(pallas::Base::from(index as u64)), - )?; - table.assign_cell( - || "table_x", - config.table_x, - new_index, - || Value::known(*x), - )?; - table.assign_cell( - || "table_y", - config.table_y, - new_index, - || Value::known(*y), - )?; - table.assign_cell( - || "table_range_check_tag", - table_range_check_tag, - new_index, - || Value::known(pallas::Base::from(4_u64)), - )?; - } - if index < (1 << 5) { - let new_index = index + (1 << 10) + (1 << 4); + /// Load the generator table into the circuit. + /// + /// | table_idx | table_x | table_y | table_range_check_tag | + /// ------------------------------------------------------------------- + /// | 0 | X(S\[0\]) | Y(S\[0\]) | 0 | + /// | 1 | X(S\[1\]) | Y(S\[1\]) | 0 | + /// | ... | ... | ... | 0 | + /// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | 0 | + /// | 0 | X(S\[0\]) | Y(S\[0\]) | 4 | + /// | 1 | X(S\[1\]) | Y(S\[1\]) | 4 | + /// | ... | ... | ... | 4 | + /// | 2^4-1 | X(S\[2^4-1\]) | Y(S\[2^4-1\]) | 4 | + /// | 0 | X(S\[0\]) | Y(S\[0\]) | 5 | + /// | 1 | X(S\[1\]) | Y(S\[1\]) | 5 | + /// | ... | ... | ... | 5 | + /// | 2^5-1 | X(S\[2^5-1\]) | Y(S\[2^5-1\]) | 5 | + pub fn load_with_tag( + &self, + table_range_check_tag: TableColumn, + layouter: &mut impl Layouter, + ) -> Result<(), Error> { + layouter.assign_table( + || "generator_table", + |mut table| { + for (index, (x, y)) in SINSEMILLA_S.iter().enumerate() { table.assign_cell( || "table_idx", - config.table_idx, - new_index, + self.table_idx, + index, || Value::known(pallas::Base::from(index as u64)), )?; - table.assign_cell( - || "table_x", - config.table_x, - new_index, - || Value::known(*x), - )?; - table.assign_cell( - || "table_y", - config.table_y, - new_index, - || Value::known(*y), - )?; + table.assign_cell(|| "table_x", self.table_x, index, || Value::known(*x))?; + table.assign_cell(|| "table_y", self.table_y, index, || Value::known(*y))?; + table.assign_cell( || "table_range_check_tag", table_range_check_tag, - new_index, - || Value::known(pallas::Base::from(5_u64)), + index, + || Value::known(pallas::Base::zero()), )?; + if index < (1 << 4) { + let new_index = index + (1 << K); + table.assign_cell( + || "table_idx", + self.table_idx, + new_index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell( + || "table_x", + self.table_x, + new_index, + || Value::known(*x), + )?; + table.assign_cell( + || "table_y", + self.table_y, + new_index, + || Value::known(*y), + )?; + table.assign_cell( + || "table_range_check_tag", + table_range_check_tag, + new_index, + || Value::known(pallas::Base::from(4_u64)), + )?; + } + if index < (1 << 5) { + let new_index = index + (1 << 10) + (1 << 4); + table.assign_cell( + || "table_idx", + self.table_idx, + new_index, + || Value::known(pallas::Base::from(index as u64)), + )?; + table.assign_cell( + || "table_x", + self.table_x, + new_index, + || Value::known(*x), + )?; + table.assign_cell( + || "table_y", + self.table_y, + new_index, + || Value::known(*y), + )?; + table.assign_cell( + || "table_range_check_tag", + table_range_check_tag, + new_index, + || Value::known(pallas::Base::from(5_u64)), + )?; + } } - } - Ok(()) - }, - ) + Ok(()) + }, + ) + } } From b4a70ab9be8da4e476a1b222e76fa52fc54d21ab Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 24 Jun 2024 16:33:07 +0200 Subject: [PATCH 095/121] Light modifications on hash_to_point --- .../src/sinsemilla/chip/hash_to_point.rs | 326 +++++++++--------- 1 file changed, 161 insertions(+), 165 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index ef30a4e9d6..a82d2632d4 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -24,169 +24,6 @@ pub enum EccPointQ<'a> { PrivatePoint(&'a NonIdentityEccPoint), } -impl SinsemillaChipOptimized -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(super) fn hash_message( - &self, - region: &mut Region<'_, pallas::Base>, - Q: pallas::Affine, - message: &>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - // Coordinates of the initial point `Q` are assigned to advice columns - let (offset, x_a, y_a) = self.public_initialization(region, Q)?; - - let (x_a, y_a, zs_sum) = - SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; - - SinsemillaChip::check_hash_result( - &self.inner, - EccPointQ::PublicPoint(Q), - message, - x_a, - y_a, - zs_sum, - ) - } - /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(super) fn hash_message_with_private_init( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - message: &>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - let (offset, x_a, y_a) = self.private_initialization(region, Q)?; - - let (x_a, y_a, zs_sum) = - SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; - - SinsemillaChip::check_hash_result( - &self.inner, - EccPointQ::PrivatePoint(Q), - message, - x_a, - y_a, - zs_sum, - ) - } - - #[allow(non_snake_case)] - /// Assign the coordinates of the initial public point `Q` to advice columns - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn public_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: pallas::Affine, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - let mut offset = 0; - - // Get the `x`- and `y`-coordinates of the starting `Q` base. - let x_q = *Q.coordinates().unwrap().x(); - let y_q = *Q.coordinates().unwrap().y(); - - // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 - // selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, offset + 1)?; - let y_a: AssignedCell, pallas::Base> = region - .assign_advice_from_constant( - || "fixed y_q", - config.double_and_add.x_p, - offset, - y_q.into(), - )?; - - y_a.value_field().into() - }; - offset += 1; - - // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. - let x_a: X = { - let x_a = region.assign_advice_from_constant( - || "fixed x_q", - config.double_and_add.x_a, - offset, - x_q.into(), - )?; - - x_a.into() - }; - - Ok((offset, x_a, y_a)) - } - - #[allow(non_snake_case)] - /// Assign the coordinates of the initial private point `Q` - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn private_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - let mut offset = 0; - - // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, - // x_p, y_Q using the q_sinsemilla4 selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, offset + 1)?; - let q_y: AssignedCell, pallas::Base> = Q.y().into(); - let y_a: AssignedCell, pallas::Base> = - q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, offset)?; - - y_a.value_field().into() - }; - offset += 1; - - let x_a: X = { - let q_x: AssignedCell, pallas::Base> = Q.x().into(); - let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, offset)?; - - x_a.into() - }; - - Ok((offset, x_a, y_a)) - } -} - impl SinsemillaChip where Hash: HashDomains, @@ -213,7 +50,7 @@ where ), Error, > { - let (offset, x_a, y_a) = self.public_q_initialization(region, Q)?; + let (offset, x_a, y_a) = self.public_initialization(region, Q)?; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; @@ -302,7 +139,7 @@ where /// | offset | x_A | q_sinsemilla4 | fixed_y_q | /// -------------------------------------- /// | 0 | x_Q | 1 | y_Q | - fn public_q_initialization( + fn public_initialization( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, @@ -623,6 +460,165 @@ where } } +impl SinsemillaChipOptimized +where + Hash: HashDomains, + Fixed: FixedPoints, + Commit: CommitDomains, +{ + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(super) fn hash_message( + &self, + region: &mut Region<'_, pallas::Base>, + Q: pallas::Affine, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + // Coordinates of the initial point `Q` are assigned to advice columns + let (offset, x_a, y_a) = self.public_initialization(region, Q)?; + + let (x_a, y_a, zs_sum) = + SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; + + SinsemillaChip::check_hash_result( + &self.inner, + EccPointQ::PublicPoint(Q), + message, + x_a, + y_a, + zs_sum, + ) + } + /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(super) fn hash_message_with_private_init( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + let (offset, x_a, y_a) = self.private_initialization(region, Q)?; + + let (x_a, y_a, zs_sum) = + SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; + + SinsemillaChip::check_hash_result( + &self.inner, + EccPointQ::PrivatePoint(Q), + message, + x_a, + y_a, + zs_sum, + ) + } + + #[allow(non_snake_case)] + /// Assign the coordinates of the initial public point `Q` to advice columns + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + fn public_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: pallas::Affine, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + + // Get the `x`- and `y`-coordinates of the starting `Q` base. + let x_q = *Q.coordinates().unwrap().x(); + let y_q = *Q.coordinates().unwrap().y(); + + // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 + // selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, 1)?; + let y_a: AssignedCell, pallas::Base> = region + .assign_advice_from_constant( + || "fixed y_q", + config.double_and_add.x_p, + 0, + y_q.into(), + )?; + + y_a.value_field().into() + }; + + // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. + let x_a: X = { + let x_a = region.assign_advice_from_constant( + || "fixed x_q", + config.double_and_add.x_a, + 1, + x_q.into(), + )?; + + x_a.into() + }; + + Ok((1, x_a, y_a)) + } + + #[allow(non_snake_case)] + /// Assign the coordinates of the initial private point `Q` + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + fn private_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + + // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, + // x_p, y_Q using the q_sinsemilla4 selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, 1)?; + let q_y: AssignedCell, pallas::Base> = Q.y().into(); + let y_a: AssignedCell, pallas::Base> = + q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, 0)?; + + y_a.value_field().into() + }; + + let x_a: X = { + let q_x: AssignedCell, pallas::Base> = Q.x().into(); + let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, 1)?; + + x_a.into() + }; + + Ok((1, x_a, y_a)) + } +} + /// The x-coordinate of the accumulator in a Sinsemilla hash instance. struct X(AssignedCell, F>); From a208dca649a7cbfb7c3182b6e6bb7eca58cc306a Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 24 Jun 2024 21:40:23 +0200 Subject: [PATCH 096/121] Add test on mux with non optimized lookup --- halo2_gadgets/src/utilities/cond_swap.rs | 124 ++++++++++++----------- 1 file changed, 65 insertions(+), 59 deletions(-) diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index ced0b9a296..00fb4d894c 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -300,7 +300,9 @@ impl CondSwapChip { mod tests { use super::super::UtilitiesInstructions; use super::{CondSwapChip, CondSwapConfig, CondSwapInstructions}; - use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; + use crate::utilities::lookup_range_check::{ + PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig, + }; use group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, @@ -309,6 +311,7 @@ mod tests { }; use pasta_curves::pallas::Base; use rand::rngs::OsRng; + use std::marker::PhantomData; #[test] fn cond_swap() { @@ -416,29 +419,32 @@ mod tests { use rand::rngs::OsRng; #[derive(Clone, Debug)] - pub struct MyConfig { + pub struct MyMuxConfig { primary: Column, advice: Column, cond_swap_config: CondSwapConfig, - ecc_config: EccConfig< - TestFixedBases, - LookupRangeCheckConfigOptimized, - >, + ecc_config: EccConfig, } #[derive(Default)] - struct MyCircuit { + struct MyMuxCircuit { left_point: Value, right_point: Value, choice: Value, + _lookup_marker: PhantomData, } - impl Circuit for MyCircuit { - type Config = MyConfig; + impl Circuit for MyMuxCircuit { + type Config = MyMuxConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - Self::default() + MyMuxCircuit:: { + left_point: Value::default(), + right_point: Value::default(), + choice: Value::default(), + _lookup_marker: PhantomData, + } } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -467,7 +473,6 @@ mod tests { CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), @@ -481,23 +486,16 @@ mod tests { ]; meta.enable_constant(lagrange_coeffs[0]); - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + let range_check = Lookup::configure(meta, advices[9], table_idx); + + let ecc_config = EccChip::::configure( meta, - advices[9], - table_idx, - table_range_check_tag, + advices, + lagrange_coeffs, + range_check, ); - let ecc_config = - EccChip::< - TestFixedBases, - LookupRangeCheckConfigOptimized< - pallas::Base, - { crate::sinsemilla::primitives::K }, - >, - >::configure(meta, advices, lagrange_coeffs, range_check); - - MyConfig { + MyMuxConfig { primary, advice: advices[0], cond_swap_config, @@ -514,7 +512,7 @@ mod tests { let cond_swap_chip = CondSwapChip::construct(config.cond_swap_config); // Construct an ECC chip - let ecc_chip = EccChip::construct(config.ecc_config); + let ecc_chip = EccChip::::construct(config.ecc_config); // Assign choice let choice = layouter.assign_region( @@ -588,40 +586,48 @@ mod tests { } } - // Test different circuits - let mut circuits = vec![]; - let mut instances = vec![]; - for choice in [false, true] { - let choice_value = if choice { - pallas::Base::one() - } else { - pallas::Base::zero() - }; - let left_point = pallas::Point::random(OsRng).to_affine(); - let right_point = pallas::Point::random(OsRng).to_affine(); - circuits.push(MyCircuit { - left_point: Value::known(left_point), - right_point: Value::known(right_point), - choice: Value::known(choice_value), - }); - let expected_output = if choice { right_point } else { left_point }; - let (expected_x, expected_y) = if bool::from(expected_output.is_identity()) { - (pallas::Base::zero(), pallas::Base::zero()) - } else { - let coords = expected_output.coordinates().unwrap(); - (*coords.x(), *coords.y()) - }; - instances.push([[expected_x, expected_y]]); - } + impl MyMuxCircuit { + fn test_mux_circuits() { + // Test different circuits + let mut circuits = vec![]; + let mut instances = vec![]; + for choice in [false, true] { + let choice_value = if choice { + pallas::Base::one() + } else { + pallas::Base::zero() + }; + let left_point = pallas::Point::random(OsRng).to_affine(); + let right_point = pallas::Point::random(OsRng).to_affine(); + circuits.push(MyMuxCircuit:: { + left_point: Value::known(left_point), + right_point: Value::known(right_point), + choice: Value::known(choice_value), + _lookup_marker: PhantomData, + }); + let expected_output = if choice { right_point } else { left_point }; + let (expected_x, expected_y) = if bool::from(expected_output.is_identity()) { + (pallas::Base::zero(), pallas::Base::zero()) + } else { + let coords = expected_output.coordinates().unwrap(); + (*coords.x(), *coords.y()) + }; + instances.push([[expected_x, expected_y]]); + } - for (circuit, instance) in circuits.iter().zip(instances.iter()) { - let prover = MockProver::::run( - 5, - circuit, - instance.iter().map(|p| p.to_vec()).collect(), - ) - .unwrap(); - assert_eq!(prover.verify(), Ok(())); + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + let prover = MockProver::::run( + 5, + circuit, + instance.iter().map(|p| p.to_vec()).collect(), + ) + .unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } } + + MyMuxCircuit::::test_mux_circuits(); + MyMuxCircuit::::test_mux_circuits(); } } From fda20b93c8afa3fccb5b1f05af47c8642c08658d Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 24 Jun 2024 22:23:38 +0200 Subject: [PATCH 097/121] Rename some lookup traits and structures LookupRangeCheck45BConfig <- LookupRangeCheckConfigOptimized PallasLookupRangeCheck <- PallasLookupRC PallasLookupRangeCheckConfig <- PallasLookupRCConfig PallasLookupRangeCheck45BConfig <- PallasLookupConfigOptimized --- halo2_gadgets/src/ecc.rs | 18 ++--- halo2_gadgets/src/ecc/chip.rs | 20 +++--- halo2_gadgets/src/ecc/chip/mul.rs | 10 +-- halo2_gadgets/src/ecc/chip/mul/overflow.rs | 6 +- .../src/ecc/chip/mul_fixed/base_field_elem.rs | 18 ++--- .../src/ecc/chip/mul_fixed/full_width.rs | 8 +-- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 37 +++++----- halo2_gadgets/src/sinsemilla.rs | 24 +++---- halo2_gadgets/src/sinsemilla/chip.rs | 49 ++++++------- .../src/sinsemilla/chip/generator_table.rs | 4 +- .../src/sinsemilla/chip/hash_to_point.rs | 4 +- halo2_gadgets/src/sinsemilla/merkle.rs | 35 +++++---- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 42 ++++++----- halo2_gadgets/src/utilities/cond_swap.rs | 14 ++-- .../src/utilities/lookup_range_check.rs | 72 +++++++++---------- 15 files changed, 189 insertions(+), 172 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 1c33fe5400..7b8139be9f 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -642,7 +642,7 @@ pub(crate) mod tests { use crate::{ tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, }, }; @@ -772,13 +772,13 @@ pub(crate) mod tests { type Base = BaseField; } - struct MyCircuit { + struct MyCircuit { test_errors: bool, _lookup_marker: PhantomData, } #[allow(non_snake_case)] - impl Circuit for MyCircuit { + impl Circuit for MyCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; @@ -962,7 +962,7 @@ pub(crate) mod tests { #[test] fn ecc_chip() { let k = 11; - let circuit: MyCircuit = MyCircuit { + let circuit: MyCircuit = MyCircuit { test_errors: true, _lookup_marker: PhantomData, }; @@ -972,7 +972,7 @@ pub(crate) mod tests { #[test] fn test_against_stored_ecc_chip() { - let circuit: MyCircuit = MyCircuit { + let circuit: MyCircuit = MyCircuit { test_errors: false, _lookup_marker: PhantomData, }; @@ -988,7 +988,7 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit: MyCircuit = MyCircuit { + let circuit: MyCircuit = MyCircuit { test_errors: false, _lookup_marker: PhantomData, }; @@ -1000,7 +1000,7 @@ pub(crate) mod tests { #[test] fn ecc_chip_4_5_b() { let k = 11; - let circuit: MyCircuit = MyCircuit { + let circuit: MyCircuit = MyCircuit { test_errors: true, _lookup_marker: PhantomData, }; @@ -1011,7 +1011,7 @@ pub(crate) mod tests { #[test] fn test_against_stored_ecc_chip_4_5_b() { - let circuit: MyCircuit = MyCircuit { + let circuit: MyCircuit = MyCircuit { test_errors: false, _lookup_marker: PhantomData, }; @@ -1028,7 +1028,7 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit: MyCircuit = MyCircuit { + let circuit: MyCircuit = MyCircuit { test_errors: false, _lookup_marker: PhantomData, }; diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 704abdc76a..32f026a415 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -2,7 +2,7 @@ use super::{BaseFitsInScalarInstructions, EccInstructions, FixedPoints}; use crate::utilities::{ - lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, + lookup_range_check::{PallasLookupRangeCheck, PallasLookupRangeCheckConfig}, UtilitiesInstructions, }; use arrayvec::ArrayVec; @@ -139,7 +139,7 @@ impl From for EccPoint { #[allow(non_snake_case)] pub struct EccConfig< FixedPoints: super::FixedPoints, - Lookup: PallasLookupRC = PallasLookupRCConfig, + Lookup: PallasLookupRangeCheck = PallasLookupRangeCheckConfig, > { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], @@ -232,13 +232,13 @@ pub trait FixedPoint: std::fmt::Debug + Eq + Clone { #[derive(Clone, Debug, Eq, PartialEq)] pub struct EccChip< FixedPoints: super::FixedPoints, - Lookup: PallasLookupRC = PallasLookupRCConfig, + Lookup: PallasLookupRangeCheck = PallasLookupRangeCheckConfig, > { config: EccConfig, } -impl, Lookup: PallasLookupRC> Chip - for EccChip +impl, Lookup: PallasLookupRangeCheck> + Chip for EccChip { type Config = EccConfig; type Loaded = (); @@ -252,13 +252,13 @@ impl, Lookup: PallasLookupRC> Ch } } -impl, Lookup: PallasLookupRC> +impl, Lookup: PallasLookupRangeCheck> UtilitiesInstructions for EccChip { type Var = AssignedCell; } -impl, Lookup: PallasLookupRC> +impl, Lookup: PallasLookupRangeCheck> EccChip { /// Reconstructs this chip from the given config. @@ -418,8 +418,8 @@ pub enum ScalarVar { FullWidth, } -impl, Lookup: PallasLookupRC> EccInstructions - for EccChip +impl, Lookup: PallasLookupRangeCheck> + EccInstructions for EccChip where >::Base: FixedPoint, @@ -639,7 +639,7 @@ where } } -impl, Lookup: PallasLookupRC> +impl, Lookup: PallasLookupRangeCheck> BaseFitsInScalarInstructions for EccChip where >::Base: diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 9cf8391dc5..2714718a7a 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -1,6 +1,6 @@ use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q}; use crate::utilities::{ - lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, + lookup_range_check::{PallasLookupRangeCheck, PallasLookupRangeCheckConfig}, {bool_check, ternary}, }; use std::{ @@ -46,7 +46,7 @@ const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, // Configuration used in complete addition @@ -61,7 +61,7 @@ pub struct Config { overflow_config: overflow::Config, } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, add_config: add::Config, @@ -473,10 +473,10 @@ pub mod tests { tests::TestFixedBases, EccInstructions, NonIdentityPoint, Point, ScalarVar, }, - utilities::{lookup_range_check::PallasLookupRC, UtilitiesInstructions}, + utilities::{lookup_range_check::PallasLookupRangeCheck, UtilitiesInstructions}, }; - pub(crate) fn test_mul( + pub(crate) fn test_mul( chip: EccChip, mut layouter: impl Layouter, p: &NonIdentityPoint>, diff --git a/halo2_gadgets/src/ecc/chip/mul/overflow.rs b/halo2_gadgets/src/ecc/chip/mul/overflow.rs index 482594e62b..fb40781f7c 100644 --- a/halo2_gadgets/src/ecc/chip/mul/overflow.rs +++ b/halo2_gadgets/src/ecc/chip/mul/overflow.rs @@ -1,7 +1,7 @@ use super::{T_Q, Z}; use crate::{ sinsemilla::primitives as sinsemilla, - utilities::lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, + utilities::lookup_range_check::{PallasLookupRangeCheck, PallasLookupRangeCheckConfig}, }; use group::ff::PrimeField; @@ -16,7 +16,7 @@ use pasta_curves::pallas; use std::iter; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Config { +pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, // 10-bit lookup table @@ -25,7 +25,7 @@ pub struct Config { advices: [Column; 3], } -impl Config { +impl Config { pub(super) fn configure( meta: &mut ConstraintSystem, lookup_config: Lookup, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs index a4a6ee08df..0e0bc7ee4b 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/base_field_elem.rs @@ -3,7 +3,7 @@ use super::H_BASE; use crate::utilities::{ bitrange_subset, bool_check, - lookup_range_check::{PallasLookupRC, PallasLookupRCConfig}, + lookup_range_check::{PallasLookupRangeCheck, PallasLookupRangeCheckConfig}, range_check, }; @@ -18,15 +18,17 @@ use pasta_curves::pallas; use std::convert::TryInto; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Config, Lookup: PallasLookupRC = PallasLookupRCConfig> -{ +pub struct Config< + Fixed: FixedPoints, + Lookup: PallasLookupRangeCheck = PallasLookupRangeCheckConfig, +> { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], lookup_config: Lookup, super_config: super::Config, } -impl, Lookup: PallasLookupRC> Config { +impl, Lookup: PallasLookupRangeCheck> Config { pub(crate) fn configure( meta: &mut ConstraintSystem, canon_advices: [Column; 3], @@ -395,10 +397,10 @@ pub mod tests { tests::{BaseField, TestFixedBases}, FixedPointBaseField, NonIdentityPoint, Point, }, - utilities::{lookup_range_check::PallasLookupRC, UtilitiesInstructions}, + utilities::{lookup_range_check::PallasLookupRangeCheck, UtilitiesInstructions}, }; - pub(crate) fn test_mul_fixed_base_field( + pub(crate) fn test_mul_fixed_base_field( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -411,7 +413,7 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( + fn test_single_base( chip: EccChip, mut layouter: impl Layouter, base: FixedPointBaseField>, @@ -421,7 +423,7 @@ pub mod tests { let column = chip.config().advices[0]; - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs index fe0ccd8d3d..f5cf9d3ce2 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs @@ -192,9 +192,9 @@ pub mod tests { tests::{FullWidth, TestFixedBases}, FixedPoint, NonIdentityPoint, Point, ScalarFixed, }; - use crate::utilities::lookup_range_check::PallasLookupRC; + use crate::utilities::lookup_range_check::PallasLookupRangeCheck; - pub(crate) fn test_mul_fixed( + pub(crate) fn test_mul_fixed( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -210,13 +210,13 @@ pub mod tests { } #[allow(clippy::op_ref)] - fn test_single_base( + fn test_single_base( chip: EccChip, mut layouter: impl Layouter, base: FixedPoint>, base_val: pallas::Affine, ) -> Result<(), Error> { - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 9827274d7d..1cd2618f68 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -325,14 +325,15 @@ pub mod tests { }, utilities::{ lookup_range_check::{ - PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheckConfig, }, UtilitiesInstructions, }, }; #[allow(clippy::op_ref)] - pub(crate) fn test_mul_fixed_short( + pub(crate) fn test_mul_fixed_short( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -340,7 +341,7 @@ pub mod tests { let base_val = Short.generator(); let test_short = FixedPointShort::from_inner(chip.clone(), Short); - fn load_magnitude_sign( + fn load_magnitude_sign( chip: EccChip, mut layouter: impl Layouter, magnitude: pallas::Base, @@ -358,7 +359,7 @@ pub mod tests { Ok((magnitude, sign)) } - fn constrain_equal_non_id( + fn constrain_equal_non_id( chip: EccChip, mut layouter: impl Layouter, base_val: pallas::Affine, @@ -470,7 +471,7 @@ pub mod tests { } #[derive(Default)] - struct MyCircuit { + struct MyCircuit { magnitude: Value, sign: Value, // For test checking @@ -478,11 +479,11 @@ pub mod tests { _lookup_marker: PhantomData, } - impl UtilitiesInstructions for MyCircuit { + impl UtilitiesInstructions for MyCircuit { type Var = AssignedCell; } - impl Circuit for MyCircuit { + impl Circuit for MyCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; @@ -581,7 +582,7 @@ pub mod tests { } } - impl MyCircuit { + impl MyCircuit { fn test_invalid_magnitude_sign() { // Magnitude larger than 64 bits should fail { @@ -742,15 +743,15 @@ pub mod tests { #[cfg(feature = "test-dev-graph")] #[test] fn invalid_magnitude_sign() { - MyCircuit::::test_invalid_magnitude_sign(); + MyCircuit::::test_invalid_magnitude_sign(); } #[test] fn invalid_magnitude_sign_4_5_b() { - MyCircuit::::test_invalid_magnitude_sign(); + MyCircuit::::test_invalid_magnitude_sign(); } - pub(crate) fn test_mul_sign( + pub(crate) fn test_mul_sign( chip: EccChip, mut layouter: impl Layouter, ) -> Result<(), Error> { @@ -817,17 +818,19 @@ pub mod tests { } #[derive(Default)] - struct MyMulSignCircuit { + struct MyMulSignCircuit { base: Value, sign: Value, _lookup_marker: PhantomData, } - impl UtilitiesInstructions for MyMulSignCircuit { + impl UtilitiesInstructions + for MyMulSignCircuit + { type Var = AssignedCell; } - impl Circuit for MyMulSignCircuit { + impl Circuit for MyMulSignCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; @@ -897,7 +900,7 @@ pub mod tests { } } - impl MyMulSignCircuit { + impl MyMulSignCircuit { fn test_invalid_magnitude_sign() { // Sign that is not +/- 1 should fail // Generate a random non-identity point @@ -951,10 +954,10 @@ pub mod tests { #[test] fn invalid_sign_in_mul_sign() { - MyMulSignCircuit::::test_invalid_magnitude_sign(); + MyMulSignCircuit::::test_invalid_magnitude_sign(); } #[test] fn invalid_sign_in_mul_sign_4_5_b() { - MyMulSignCircuit::::test_invalid_magnitude_sign(); + MyMulSignCircuit::::test_invalid_magnitude_sign(); } } diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 7454cefcdb..4f15a8fa60 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -598,7 +598,7 @@ pub(crate) mod tests { }, tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - LookupRangeCheck, LookupRangeCheckConfigOptimized, PallasLookupRCConfig, + LookupRangeCheck, LookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, }, }; @@ -645,18 +645,18 @@ pub(crate) mod tests { impl Circuit for MyCircuit { #[allow(clippy::type_complexity)] type Config = ( - EccConfig, + EccConfig, SinsemillaConfig< TestHashDomain, TestCommitDomain, TestFixedBases, - PallasLookupRCConfig, + PallasLookupRangeCheckConfig, >, SinsemillaConfig< TestHashDomain, TestCommitDomain, TestFixedBases, - PallasLookupRCConfig, + PallasLookupRangeCheckConfig, >, ); type FloorPlanner = SimpleFloorPlanner; @@ -703,9 +703,9 @@ pub(crate) mod tests { meta.lookup_table_column(), ); - let range_check = PallasLookupRCConfig::configure(meta, advices[9], table_idx); + let range_check = PallasLookupRangeCheckConfig::configure(meta, advices[9], table_idx); - let ecc_config = EccChip::::configure( + let ecc_config = EccChip::::configure( meta, advices, lagrange_coeffs, @@ -745,7 +745,7 @@ pub(crate) mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - PallasLookupRCConfig, + PallasLookupRangeCheckConfig, >::load(config.1.clone(), &mut layouter)?; // This MerkleCRH example is purely for illustrative purposes. @@ -907,19 +907,19 @@ pub(crate) mod tests { type Config = ( EccConfig< TestFixedBases, - LookupRangeCheckConfigOptimized, + LookupRangeCheck45BConfig, >, SinsemillaConfig< TestHashDomain, TestCommitDomain, TestFixedBases, - LookupRangeCheckConfigOptimized, + LookupRangeCheck45BConfig, >, SinsemillaConfig< TestHashDomain, TestCommitDomain, TestFixedBases, - LookupRangeCheckConfigOptimized, + LookupRangeCheck45BConfig, >, ); type FloorPlanner = SimpleFloorPlanner; @@ -967,7 +967,7 @@ pub(crate) mod tests { meta.lookup_table_column(), ); - let range_check = LookupRangeCheckConfigOptimized::configure_with_tag( + let range_check = LookupRangeCheck45BConfig::configure_with_tag( meta, advices[9], table_idx, @@ -976,7 +976,7 @@ pub(crate) mod tests { let ecc_config = EccChip::< TestFixedBases, - LookupRangeCheckConfigOptimized, + LookupRangeCheck45BConfig, >::configure(meta, advices, lagrange_coeffs, range_check); let config1 = SinsemillaChipOptimized::configure( diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 03438d9e58..3d1f61c9b5 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -11,7 +11,7 @@ use crate::{ FixedPoints, }, utilities::lookup_range_check::{ - PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, }, }; use std::marker::PhantomData; @@ -33,12 +33,12 @@ mod hash_to_point; /// Configuration for the Sinsemilla hash chip #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaConfig +pub struct SinsemillaConfig where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { /// Binary selector used in lookup argument and in the body of the Sinsemilla hash. q_sinsemilla1: Selector, @@ -71,7 +71,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { /// Returns an array of all advice columns in this config, in arbitrary order. pub(super) fn advices(&self) -> [Column; 5] { @@ -101,12 +101,12 @@ where /// /// [Chip description](https://zcash.github.io/halo2/design/gadgets/sinsemilla.html#plonk--halo-2-constraints). #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaChip +pub struct SinsemillaChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { config: SinsemillaConfig, } @@ -116,7 +116,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { type Config = SinsemillaConfig; type Loaded = (); @@ -135,7 +135,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { @@ -325,7 +325,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { type CellValue = AssignedCell; @@ -392,7 +392,7 @@ where Fixed: FixedPoints, Commit: CommitDomains, { - inner: SinsemillaChip, + inner: SinsemillaChip, } impl Chip for SinsemillaChipOptimized @@ -401,7 +401,7 @@ where Fixed: FixedPoints, Commit: CommitDomains, { - type Config = SinsemillaConfig; + type Config = SinsemillaConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -422,7 +422,7 @@ where /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { Self { - inner: SinsemillaChip::::construct( + inner: SinsemillaChip::::construct( config, ), } @@ -430,7 +430,7 @@ where /// Loads the lookup table required by this chip into the circuit. pub fn load( - config: SinsemillaConfig, + config: SinsemillaConfig, layouter: &mut impl Layouter, ) -> Result<>::Loaded, Error> { // Load the lookup table. @@ -443,7 +443,7 @@ where #[allow(non_snake_case)] fn create_initial_y_q_gate( meta: &mut ConstraintSystem, - config: &SinsemillaConfig, + config: &SinsemillaConfig, ) { let two = pallas::Base::from(2); @@ -479,20 +479,21 @@ where witness_pieces: Column, fixed_y_q: Column, lookup: (TableColumn, TableColumn, TableColumn), - range_check: PallasLookupConfigOptimized, + range_check: PallasLookupRangeCheck45BConfig, ) -> >::Config { - let config = SinsemillaChip::::create_config( - meta, - advices, - witness_pieces, - fixed_y_q, - lookup, - range_check, - ); + let config = + SinsemillaChip::::create_config( + meta, + advices, + witness_pieces, + fixed_y_q, + lookup, + range_check, + ); Self::create_initial_y_q_gate(meta, &config); - SinsemillaChip::::create_sinsemilla_gate( + SinsemillaChip::::create_sinsemilla_gate( meta, &config, ); diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 8d052cfb34..95ef9278c5 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -9,7 +9,7 @@ use super::{CommitDomains, FixedPoints, HashDomains}; use crate::sinsemilla::primitives::K; use crate::{ sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, - utilities::lookup_range_check::PallasLookupRC, + utilities::lookup_range_check::PallasLookupRangeCheck, }; use pasta_curves::pallas; @@ -34,7 +34,7 @@ impl GeneratorTableConfig { Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { let (table_idx, table_x, table_y) = ( config.generator_table.table_idx, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index a82d2632d4..036eabf067 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -3,7 +3,7 @@ use crate::{ ecc::FixedPoints, sinsemilla::chip::{NonIdentityEccPoint, SinsemillaChip, SinsemillaChipOptimized}, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, - utilities::lookup_range_check::PallasLookupRC, + utilities::lookup_range_check::PallasLookupRangeCheck, }; use ff::Field; @@ -29,7 +29,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). #[allow(non_snake_case)] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 7c548f8511..65e6cf87c4 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -180,14 +180,17 @@ pub mod tests { use crate::{ ecc::tests::TestFixedBases, sinsemilla::{ - chip::SinsemillaChip, + chip::{SinsemillaChip, SinsemillaChipOptimized}, + merkle::chip::MerkleChipOptimized, tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, tests::test_utils::test_against_stored_circuit, utilities::{ i2lebsp, - lookup_range_check::{LookupRangeCheck, PallasLookupRCConfig}, + lookup_range_check::{ + LookupRangeCheck, LookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + }, UtilitiesInstructions, }, }; @@ -200,9 +203,6 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::sinsemilla::chip::SinsemillaChipOptimized; - use crate::sinsemilla::merkle::chip::MerkleChipOptimized; - use crate::utilities::lookup_range_check::LookupRangeCheckConfigOptimized; use rand::{rngs::OsRng, RngCore}; use std::{convert::TryInto, iter}; @@ -217,8 +217,18 @@ pub mod tests { impl Circuit for MyCircuit { type Config = ( - MerkleConfig, - MerkleConfig, + MerkleConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + PallasLookupRangeCheckConfig, + >, + MerkleConfig< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + PallasLookupRangeCheckConfig, + >, ); type FloorPlanner = SimpleFloorPlanner; @@ -256,7 +266,7 @@ pub mod tests { meta.lookup_table_column(), ); - let range_check = PallasLookupRCConfig::configure(meta, advices[9], lookup.0); + let range_check = PallasLookupRangeCheckConfig::configure(meta, advices[9], lookup.0); let sinsemilla_config_1 = SinsemillaChip::configure( meta, @@ -291,7 +301,7 @@ pub mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - PallasLookupRCConfig, + PallasLookupRangeCheckConfig, >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. @@ -428,13 +438,13 @@ pub mod tests { TestHashDomain, TestCommitDomain, TestFixedBases, - LookupRangeCheckConfigOptimized, + LookupRangeCheck45BConfig, >, MerkleConfig< TestHashDomain, TestCommitDomain, TestFixedBases, - LookupRangeCheckConfigOptimized, + LookupRangeCheck45BConfig, >, ); type FloorPlanner = SimpleFloorPlanner; @@ -473,8 +483,7 @@ pub mod tests { meta.lookup_table_column(), ); - let range_check = - LookupRangeCheckConfigOptimized::configure(meta, advices[9], lookup.0); + let range_check = LookupRangeCheck45BConfig::configure(meta, advices[9], lookup.0); let sinsemilla_config_1 = SinsemillaChipOptimized::configure( meta, diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 3b5d1d839c..3e73ad0e85 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -12,7 +12,9 @@ use super::MerkleInstructions; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, utilities::{ - lookup_range_check::{PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig}, + lookup_range_check::{ + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + }, RangeConstrained, }, { @@ -31,12 +33,12 @@ use group::ff::PrimeField; /// Configuration for the `MerkleChip` implementation. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleConfig +pub struct MerkleConfig where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { advices: [Column; 5], q_decompose: Selector, @@ -55,12 +57,12 @@ where /// This chip does **NOT** constrain `left⋆` and `right⋆` to be canonical encodings of /// `left` and `right`. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleChip +pub struct MerkleChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { config: MerkleConfig, } @@ -70,7 +72,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { type Config = MerkleConfig; type Loaded = (); @@ -89,7 +91,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { /// Configures the [`MerkleChip`]. pub fn configure( @@ -229,7 +231,7 @@ where Hash: HashDomains, Commit: CommitDomains, F: FixedPoints, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { } @@ -239,7 +241,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { } @@ -257,7 +259,7 @@ where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { #[allow(non_snake_case)] fn hash_layer( @@ -476,7 +478,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { type Var = AssignedCell; } @@ -487,7 +489,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { #[allow(clippy::type_complexity)] fn swap( @@ -521,7 +523,7 @@ where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, - Lookup: PallasLookupRC, + Lookup: PallasLookupRangeCheck, { type CellValue = as SinsemillaInstructions< pallas::Affine, @@ -609,7 +611,7 @@ where Fixed: FixedPoints, Commit: CommitDomains, { - base: MerkleChip, + base: MerkleChip, } impl Chip for MerkleChipOptimized @@ -618,7 +620,7 @@ where Fixed: FixedPoints, Commit: CommitDomains, { - type Config = MerkleConfig; + type Config = MerkleConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -639,20 +641,22 @@ where /// Configures the [`MerkleChip`]. pub fn configure( meta: &mut ConstraintSystem, - sinsemilla_config: SinsemillaConfig, - ) -> MerkleConfig { + sinsemilla_config: SinsemillaConfig, + ) -> MerkleConfig { MerkleChip::configure(meta, sinsemilla_config) } /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. - pub fn construct(config: MerkleConfig) -> Self { + pub fn construct( + config: MerkleConfig, + ) -> Self { MerkleChipOptimized { base: MerkleChip { config }, } } } -impl MerkleSinsemillaInstructions +impl MerkleSinsemillaInstructions for MerkleChipOptimized where Hash: HashDomains, diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 00fb4d894c..aed5dc695c 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -301,7 +301,7 @@ mod tests { use super::super::UtilitiesInstructions; use super::{CondSwapChip, CondSwapConfig, CondSwapInstructions}; use crate::utilities::lookup_range_check::{ - PallasLookupConfigOptimized, PallasLookupRC, PallasLookupRCConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, }; use group::ff::{Field, PrimeField}; use halo2_proofs::{ @@ -419,7 +419,7 @@ mod tests { use rand::rngs::OsRng; #[derive(Clone, Debug)] - pub struct MyMuxConfig { + pub struct MyMuxConfig { primary: Column, advice: Column, cond_swap_config: CondSwapConfig, @@ -427,14 +427,14 @@ mod tests { } #[derive(Default)] - struct MyMuxCircuit { + struct MyMuxCircuit { left_point: Value, right_point: Value, choice: Value, _lookup_marker: PhantomData, } - impl Circuit for MyMuxCircuit { + impl Circuit for MyMuxCircuit { type Config = MyMuxConfig; type FloorPlanner = SimpleFloorPlanner; @@ -586,7 +586,7 @@ mod tests { } } - impl MyMuxCircuit { + impl MyMuxCircuit { fn test_mux_circuits() { // Test different circuits let mut circuits = vec![]; @@ -627,7 +627,7 @@ mod tests { } } - MyMuxCircuit::::test_mux_circuits(); - MyMuxCircuit::::test_mux_circuits(); + MyMuxCircuit::::test_mux_circuits(); + MyMuxCircuit::::test_mux_circuits(); } } diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 2eb20862c7..cfb4505c0b 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -60,14 +60,14 @@ impl RangeConstrained> { /// Configuration that provides methods for an efficient 4, 5, and 10-bit lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] -pub struct LookupRangeCheckConfigOptimized { +pub struct LookupRangeCheck45BConfig { base: LookupRangeCheckConfig, q_range_check_4: Selector, q_range_check_5: Selector, table_range_check_tag: TableColumn, } -impl LookupRangeCheckConfigOptimized { +impl LookupRangeCheck45BConfig { /// The `running_sum` advice column breaks the field element into `K`-bit /// words. It is used to construct the input expression to the lookup /// argument. @@ -94,7 +94,7 @@ impl LookupRangeCheckConfigOptimized { let q_range_check_5 = meta.complex_selector(); // if the order of the creation makes a difference - let config = LookupRangeCheckConfigOptimized { + let config = LookupRangeCheck45BConfig { base: LookupRangeCheckConfig { q_lookup, q_running, @@ -195,9 +195,7 @@ impl LookupRangeCheckConfigOptimized { } } -impl LookupRangeCheck - for LookupRangeCheckConfigOptimized -{ +impl LookupRangeCheck for LookupRangeCheck45BConfig { fn config(&self) -> &LookupRangeCheckConfig { &self.base } @@ -283,15 +281,13 @@ impl LookupRangeCheck } } -/// In this crate, `LookupRangeCheckConfigOptimized` is always used with `pallas::Base` as the prime field +/// In this crate, `LookupRangeCheck45BConfig` is always used with `pallas::Base` as the prime field /// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, /// we introduce this alias and use it instead of that long construction. -/// -///todo: rename PallasLookupConfig(?) and PallasLookupConfigOptimized, LookupRangeCheckConfigOptimized -pub type PallasLookupConfigOptimized = - LookupRangeCheckConfigOptimized; +pub type PallasLookupRangeCheck45BConfig = + LookupRangeCheck45BConfig; -impl PallasLookupRC for PallasLookupConfigOptimized {} +impl PallasLookupRangeCheck for PallasLookupRangeCheck45BConfig {} /// Configuration that provides methods for a 10-bit lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] @@ -677,19 +673,19 @@ impl LookupRangeCheck for LookupRangeCh } } -/// `PallasLookupRC` a shorthand for `LookupRangeCheck` specialized with `pallas::Base` and +/// `PallasLookupRangeCheck` a shorthand for `LookupRangeCheck` specialized with `pallas::Base` and /// `sinsemilla::K` and used to improve readability. In addition, it extends /// the `LookupRangeCheck` with additional standard traits. -pub trait PallasLookupRC: +pub trait PallasLookupRangeCheck: LookupRangeCheck + Eq + PartialEq + Clone + Copy + Debug { } -/// `PallasLookupRCConfig` is a shorthand for `LookupRangeCheckConfig` specialized with +/// `PallasLookupRangeCheckConfig` is a shorthand for `LookupRangeCheckConfig` specialized with /// `pallas::Base` and `sinsemilla::K` and used to improve readability``` -pub type PallasLookupRCConfig = LookupRangeCheckConfig; +pub type PallasLookupRangeCheckConfig = LookupRangeCheckConfig; -impl PallasLookupRC for PallasLookupRCConfig {} +impl PallasLookupRangeCheck for PallasLookupRangeCheckConfig {} #[cfg(test)] mod tests { @@ -707,22 +703,22 @@ mod tests { sinsemilla::primitives::K, tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - LookupRangeCheck, LookupRangeCheckConfig, LookupRangeCheckConfigOptimized, - PallasLookupConfigOptimized, PallasLookupRCConfig, + LookupRangeCheck, LookupRangeCheck45BConfig, LookupRangeCheckConfig, + PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, }, }; use std::{convert::TryInto, marker::PhantomData}; fn configure_optimized( meta: &mut ConstraintSystem, - ) -> LookupRangeCheckConfigOptimized { + ) -> LookupRangeCheck45BConfig { let running_sum = meta.advice_column(); let table_idx = meta.lookup_table_column(); let table_range_check_tag = meta.lookup_table_column(); let constants = meta.fixed_column(); meta.enable_constant(constants); - LookupRangeCheckConfigOptimized::::configure_with_tag( + LookupRangeCheck45BConfig::::configure_with_tag( meta, running_sum, table_idx, @@ -826,8 +822,8 @@ mod tests { } } - impl Circuit for MyLookupCircuit> { - type Config = LookupRangeCheckConfigOptimized; + impl Circuit for MyLookupCircuit> { + type Config = LookupRangeCheck45BConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -849,11 +845,12 @@ mod tests { #[test] fn lookup_range_check() { - let circuit: MyLookupCircuit = MyLookupCircuit { - num_words: 6, - _field_marker: PhantomData, - _lookup_marker: PhantomData, - }; + let circuit: MyLookupCircuit = + MyLookupCircuit { + num_words: 6, + _field_marker: PhantomData, + _lookup_marker: PhantomData, + }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); @@ -863,11 +860,12 @@ mod tests { #[test] fn lookup_range_check_4_5_b() { - let circuit: MyLookupCircuit = MyLookupCircuit { - num_words: 6, - _field_marker: PhantomData, - _lookup_marker: PhantomData, - }; + let circuit: MyLookupCircuit = + MyLookupCircuit { + num_words: 6, + _field_marker: PhantomData, + _lookup_marker: PhantomData, + }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); @@ -926,9 +924,9 @@ mod tests { } impl Circuit - for MyShortRangeCheckCircuit> + for MyShortRangeCheckCircuit> { - type Config = LookupRangeCheckConfigOptimized; + type Config = LookupRangeCheck45BConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -961,7 +959,7 @@ mod tests { expected_proof_size: usize, ) { if optimized { - let circuit: MyShortRangeCheckCircuit = + let circuit: MyShortRangeCheckCircuit = MyShortRangeCheckCircuit { element: Value::known(element), num_bits, @@ -974,7 +972,7 @@ mod tests { test_against_stored_circuit(circuit, circuit_name, expected_proof_size); } } else { - let circuit: MyShortRangeCheckCircuit = + let circuit: MyShortRangeCheckCircuit = MyShortRangeCheckCircuit { element: Value::known(element), num_bits, From cd4d43a2358314d2fccf4c30cf139b60f6e02017 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 24 Jun 2024 22:43:13 +0200 Subject: [PATCH 098/121] Rename Sinsemilla/MerkleChipOptimized Sinsemilla45BChip <- SinsemillaChipOptimized Sinsemilla45BInstructions <- SinsemillaInstructionsOptimized Merkle45BChip <- MerkleChipOptimized --- halo2_gadgets/src/sinsemilla.rs | 20 ++++----- halo2_gadgets/src/sinsemilla/chip.rs | 22 +++++----- .../src/sinsemilla/chip/hash_to_point.rs | 4 +- halo2_gadgets/src/sinsemilla/merkle.rs | 20 ++++----- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 44 +++++++++---------- 5 files changed, 55 insertions(+), 55 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 4f15a8fa60..d390cb2cec 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -451,11 +451,11 @@ where } } -/// `SinsemillaInstructionsOptimized` provides an optimized set of instructions +/// `Sinsemilla45BInstructions` provides an optimized set of instructions /// for implementing the Sinsemilla hash function and commitment scheme /// on elliptic curves. This trait is an extension of the `SinsemillaInstructions` trait, /// designed to enhance performance in specific cryptographic scenarios.ld -pub trait SinsemillaInstructionsOptimized: +pub trait Sinsemilla45BInstructions: SinsemillaInstructions { /// Hashes a message to an ECC curve point. @@ -476,7 +476,7 @@ pub trait SinsemillaInstructionsOptimized HashDomain where - SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, + SinsemillaChip: Sinsemilla45BInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, @@ -505,7 +505,7 @@ HashDomain impl CommitDomain where - SinsemillaChip: SinsemillaInstructionsOptimized + Clone + Debug + Eq, + SinsemillaChip: Sinsemilla45BInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, @@ -593,7 +593,7 @@ pub(crate) mod tests { NonIdentityPoint, ScalarFixed, }, sinsemilla::{ - chip::SinsemillaChipOptimized, + chip::Sinsemilla45BChip, primitives::{self as sinsemilla, K}, }, tests::test_utils::test_against_stored_circuit, @@ -979,7 +979,7 @@ pub(crate) mod tests { LookupRangeCheck45BConfig, >::configure(meta, advices, lagrange_coeffs, range_check); - let config1 = SinsemillaChipOptimized::configure( + let config1 = Sinsemilla45BChip::configure( meta, advices[..5].try_into().unwrap(), advices[2], @@ -987,7 +987,7 @@ pub(crate) mod tests { lookup, range_check, ); - let config2 = SinsemillaChipOptimized::configure( + let config2 = Sinsemilla45BChip::configure( meta, advices[5..].try_into().unwrap(), advices[7], @@ -1008,7 +1008,7 @@ pub(crate) mod tests { let ecc_chip = EccChip::construct(config.0); // The two `SinsemillaChip`s share the same lookup table. - SinsemillaChipOptimized::::load( + Sinsemilla45BChip::::load( config.1.clone(), &mut layouter, )?; @@ -1016,7 +1016,7 @@ pub(crate) mod tests { // This MerkleCRH example is purely for illustrative purposes. // It is not an implementation of the Orchard protocol spec. { - let chip1 = SinsemillaChipOptimized::construct(config.1); + let chip1 = Sinsemilla45BChip::construct(config.1); let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); @@ -1088,7 +1088,7 @@ pub(crate) mod tests { } { - let chip2 = SinsemillaChipOptimized::construct(config.2); + let chip2 = Sinsemilla45BChip::construct(config.2); let test_commit = CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 3d1f61c9b5..765ddb7420 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -2,8 +2,8 @@ use super::{ message::{Message, MessagePiece}, - primitives as sinsemilla, CommitDomains, HashDomains, SinsemillaInstructions, - SinsemillaInstructionsOptimized, + primitives as sinsemilla, CommitDomains, HashDomains, Sinsemilla45BInstructions, + SinsemillaInstructions, }; use crate::{ ecc::{ @@ -382,11 +382,11 @@ where } } -/// 'SinsemillaChipOptimized' is an extended version of the SinsemillaChip. +/// 'Sinsemilla45BChip' is an extended version of the SinsemillaChip. /// The corresponding lookup table support optimized range check for 4 and 5 bits. /// It also implements methods for hash optimization. #[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaChipOptimized +pub struct Sinsemilla45BChip where Hash: HashDomains, Fixed: FixedPoints, @@ -395,7 +395,7 @@ where inner: SinsemillaChip, } -impl Chip for SinsemillaChipOptimized +impl Chip for Sinsemilla45BChip where Hash: HashDomains, Fixed: FixedPoints, @@ -413,7 +413,7 @@ where } } -impl SinsemillaChipOptimized +impl Sinsemilla45BChip where Hash: HashDomains, F: FixedPoints, @@ -501,9 +501,9 @@ where } } -// Implement `SinsemillaInstructions` for `SinsemillaChipOptimized` +// Implement `SinsemillaInstructions` for `Sinsemilla45BChip` impl SinsemillaInstructions - for SinsemillaChipOptimized + for Sinsemilla45BChip where Hash: HashDomains, F: FixedPoints, @@ -552,10 +552,10 @@ where } } -// Implement `SinsemillaInstructionsOptimized` for `SinsemillaChipOptimized` +// Implement `Sinsemilla45BInstructions` for `Sinsemilla45BChip` impl - SinsemillaInstructionsOptimized - for SinsemillaChipOptimized + Sinsemilla45BInstructions + for Sinsemilla45BChip where Hash: HashDomains, F: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 036eabf067..290593b800 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -1,7 +1,7 @@ use super::super::{CommitDomains, HashDomains, SinsemillaInstructions}; use crate::{ ecc::FixedPoints, - sinsemilla::chip::{NonIdentityEccPoint, SinsemillaChip, SinsemillaChipOptimized}, + sinsemilla::chip::{NonIdentityEccPoint, Sinsemilla45BChip, SinsemillaChip}, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, utilities::lookup_range_check::PallasLookupRangeCheck, }; @@ -460,7 +460,7 @@ where } } -impl SinsemillaChipOptimized +impl Sinsemilla45BChip where Hash: HashDomains, Fixed: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 65e6cf87c4..3cf2166653 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -180,8 +180,8 @@ pub mod tests { use crate::{ ecc::tests::TestFixedBases, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaChipOptimized}, - merkle::chip::MerkleChipOptimized, + chip::{Sinsemilla45BChip, SinsemillaChip}, + merkle::chip::Merkle45BChip, tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, @@ -485,7 +485,7 @@ pub mod tests { let range_check = LookupRangeCheck45BConfig::configure(meta, advices[9], lookup.0); - let sinsemilla_config_1 = SinsemillaChipOptimized::configure( + let sinsemilla_config_1 = Sinsemilla45BChip::configure( meta, advices[5..].try_into().unwrap(), advices[7], @@ -493,9 +493,9 @@ pub mod tests { lookup, range_check, ); - let config1 = MerkleChipOptimized::configure(meta, sinsemilla_config_1); + let config1 = Merkle45BChip::configure(meta, sinsemilla_config_1); - let sinsemilla_config_2 = SinsemillaChipOptimized::configure( + let sinsemilla_config_2 = Sinsemilla45BChip::configure( meta, advices[..5].try_into().unwrap(), advices[2], @@ -503,7 +503,7 @@ pub mod tests { lookup, range_check, ); - let config2 = MerkleChipOptimized::configure(meta, sinsemilla_config_2); + let config2 = Merkle45BChip::configure(meta, sinsemilla_config_2); (config1, config2) } @@ -513,15 +513,15 @@ pub mod tests { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - // Load generator table (shared across both configs) for SinsemillaChipOptimized - SinsemillaChipOptimized::::load( + // Load generator table (shared across both configs) for Sinsemilla45BChip + Sinsemilla45BChip::::load( config.0.sinsemilla_config.clone(), &mut layouter, )?; // Construct Merkle chips which will be placed side-by-side in the circuit. - let chip_1 = MerkleChipOptimized::construct(config.0.clone()); - let chip_2 = MerkleChipOptimized::construct(config.1.clone()); + let chip_1 = Merkle45BChip::construct(config.0.clone()); + let chip_2 = Merkle45BChip::construct(config.1.clone()); let leaf = chip_1.load_private( layouter.namespace(|| ""), diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 3e73ad0e85..e8b963feed 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -20,7 +20,7 @@ use crate::{ { ecc::FixedPoints, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaChipOptimized, SinsemillaConfig}, + chip::{Sinsemilla45BChip, SinsemillaChip, SinsemillaConfig}, CommitDomains, HashDomains, SinsemillaInstructions, }, utilities::{ @@ -603,9 +603,9 @@ where } } -/// 'MerkleChipOptimized' Chip extends 'MerkleChip', supporting new methods +/// 'Merkle45BChip' Chip extends 'MerkleChip', supporting new methods #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleChipOptimized +pub struct Merkle45BChip where Hash: HashDomains, Fixed: FixedPoints, @@ -614,7 +614,7 @@ where base: MerkleChip, } -impl Chip for MerkleChipOptimized +impl Chip for Merkle45BChip where Hash: HashDomains, Fixed: FixedPoints, @@ -632,7 +632,7 @@ where } } -impl MerkleChipOptimized +impl Merkle45BChip where Hash: HashDomains, F: FixedPoints, @@ -650,14 +650,14 @@ where pub fn construct( config: MerkleConfig, ) -> Self { - MerkleChipOptimized { + Merkle45BChip { base: MerkleChip { config }, } } } impl MerkleSinsemillaInstructions - for MerkleChipOptimized + for Merkle45BChip where Hash: HashDomains, F: FixedPoints, @@ -665,7 +665,7 @@ where { } -impl UtilitiesInstructions for MerkleChipOptimized +impl UtilitiesInstructions for Merkle45BChip where Hash: HashDomains, F: FixedPoints, @@ -674,7 +674,7 @@ where type Var = AssignedCell; } -impl CondSwapInstructions for MerkleChipOptimized +impl CondSwapInstructions for Merkle45BChip where Hash: HashDomains, F: FixedPoints, @@ -704,56 +704,56 @@ where } impl SinsemillaInstructions - for MerkleChipOptimized + for Merkle45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, { - type CellValue = as SinsemillaInstructions< + type CellValue = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::CellValue; - type Message = as SinsemillaInstructions< + type Message = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::Message; - type MessagePiece = as SinsemillaInstructions< + type MessagePiece = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::MessagePiece; - type RunningSum = as SinsemillaInstructions< + type RunningSum = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::RunningSum; - type X = as SinsemillaInstructions< + type X = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::X; - type NonIdentityPoint = as SinsemillaInstructions< + type NonIdentityPoint = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::NonIdentityPoint; - type FixedPoints = as SinsemillaInstructions< + type FixedPoints = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::FixedPoints; - type HashDomains = as SinsemillaInstructions< + type HashDomains = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::HashDomains; - type CommitDomains = as SinsemillaInstructions< + type CommitDomains = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, @@ -766,7 +766,7 @@ where num_words: usize, ) -> Result { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChipOptimized::::construct(config); + let chip = Sinsemilla45BChip::::construct(config); chip.witness_message_piece(layouter, value, num_words) } @@ -779,11 +779,11 @@ where message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaChipOptimized::::construct(config); + let chip = Sinsemilla45BChip::::construct(config); chip.hash_to_point(layouter, Q, message) } fn extract(point: &Self::NonIdentityPoint) -> Self::X { - SinsemillaChipOptimized::::extract(point) + Sinsemilla45BChip::::extract(point) } } From 18e3e0da3f46882c73668f96dd452d2d293d7938 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 25 Jun 2024 10:10:37 +0200 Subject: [PATCH 099/121] Put together some imports --- .../src/sinsemilla/chip/generator_table.rs | 3 +-- halo2_gadgets/src/utilities/cond_swap.rs | 13 +++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 95ef9278c5..d5fe0f0553 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -6,9 +6,8 @@ use halo2_proofs::{ }; use super::{CommitDomains, FixedPoints, HashDomains}; -use crate::sinsemilla::primitives::K; use crate::{ - sinsemilla::primitives::{self as sinsemilla, SINSEMILLA_S}, + sinsemilla::primitives::{self as sinsemilla, K, SINSEMILLA_S}, utilities::lookup_range_check::PallasLookupRangeCheck, }; use pasta_curves::pallas; diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index aed5dc695c..0cf6f3e181 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -6,8 +6,7 @@ use crate::ecc::chip::{EccPoint, NonIdentityEccPoint}; use group::ff::{Field, PrimeField}; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, - plonk, - plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector}, + plonk::{self, Advice, Column, ConstraintSystem, Constraints, Error, Selector}, poly::Rotation, }; use pasta_curves::pallas; @@ -298,10 +297,12 @@ impl CondSwapChip { #[cfg(test)] mod tests { - use super::super::UtilitiesInstructions; - use super::{CondSwapChip, CondSwapConfig, CondSwapInstructions}; - use crate::utilities::lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + use crate::utilities::{ + cond_swap::{CondSwapChip, CondSwapConfig, CondSwapInstructions}, + lookup_range_check::{ + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + }, + UtilitiesInstructions, }; use group::ff::{Field, PrimeField}; use halo2_proofs::{ From d6bcf3b5c12568aee591d3dbb86b358ff3ff309b Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 25 Jun 2024 14:59:39 +0200 Subject: [PATCH 100/121] Fix LookupangeCheck loading in Sinsemilla Previously, the SinsemillaChip always loaded the lookup range check without tag column and Sinsemilla45BChip always loaded the lookup range check with tag column. Now, we load lookup range check with or without tag according to the lookup type (LookupRangeCheckConfig or LookupRangeCheck45BConfig). --- halo2_gadgets/src/sinsemilla/chip.rs | 9 ++++----- .../src/sinsemilla/chip/generator_table.rs | 15 ++++++++++++++- halo2_gadgets/src/utilities/lookup_range_check.rs | 15 +++++++++++---- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 765ddb7420..494639ff13 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -148,8 +148,9 @@ where layouter: &mut impl Layouter, ) -> Result<>::Loaded, Error> { // Load the lookup table. - - config.generator_table.load(layouter) + config + .generator_table + .load(config.lookup_config.table_range_check_tag(), layouter) } /// # Side-effects @@ -434,9 +435,7 @@ where layouter: &mut impl Layouter, ) -> Result<>::Loaded, Error> { // Load the lookup table. - config - .generator_table - .load_with_tag(config.lookup_config.table_range_check_tag(), layouter) + SinsemillaChip::::load(config, layouter) } /// Assign y_q to an advice column diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index d5fe0f0553..57ff7e7239 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -81,7 +81,20 @@ impl GeneratorTableConfig { }); } - pub fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + pub fn load( + &self, + table_range_check_tag: Option, + layouter: &mut impl Layouter, + ) -> Result<(), Error> { + match table_range_check_tag { + Some(tag) => self.load_with_tag(tag, layouter), + None => self.load_without_tag(layouter), + } + } + pub fn load_without_tag( + &self, + layouter: &mut impl Layouter, + ) -> Result<(), Error> { layouter.assign_table( || "generator_table", |mut table| { diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index cfb4505c0b..890d96dec7 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -189,10 +189,6 @@ impl LookupRangeCheck45BConfig { config } - - pub(crate) fn table_range_check_tag(&self) -> TableColumn { - self.table_range_check_tag - } } impl LookupRangeCheck for LookupRangeCheck45BConfig { @@ -209,6 +205,10 @@ impl LookupRangeCheck for LookupRangeCh Self::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) } + fn table_range_check_tag(&self) -> Option { + Some(self.table_range_check_tag) + } + #[cfg(test)] // Fill `table_idx` and `table_range_check_tag`. // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table @@ -324,6 +324,9 @@ pub trait LookupRangeCheck { where Self: Sized; + /// Returns the table column that contains the range check tag. + fn table_range_check_tag(&self) -> Option; + #[cfg(test)] // Fill `table_idx` and `table_range_check_tag`. // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table @@ -610,6 +613,10 @@ impl LookupRangeCheck for LookupRangeCh config } + fn table_range_check_tag(&self) -> Option { + None + } + #[cfg(test)] // Fill `table_idx` and `table_range_check_tag`. // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table From b5d89162ba2a08e51bea2e49e5255a6648b24381 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 25 Jun 2024 21:14:39 +0200 Subject: [PATCH 101/121] Fix Sinsemilla45BChip and Merkle45BChip It is now possible to use Sinsemilla/Merkle45BChip with non optimized lookup. --- halo2_gadgets/src/sinsemilla.rs | 13 ++-- halo2_gadgets/src/sinsemilla/chip.rs | 65 ++++++++-------- .../src/sinsemilla/chip/hash_to_point.rs | 3 +- halo2_gadgets/src/sinsemilla/merkle.rs | 13 ++-- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 77 ++++++++++--------- 5 files changed, 92 insertions(+), 79 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index d390cb2cec..2b689884d8 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -598,7 +598,8 @@ pub(crate) mod tests { }, tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - LookupRangeCheck, LookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + LookupRangeCheck, LookupRangeCheck45BConfig, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheckConfig, }, }; @@ -1008,10 +1009,12 @@ pub(crate) mod tests { let ecc_chip = EccChip::construct(config.0); // The two `SinsemillaChip`s share the same lookup table. - Sinsemilla45BChip::::load( - config.1.clone(), - &mut layouter, - )?; + Sinsemilla45BChip::< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + PallasLookupRangeCheck45BConfig, + >::load(config.1.clone(), &mut layouter)?; // This MerkleCRH example is purely for illustrative purposes. // It is not an implementation of the Orchard protocol spec. diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 494639ff13..4056e2db8f 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -10,9 +10,7 @@ use crate::{ chip::{DoubleAndAdd, NonIdentityEccPoint}, FixedPoints, }, - utilities::lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, - }, + utilities::lookup_range_check::{PallasLookupRangeCheck, PallasLookupRangeCheckConfig}, }; use std::marker::PhantomData; @@ -384,25 +382,27 @@ where } /// 'Sinsemilla45BChip' is an extended version of the SinsemillaChip. -/// The corresponding lookup table support optimized range check for 4 and 5 bits. -/// It also implements methods for hash optimization. +/// It implements a method for hashing from a private initialization. #[derive(Eq, PartialEq, Clone, Debug)] -pub struct Sinsemilla45BChip +pub struct Sinsemilla45BChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { - inner: SinsemillaChip, + inner: SinsemillaChip, } -impl Chip for Sinsemilla45BChip +impl Chip + for Sinsemilla45BChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { - type Config = SinsemillaConfig; + type Config = SinsemillaConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -414,35 +414,34 @@ where } } -impl Sinsemilla45BChip +impl Sinsemilla45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { /// Reconstructs this chip from the given config. pub fn construct(config: >::Config) -> Self { Self { - inner: SinsemillaChip::::construct( - config, - ), + inner: SinsemillaChip::::construct(config), } } /// Loads the lookup table required by this chip into the circuit. pub fn load( - config: SinsemillaConfig, + config: SinsemillaConfig, layouter: &mut impl Layouter, ) -> Result<>::Loaded, Error> { // Load the lookup table. - SinsemillaChip::::load(config, layouter) + SinsemillaChip::::load(config, layouter) } /// Assign y_q to an advice column #[allow(non_snake_case)] fn create_initial_y_q_gate( meta: &mut ConstraintSystem, - config: &SinsemillaConfig, + config: &SinsemillaConfig, ) { let two = pallas::Base::from(2); @@ -478,35 +477,34 @@ where witness_pieces: Column, fixed_y_q: Column, lookup: (TableColumn, TableColumn, TableColumn), - range_check: PallasLookupRangeCheck45BConfig, + range_check: Lookup, ) -> >::Config { - let config = - SinsemillaChip::::create_config( - meta, - advices, - witness_pieces, - fixed_y_q, - lookup, - range_check, - ); + let config = SinsemillaChip::::create_config( + meta, + advices, + witness_pieces, + fixed_y_q, + lookup, + range_check, + ); Self::create_initial_y_q_gate(meta, &config); - SinsemillaChip::::create_sinsemilla_gate( - meta, &config, - ); + SinsemillaChip::::create_sinsemilla_gate(meta, &config); config } } // Implement `SinsemillaInstructions` for `Sinsemilla45BChip` -impl SinsemillaInstructions - for Sinsemilla45BChip +impl + SinsemillaInstructions + for Sinsemilla45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { type CellValue = AssignedCell; @@ -552,13 +550,14 @@ where } // Implement `Sinsemilla45BInstructions` for `Sinsemilla45BChip` -impl +impl Sinsemilla45BInstructions - for Sinsemilla45BChip + for Sinsemilla45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { #[allow(non_snake_case)] #[allow(clippy::type_complexity)] diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 290593b800..2ab2fbe83a 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -460,11 +460,12 @@ where } } -impl Sinsemilla45BChip +impl Sinsemilla45BChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { #[allow(non_snake_case)] #[allow(clippy::type_complexity)] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 3cf2166653..eabd63b295 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -189,7 +189,8 @@ pub mod tests { utilities::{ i2lebsp, lookup_range_check::{ - LookupRangeCheck, LookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + LookupRangeCheck, LookupRangeCheck45BConfig, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheckConfig, }, UtilitiesInstructions, }, @@ -514,10 +515,12 @@ pub mod tests { mut layouter: impl Layouter, ) -> Result<(), Error> { // Load generator table (shared across both configs) for Sinsemilla45BChip - Sinsemilla45BChip::::load( - config.0.sinsemilla_config.clone(), - &mut layouter, - )?; + Sinsemilla45BChip::< + TestHashDomain, + TestCommitDomain, + TestFixedBases, + PallasLookupRangeCheck45BConfig, + >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. let chip_1 = Merkle45BChip::construct(config.0.clone()); diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index e8b963feed..4719da25ef 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -12,9 +12,7 @@ use super::MerkleInstructions; use crate::{ sinsemilla::{primitives as sinsemilla, MessagePiece}, utilities::{ - lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, - }, + lookup_range_check::{PallasLookupRangeCheck, PallasLookupRangeCheckConfig}, RangeConstrained, }, { @@ -605,22 +603,24 @@ where /// 'Merkle45BChip' Chip extends 'MerkleChip', supporting new methods #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Merkle45BChip +pub struct Merkle45BChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { - base: MerkleChip, + base: MerkleChip, } -impl Chip for Merkle45BChip +impl Chip for Merkle45BChip where Hash: HashDomains, Fixed: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { - type Config = MerkleConfig; + type Config = MerkleConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -632,53 +632,57 @@ where } } -impl Merkle45BChip +impl Merkle45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { /// Configures the [`MerkleChip`]. pub fn configure( meta: &mut ConstraintSystem, - sinsemilla_config: SinsemillaConfig, - ) -> MerkleConfig { + sinsemilla_config: SinsemillaConfig, + ) -> MerkleConfig { MerkleChip::configure(meta, sinsemilla_config) } /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. - pub fn construct( - config: MerkleConfig, - ) -> Self { + pub fn construct(config: MerkleConfig) -> Self { Merkle45BChip { base: MerkleChip { config }, } } } -impl MerkleSinsemillaInstructions - for Merkle45BChip +impl MerkleSinsemillaInstructions + for Merkle45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { } -impl UtilitiesInstructions for Merkle45BChip +impl UtilitiesInstructions + for Merkle45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { type Var = AssignedCell; } -impl CondSwapInstructions for Merkle45BChip +impl CondSwapInstructions + for Merkle45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { #[allow(clippy::type_complexity)] fn swap( @@ -703,57 +707,60 @@ where } } -impl SinsemillaInstructions - for Merkle45BChip +impl + SinsemillaInstructions + for Merkle45BChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, + Lookup: PallasLookupRangeCheck, { - type CellValue = as SinsemillaInstructions< + type CellValue = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::CellValue; - type Message = as SinsemillaInstructions< + type Message = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::Message; - type MessagePiece = as SinsemillaInstructions< + type MessagePiece = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::MessagePiece; - type RunningSum = as SinsemillaInstructions< + type RunningSum = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::RunningSum; - type X = as SinsemillaInstructions< + type X = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::X; - type NonIdentityPoint = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::NonIdentityPoint; - type FixedPoints = as SinsemillaInstructions< + type NonIdentityPoint = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::NonIdentityPoint; + type FixedPoints = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::FixedPoints; - type HashDomains = as SinsemillaInstructions< + type HashDomains = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::HashDomains; - type CommitDomains = as SinsemillaInstructions< + type CommitDomains = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, @@ -766,7 +773,7 @@ where num_words: usize, ) -> Result { let config = self.config().sinsemilla_config.clone(); - let chip = Sinsemilla45BChip::::construct(config); + let chip = Sinsemilla45BChip::::construct(config); chip.witness_message_piece(layouter, value, num_words) } @@ -779,11 +786,11 @@ where message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { let config = self.config().sinsemilla_config.clone(); - let chip = Sinsemilla45BChip::::construct(config); + let chip = Sinsemilla45BChip::::construct(config); chip.hash_to_point(layouter, Q, message) } fn extract(point: &Self::NonIdentityPoint) -> Self::X { - Sinsemilla45BChip::::extract(point) + Sinsemilla45BChip::::extract(point) } } From 1fbc7defdb30d1994c0f1bec5c8d9bf5c4a2d658 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 25 Jun 2024 21:25:49 +0200 Subject: [PATCH 102/121] Rename Sinsemilla/Merkle45BChip SinsemillaWithPrivateInitChip <- Sinsemilla45BChip SinsemillaWithPrivateInitInstructions <- Sinsemilla45BInstructions MerkleWithPrivateInitChip <- Merkle45BChip --- halo2_gadgets/src/sinsemilla.rs | 29 ++--- halo2_gadgets/src/sinsemilla/chip.rs | 24 ++-- .../src/sinsemilla/chip/hash_to_point.rs | 4 +- halo2_gadgets/src/sinsemilla/merkle.rs | 18 +-- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 108 ++++++++++-------- 5 files changed, 96 insertions(+), 87 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 2b689884d8..277d208497 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -451,12 +451,13 @@ where } } -/// `Sinsemilla45BInstructions` provides an optimized set of instructions -/// for implementing the Sinsemilla hash function and commitment scheme -/// on elliptic curves. This trait is an extension of the `SinsemillaInstructions` trait, -/// designed to enhance performance in specific cryptographic scenarios.ld -pub trait Sinsemilla45BInstructions: - SinsemillaInstructions +/// `SinsemillaWithPrivateInitInstructions` provides a method to hash a message from an initial +/// private point. +pub trait SinsemillaWithPrivateInitInstructions< + C: CurveAffine, + const K: usize, + const MAX_WORDS: usize, +>: SinsemillaInstructions { /// Hashes a message to an ECC curve point. /// This returns both the resulting point, as well as the message @@ -476,7 +477,7 @@ pub trait Sinsemilla45BInstructions HashDomain where - SinsemillaChip: Sinsemilla45BInstructions + Clone + Debug + Eq, + SinsemillaChip: SinsemillaWithPrivateInitInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, @@ -505,7 +506,7 @@ HashDomain impl CommitDomain where - SinsemillaChip: Sinsemilla45BInstructions + Clone + Debug + Eq, + SinsemillaChip: SinsemillaWithPrivateInitInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, NonIdentityPoint = >::NonIdentityPoint, @@ -593,7 +594,7 @@ pub(crate) mod tests { NonIdentityPoint, ScalarFixed, }, sinsemilla::{ - chip::Sinsemilla45BChip, + chip::SinsemillaWithPrivateInitChip, primitives::{self as sinsemilla, K}, }, tests::test_utils::test_against_stored_circuit, @@ -980,7 +981,7 @@ pub(crate) mod tests { LookupRangeCheck45BConfig, >::configure(meta, advices, lagrange_coeffs, range_check); - let config1 = Sinsemilla45BChip::configure( + let config1 = SinsemillaWithPrivateInitChip::configure( meta, advices[..5].try_into().unwrap(), advices[2], @@ -988,7 +989,7 @@ pub(crate) mod tests { lookup, range_check, ); - let config2 = Sinsemilla45BChip::configure( + let config2 = SinsemillaWithPrivateInitChip::configure( meta, advices[5..].try_into().unwrap(), advices[7], @@ -1009,7 +1010,7 @@ pub(crate) mod tests { let ecc_chip = EccChip::construct(config.0); // The two `SinsemillaChip`s share the same lookup table. - Sinsemilla45BChip::< + SinsemillaWithPrivateInitChip::< TestHashDomain, TestCommitDomain, TestFixedBases, @@ -1019,7 +1020,7 @@ pub(crate) mod tests { // This MerkleCRH example is purely for illustrative purposes. // It is not an implementation of the Orchard protocol spec. { - let chip1 = Sinsemilla45BChip::construct(config.1); + let chip1 = SinsemillaWithPrivateInitChip::construct(config.1); let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); @@ -1091,7 +1092,7 @@ pub(crate) mod tests { } { - let chip2 = Sinsemilla45BChip::construct(config.2); + let chip2 = SinsemillaWithPrivateInitChip::construct(config.2); let test_commit = CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 4056e2db8f..accd50d861 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -2,8 +2,8 @@ use super::{ message::{Message, MessagePiece}, - primitives as sinsemilla, CommitDomains, HashDomains, Sinsemilla45BInstructions, - SinsemillaInstructions, + primitives as sinsemilla, CommitDomains, HashDomains, SinsemillaInstructions, + SinsemillaWithPrivateInitInstructions, }; use crate::{ ecc::{ @@ -381,10 +381,10 @@ where } } -/// 'Sinsemilla45BChip' is an extended version of the SinsemillaChip. -/// It implements a method for hashing from a private initialization. +/// 'SinsemillaWithPrivateInitChip' is an extended version of the SinsemillaChip. +/// It implements a method for hashing from a private initialization point. #[derive(Eq, PartialEq, Clone, Debug)] -pub struct Sinsemilla45BChip +pub struct SinsemillaWithPrivateInitChip where Hash: HashDomains, Fixed: FixedPoints, @@ -395,7 +395,7 @@ where } impl Chip - for Sinsemilla45BChip + for SinsemillaWithPrivateInitChip where Hash: HashDomains, Fixed: FixedPoints, @@ -414,7 +414,7 @@ where } } -impl Sinsemilla45BChip +impl SinsemillaWithPrivateInitChip where Hash: HashDomains, F: FixedPoints, @@ -496,10 +496,10 @@ where } } -// Implement `SinsemillaInstructions` for `Sinsemilla45BChip` +// Implement `SinsemillaInstructions` for `SinsemillaWithPrivateInitChip` impl SinsemillaInstructions - for Sinsemilla45BChip + for SinsemillaWithPrivateInitChip where Hash: HashDomains, F: FixedPoints, @@ -549,10 +549,10 @@ where } } -// Implement `Sinsemilla45BInstructions` for `Sinsemilla45BChip` +// Implement `SinsemillaWithPrivateInitInstructions` for `SinsemillaWithPrivateInitChip` impl - Sinsemilla45BInstructions - for Sinsemilla45BChip + SinsemillaWithPrivateInitInstructions + for SinsemillaWithPrivateInitChip where Hash: HashDomains, F: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 2ab2fbe83a..208002f9b2 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -1,7 +1,7 @@ use super::super::{CommitDomains, HashDomains, SinsemillaInstructions}; use crate::{ ecc::FixedPoints, - sinsemilla::chip::{NonIdentityEccPoint, Sinsemilla45BChip, SinsemillaChip}, + sinsemilla::chip::{NonIdentityEccPoint, SinsemillaChip, SinsemillaWithPrivateInitChip}, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, utilities::lookup_range_check::PallasLookupRangeCheck, }; @@ -460,7 +460,7 @@ where } } -impl Sinsemilla45BChip +impl SinsemillaWithPrivateInitChip where Hash: HashDomains, Fixed: FixedPoints, diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index eabd63b295..2402fc16ed 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -180,8 +180,8 @@ pub mod tests { use crate::{ ecc::tests::TestFixedBases, sinsemilla::{ - chip::{Sinsemilla45BChip, SinsemillaChip}, - merkle::chip::Merkle45BChip, + chip::{SinsemillaChip, SinsemillaWithPrivateInitChip}, + merkle::chip::MerkleWithPrivateInitChip, tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, @@ -486,7 +486,7 @@ pub mod tests { let range_check = LookupRangeCheck45BConfig::configure(meta, advices[9], lookup.0); - let sinsemilla_config_1 = Sinsemilla45BChip::configure( + let sinsemilla_config_1 = SinsemillaWithPrivateInitChip::configure( meta, advices[5..].try_into().unwrap(), advices[7], @@ -494,9 +494,9 @@ pub mod tests { lookup, range_check, ); - let config1 = Merkle45BChip::configure(meta, sinsemilla_config_1); + let config1 = MerkleWithPrivateInitChip::configure(meta, sinsemilla_config_1); - let sinsemilla_config_2 = Sinsemilla45BChip::configure( + let sinsemilla_config_2 = SinsemillaWithPrivateInitChip::configure( meta, advices[..5].try_into().unwrap(), advices[2], @@ -504,7 +504,7 @@ pub mod tests { lookup, range_check, ); - let config2 = Merkle45BChip::configure(meta, sinsemilla_config_2); + let config2 = MerkleWithPrivateInitChip::configure(meta, sinsemilla_config_2); (config1, config2) } @@ -515,7 +515,7 @@ pub mod tests { mut layouter: impl Layouter, ) -> Result<(), Error> { // Load generator table (shared across both configs) for Sinsemilla45BChip - Sinsemilla45BChip::< + SinsemillaWithPrivateInitChip::< TestHashDomain, TestCommitDomain, TestFixedBases, @@ -523,8 +523,8 @@ pub mod tests { >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. - let chip_1 = Merkle45BChip::construct(config.0.clone()); - let chip_2 = Merkle45BChip::construct(config.1.clone()); + let chip_1 = MerkleWithPrivateInitChip::construct(config.0.clone()); + let chip_2 = MerkleWithPrivateInitChip::construct(config.1.clone()); let leaf = chip_1.load_private( layouter.namespace(|| ""), diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 4719da25ef..6ec65fecad 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -18,7 +18,7 @@ use crate::{ { ecc::FixedPoints, sinsemilla::{ - chip::{Sinsemilla45BChip, SinsemillaChip, SinsemillaConfig}, + chip::{SinsemillaChip, SinsemillaConfig, SinsemillaWithPrivateInitChip}, CommitDomains, HashDomains, SinsemillaInstructions, }, utilities::{ @@ -601,9 +601,9 @@ where } } -/// 'Merkle45BChip' Chip extends 'MerkleChip', supporting new methods +/// 'MerkleWithPrivateInitChip' Chip extends 'MerkleChip', supporting new methods #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Merkle45BChip +pub struct MerkleWithPrivateInitChip where Hash: HashDomains, Fixed: FixedPoints, @@ -613,7 +613,8 @@ where base: MerkleChip, } -impl Chip for Merkle45BChip +impl Chip + for MerkleWithPrivateInitChip where Hash: HashDomains, Fixed: FixedPoints, @@ -632,7 +633,7 @@ where } } -impl Merkle45BChip +impl MerkleWithPrivateInitChip where Hash: HashDomains, F: FixedPoints, @@ -649,14 +650,14 @@ where /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. pub fn construct(config: MerkleConfig) -> Self { - Merkle45BChip { + MerkleWithPrivateInitChip { base: MerkleChip { config }, } } } impl MerkleSinsemillaInstructions - for Merkle45BChip + for MerkleWithPrivateInitChip where Hash: HashDomains, F: FixedPoints, @@ -666,7 +667,7 @@ where } impl UtilitiesInstructions - for Merkle45BChip + for MerkleWithPrivateInitChip where Hash: HashDomains, F: FixedPoints, @@ -677,7 +678,7 @@ where } impl CondSwapInstructions - for Merkle45BChip + for MerkleWithPrivateInitChip where Hash: HashDomains, F: FixedPoints, @@ -709,62 +710,69 @@ where impl SinsemillaInstructions - for Merkle45BChip + for MerkleWithPrivateInitChip where Hash: HashDomains, F: FixedPoints, Commit: CommitDomains, Lookup: PallasLookupRangeCheck, { - type CellValue = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CellValue; + type CellValue = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CellValue; - type Message = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::Message; - type MessagePiece = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::MessagePiece; - type RunningSum = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::RunningSum; + type Message = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::Message; + type MessagePiece = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::MessagePiece; + type RunningSum = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::RunningSum; - type X = as SinsemillaInstructions< + type X = as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::X; type NonIdentityPoint = - as SinsemillaInstructions< + as SinsemillaInstructions< pallas::Affine, { sinsemilla::K }, { sinsemilla::C }, >>::NonIdentityPoint; - type FixedPoints = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::FixedPoints; + type FixedPoints = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::FixedPoints; - type HashDomains = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::HashDomains; - type CommitDomains = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CommitDomains; + type HashDomains = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::HashDomains; + type CommitDomains = + as SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + >>::CommitDomains; fn witness_message_piece( &self, @@ -773,7 +781,7 @@ where num_words: usize, ) -> Result { let config = self.config().sinsemilla_config.clone(); - let chip = Sinsemilla45BChip::::construct(config); + let chip = SinsemillaWithPrivateInitChip::::construct(config); chip.witness_message_piece(layouter, value, num_words) } @@ -786,11 +794,11 @@ where message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { let config = self.config().sinsemilla_config.clone(); - let chip = Sinsemilla45BChip::::construct(config); + let chip = SinsemillaWithPrivateInitChip::::construct(config); chip.hash_to_point(layouter, Q, message) } fn extract(point: &Self::NonIdentityPoint) -> Self::X { - Sinsemilla45BChip::::extract(point) + SinsemillaWithPrivateInitChip::::extract(point) } } From 37e9380b5f4d91923cd80809ea43ef18dd454db4 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 25 Jun 2024 22:06:30 +0200 Subject: [PATCH 103/121] Clean lookup range check tests --- .../proof_lookup_range_check_4_5_b.bin | Bin 2048 -> 2048 bytes .../proof_short_range_check_4_5_b_case0.bin | Bin 2048 -> 2048 bytes .../proof_short_range_check_4_5_b_case1.bin | Bin 2048 -> 2048 bytes .../proof_short_range_check_4_5_b_case2.bin | Bin 2048 -> 2048 bytes .../proof_short_range_check_4_5_b_case3.bin | Bin 2048 -> 2048 bytes .../vk_lookup_range_check_4_5_b.rdata | 12 +- .../vk_short_range_check_4_5_b_case0.rdata | 12 +- .../vk_short_range_check_4_5_b_case1.rdata | 12 +- .../vk_short_range_check_4_5_b_case2.rdata | 12 +- .../vk_short_range_check_4_5_b_case3.rdata | 12 +- .../src/utilities/lookup_range_check.rs | 524 +++++++----------- 11 files changed, 222 insertions(+), 362 deletions(-) diff --git a/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b.bin b/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b.bin index 976409570e71c45d7f67e95a087372b6455a8f9b..a212b5d2881585ac95f5e6fd97a1365501d0f451 100644 GIT binary patch literal 2048 zcmbu(=_3=21Hf@)8`Cf*79z(Sx$i|ALzl3c5VBYY4I8=ggf*2Yxt`49p703E+z4(3Ke%^ffvJES+;t5m7Voj@`e`99#ZOY{N?|=#Pu*omD zml^F_E{XdW56X8kJ9gRM7xHNT3}~rN!d%wt45-5+jv$l4SPUZUP%q^stz^$YC?08h z>=gTWi`^hoQ8m%f&Nc|SF$?^m zt+8j^!Y+}G6WI0!=T3){$rNX04|Bi=FXhiQCtOFF4?^K`RS)aM9a>cdCx^`hG4ziF zH39bB3{-oe%Owr#iDFiIvb$ROvQiDz5&=%kT_&-d#>a z`+n9OVgc&*28T-XRJU_Z)nlScos{(lwrw*^Ac(`@OKLi=1Vfjm&y8l;icZoM6S z+vU+JZzU(ogF4>N4Y=-7$@hWs2UdS*mZ%JL1jz~+oQDPe>Qn>rYt(Wt03(=S$f7fn zz1*~K(7Mz*A;obvE|8P531qtYg?;dEcC0+~vkUuOQl+>)1Fj~~G@2(t2ovD?8I8AF zKBXC@kSj&zRL0LKX*54^fox@UjuRWyP#f@7m-9`8JwIftBB#21FBbm^>>>7OIS+bK zqA8Z%+WieW{x7K)@NM*Y4aT(vI>FkIccx}vEjJ7tf?<;_^w{Luy7`#@oLoWqttieD z$7XA931LPB-(2W7ZM11rK-DsOd- zfeE0pXx~a$xFX0SN~!qrJw;`a$rT-7AE3{x#h(%N$SeToX`_&ZjS9)7nem3Q;vax_ zdmvZ#+#I??F2BurtFJ9nSp8oE-d1&eMP^J>crMXq;0=9z7LQ)^xs#S2){oVVh-~(L zWz>g1tZq4D`2qqwE%pHe001r0DVKVB#W7|A0tQ5hpxl$|5O1MM05#{u{1ePkNiH(PxH)4 zNfX<^Av4}RXiv6NkHVgI&L?7s@I?tRm!>utLg~#8yo$lc=-Biu1On!O#Ez~ zMBO$wCi$z_b|@7uqM4QE`tjY|%<@fDwJC$A4)adqMuF78xU5Z4jl!0>$jab#yWpq) zl1heo^2Z*=U3^-e?pI#gcbVKEX?FG((5Gef(GCNNZFjJ=?ldNh<7K7K!Y>+73pRXnkVv6Essior0z8)jh3u6 zpkC7~MD31_Og&x+KP|R0W^JA1y=%a!7uL!V-5>=eHx(UOOro}rHrNktewG|LDC&@O zy_G`=_AZcX4L;*8>)Kzq^tJS)+c7JzFl97BkKXv&>VnR}1c$Gj`n886x30Os|^k26y}2Ss#~7jc$Y$Ir_rBgKu?jp8Mhr?lj~4vP*dO%CRF3${!w{Wo_4e zvPlqY`L4v|#tk~}TE&Y*j(XyqJ^1(V7OwCO-+dbC*h8V!ik@NjCzvAZjqhsNyu zU>&8PDxNPYZwjVMD`3QYz3MNxB-H7gch#W3q)li?5_WbvSsLQRJ$PHbed0M{%+0zYlP*vt%8t+0C~_|D-TU1;>3!shG)K+59j?5*=(TRmcaz3E&XejU$OdD9#^_R?X?V-D2?xfSO^i|nmG5x1UM~BcL!e=aZ!58xJ$bQ2&!+>JzBzSQA8WiAxr$M*&pE_diNArG8 zdl)=#!^6&Gp7j_8s1imVp88=~8Q7>3#3#TRjl62c(h-MON>6O@`&*adtH$laQ#b}j zQiDQ8^PaS>6o`eMF8h+Oab)OW*TCW&lY3bko5{pdhp(-VZqHCk9B4QS^QT_=S2Ch2 z{i#Ir(YVa3W>y-Q@fHQjBl=%)F^%`I7N1YDaON6txpT)fYnsS=wGKWHuCBVEscp3) zNyS|5>8rcN@_gE-5<1i%@3HPQULm5jj%_%w#|)D6gtRN)wVN0ZHk-zr&7~Jew~#8M zeNKT3Zp2kRzcr?u_pi3344z8B*9#B+#6CAEZWJzY;Q$SrU5z)_kx^;tLNFsTxQRz? zSRBLQBHc-$TFMvxq*x1dz#Y+%a>~&4jR52ozV23k)Y_Kw0Dz&5anE64aYDp-nxgo! zmK893<3PYRDcN6DZFZf#TaUhZ@S*Nx%r)YrVTqj{sh<-8IlBwNqC5JRuzYBnn*zIr zqC`SPjRsphMhN`r_g3~-#bP5 z*_AcW4BqB@CBSbwsuu#x4!aiveYRO*S@h54-alAHFZbub0a}?whi6L!oKKMehl5IHJt z9?~!MJO9nz|K=HiJ0bwmi?t2vy6K4wwqRb_jP3BNJ7WK)qkF8sl1yjkb;A~Ed{9-- z#5k{HQe9kn%8QZP$DYK#Ll^C#R`*dN zat0ys=O&sho73McGyL>yb$_@!F;~$~>Ic3(pDfDAmYL)#e(i{si>?aj;>U2j>4{W& zb)ALZHA^d+fAppw#L-#}+GXFN&Ga7W9fZv$1e=+=ycahSL&K})+w)R1_Jby<`qz2R z*^-*v3e++ng9O9|g?eqD`LuMGa~yOy9C_Yu8(a*3f5_5B`;eSRv)sZKw88B7x9uG} zXXqmd73Ym_UwZIvCtO%7`pu>xF*Gn|@2p{X%epZ>h9ob>Y4i75jTTbpd7t6Otz3tX zg70okDmZ0PF>Qo^ZiM0yTMR0>8ux^Gkkwu^5}~2cg-l3H5n0yT-RxLXkur%)trrmh zzj|hPt50w#PX%VFcE`9A8s)Pbu+rdDMg#kQ`T{RKzHg?>fBmZ(R#&;#Pl26_-}TsIaG;7Tr=dvy)Z4e-P8UUUf{y9f zOPNS+qizmiD(Q5Q;FRXFLSAkbO21#?t2YRqS7S`ZswV{06l!wKSgs)-1~H-TV#9@9OQ(TZp)grWF$Lr_dC-e5pV* z>ap*Ts^v}X`lzr@4rgh2;Zd$vo38`-B}G&Qp3QSn+fid3R1^-8t+2{wO%U?H!`*Mwq8!qNr1MN-9PhgBEn_F1Zhi kSQ`Wt?AMGvNYB}}#c19Vlb*#H0l diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0.bin index 9b160e77ba5b4056841c9a0cc2712ba3ad239e00..081b7e641c51decd4b394b62b69bf1afa938a65a 100644 GIT binary patch delta 1978 zcmV;r2SxaR5P%SWM$W1STQ8+wjUZ>e<*wK1`kev?7LV$3gxt>eJKJ3|bA{MLT$3}m zDS+E=T;9YJnXk|KsIV5K5r*=PvhSr1`#F>aUO%ZP!rNFQghdp{GvoOYJ!+ad-!_g* z#4uDE22M{p3YozB%hoqvHf#`&+eGRz0FKqUO?|Pu5jf9(ArMFh$+VqYIDNj@!#zt3 z1;%w#*nX7@tiWy!JXlkWCWQz;KfbEjykxz2Ry?F{2iOC}EPkQ7%=Qj-)IG}mnJe4F z1Y%4QkzP9$;Nb6F_e?yQUI(E9hiVK!hZ2G6EdmQYci@G>PJFy*XlyA6-Q?J%-*$(AI^-V+ybM-O=u zW>MRJg=1qDs>3exbet?(qKb}E|Y-*Uw;7HrmA=%d*g?_ttJ0@ zXbh44pM^RrhH*F=puk%Zkh06#fGhT+Kh zAbcDR#SR@;dStgVGL}{!`W13AZ!MJtGfCftMWg1{Yv{xP)s(P%?$P@fOO3XtFpbK3 z8%87{qP6pp*nz;{*t9vH0DsBZiQFQD_tB1Fp19A4+JA8t5U=ju9o>Z#5vqlEP|`jT zIdBKp?%ZrwImq<2gc(;56LB87W#V6($&24x*~iK?rf@>5a8YU{#5Fx|??pERE1@4> zQq9^D19s{NP2nGH0qxx2_;s6M^7No!VOoC;EsvN_Y(!?5B}QC)KANi0f9(3L77;WDl9k{<4=9(7__RfBIh zBbhY)#n3ef5KzUWjcujS&u`|v123BQpr*1jxW>QIqxK+6vTt3=3oSlM0B)L`b43lM zdKTmPb%hywi?!wDTAWhimc{`&e+G76mGib+DSviHh~X=x1yV^p>D6r<+jMhl?wA3c zH$j|#$EXWc)cZY7c)lokNHf%&x7n%-f}r+HJ#S}p&vA()i~opdR0mkVDjosr``^k| z_aMYlBEQ^E1#lHd<6YkW-IfCTPPBxN8Ab{JRT3uN6SCt3{qbZbAD?DMaq#=&D0g*h z=6`YTkz-4(xsPA#;YZNc;%>^bFX*+i?yjv-2G7c~*3AlGZz@17OdG-IVHc*trx|^P zB6D1L$%;{EsQcZ4QhAcFHI~JXJ;sJ;mPJ<-C8}1^KY)qJ8eQ2bF!qlBlc*m?@>}DB z2TU@kzfsGm{yM*jW%|X$VpKc=flJO*L4U%7c|zSm6Yj3g0Z8yTBet&WavpiE^M+Y- zs=tV5Ce{TtWQvCXE@4~#pZ{k|%5ICY=C>Oja#&e}MM_@n42^t0)UtJDnElwFh(_^q z0S`%RqUgBx0Ljo}g}?SO{;Aq+Dul_uf?%;F?P<>R8%?mrm|nD%x5$D|FS4>uhJQ&p z6S+_gb{s*fdM<>5(8y`3P$7{b0RS&;AT$-fDi|bdJ<7_gtuiQgbQ~z)1LQ;ScaQQl zi#U)&g<41FAI9e#38%^vQa3SaIj2j#;BP=1tSn$|D7}A4x$;&5IO`FxRoJO zZ{7UkrfrKYK>|awY>4@ZX3Y+}|cL*^ANYUA|Z9`srk6gRpVf zwL*?vxF)p~r4O z(6kfi#Zg>!Y?;<;xlHXqQ7cQEWrSqMQ%OxNIud(k2FI0zBP+~Ixr{d|RQh~PE8(wZ MmNbq66u=G@17OJ3dH?_b delta 1978 zcmV;r2SxaR5P%SW;WpDb+VrCK3z(7Nri@Xtivq9mT}m5WvGF+su33V=B;FPMv7ouQ z#zbf*7EtNqWn=B&4arEpj)9+U!-HN1K1oZ7rOpvX!c5mRW!a#rPXypt@|sCDDgk1V z@3NdOiqEjE-5PzMAcvX{GI~1y@<|HXd1(i1k`r7#tY*-Eig~XeTQz5$-c3b5F=8k= zX2E~vl}Y5`7q`;?40a18i)}ms$U92c@<~A4UwDWfu|3?z83<^_ zqDqplORP9w7>`wIFTZL8KmU7W89yl_=Hi4z2^eQ=O9e7 zpOVIwOA8;UxFX6wcjPbf6hn>b?*itC9ympC3ZJomx-^N=j!kWd-7Bx{CD}1LEJ5|6 zsMtTi_H>i}FU!XN)3uYPCn{=XlRss5Xp_MbVNMJ>we6<&$HcUBz{%jCRjMHxq>)!^ zTr>xfFQQXq6`E=+GzLSQv3QA{LK3&3Zg(7&k0$Cmd-Ar(HlLsAafXmE$oLzBd+iOlAWx$C`wb#EH)8@TCPw--V%?s`_7Ac5 z!5E)!)S(T@_QfMVfAF_82c?Ed34b%HT56Y^W=hl>FVM; znP$x;^KAFBdcXx46Ib6}bz`%F3F3^U{~+Q8VnaQbJ=yAjunobUME2}X|1!_OA{0D52FegSmL6LMzv6AH& zI|AD=L>@1{4}Ux+ZFvGwYy2ZxQI{g&p9M7?_fZyHf72z82wY8WmduL)m46c=Q9!|6 zn`SX3l1e-n$#BVtb-=5KAPxyhf9W9uU8mVZT#Nu&y+rDs_=WH*_rv>RudhWkpy(+$ zf$AI%BmB%(SN~;zu!7|voFrcjul`Rs1tL>m-zGN+J%9ZaDb?S6uZIqdohD-yQj9P0 zI{!+Lq#S*6A`wJbq(vP^0luxgKImrram8R5c#@Stis#Z;s;VpqaJp;n!A0|=9=p;^ z2vj%m1KPa{pNcv}P<4LMP)tW`Kg-qZ4QMSaJoDF19{}be3|MwNcD;+%5jX?VDW-BB zP)!n?`G0CogrENd`#NQWVS-|r#8!&gUM;AL@}QBQiWZmu*waCZ{wfI5P_z(5vxC|h zHH!IdkT?Vp#!sZe*<`CXD?F`mx@A};*lm2QxMw=Y*F67- zHydr(rc0L%eDJRWy)&Cl)Qb>*C*P}4lMe*z`G3DKQ?M@KJG!)k4R)xG0onky`xgK` zYyLkmxIa+>;36wtKzsv`_W_9|pd#>c@x&>8dZir-Y|}Y_){%6$XKW-HF)1H%GgCGRHQ%l{Dg` zzxldITjev!X`KtCh+j}U!J}xsIt-#lhcAzr z;kDRD-?o9c4fg7K1@@kdx4M{Gto8nYF^LFu>mZ;*n1u|c8IFs(M!-HT7Ck>UKVs2p zUZz=Cp-T^-_?AV0-36uJ-}IUn7f?a&iMHZl#5N023KVEgMUNQ=zbu1 z*yl>8xV@57qd?Yc9JXlB%x0ejHnUXOXIyRJl%U4HP$VE*O-$&{)#vKsy)^=`TAN{5*j$-N58C;YYQJ(w{hI&# z&X|>I+y=Yvgwn6vg^~q32n+d1iweU4&oK?=2QP}+Zh!qqST|dgxZQs{Q0)nt=+oP2 zUJJB}BtCcl@4_TsyjNUuJ8t|gROTM+z;Ss9+(XXC=C5WX6jHKsD-=kK9!aU;ADQG)kYa-%C>M5&;9f!_2xh>u8(tpWv3wH)O6f^KjG887T4cM7_nv zId1q1Q|cmY+^&FksuOtnEr4tr$84qVI~yd|p5xbllL%HDSPT#dtwO@Nvj|HNp+Sxz zmf}h96_eRH$$G(v9KWc3KyyG$5(&jt9Fy1u)|@!WE|Y-*Uw;7MXSvWNXm1&JPX}on1p|8&QI`6*9Sd0RHN$pg{6I#4Ns4g~H ziCCS_q~|<*H>k|zp=-zB3JcpzeL>SL3#&oL+A2;xcIZH2&cC{LMlXf`8 zObTE$3*Bb8#(z*R$xXi^wiF1zbJ$KRd49;^&%Bq2b`T8D%pL8=-|H_Q4z@$Iy(-yR zJOqNejIi!i?w%vb6_H1Z<`?ubj%HOpF$yEAz3frkosw2;Ky)D@1^&#GLvUPx8$O4o>I93E+bXuI;Mt?OSDtmTW5GxU}UOy$QD+}A0 z=(irzvV@^d7`5sZ3TK@SIgc5Mu5Rz!~%hJKr;A~kRn0vg4)Gw0~X^> zM>J&Lj1v`_W^3T?E?*biMUiFt4gQXXThZYP3}@BdwSFpnrH#VZNsQ@Ka@ySR5%QBP zXhvWKrhmTgv@B(0%7e?*pG^5qBSiAAm_76ODh>Mh~W{EeqH@eJa-^Ka; zzb-}I+Xed;(#vgf;;Ev;v_L<0!$pqj?NS2&vVT_n0(uqpJL2CA&{8A7?rng zDYXRSxj~YgJi9>{xw1VMuyB=U>~PtSNIZCdmft9;G~+`~H;uDy#PY+BjA$*8GO7V1 zJ`R(}q-ZYwx{t>w1JdOYV7q2eJrS8g4#cu0ZeSJ5@ls3ORleSah?uZ8tqmHznH6f~ z41fLqB=&D1QV7+<2iJe99P*DIM3Eo-$4{&&b0oY@y=W}%ZH}Wc^1=ndl?OSi>4ZZpz z8Z9HSP{2OgYwKVw4mYZ(DDS88ag5zJ)_f+!dXjI25&61p$TQ2F+)VD(Y6Rcl2@ zJR4wujg;RDq##^48aI2jg%ABJD4wO~*@<;ZZpko-s~mS?i0e$V<~)1=XDXJv2p5ep zjErTZxssFqeW*H_-gJ#oY%$Dj=YM!UBQi;Zan-3$KM|P+a?0qN1TzT661JycGvy2_ z;vaPE>|HuqDcqZ2*9|qRmrx7p$6u)*L`G`2XhNLc+a~vM5qRfN!1{vE4M{3THDBi@ zcKMswRqTTLlD?cjxZONehcqWv#U?mstnjraTzr-U*>DY=6?!}_jjBp69e?3%!E71q z%0JAN>Av`E=oRY?!VUexYx7W(CZ<@?tIum&T=-T*j0YAT_W#sjWg%4XW@T6=7XZd| z7D7}U26;tnyK2S=9_Qq@xoAhg!{1KYCEkDxqntu)?z-KX= z{!wZC(0#E5;UGN*B=^_H7Ax~kd)b=p+6(*dDM%JQ##gE7kv59%$X(pmVEJ-}ffTk9 MZJ(}zhl6KsECzwZ#{d8T delta 1978 zcmV;r2SxaR5P%SW8RV*o6X%@;r?Aomx)esUn${N)luNbLe{&I~a0p5<>$hl)B$3Ua z#R^j~g;+Js^?J8*d6p3*)mNdw*ga_y3{qOXVQu~bG6T~aX4(v1u_Z>?SEYcKf3y(w z&GB=gSE=sC%~3X0?t((*eZ;2_pGEFU%v9*|?ZUO~Qkjx}6>Y^GFKuRzi*Z37HwAMB zGf$kyqT4VIVIgy)rblygH(e!5)akvZ=TOi`Vj21%R8eiJRlmRSdiP*MkD^nwPc)YC2o(@V&nJ_CKG_I02s)!?YQV;eN-h86;Ay%VfDF4Ei zE6^1}=H#${f+UIATnM4ZKr5z_Q|4ggbvG4Q8lxkEP=Xy{x998VH4S>sck+vi8Jiv6 zplCT3dQ^)gPEz3nxGgO_n}A*10lA$;}g>@qYg zmCn3>Tp5=H>|DO<_9Z^qr9Ijkrp9E<1TW6!3Wo@pygYRSRK+|Y^qIZM4xWcTf~9vE z>Dni%c)7K)`rlsploPvC0q&py54VAP2}D8Iic5G&dUxv1c&zn$1XH{mHzS&{%Z#iB zLIsBDoNaPdv5vOe(883;CZs=ykI{HS1SVqznxK+W7?XhlUw;5rR}%1XKE$r3q_xH* z7BF%=k%Lb3rCcDOGjPR{LOmt*=XKOxy33_Z0*bUU>1*!%i=~_qzcFtKR8wYx%vBW2 zLJfdNxqeWz5OC0(j;0sWQK=;s!IvI6GIWuAC+3KILRvxLLL%qF6-aSnDO`O0VIy;w6MxqTc z;yQ67gB)f2mv#vqVMkrcDXN%VFM#w%zY+w>h!<>dXMcuUFBDiKpLJ6OYywi5^Zk$l z{OAVSNy%8Qxlz;YPUskaJ3sg;Q9yaRiK@ov&Arifzu}eTkgQC*Vn4QATnYEHDO6Vp z#lGt330sT9dV>PE5A$3C5e<ZY3xB)< zAFLUZ0DqC$iH-~P_d1jSluVG!MonE;Ly?#wt(HS2#u;J1x1_ekJS*0W7dBt8V|Y1F zJ3QdOo#LG!19@GszobTpnu=hCJtKkNozLLTBIldk3>-U>zyUX5$aKJaqu>p)(?+27 z9th=gxwwX@9;emqs(M-3}YB;&!4#^%!dT@GcsP zYQy`+Gyq)f@9b&buNH@Ok~SbWl?5SwWKI+$iaO)TYf4q1gSZITmS-uC+tuNY1q>HEkV&$z@Agn86o3~ z^?yo+&v)FOx_Tlqw6BR)1Db$~&B%3(*X&vimUpToEqj>(R7<8N+0# z%naeQ@p{4Hgs~rCFny+4tV+k0r6<=~EnM$TJ0A@$(8Dm1_Tp2#!ljCgEik?xw%fm^ z@I(hQcEOf#!9$InM}dg`(?~{_K|9jb8=kn2iq^LeR4IhETRbvZGIv>#zDkE#Hh<^i z08vEhUj{-{(eS8$^=8eo4DaEQmlx{&s$HVkuf|(R@Sjv*w3sQB;`o0?>hHWaS&5)h z-olZxEpEh}P5;ZcZg!6NFA)vGa@O?kGCny7qMrQ`D?)7ddf|!05}l{sf_3TmK8}AV z2Y4}n8z1*;w_>F>);#_a_SOh78-Em-^H;c1AH4^qP=CvGc0^=53)~tw2^p;I0QiTr z(Bm{$aFxt5W7ra0xZ8}?BAgKdm%;ZFdnpyIhI4=rhdeuGvaUZdSx25a4hr{E5o33> zqS!N0D4mP(9d~bO>qr#@?i_iQP!B7Wl^BS)xQA<**(*i|ok{a0D&FAMyniy=4_}T{ zSPJ+#>xTW@QzW@g$x7^~`oSwN^H`?OYy)9>f5CZDSW|!zX zfQK||zOKc!_B6#22JL+FT}>d~D*Cf6HI3_8yp{y2hWV#WK1Yz9NX&hv^LB=t>U*ri zwzGSTMG$y8qZ*a^WH$H)W!FCRJn#7U=^Wz=uET%D9vqr~xcnju;+dr*H4k$XliAv| zrDI}{AB}M>0gc!hHShG(HkPDC(6t79ANMnyar`yCf(Pc`b$vDqXb7lZ?Y&+>Gm8oHYi5=8tA9(>SBq%r?4zR)iZ>QFAjI86e?vo`~@Kh4?FW zPu}F7G>I5$tdzDE{J77g1Hn{yzr|`JpRnmWnx}-OuBtPbfaxJj z#SwkK%RP}jelbt>S;ha{98x@8Utv7pRQ4e+@MsZnKUJ5^EGE=4N#HD&f*Aw-UN$#z z;j|}zHs`Vn$~7tR8(d+EpbH|&3}xWzzCKFOwAWHKTxu{iFxhlmdaZU;k9G{pk9@~*^4f5&y9zvSW<}y zRT-K3vRZyxSj_NpMzvw4HY*(lt#u1W!mb|~bZ{gJHO0v&-MU5%d zk3%C?KWEb9+%uSRZ$ZNXcg*dq=c;sAKb&tNY4R=YKYii!;jMj^V)!L+#~tD$C}BtF zB=VR#p+X*5S?DKV<-FzIzDl>h;)c@I!0<_!w7YbeO@HVx7N{aF4IpJchJcGMsML&u`WIm$uD*aJtut@*<#M@hO$B{pOtyVObVk9AAg< zu^jc%6ACejTE0_sU`-3hz@;${0)dUvNpOx20UBbBO;$YbazE5^l2P-ycb!U%&3L<< zMZDQv*MA?TA*s+}1#TxD0yD~WDBo;Ma1E;hICK+D_czi_iMkE)tsGa)3irZOzLnN0 zV62sjtQjI(aaPbzUTg3(!lGURNdWt6ImY=@UE{i{IHMTPiSpD{5Rklb&mn%r0uH<1 zs~asfd_NpF$T=+V>+pN%TUgs5kwND07uxY=-+xFQ@H0GEEPgVI?lX-w%8aK5b~a8 zof24aGbD{#HoQnAdbAG5DK`f;~}gpYbQX#ZB;)EeP^P#f0dc0*~z*&b?Ka3kJ+ptZHY_}5=N`Hb8Iwd6J0fa-L;39Fq0sNf~8fMZC;wz&W z0av&Q3E!9P>k$7g2{5HMqljwL`Uh#^Xg%?RoO@<~uT}WOsw|W`s){)~riq4=OHGlRI zCo*m-s2ANC{2wJZ^01@(YWUQiK>>*pUM3ne-Freq0+!vg#S!9d>DnN=E9{N~^B*MJ z-dKxV(QnBzX{*_LGnkHKgr$ws{-#b?8OFOdK|`Kzd5?<_=3gJ(1jyXfdFxc@F(QR9 z=}p_c0lZ;&dl2J6&SVQ0u7G8)UVkaX)quy@1pf_Cw%hInjqHl~uV_((1=6E9B-;4eEg4K47b>tsb)BOEPE)$gAmfACyCl-}vr?Zub2e7=INdokq8T z7==+6IrG&P@7Ndvn$~se@DztePm~wMy!iEDZ9Ar6t<7yNy6Nf8Sr;;eUmUE z6`;MN7HY99P~cF0LSdDJkp^(rpdFR@oA7)2u>?24r1L!UKh(InH%llY9EI?YacE*E z6F{N2tjZJ+a{GsW%2KPA;VWexglCVts&3@FA5ORrrlzi_v+UWxdH)U4Oo#4SzvG`= MUwN;A)~p2)Iwx|(QUCw| delta 1978 zcmV;r2SxaR5P%SWg5n;;ai9-I4s~%70FeSDbO)ws638|`!ke?_z&<=X=t!{W@XAHK z#;M4bZ-Ng&xxFAQD6}q23N&nLoo;vvYNjj_scVDy$KLo_#58I|kWm{&_}O?m%~dk^ zA8Pfu&$LAHAQO~mr%^l0Us^H=46RH*k%YJgT9`C~BYP-+vo@4`?6>+WO~I5H>{(0`l2b(bolZDx9;-C zFjT0x2e>GP<(Gu+Ig_;l+9~B^!mQ7Nc;1qEOV>yR<>3Z3QQINo&S1sZdnJqklM?ze ze6aJg-qtU~c=(TzwR??Epl5jHD(lFx6Ukv@_$D=fCYk`dUG)MtvE%~#&?T5Et}6*2 zt;0`5LZh<)=1B0g0}(bu<6qT)c=is8+}%upf^0#$2v_+seg*~cjH5Y}xXc=%3jPMY zt>!eXMFo+xJ=Q7$7p!sjRl9$4Pd$jWQxKo5lZW|~#Gq+T zrVXQi58}T!kBjAKWHN#l-Bx}RlNh}iMatcxC&cUkcCS4S7{#{m{J4e>*dJ| zxMsAD4re87s7FbrOF~QzR7i;(B@y$vYr}p8ZCepS6O(}gUw;7LEqyJ_#tu_otv~3R zv%bk-w#gx@j{{9*vFH`yDcUkXLiXNd1gM&yMhMBX#f9ejgR6Unig2-$s*=~GDnb%g z#XQKZZh-6Y)zt%7!N?3WTlr$n9R~gJgSAX<-2IuIk&K-5=P_FCHKxnY+ zhs+eQc&mUGjz4NM_^mKQ1*NAum*Tit7ue=|MdN6xp~qKEh;%o0e(qM%ycC=41bTVP z9W$l%5bqI;*n;PJe={~T**mzG-Btb950CqvGC|^R&lu|(0BG^r)#g?_3I;Qv)-nDy zT9u2_6My!Q%ZoPU@O;p75)8j8E!q?{HqPD3LjLM7w&zF5D*3eZ11v;zBUtr~Mt?4# zVCk_m4W1#v1MdZXhV|wS9f!!eh##e1%Kk!Za)v!jb$|m-5c)w=JMI(2CZED z13YJHuFCLO_6^NUsK;GgxLb^#AzKY~*uzDmiBh;C+n|hOl}3LP z?0@+ZR7E!@&Bac&G9w9PlpQF+4`+-HAygbLB_!j*IL`dMN}@Q3y5u=7YY-eHv0#=* zVmoSQ#TlgD8h<2%!tB(e+f*I0f~0>NMz8r*h3x9+81%#N!g_cIx!LF*H#|U+JSHC@ zS;NHXsmR(isl-)IR!h!$R847vu+@sSvm$iS&3`3> zP1${6T)l@)Q6%od-(rpGh|PdB7&5}guc15ZQ8Z}P=Ft%JH>_9)T8ljNCRr&MrEwQ0 zJlr|l^9>7&g@w8kUK(Kjxkz=caFUU&*qcW+aQ^_ocg1KB-+Uu{{@(jXg$ zEG1L>^HBui-}m$Q)^deF-kWsmbrPrZypTNm>JtHmg(N+fNY4NvQ&{#tGk@l_-K5D4 z)a|S<;_AOb;m$R$FO|{Qx1j7>v*C}V;dmtH=*+Zn+W^`dEJBSn@+aXNJA*qA9a~@N zB@$uPOnkz~-YjG~L`{jSmweFZs%sVW$cfv54&vl{aP4YszOTc#ZMap`WzSh2XTxfE z^y?sy+S{Vay3v$!MQIA;Xe+*a5YcasVUl0#J|z?NXQNddvz$?1Rod>=voyfa5NGHy M_<+?(kC&wp1pDvR)Bpeg diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3.bin index 569c1ccd863f17fe3f99cad2cc892bac6a1258e4..fd9a9337cbfad4789ce86a9e927cdafadd7f465c 100644 GIT binary patch literal 2048 zcmbu2`9Bkk1AuuWVq5H$Gh@ls%$;mwY&Q4xjmArQjWkq@;T7UF_tk4(q0Gl-xvH1Q z@n(ufG{@p)jdG^sXgRXPDBnM!AHL7;&-0u}+^K^u^#AzSK6>{1n5R4w z^#SIJY_T{yX#}+v`ZKK*E)l84Az6n`#@BHl=mM0kx2QKfL0jGjVjS9@Rt1!~@qGC* zW>ix@0C|`vxunIi@NH@ zvll(J04E!AJEbVi9rgWM)LBi_t%CQ1M^QagPTA=^oq&W)!d+(qj2hg=|L&l_-|%wYH~8HPg=MMJ+OR2_cq5s@%-F6} zy1C{O_9;qq>b-+&S@t@is6u(g98{)CQF%#|Nun1^mB+-tqrOc0LayT!K8hj4iJNwP zHtT%%=I(p9EyPY6Nc@EOWji$YTXFC&pKF)zY?v7*Mh8pwtMcBU;p-TWA(oMhqDeS3 z@HfO`ED@rQoU25e&=|2_X#Dc70+wV$mFoW2+tHD|Cl%A2VcFfl1c&L9t$$A_|7b<6 zA!^}n2B&_qm-v7EpY^L$vV69Mi(5jk$oe6vU>0I32*VTm4B(=*y;q9U&y87g93%Qt zlLc?3^qGeTc^T&M%bZ9Z* z?Nz2kK!|icMlr50G8=vT5eqF5ICXK2G~7xuArr6JECGe_tKKTt9W5-Jdu)c3?S>}- zJCKI>|I!b4+0^)o2-RO2pNz6=c%Q4tFV5jykKp6pQout*Kgjy1RdM>|o*e5)ejWhh zv{=qX%Pd?)QLv#LG5+^vg8SAb7eL)$yn@zh*&M)5I&e}Jo-l9^+hJ(gXU1E?pFgZA z)EfSj-;aMi5m8dH#dZwq3Q_Gd|)Y^Vj>Snn$C+-HJ+j{cL zTwGNR$zIUW52=S2nn<;$W`&-&%4-;%f+Z+;y)(kP>teZO*Xzf%+S@EE$kQ7;9x@bz zE6zTV$qr}CU-^1yM$d#&qA2sd48)6zSNcZzOdvCF>DjM_lb`RZnplfALD?S`Kr+Yr zjbZ;-=y<6H-XLpK7xdl7gZ2Z>h@M`to@F^SWJX%^`SMO#5GbIs-+%c(<{x)DOrVg` z!qNHzK6?=o#{-syyNvOsxmr4ckR#JSpYT@wO#6Yw4|nz@M}C zw}y;;wUU1+$yf0^FGS>+9TxgPR^fAY$Gyi?$@vOdJrkIi^6ntpUX6uv=uBivM;uG* zSFe7)B+XHsi%!-==-Mg-`Fh&lyNDz)3RY(pa&ea>{8FcXm3!~6entIgsndZDGvz2H zf24Y{Hjx(OU!T$@`#j7-GRkY;ZS#wJ(V95v55*}R`Uq7$;ZjcLgEPn@X6{_PF6323 zTx%(GC+&FQ^jMNFmP)g;e5N}>UahB>?53~miS00c^H5T{QMYu)Ja-R>K-oiKhS&~N z&KlMh3jgfh1svksqA7)Y0KpEjHPcKRD&Bm`LhY}+rGkGhZ<3rKDFYh)jfPcxgu^th zr@g%>Rvxpv02{N#xy&z?cUT-(>irF3W-G5;8dQxdxmu#gO6Km(V06q`gU&NC*R|c- zBf+bha#;<2LA$vTPW$rrmmmZD%_X5#4WZ}NL~;z}&*tUC`lnPL=*2kC+ULoQX3)UY zL#evh*%D|jhl8Iqfy!lyQ?~K)<&obU79I|Nr+?Cv*);n2`gx0e)BbXD%{QEG;8Z0c z%GdgJi=Fu^mpHc&B)j)GTYZi6Z%o#pX^a4NPMaQZ-f@nKRjBN}Kc1u_?o%_+=TW`G zy5OXfsS?kUyUF%h<8>JlD&;xqbEA$4>G{!;R;dh%&B((Gx!^iO&w%$m13SMbZ)jxW z8?Fr$DP&|3&>{xy4Asxvh|a=EW3m_O#2UqxXj*zP!mD&~wi{M;kPr-UVGXscM`{W# zWLzr2H0f1I9qJwFHUl2NDf|TskCJwJOSxTJdRJ z@eRhEM>DlMM(I(Zp7EHE27;StZ8r47?$e0(=_8RQg4}s36d13=s8+*{P8`ZGomEi9 zfffG@F-`cxk7IbP;{(cR3E~E-5BcX^mU8kJr^&8%FdXU|xg^~u3>RD>j zUrJ0A>?fwoJU^Uv5Oeef}vo&wFc2k*--C52Z=YsZpUoE<(l|37>? zwP{Y2$RTB$b}40g@hXCdmL~Bod;L~25c8}uw8To&7nH18609P09KMWhU!ELmTp1W8 zGSx15gp_qy9xPq;@LFKIy?yWkr@i*UFS*id$&Vu=EB638{pw}&*gm0J92vhWgyR^% zMgFn}{J;L+`q+k{+1B%(gamjiD6M8Da9ESJU)|=f7TBvlOO? zof)v=Zw{P|)--iLUzlVnJ%>&B`r7#^zUjUVN+F@a=rYtGxbk*bdJO4V1~LwTz5!m2 z>N(sHMum#9d_Y(LVSOfc8ZkX*9c`UgZ&6|~D8V(%44P5uwcgmkl%UidS-Nfqw>^$C zVSNs!6rXU0Mcwp^#)>?USW)WKF5YmWlYEo-j`Yk-`-?tMy;#k-o26 zot@};e@FUv_j7Eny{)S5Wrb7e-&{v>-dPplT7esg92dT|sEGE-NC!xwW8+C=)fIM8 zw#Z@@`}(hJJ=Nao9;#P1rMR)H@ja}EKM1~B5E#$zWfV>z+gw{(m+vc3INi_m(mpOE z4%bolOQjAz-+`v_-VqIKhvyq^g|J$96J;+TK+2Ot2eT34ChCt=Gl#e!cZ~__QwC)2 z@VI_<(MBA{aiqoss4g)Dm7#2Eyag1V#B3)9hS;?CwxP;u>l%y8wd}t1T6+6ML#o<< z=GxqK)jOPApCALdVxRf+_?EoobgKv@2df~7meyCmJWB6Li-F5+CQETYUpf^Fzr&^E zqv3fm_CGy`lDGNx9-#AWByIp{5_h4`rG$6<;m(Vz;7@zD>I}L7QpZssZ3;j>eZ4F# zRBqyb4xNFsRBeXq7P2-!2v!1lU?gy~MRFt6R zv8i1b88hr-1F)aFa~HNf*YcTp_J=ORc!x(j#*TRX=+*v09K2*MWB5YTKv;8Da(|79 z%Q@X%{P5N69IR!jEHcicVAsiP>I+9=)=Rs*dtLnLd|~+?Eq8xguGIwT;;lN0eiCo+ zGBuRn&B$z%&}<>rz}9kz)zV$dECNYwzA}D&FAFr^^KJi^<~UkMe%jqO(2CMYH-wE@ zom=B;H?MVc`(r7Sh=?bkpDc;r_(Q00706W%Km$c5B%_i>Ma6QRZ<@~({gf+hy(Tof z23Uy*)@yzulC4-zP@S%pOOxJQy(bVIIb1nVm(!rfJcvzzJMc$KiD_k@E8;FIS;1r2 zEkil_Sibbs0wdYtZWm-ug@)@>VL!En5FQ-enXEJAwhRK_idOT=17`;p4lCY$6Xrh>*~XHs;>`a~yKc8K(^CVhwPnpSPZ zw-t2Zkayuf`jwbvh9GRki1}SIqp~0BzjaOXV!3Z4I3vF)+^Ra|){7eS5wF3@$LqCR z!2Tt!WQVH?_-@HfpzVt+4f4y5X}-*h!q?<)64P9hZHdUeJQ4gcjOO}==l7v0-1))7 mv*KhLm`=KActFVTuIC>KmDUbEU`aP$?YwFh1Olo#8vPG`qM{Z6 diff --git a/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata index 7f228e6244..ef4e10414c 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata @@ -85,7 +85,7 @@ PinnedVerificationKey { fixed_queries: [ ( Column { - index: 2, + index: 1, column_type: Fixed, }, Rotation( @@ -103,7 +103,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 2, column_type: Fixed, }, Rotation( @@ -159,7 +159,7 @@ PinnedVerificationKey { permutation: Argument { columns: [ Column { - index: 2, + index: 1, column_type: Fixed, }, Column { @@ -430,7 +430,7 @@ PinnedVerificationKey { }, Fixed { query_index: 2, - column_index: 1, + column_index: 2, rotation: Rotation( 0, ), @@ -440,7 +440,7 @@ PinnedVerificationKey { ], constants: [ Column { - index: 2, + index: 1, column_type: Fixed, }, ], @@ -448,8 +448,8 @@ PinnedVerificationKey { }, fixed_commitments: [ (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), - (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x1e8ad0c6992851e2d92d368088d79e3326cd63e2a12bb086407dc3dbe0691fb0, 0x0895d1133a5889cf2a52bf5a7ac48502ac399a0088625be4db7aaec534ee8576), (0x1e8ad0c6992851e2d92d368088d79e3326cd63e2a12bb086407dc3dbe0691fb0, 0x0895d1133a5889cf2a52bf5a7ac48502ac399a0088625be4db7aaec534ee8576), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata index 6f2d4066cd..9a349719b1 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata @@ -85,7 +85,7 @@ PinnedVerificationKey { fixed_queries: [ ( Column { - index: 2, + index: 1, column_type: Fixed, }, Rotation( @@ -103,7 +103,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 2, column_type: Fixed, }, Rotation( @@ -159,7 +159,7 @@ PinnedVerificationKey { permutation: Argument { columns: [ Column { - index: 2, + index: 1, column_type: Fixed, }, Column { @@ -430,7 +430,7 @@ PinnedVerificationKey { }, Fixed { query_index: 2, - column_index: 1, + column_index: 2, rotation: Rotation( 0, ), @@ -440,7 +440,7 @@ PinnedVerificationKey { ], constants: [ Column { - index: 2, + index: 1, column_type: Fixed, }, ], @@ -448,8 +448,8 @@ PinnedVerificationKey { }, fixed_commitments: [ (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), - (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x27c2b8ac34f64d4d18eada2b41dc9d8c30409eb866c7e4d539204fadcb696826, 0x0881a9c2e2e4a577b5a951254bd508dedafa5f1c7be905aaf4fbac60971bc9f7), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata index 754fc559c7..9ab4b44532 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata @@ -85,7 +85,7 @@ PinnedVerificationKey { fixed_queries: [ ( Column { - index: 2, + index: 1, column_type: Fixed, }, Rotation( @@ -103,7 +103,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 2, column_type: Fixed, }, Rotation( @@ -159,7 +159,7 @@ PinnedVerificationKey { permutation: Argument { columns: [ Column { - index: 2, + index: 1, column_type: Fixed, }, Column { @@ -430,7 +430,7 @@ PinnedVerificationKey { }, Fixed { query_index: 2, - column_index: 1, + column_index: 2, rotation: Rotation( 0, ), @@ -440,7 +440,7 @@ PinnedVerificationKey { ], constants: [ Column { - index: 2, + index: 1, column_type: Fixed, }, ], @@ -448,8 +448,8 @@ PinnedVerificationKey { }, fixed_commitments: [ (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), - (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x369f0b3422178fecf6e9a4fc7224622da26e8b5c74fb9aca5864c9f72e30bd5c, 0x2d7892875c06c460c9c9f66449103e7b6ef2871fb0a4e39b9af90e938c8e291b), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata index 0a3f3a30fe..88010f3034 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata @@ -85,7 +85,7 @@ PinnedVerificationKey { fixed_queries: [ ( Column { - index: 2, + index: 1, column_type: Fixed, }, Rotation( @@ -103,7 +103,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 2, column_type: Fixed, }, Rotation( @@ -159,7 +159,7 @@ PinnedVerificationKey { permutation: Argument { columns: [ Column { - index: 2, + index: 1, column_type: Fixed, }, Column { @@ -430,7 +430,7 @@ PinnedVerificationKey { }, Fixed { query_index: 2, - column_index: 1, + column_index: 2, rotation: Rotation( 0, ), @@ -440,7 +440,7 @@ PinnedVerificationKey { ], constants: [ Column { - index: 2, + index: 1, column_type: Fixed, }, ], @@ -448,8 +448,8 @@ PinnedVerificationKey { }, fixed_commitments: [ (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), - (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x2ca6650c6fcad471c1c9d29e9115516064a1fe096af3b13821cf1fe7fee088eb, 0x18e61f68d5978b837a3e2295fe7ae7ca672268a519394f41aabd085aadc1221d), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x0980acedb0fd2c02718002125bf80f969175d1f90d1320f9f3d5e2ac584e0212, 0x235c651fefd49e387ef9a6293a428810994974d218c4757ca3f9c0971ae25767), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata index a3969f9746..7e9d891fe0 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata @@ -85,7 +85,7 @@ PinnedVerificationKey { fixed_queries: [ ( Column { - index: 2, + index: 1, column_type: Fixed, }, Rotation( @@ -103,7 +103,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 2, column_type: Fixed, }, Rotation( @@ -159,7 +159,7 @@ PinnedVerificationKey { permutation: Argument { columns: [ Column { - index: 2, + index: 1, column_type: Fixed, }, Column { @@ -430,7 +430,7 @@ PinnedVerificationKey { }, Fixed { query_index: 2, - column_index: 1, + column_index: 2, rotation: Rotation( 0, ), @@ -440,7 +440,7 @@ PinnedVerificationKey { ], constants: [ Column { - index: 2, + index: 1, column_type: Fixed, }, ], @@ -448,8 +448,8 @@ PinnedVerificationKey { }, fixed_commitments: [ (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), - (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x27c2b8ac34f64d4d18eada2b41dc9d8c30409eb866c7e4d539204fadcb696826, 0x0881a9c2e2e4a577b5a951254bd508dedafa5f1c7be905aaf4fbac60971bc9f7), (0x2bbc94ef7b22aebef24f9a4b0cc1831882548b605171366017d45c3e6fd92075, 0x082b801a6e176239943bfb759fb02138f47a5c8cc4aa7fa0af559fde4e3abd97), (0x27c2b8ac34f64d4d18eada2b41dc9d8c30409eb866c7e4d539204fadcb696826, 0x0881a9c2e2e4a577b5a951254bd508dedafa5f1c7be905aaf4fbac60971bc9f7), diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 890d96dec7..28ad379610 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -710,40 +710,12 @@ mod tests { sinsemilla::primitives::K, tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - LookupRangeCheck, LookupRangeCheck45BConfig, LookupRangeCheckConfig, - PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + LookupRangeCheck, PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheckConfig, }, }; use std::{convert::TryInto, marker::PhantomData}; - fn configure_optimized( - meta: &mut ConstraintSystem, - ) -> LookupRangeCheck45BConfig { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - LookupRangeCheck45BConfig::::configure_with_tag( - meta, - running_sum, - table_idx, - table_range_check_tag, - ) - } - - fn configure_non_optimized( - meta: &mut ConstraintSystem, - ) -> LookupRangeCheckConfig { - let running_sum = meta.advice_column(); - let table_idx = meta.lookup_table_column(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - LookupRangeCheckConfig::::configure(meta, running_sum, table_idx) - } - #[derive(Clone, Copy)] struct MyLookupCircuit> { num_words: usize, @@ -751,102 +723,87 @@ mod tests { _lookup_marker: PhantomData, } - fn lookup_synthesize>( - circuit: &MyLookupCircuit, - config: Lookup, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_words * K bits. - let elements_and_expected_final_zs = [ - (F::from((1 << (circuit.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long - (F::from(1 << (circuit.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long - ]; - - fn expected_zs(element: F, num_words: usize) -> Vec { - let chunks = { - element - .to_le_bits() - .iter() - .by_vals() - .take(num_words * K) - .collect::>() - .chunks_exact(K) - .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) - .collect::>() - }; - let expected_zs = { - let inv_two_pow_k = F::from(1 << K).invert().unwrap(); - chunks.iter().fold(vec![element], |mut zs, a_i| { - // z_{i + 1} = (z_i - a_i) / 2^{K} - let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; - zs.push(z); - zs - }) - }; - expected_zs - } - - for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { - let expected_zs = expected_zs::(*element, circuit.num_words); - - let zs = config.witness_check( - layouter.namespace(|| format!("Lookup {:?}", circuit.num_words)), - Value::known(*element), - circuit.num_words, - *strict, - )?; - - assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); - - for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { - z.value().assert_if_known(|z| &&expected_z == z); - } - } - Ok(()) - } - - impl Circuit for MyLookupCircuit> { - type Config = LookupRangeCheckConfig; + impl + std::clone::Clone> Circuit + for MyLookupCircuit + { + type Config = Lookup; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - *self + MyLookupCircuit { + num_words: self.num_words, + _field_marker: PhantomData, + _lookup_marker: PhantomData, + } } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - configure_non_optimized(meta) + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + Lookup::configure(meta, running_sum, table_idx) } fn synthesize( &self, config: Self::Config, - layouter: impl Layouter, + mut layouter: impl Layouter, ) -> Result<(), Error> { - lookup_synthesize(self, config, layouter) - } - } + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_words * K bits. + let elements_and_expected_final_zs = [ + (F::from((1 << (self.num_words * K)) - 1), F::ZERO, true), // a word that is within self.num_words * K bits long + (F::from(1 << (self.num_words * K)), F::ONE, false), // a word that is just over self.num_words * K bits long + ]; + + fn expected_zs( + element: F, + num_words: usize, + ) -> Vec { + let chunks = { + element + .to_le_bits() + .iter() + .by_vals() + .take(num_words * K) + .collect::>() + .chunks_exact(K) + .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) + .collect::>() + }; + let expected_zs = { + let inv_two_pow_k = F::from(1 << K).invert().unwrap(); + chunks.iter().fold(vec![element], |mut zs, a_i| { + // z_{i + 1} = (z_i - a_i) / 2^{K} + let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; + zs.push(z); + zs + }) + }; + expected_zs + } - impl Circuit for MyLookupCircuit> { - type Config = LookupRangeCheck45BConfig; - type FloorPlanner = SimpleFloorPlanner; + for (element, expected_final_z, strict) in elements_and_expected_final_zs.iter() { + let expected_zs = expected_zs::(*element, self.num_words); - fn without_witnesses(&self) -> Self { - *self - } + let zs = config.witness_check( + layouter.namespace(|| format!("Lookup {:?}", self.num_words)), + Value::known(*element), + self.num_words, + *strict, + )?; - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - configure_optimized(meta) - } + assert_eq!(*expected_zs.last().unwrap(), *expected_final_z); - fn synthesize( - &self, - config: Self::Config, - layouter: impl Layouter, - ) -> Result<(), Error> { - lookup_synthesize(self, config, layouter) + for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { + z.value().assert_if_known(|z| &&expected_z == z); + } + } + Ok(()) } } @@ -887,53 +844,10 @@ mod tests { _lookup_marker: PhantomData, } - fn short_range_synthesize>( - circuit: &MyShortRangeCheckCircuit, - config: Lookup, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Load table_idx - config.load(&mut layouter)?; - - // Lookup constraining element to be no longer than num_bits. - config.witness_short_check( - layouter.namespace(|| format!("Lookup {:?} bits", circuit.num_bits)), - circuit.element, - circuit.num_bits, - )?; - - Ok(()) - } - - impl Circuit for MyShortRangeCheckCircuit> { - type Config = LookupRangeCheckConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - MyShortRangeCheckCircuit { - element: Value::unknown(), - num_bits: self.num_bits, - _lookup_marker: PhantomData, - } - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - configure_non_optimized(meta) - } - - fn synthesize( - &self, - config: Self::Config, - layouter: impl Layouter, - ) -> Result<(), Error> { - short_range_synthesize(self, config, layouter) - } - } - - impl Circuit - for MyShortRangeCheckCircuit> + impl + std::clone::Clone> Circuit + for MyShortRangeCheckCircuit { - type Config = LookupRangeCheck45BConfig; + type Config = Lookup; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -945,223 +859,164 @@ mod tests { } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - configure_optimized(meta) + let running_sum = meta.advice_column(); + let table_idx = meta.lookup_table_column(); + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + Lookup::configure(meta, running_sum, table_idx) } fn synthesize( &self, config: Self::Config, - layouter: impl Layouter, + mut layouter: impl Layouter, ) -> Result<(), Error> { - short_range_synthesize(self, config, layouter) + // Load table_idx + config.load(&mut layouter)?; + + // Lookup constraining element to be no longer than num_bits. + config.witness_short_check( + layouter.namespace(|| format!("Lookup {:?} bits", self.num_bits)), + self.element, + self.num_bits, + )?; + + Ok(()) } } - fn test_short_range_check( + fn test_short_range_check( element: pallas::Base, num_bits: usize, - proof_result: Result<(), Vec>, - optimized: bool, + proof_result: &Result<(), Vec>, circuit_name: &str, expected_proof_size: usize, ) { - if optimized { - let circuit: MyShortRangeCheckCircuit = - MyShortRangeCheckCircuit { - element: Value::known(element), - num_bits, - _lookup_marker: PhantomData, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), proof_result); - - if proof_result.is_ok() { - test_against_stored_circuit(circuit, circuit_name, expected_proof_size); - } - } else { - let circuit: MyShortRangeCheckCircuit = - MyShortRangeCheckCircuit { - element: Value::known(element), - num_bits, - _lookup_marker: PhantomData, - }; - let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), proof_result); - - if proof_result.is_ok() { - test_against_stored_circuit(circuit, circuit_name, expected_proof_size); - } + let circuit: MyShortRangeCheckCircuit = MyShortRangeCheckCircuit { + element: Value::known(element), + num_bits, + _lookup_marker: PhantomData, }; + let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), *proof_result); + + if proof_result.is_ok() { + test_against_stored_circuit(circuit, circuit_name, expected_proof_size); + } } #[test] fn short_range_check() { // Edge case: zero bits (case 0) - test_short_range_check( - pallas::Base::ZERO, - 0, - Ok(()), - false, + let element = pallas::Base::ZERO; + let num_bits = 0; + test_short_range_check::( + element, + num_bits, + &Ok(()), "short_range_check_case0", 1888, ); + test_short_range_check::( + element, + num_bits, + &Ok(()), + "short_range_check_4_5_b_case0", + 2048, + ); // Edge case: K bits (case 1) - test_short_range_check( - pallas::Base::from((1 << K) - 1), - K, - Ok(()), - false, + let element = pallas::Base::from((1 << K) - 1); + let num_bits = K; + test_short_range_check::( + element, + num_bits, + &Ok(()), "short_range_check_case1", 1888, ); + test_short_range_check::( + element, + num_bits, + &Ok(()), + "short_range_check_4_5_b_case1", + 2048, + ); // Element within `num_bits` (case 2) - test_short_range_check( - pallas::Base::from((1 << 6) - 1), - 6, - Ok(()), - false, + let element = pallas::Base::from((1 << 6) - 1); + let num_bits = 6; + test_short_range_check::( + element, + num_bits, + &Ok(()), "short_range_check_case2", 1888, ); + test_short_range_check::( + element, + num_bits, + &Ok(()), + "short_range_check_4_5_b_case2", + 2048, + ); // Element larger than `num_bits` but within K bits - test_short_range_check( - pallas::Base::from(1 << 6), - 6, - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }]), - false, + let element = pallas::Base::from(1 << 6); + let num_bits = 6; + let error = Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 1, + }, + }]); + test_short_range_check::( + element, + num_bits, + &error, "not_saved", 0, ); - - // Element larger than K bits - test_short_range_check( - pallas::Base::from(1 << K), - 6, - Err(vec![ - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }, - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }, - ]), - false, + test_short_range_check::( + element, + num_bits, + &error, "not_saved", 0, ); - // Element which is not within `num_bits`, but which has a shifted value within - // num_bits + // Element larger than K bits + let element = pallas::Base::from(1 << K); let num_bits = 6; - let shifted = pallas::Base::from((1 << num_bits) - 1); - // Recall that shifted = element * 2^{K-s} - // => element = shifted * 2^{s-K} - let element = shifted - * pallas::Base::from(1 << (K as u64 - num_bits)) - .invert() - .unwrap(); - test_short_range_check( - element, - num_bits as usize, - Err(vec![VerifyFailure::Lookup { + let error = Err(vec![ + VerifyFailure::Lookup { lookup_index: 0, location: FailureLocation::InRegion { region: (1, "Range check 6 bits").into(), offset: 0, }, - }]), - false, - "not_saved", - 0, - ); - } - - #[test] - fn short_range_check_4_5_b() { - // Edge case: zero bits - test_short_range_check( - pallas::Base::ZERO, - 0, - Ok(()), - true, - "short_range_check_4_5_b_case0", - 2048, - ); - - // Edge case: K bits - test_short_range_check( - pallas::Base::from((1 << K) - 1), - K, - Ok(()), - true, - "short_range_check_4_5_b_case1", - 2048, - ); - - // Element within `num_bits` - test_short_range_check( - pallas::Base::from((1 << 6) - 1), - 6, - Ok(()), - true, - "short_range_check_4_5_b_case2", - 2048, - ); - - // Element larger than `num_bits` but within K bits - test_short_range_check( - pallas::Base::from(1 << 6), - 6, - Err(vec![VerifyFailure::Lookup { + }, + VerifyFailure::Lookup { lookup_index: 0, location: FailureLocation::InRegion { region: (1, "Range check 6 bits").into(), offset: 1, }, - }]), - true, + }, + ]); + test_short_range_check::( + element, + num_bits, + &error, "not_saved", 0, ); - - // Element larger than K bits - test_short_range_check( - pallas::Base::from(1 << K), - 6, - Err(vec![ - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }, - VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 1, - }, - }, - ]), - true, + test_short_range_check::( + element, + num_bits, + &error, "not_saved", 0, ); @@ -1176,43 +1031,48 @@ mod tests { * pallas::Base::from(1 << (K as u64 - num_bits)) .invert() .unwrap(); - test_short_range_check( + let error = Err(vec![VerifyFailure::Lookup { + lookup_index: 0, + location: FailureLocation::InRegion { + region: (1, "Range check 6 bits").into(), + offset: 0, + }, + }]); + test_short_range_check::( element, num_bits as usize, - Err(vec![VerifyFailure::Lookup { - lookup_index: 0, - location: FailureLocation::InRegion { - region: (1, "Range check 6 bits").into(), - offset: 0, - }, - }]), - true, + &error, + "not_saved", + 0, + ); + test_short_range_check::( + element, + num_bits as usize, + &error, "not_saved", 0, ); // Element within 4 bits - test_short_range_check( + test_short_range_check::( pallas::Base::from((1 << 4) - 1), 4, - Ok(()), - true, + &Ok(()), "short_range_check_4_5_b_case3", 2048, ); // Element larger than 5 bits - test_short_range_check( + test_short_range_check::( pallas::Base::from(1 << 5), 5, - Err(vec![VerifyFailure::Lookup { + &Err(vec![VerifyFailure::Lookup { lookup_index: 0, location: FailureLocation::InRegion { region: (1, "Range check 5 bits").into(), offset: 0, }, }]), - true, "not_saved", 0, ); From eda965fc976d7befe9d80281f848ccd85ba1130f Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 27 Jun 2024 10:19:38 +0200 Subject: [PATCH 104/121] Rename some layouter images --- halo2_gadgets/src/sinsemilla.rs | 9 ++++++--- halo2_gadgets/src/sinsemilla/merkle.rs | 9 ++++++--- ...> proof_merkle_with_private_init_chip_4_5_b.bin} | Bin ...oof_sinsemilla_with_private_init_chip_4_5_b.bin} | Bin ...=> vk_merkle_with_private_init_chip_4_5_b.rdata} | 0 ...k_sinsemilla_with_private_init_chip_4_5_b.rdata} | 0 6 files changed, 12 insertions(+), 6 deletions(-) rename halo2_gadgets/src/tests/circuit_data/{proof_merkle_chip_4_5_b.bin => proof_merkle_with_private_init_chip_4_5_b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_sinsemilla_chip_4_5_b.bin => proof_sinsemilla_with_private_init_chip_4_5_b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_merkle_chip_4_5_b.rdata => vk_merkle_with_private_init_chip_4_5_b.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_sinsemilla_chip_4_5_b.rdata => vk_sinsemilla_with_private_init_chip_4_5_b.rdata} (100%) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 277d208497..27a7d573ed 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -1151,7 +1151,7 @@ pub(crate) mod tests { fn test_against_stored_sinsemilla_chip_4_5_b() { let circuit = MyCircuit45B {}; - test_against_stored_circuit(circuit, "sinsemilla_chip_4_5_b", 4672); + test_against_stored_circuit(circuit, "sinsemilla_with_private_init_chip_4_5_b", 4672); } #[cfg(feature = "test-dev-graph")] @@ -1159,8 +1159,11 @@ pub(crate) mod tests { fn print_sinsemilla_chip_4_5_b() { use plotters::prelude::*; - let root = BitMapBackend::new("sinsemilla-hash-4-5-b-layout.png", (1024, 7680)) - .into_drawing_area(); + let root = BitMapBackend::new( + "sinsemilla-with-private-init-4-5-b-layout.png", + (1024, 7680), + ) + .into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 2402fc16ed..59dfb41067 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -624,7 +624,7 @@ pub mod tests { fn test_against_stored_merkle_chip_4_5_b() { let circuit = generate_circuit_4_5_b(); - test_against_stored_circuit(circuit, "merkle_chip_4_5_b", 4160); + test_against_stored_circuit(circuit, "merkle_with_private_init_chip_4_5_b", 4160); } #[cfg(feature = "test-dev-graph")] @@ -632,8 +632,11 @@ pub mod tests { fn print_merkle_chip_4_5_b() { use plotters::prelude::*; - let root = - BitMapBackend::new("merkle-path-4-5-b-layout.png", (1024, 7680)).into_drawing_area(); + let root = BitMapBackend::new( + "merkle-path-with-private-init-4-5-b-layout.png", + (1024, 7680), + ) + .into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); diff --git a/halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b.bin b/halo2_gadgets/src/tests/circuit_data/proof_merkle_with_private_init_chip_4_5_b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_merkle_chip_4_5_b.bin rename to halo2_gadgets/src/tests/circuit_data/proof_merkle_with_private_init_chip_4_5_b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b.bin b/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_with_private_init_chip_4_5_b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_chip_4_5_b.bin rename to halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_with_private_init_chip_4_5_b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/vk_merkle_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_merkle_with_private_init_chip_4_5_b.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_merkle_chip_4_5_b.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_merkle_with_private_init_chip_4_5_b.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5_b.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_chip_4_5_b.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5_b.rdata From 6af9ebf37481b412d6bf8cf6e2a74f74d3d13ccb Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 27 Jun 2024 10:36:16 +0200 Subject: [PATCH 105/121] Update some comments --- halo2_gadgets/src/sinsemilla/chip/generator_table.rs | 10 ++++++++++ halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs index 57ff7e7239..6931655437 100644 --- a/halo2_gadgets/src/sinsemilla/chip/generator_table.rs +++ b/halo2_gadgets/src/sinsemilla/chip/generator_table.rs @@ -81,6 +81,7 @@ impl GeneratorTableConfig { }); } + /// Load the generator table into the circuit. pub fn load( &self, table_range_check_tag: Option, @@ -91,6 +92,15 @@ impl GeneratorTableConfig { None => self.load_without_tag(layouter), } } + + /// Load the generator table into the circuit. + /// + /// | table_idx | table_x | table_y | + /// ------------------------------------------------ + /// | 0 | X(S\[0\]) | Y(S\[0\]) | + /// | 1 | X(S\[1\]) | Y(S\[1\]) | + /// | ... | ... | ... | + /// | 2^10-1 | X(S\[2^10-1\]) | Y(S\[2^10-1\]) | pub fn load_without_tag( &self, layouter: &mut impl Layouter, diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 208002f9b2..b713f2eb00 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -17,7 +17,7 @@ use pasta_curves::{arithmetic::CurveAffine, pallas}; use std::ops::Deref; -/// Define an enum that can hold either a public or a private ECC Point +/// `EccPointQ` can hold either a public or a private ECC Point #[derive(Debug, Clone)] pub enum EccPointQ<'a> { PublicPoint(pallas::Affine), From 2021f5eea4a4c5d31d82552c0965dc01acbfe86a Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 1 Jul 2024 14:20:35 +0200 Subject: [PATCH 106/121] Simplify Sinsemilla/Merkle chips thanks to enable_hash_from_private_point variable We add enable_hash_from_private_point into SinsemillaChip in order to put together SinsemillaChip and SinsemillaWithPrivateInitChip. If enable_hash_from_private_point is set, it is possible to hash from a private point. Otherwise, it is not allowed. That allows also to put together MerkleChip and MerkleWithPrivateInitChip. --- halo2_gadgets/src/sinsemilla.rs | 820 +++++++----------- halo2_gadgets/src/sinsemilla/chip.rs | 233 +---- .../src/sinsemilla/chip/hash_to_point.rs | 248 ++---- halo2_gadgets/src/sinsemilla/merkle.rs | 37 +- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 201 +---- ...insemilla_with_private_init_chip_4_5_b.bin | Bin 4672 -> 4672 bytes ...semilla_with_private_init_chip_4_5_b.rdata | 66 +- halo2_proofs/src/plonk/error.rs | 8 +- 8 files changed, 489 insertions(+), 1124 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 27a7d573ed..76581cb9ae 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -88,6 +88,20 @@ pub trait SinsemillaInstructions Result<(Self::NonIdentityPoint, Vec), Error>; + /// Hashes a message to an ECC curve point. + /// This returns both the resulting point, as well as the message + /// decomposition in the form of intermediate values in a cumulative + /// sum. + /// The initial point `Q` is a private point. + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn hash_to_point_with_private_init( + &self, + layouter: impl Layouter, + Q: &Self::NonIdentityPoint, + message: Self::Message, + ) -> Result<(Self::NonIdentityPoint, Vec), Error>; + /// Extracts the x-coordinate of the output of a Sinsemilla hash. fn extract(point: &Self::NonIdentityPoint) -> Self::X; } @@ -329,6 +343,21 @@ where .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) } + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + /// Evaluate the Sinsemilla hash of `message` from the private initial point `Q`. + pub fn hash_to_point_with_private_init( + &self, + layouter: impl Layouter, + Q: &>::NonIdentityPoint, + message: Message, + ) -> Result<(ecc::NonIdentityPoint, Vec), Error> { + assert_eq!(self.sinsemilla_chip, message.chip); + self.sinsemilla_chip + .hash_to_point_with_private_init(layouter, Q, message.inner) + .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) + } + /// $\mathsf{SinsemillaHash}$ from [§ 5.4.1.9][concretesinsemillahash]. /// /// [concretesinsemillahash]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash @@ -449,89 +478,6 @@ where let (p, zs) = self.commit(layouter.namespace(|| "commit"), message, r)?; Ok((p.extract_p(), zs)) } -} - -/// `SinsemillaWithPrivateInitInstructions` provides a method to hash a message from an initial -/// private point. -pub trait SinsemillaWithPrivateInitInstructions< - C: CurveAffine, - const K: usize, - const MAX_WORDS: usize, ->: SinsemillaInstructions -{ - /// Hashes a message to an ECC curve point. - /// This returns both the resulting point, as well as the message - /// decomposition in the form of intermediate values in a cumulative - /// sum. - /// The initial point `Q` is a private point. - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( - &self, - layouter: impl Layouter, - Q: &Self::NonIdentityPoint, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec), Error>; -} - -impl -HashDomain - where - SinsemillaChip: SinsemillaWithPrivateInitInstructions + Clone + Debug + Eq, - EccChip: EccInstructions< - C, - NonIdentityPoint = >::NonIdentityPoint, - FixedPoints = >::FixedPoints, - > + Clone - + Debug - + Eq, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - /// Evaluate the Sinsemilla hash of `message` from the private initial point `Q`. - pub fn hash_to_point_with_private_init( - &self, - layouter: impl Layouter, - Q: &>::NonIdentityPoint, - message: Message, - ) -> Result<(ecc::NonIdentityPoint, Vec), Error> { - assert_eq!(self.sinsemilla_chip, message.chip); - self.sinsemilla_chip - .hash_to_point_with_private_init(layouter, Q, message.inner) - .map(|(point, zs)| (ecc::NonIdentityPoint::from_inner(self.ecc_chip.clone(), point), zs)) - } - -} - -impl -CommitDomain - where - SinsemillaChip: SinsemillaWithPrivateInitInstructions + Clone + Debug + Eq, - EccChip: EccInstructions< - C, - NonIdentityPoint = >::NonIdentityPoint, - FixedPoints = >::FixedPoints, - > + Clone - + Debug - + Eq, -{ - #[allow(clippy::type_complexity)] - /// Evaluates the Sinsemilla hash of `message` from the public initial point `Q` stored - /// into `CommitDomain`. - pub fn hash( - &self, - layouter: impl Layouter, - message: Message, - ) -> Result< - ( - ecc::NonIdentityPoint, - Vec, - ), - Error, - > { - assert_eq!(self.M.sinsemilla_chip, message.chip); - self.M.hash_to_point(layouter, message) - } #[allow(non_snake_case)] #[allow(clippy::type_complexity)] @@ -593,14 +539,10 @@ pub(crate) mod tests { tests::{FullWidth, TestFixedBases}, NonIdentityPoint, ScalarFixed, }, - sinsemilla::{ - chip::SinsemillaWithPrivateInitChip, - primitives::{self as sinsemilla, K}, - }, + sinsemilla::primitives::{self as sinsemilla, K}, tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - LookupRangeCheck, LookupRangeCheck45BConfig, PallasLookupRangeCheck45BConfig, - PallasLookupRangeCheckConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, }, }; @@ -609,6 +551,7 @@ pub(crate) mod tests { use pasta_curves::pallas; use std::convert::TryInto; + use std::marker::PhantomData; pub(crate) const PERSONALIZATION: &str = "MerkleCRH"; @@ -642,247 +585,260 @@ pub(crate) mod tests { } } - struct MyCircuit {} + struct MyCircuit { + _lookup_marker: PhantomData, + } + + type MyConfig = ( + EccConfig, + SinsemillaConfig, + SinsemillaConfig, + ); + + fn configure( + meta: &mut ConstraintSystem, + enable_hash_from_private_point: bool, + ) -> MyConfig { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + let table_idx = meta.lookup_table_column(); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + // Fixed columns for the Sinsemilla generator lookup table + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); - impl Circuit for MyCircuit { - #[allow(clippy::type_complexity)] - type Config = ( - EccConfig, - SinsemillaConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - PallasLookupRangeCheckConfig, - >, - SinsemillaConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - PallasLookupRangeCheckConfig, - >, + let range_check = Lookup::configure(meta, advices[9], table_idx); + + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, ); + + let config1 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + lagrange_coeffs[0], + lookup, + range_check, + enable_hash_from_private_point, + ); + let config2 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + lagrange_coeffs[1], + lookup, + range_check, + enable_hash_from_private_point, + ); + (ecc_config, config1, config2) + } + + fn synthesize( + config: MyConfig, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let rng = OsRng; + + let ecc_chip = EccChip::construct(config.0); + + // The two `SinsemillaChip`s share the same lookup table. + SinsemillaChip::::load( + config.1.clone(), + &mut layouter, + )?; + + // This MerkleCRH example is purely for illustrative purposes. + // It is not an implementation of the Orchard protocol spec. + { + let chip1 = SinsemillaChip::construct(config.1); + + let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); + + // Layer 31, l = MERKLE_DEPTH - 1 - layer = 0 + let l_bitstring = vec![Value::known(false); K]; + let l = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "l"), + &l_bitstring, + )?; + + // Left leaf + let left_bitstring: Vec> = (0..250) + .map(|_| Value::known(rand::random::())) + .collect(); + let left = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "left"), + &left_bitstring, + )?; + + // Right leaf + let right_bitstring: Vec> = (0..250) + .map(|_| Value::known(rand::random::())) + .collect(); + let right = MessagePiece::from_bitstring( + chip1.clone(), + layouter.namespace(|| "right"), + &right_bitstring, + )?; + + let l_bitstring: Value> = l_bitstring.into_iter().collect(); + let left_bitstring: Value> = left_bitstring.into_iter().collect(); + let right_bitstring: Value> = right_bitstring.into_iter().collect(); + + // Witness expected parent + let expected_parent = { + let expected_parent = l_bitstring.zip(left_bitstring.zip(right_bitstring)).map( + |(l, (left, right))| { + let merkle_crh = sinsemilla::HashDomain::from_Q((*Q).into()); + let point = merkle_crh + .hash_to_point( + l.into_iter() + .chain(left.into_iter()) + .chain(right.into_iter()), + ) + .unwrap(); + point.to_affine() + }, + ); + + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "Witness expected parent"), + expected_parent, + )? + }; + + // Parent + let (parent, _) = { + let message = Message::from_pieces(chip1, vec![l, left, right]); + merkle_crh.hash_to_point(layouter.namespace(|| "parent"), message)? + }; + + parent.constrain_equal( + layouter.namespace(|| "parent == expected parent"), + &expected_parent, + )?; + } + + { + let chip2 = SinsemillaChip::construct(config.2); + + let test_commit = CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); + let r_val = pallas::Scalar::random(rng); + let message: Vec> = (0..500) + .map(|_| Value::known(rand::random::())) + .collect(); + + let (result, _) = { + let r = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "r"), + Value::known(r_val), + )?; + let message = Message::from_bitstring( + chip2, + layouter.namespace(|| "witness message"), + message.clone(), + )?; + test_commit.commit(layouter.namespace(|| "commit"), message, r)? + }; + + // Witness expected result. + let expected_result = { + let message: Value> = message.into_iter().collect(); + let expected_result = message.map(|message| { + let domain = sinsemilla::CommitDomain::new(PERSONALIZATION); + let point = domain.commit(message.into_iter(), &r_val).unwrap(); + point.to_affine() + }); + + NonIdentityPoint::new( + ecc_chip, + layouter.namespace(|| "Witness expected result"), + expected_result, + )? + }; + + result.constrain_equal( + layouter.namespace(|| "result == expected result"), + &expected_result, + ) + } + } + + impl Circuit for MyCircuit { + #[allow(clippy::type_complexity)] + type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit {} + MyCircuit { + _lookup_marker: PhantomData, + } } #[allow(non_snake_case)] fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let table_idx = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - // Fixed columns for the Sinsemilla generator lookup table - let lookup = ( - table_idx, - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - - let range_check = PallasLookupRangeCheckConfig::configure(meta, advices[9], table_idx); - - let ecc_config = EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ); - - let config1 = SinsemillaChip::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - lagrange_coeffs[0], - lookup, - range_check, - ); - let config2 = SinsemillaChip::configure( - meta, - advices[5..].try_into().unwrap(), - advices[7], - lagrange_coeffs[1], - lookup, - range_check, - ); - (ecc_config, config1, config2) + configure::(meta, false) } fn synthesize( &self, config: Self::Config, - mut layouter: impl Layouter, + layouter: impl Layouter, ) -> Result<(), Error> { - let rng = OsRng; - - let ecc_chip = EccChip::construct(config.0); - - // The two `SinsemillaChip`s share the same lookup table. - SinsemillaChip::< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - PallasLookupRangeCheckConfig, - >::load(config.1.clone(), &mut layouter)?; - - // This MerkleCRH example is purely for illustrative purposes. - // It is not an implementation of the Orchard protocol spec. - { - let chip1 = SinsemillaChip::construct(config.1); - - let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); - - // Layer 31, l = MERKLE_DEPTH - 1 - layer = 0 - let l_bitstring = vec![Value::known(false); K]; - let l = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "l"), - &l_bitstring, - )?; - - // Left leaf - let left_bitstring: Vec> = (0..250) - .map(|_| Value::known(rand::random::())) - .collect(); - let left = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "left"), - &left_bitstring, - )?; - - // Right leaf - let right_bitstring: Vec> = (0..250) - .map(|_| Value::known(rand::random::())) - .collect(); - let right = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "right"), - &right_bitstring, - )?; - - let l_bitstring: Value> = l_bitstring.into_iter().collect(); - let left_bitstring: Value> = left_bitstring.into_iter().collect(); - let right_bitstring: Value> = right_bitstring.into_iter().collect(); - - // Witness expected parent - let expected_parent = { - let expected_parent = l_bitstring.zip(left_bitstring.zip(right_bitstring)).map( - |(l, (left, right))| { - let merkle_crh = sinsemilla::HashDomain::from_Q((*Q).into()); - let point = merkle_crh - .hash_to_point( - l.into_iter() - .chain(left.into_iter()) - .chain(right.into_iter()), - ) - .unwrap(); - point.to_affine() - }, - ); - - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "Witness expected parent"), - expected_parent, - )? - }; - - // Parent - let (parent, _) = { - let message = Message::from_pieces(chip1, vec![l, left, right]); - merkle_crh.hash_to_point(layouter.namespace(|| "parent"), message)? - }; - - parent.constrain_equal( - layouter.namespace(|| "parent == expected parent"), - &expected_parent, - )?; - } - - { - let chip2 = SinsemillaChip::construct(config.2); - - let test_commit = - CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); - let r_val = pallas::Scalar::random(rng); - let message: Vec> = (0..500) - .map(|_| Value::known(rand::random::())) - .collect(); - - let (result, _) = { - let r = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "r"), - Value::known(r_val), - )?; - let message = Message::from_bitstring( - chip2, - layouter.namespace(|| "witness message"), - message.clone(), - )?; - test_commit.commit(layouter.namespace(|| "commit"), message, r)? - }; - - // Witness expected result. - let expected_result = { - let message: Value> = message.into_iter().collect(); - let expected_result = message.map(|message| { - let domain = sinsemilla::CommitDomain::new(PERSONALIZATION); - let point = domain.commit(message.into_iter(), &r_val).unwrap(); - point.to_affine() - }); - - NonIdentityPoint::new( - ecc_chip, - layouter.namespace(|| "Witness expected result"), - expected_result, - )? - }; - - result.constrain_equal( - layouter.namespace(|| "result == expected result"), - &expected_result, - ) - } + synthesize(config, layouter) } } #[test] fn sinsemilla_chip() { let k = 11; - let circuit = MyCircuit {}; + let circuit: MyCircuit = MyCircuit { + _lookup_marker: PhantomData, + }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] fn test_against_stored_sinsemilla_chip() { - let circuit = MyCircuit {}; + let circuit: MyCircuit = MyCircuit { + _lookup_marker: PhantomData, + }; test_against_stored_circuit(circuit, "sinsemilla_chip", 4576); } @@ -896,267 +852,68 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit {}; + let circuit: MyCircuit = MyCircuit { + _lookup_marker: PhantomData, + }; halo2_proofs::dev::CircuitLayout::default() .render(11, &circuit, &root) .unwrap(); } - struct MyCircuit45B {} + struct MyCircuitWithHashFromPrivatePoint { + _lookup_marker: PhantomData, + } - impl Circuit for MyCircuit45B { + impl Circuit + for MyCircuitWithHashFromPrivatePoint + { #[allow(clippy::type_complexity)] - type Config = ( - EccConfig< - TestFixedBases, - LookupRangeCheck45BConfig, - >, - SinsemillaConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheck45BConfig, - >, - SinsemillaConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheck45BConfig, - >, - ); + type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit45B {} + MyCircuitWithHashFromPrivatePoint { + _lookup_marker: PhantomData, + } } #[allow(non_snake_case)] fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - // Fixed columns for the Sinsemilla generator lookup table - let lookup = ( - table_idx, - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - - let range_check = LookupRangeCheck45BConfig::configure_with_tag( - meta, - advices[9], - table_idx, - table_range_check_tag, - ); - - let ecc_config = EccChip::< - TestFixedBases, - LookupRangeCheck45BConfig, - >::configure(meta, advices, lagrange_coeffs, range_check); - - let config1 = SinsemillaWithPrivateInitChip::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - lagrange_coeffs[0], - lookup, - range_check, - ); - let config2 = SinsemillaWithPrivateInitChip::configure( - meta, - advices[5..].try_into().unwrap(), - advices[7], - lagrange_coeffs[1], - lookup, - range_check, - ); - (ecc_config, config1, config2) + configure::(meta, true) } fn synthesize( &self, config: Self::Config, - mut layouter: impl Layouter, + layouter: impl Layouter, ) -> Result<(), Error> { - let rng = OsRng; - - let ecc_chip = EccChip::construct(config.0); - - // The two `SinsemillaChip`s share the same lookup table. - SinsemillaWithPrivateInitChip::< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - PallasLookupRangeCheck45BConfig, - >::load(config.1.clone(), &mut layouter)?; - - // This MerkleCRH example is purely for illustrative purposes. - // It is not an implementation of the Orchard protocol spec. - { - let chip1 = SinsemillaWithPrivateInitChip::construct(config.1); - - let merkle_crh = HashDomain::new(chip1.clone(), ecc_chip.clone(), &TestHashDomain); - - // Layer 31, l = MERKLE_DEPTH - 1 - layer = 0 - let l_bitstring = vec![Value::known(false); K]; - let l = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "l"), - &l_bitstring, - )?; - - // Left leaf - let left_bitstring: Vec> = (0..250) - .map(|_| Value::known(rand::random::())) - .collect(); - let left = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "left"), - &left_bitstring, - )?; - - // Right leaf - let right_bitstring: Vec> = (0..250) - .map(|_| Value::known(rand::random::())) - .collect(); - let right = MessagePiece::from_bitstring( - chip1.clone(), - layouter.namespace(|| "right"), - &right_bitstring, - )?; - - let l_bitstring: Value> = l_bitstring.into_iter().collect(); - let left_bitstring: Value> = left_bitstring.into_iter().collect(); - let right_bitstring: Value> = right_bitstring.into_iter().collect(); - - // Witness expected parent - let expected_parent = { - let expected_parent = l_bitstring.zip(left_bitstring.zip(right_bitstring)).map( - |(l, (left, right))| { - let merkle_crh = sinsemilla::HashDomain::from_Q((*Q).into()); - let point = merkle_crh - .hash_to_point( - l.into_iter() - .chain(left.into_iter()) - .chain(right.into_iter()), - ) - .unwrap(); - point.to_affine() - }, - ); - - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "Witness expected parent"), - expected_parent, - )? - }; - - // Parent - let (parent, _) = { - let message = Message::from_pieces(chip1, vec![l, left, right]); - merkle_crh.hash_to_point(layouter.namespace(|| "parent"), message)? - }; - - parent.constrain_equal( - layouter.namespace(|| "parent == expected parent"), - &expected_parent, - )?; - } - - { - let chip2 = SinsemillaWithPrivateInitChip::construct(config.2); - - let test_commit = - CommitDomain::new(chip2.clone(), ecc_chip.clone(), &TestCommitDomain); - let r_val = pallas::Scalar::random(rng); - let message: Vec> = (0..500) - .map(|_| Value::known(rand::random::())) - .collect(); - - let (result, _) = { - let r = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "r"), - Value::known(r_val), - )?; - let message = Message::from_bitstring( - chip2, - layouter.namespace(|| "witness message"), - message.clone(), - )?; - test_commit.commit(layouter.namespace(|| "commit"), message, r)? - }; - - // Witness expected result. - let expected_result = { - let message: Value> = message.into_iter().collect(); - let expected_result = message.map(|message| { - let domain = sinsemilla::CommitDomain::new(PERSONALIZATION); - let point = domain.commit(message.into_iter(), &r_val).unwrap(); - point.to_affine() - }); - - NonIdentityPoint::new( - ecc_chip, - layouter.namespace(|| "Witness expected result"), - expected_result, - )? - }; - - result.constrain_equal( - layouter.namespace(|| "result == expected result"), - &expected_result, - ) - } + synthesize(config, layouter) } } #[test] - fn sinsemilla_chip_4_5_b() { + fn sinsemilla_with_hash_from_private_point_chip_4_5_b() { let k = 11; - let circuit = MyCircuit45B {}; + let circuit: MyCircuitWithHashFromPrivatePoint = + MyCircuitWithHashFromPrivatePoint { + _lookup_marker: PhantomData, + }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] - fn test_against_stored_sinsemilla_chip_4_5_b() { - let circuit = MyCircuit45B {}; - + fn test_against_stored_sinsemilla_with_hash_from_private_point_chip_4_5_b() { + let circuit: MyCircuitWithHashFromPrivatePoint = + MyCircuitWithHashFromPrivatePoint { + _lookup_marker: PhantomData, + }; test_against_stored_circuit(circuit, "sinsemilla_with_private_init_chip_4_5_b", 4672); } #[cfg(feature = "test-dev-graph")] #[test] - fn print_sinsemilla_chip_4_5_b() { + fn print_sinsemilla_with_hash_from_private_point_chip_4_5_b() { use plotters::prelude::*; let root = BitMapBackend::new( @@ -1167,7 +924,10 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit45B {}; + let circuit: MyCircuitWithHashFromPrivatePoint = + MyCircuitWithHashFromPrivatePoint { + _lookup_marker: PhantomData, + }; halo2_proofs::dev::CircuitLayout::default() .render(11, &circuit, &root) .unwrap(); diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index accd50d861..7af7924891 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -3,7 +3,6 @@ use super::{ message::{Message, MessagePiece}, primitives as sinsemilla, CommitDomains, HashDomains, SinsemillaInstructions, - SinsemillaWithPrivateInitInstructions, }; use crate::{ ecc::{ @@ -61,6 +60,8 @@ where pub(super) generator_table: GeneratorTableConfig, /// An advice column configured to perform lookup range checks. lookup_config: Lookup, + + enable_hash_from_private_point: bool, _marker: PhantomData<(Hash, Commit, F)>, } @@ -163,6 +164,7 @@ where fixed_y_q: Column, lookup: (TableColumn, TableColumn, TableColumn), range_check: Lookup, + enable_hash_from_private_point: bool, ) -> >::Config { // create SinsemillaConfig let config = Self::create_config( @@ -172,9 +174,14 @@ where fixed_y_q, lookup, range_check, + enable_hash_from_private_point, ); - Self::create_initial_y_q_gate(meta, &config); + if enable_hash_from_private_point { + Self::create_initial_private_y_q_gate(meta, &config); + } else { + Self::create_initial_public_y_q_gate(meta, &config); + } Self::create_sinsemilla_gate(meta, &config); @@ -188,6 +195,7 @@ where fixed_y_q: Column, lookup: (TableColumn, TableColumn, TableColumn), range_check: Lookup, + enable_hash_from_private_point: bool, ) -> >::Config { // Enable equality on all advice columns for advice in advices.iter() { @@ -213,6 +221,7 @@ where table_y: lookup.2, }, lookup_config: range_check, + enable_hash_from_private_point, _marker: PhantomData, }; @@ -224,7 +233,7 @@ where /// Assign y_q to a fixed column #[allow(non_snake_case)] - fn create_initial_y_q_gate( + fn create_initial_public_y_q_gate( meta: &mut ConstraintSystem, config: &SinsemillaConfig, ) { @@ -251,6 +260,35 @@ where }); } + /// Assign y_q to an advice column + #[allow(non_snake_case)] + fn create_initial_private_y_q_gate( + meta: &mut ConstraintSystem, + config: &SinsemillaConfig, + ) { + let two = pallas::Base::from(2); + + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) + let Y_A = |meta: &mut VirtualCells, rotation| { + config.double_and_add.Y_A(meta, rotation) + }; + + // Check that the initial x_A, x_P, lambda_1, lambda_2 are consistent with y_Q. + // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial + meta.create_gate("Initial y_Q", |meta| { + let q_s4 = meta.query_selector(config.q_sinsemilla4); + let y_q = meta.query_advice(config.double_and_add.x_p, Rotation::prev()); + + // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) + let Y_A_cur = Y_A(meta, Rotation::cur()); + + // 2 * y_q - Y_{A,0} = 0 + let init_y_q_check = y_q * two - Y_A_cur; + + Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) + }); + } + #[allow(non_snake_case)] pub(crate) fn create_sinsemilla_gate( meta: &mut ConstraintSystem, @@ -376,171 +414,21 @@ where ) } - fn extract(point: &Self::NonIdentityPoint) -> Self::X { - point.x() - } -} - -/// 'SinsemillaWithPrivateInitChip' is an extended version of the SinsemillaChip. -/// It implements a method for hashing from a private initialization point. -#[derive(Eq, PartialEq, Clone, Debug)] -pub struct SinsemillaWithPrivateInitChip -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - inner: SinsemillaChip, -} - -impl Chip - for SinsemillaWithPrivateInitChip -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - type Config = SinsemillaConfig; - type Loaded = (); - - fn config(&self) -> &Self::Config { - self.inner.config() - } - - fn loaded(&self) -> &Self::Loaded { - &() - } -} - -impl SinsemillaWithPrivateInitChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - /// Reconstructs this chip from the given config. - pub fn construct(config: >::Config) -> Self { - Self { - inner: SinsemillaChip::::construct(config), - } - } - - /// Loads the lookup table required by this chip into the circuit. - pub fn load( - config: SinsemillaConfig, - layouter: &mut impl Layouter, - ) -> Result<>::Loaded, Error> { - // Load the lookup table. - SinsemillaChip::::load(config, layouter) - } - - /// Assign y_q to an advice column - #[allow(non_snake_case)] - fn create_initial_y_q_gate( - meta: &mut ConstraintSystem, - config: &SinsemillaConfig, - ) { - let two = pallas::Base::from(2); - - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) - let Y_A = |meta: &mut VirtualCells, rotation| { - config.double_and_add.Y_A(meta, rotation) - }; - - // Check that the initial x_A, x_P, lambda_1, lambda_2 are consistent with y_Q. - // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial - meta.create_gate("Initial y_Q", |meta| { - let q_s4 = meta.query_selector(config.q_sinsemilla4); - let y_q = meta.query_advice(config.double_and_add.x_p, Rotation::prev()); - - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) - let Y_A_cur = Y_A(meta, Rotation::cur()); - - // 2 * y_q - Y_{A,0} = 0 - let init_y_q_check = y_q * two - Y_A_cur; - - Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) - }); - } - - /// # Side-effects - /// - /// All columns in `advices` and will be equality-enabled. - #[allow(clippy::too_many_arguments)] - #[allow(non_snake_case)] - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - lookup: (TableColumn, TableColumn, TableColumn), - range_check: Lookup, - ) -> >::Config { - let config = SinsemillaChip::::create_config( - meta, - advices, - witness_pieces, - fixed_y_q, - lookup, - range_check, - ); - - Self::create_initial_y_q_gate(meta, &config); - - SinsemillaChip::::create_sinsemilla_gate(meta, &config); - - config - } -} - -// Implement `SinsemillaInstructions` for `SinsemillaWithPrivateInitChip` -impl - SinsemillaInstructions - for SinsemillaWithPrivateInitChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - type CellValue = AssignedCell; - - type Message = Message; - type MessagePiece = MessagePiece; - - type RunningSum = Vec; - - type X = AssignedCell; - type NonIdentityPoint = NonIdentityEccPoint; - type FixedPoints = F; - - type HashDomains = Hash; - type CommitDomains = Commit; - - fn witness_message_piece( - &self, - layouter: impl Layouter, - field_elem: Value, - num_words: usize, - ) -> Result { - self.inner - .witness_message_piece(layouter, field_elem, num_words) - } - #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - fn hash_to_point( + fn hash_to_point_with_private_init( &self, mut layouter: impl Layouter, - Q: pallas::Affine, + Q: &Self::NonIdentityPoint, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec), Error> { + if !self.config().enable_hash_from_private_point { + return Err(Error::HashFromPrivatePoint); + } + layouter.assign_region( || "hash_to_point", - |mut region| self.hash_message(&mut region, Q, &message), + |mut region| self.hash_message_with_private_init(&mut region, Q, &message), ) } @@ -548,28 +436,3 @@ where point.x() } } - -// Implement `SinsemillaWithPrivateInitInstructions` for `SinsemillaWithPrivateInitChip` -impl - SinsemillaWithPrivateInitInstructions - for SinsemillaWithPrivateInitChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn hash_to_point_with_private_init( - &self, - mut layouter: impl Layouter, - Q: &Self::NonIdentityPoint, - message: Self::Message, - ) -> Result<(Self::NonIdentityPoint, Vec), Error> { - layouter.assign_region( - || "hash_to_point", - |mut region| self.hash_message_with_private_init(&mut region, Q, &message), - ) - } -} diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index b713f2eb00..03d7d6e82d 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -1,7 +1,7 @@ use super::super::{CommitDomains, HashDomains, SinsemillaInstructions}; use crate::{ ecc::FixedPoints, - sinsemilla::chip::{NonIdentityEccPoint, SinsemillaChip, SinsemillaWithPrivateInitChip}, + sinsemilla::chip::{NonIdentityEccPoint, SinsemillaChip}, sinsemilla::primitives::{self as sinsemilla, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}, utilities::lookup_range_check::PallasLookupRangeCheck, }; @@ -57,6 +57,36 @@ where self.check_hash_result(EccPointQ::PublicPoint(Q), message, x_a, y_a, zs_sum) } + /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + pub(super) fn hash_message_with_private_init( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + message: &>::Message, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + if !self.config().enable_hash_from_private_point { + return Err(Error::HashFromPrivatePoint); + } + + let (offset, x_a, y_a) = self.private_initialization(region, Q)?; + + let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; + + self.check_hash_result(EccPointQ::PrivatePoint(Q), message, x_a, y_a, zs_sum) + } + #[allow(unused_variables)] #[allow(non_snake_case)] #[allow(clippy::type_complexity)] @@ -145,7 +175,7 @@ where Q: pallas::Affine, ) -> Result<(usize, X, Y), Error> { let config = self.config().clone(); - let offset = 0; + let mut offset = 0; // Get the `x`- and `y`-coordinates of the starting `Q` base. let x_q = *Q.coordinates().unwrap().x(); @@ -153,7 +183,19 @@ where // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 // selector. - let y_a: Y = { + let y_a: Y = if config.enable_hash_from_private_point { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, 1)?; + let y_a: AssignedCell, pallas::Base> = region + .assign_advice_from_constant( + || "fixed y_q", + config.double_and_add.x_p, + offset, + y_q.into(), + )?; + offset += 1; + y_a.value_field().into() + } else { // Enable `q_sinsemilla4` on the first row. config.q_sinsemilla4.enable(region, offset)?; region.assign_fixed( @@ -181,6 +223,46 @@ where Ok((offset, x_a, y_a)) } + #[allow(non_snake_case)] + /// Assign the coordinates of the initial private point `Q` + /// + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | + fn private_initialization( + &self, + region: &mut Region<'_, pallas::Base>, + Q: &NonIdentityEccPoint, + ) -> Result<(usize, X, Y), Error> { + let config = self.config().clone(); + + if !config.enable_hash_from_private_point { + return Err(Error::HashFromPrivatePoint); + } + + // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, + // x_p, y_Q using the q_sinsemilla4 selector. + let y_a: Y = { + // Enable `q_sinsemilla4` on the second row. + config.q_sinsemilla4.enable(region, 1)?; + let q_y: AssignedCell, pallas::Base> = Q.y().into(); + let y_a: AssignedCell, pallas::Base> = + q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, 0)?; + + y_a.value_field().into() + }; + + let x_a: X = { + let q_x: AssignedCell, pallas::Base> = Q.x().into(); + let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, 1)?; + + x_a.into() + }; + + Ok((1, x_a, y_a)) + } + #[allow(clippy::type_complexity)] /// Hash `message` from the initial point `Q`. fn hash_all_pieces( @@ -460,166 +542,6 @@ where } } -impl SinsemillaWithPrivateInitChip -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(super) fn hash_message( - &self, - region: &mut Region<'_, pallas::Base>, - Q: pallas::Affine, - message: &>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - // Coordinates of the initial point `Q` are assigned to advice columns - let (offset, x_a, y_a) = self.public_initialization(region, Q)?; - - let (x_a, y_a, zs_sum) = - SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; - - SinsemillaChip::check_hash_result( - &self.inner, - EccPointQ::PublicPoint(Q), - message, - x_a, - y_a, - zs_sum, - ) - } - /// [Specification](https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial). - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - pub(super) fn hash_message_with_private_init( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - message: &>::Message, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - let (offset, x_a, y_a) = self.private_initialization(region, Q)?; - - let (x_a, y_a, zs_sum) = - SinsemillaChip::hash_all_pieces(&self.inner, region, offset, message, x_a, y_a)?; - - SinsemillaChip::check_hash_result( - &self.inner, - EccPointQ::PrivatePoint(Q), - message, - x_a, - y_a, - zs_sum, - ) - } - - #[allow(non_snake_case)] - /// Assign the coordinates of the initial public point `Q` to advice columns - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn public_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: pallas::Affine, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - - // Get the `x`- and `y`-coordinates of the starting `Q` base. - let x_q = *Q.coordinates().unwrap().x(); - let y_q = *Q.coordinates().unwrap().y(); - - // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 - // selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, 1)?; - let y_a: AssignedCell, pallas::Base> = region - .assign_advice_from_constant( - || "fixed y_q", - config.double_and_add.x_p, - 0, - y_q.into(), - )?; - - y_a.value_field().into() - }; - - // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. - let x_a: X = { - let x_a = region.assign_advice_from_constant( - || "fixed x_q", - config.double_and_add.x_a, - 1, - x_q.into(), - )?; - - x_a.into() - }; - - Ok((1, x_a, y_a)) - } - - #[allow(non_snake_case)] - /// Assign the coordinates of the initial private point `Q` - /// - /// | offset | x_A | x_P | q_sinsemilla4 | - /// -------------------------------------- - /// | 0 | | y_Q | | - /// | 1 | x_Q | | 1 | - fn private_initialization( - &self, - region: &mut Region<'_, pallas::Base>, - Q: &NonIdentityEccPoint, - ) -> Result<(usize, X, Y), Error> { - let config = self.config().clone(); - - // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, - // x_p, y_Q using the q_sinsemilla4 selector. - let y_a: Y = { - // Enable `q_sinsemilla4` on the second row. - config.q_sinsemilla4.enable(region, 1)?; - let q_y: AssignedCell, pallas::Base> = Q.y().into(); - let y_a: AssignedCell, pallas::Base> = - q_y.copy_advice(|| "fixed y_q", region, config.double_and_add.x_p, 0)?; - - y_a.value_field().into() - }; - - let x_a: X = { - let q_x: AssignedCell, pallas::Base> = Q.x().into(); - let x_a = q_x.copy_advice(|| "fixed x_q", region, config.double_and_add.x_a, 1)?; - - x_a.into() - }; - - Ok((1, x_a, y_a)) - } -} - /// The x-coordinate of the accumulator in a Sinsemilla hash instance. struct X(AssignedCell, F>); diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 59dfb41067..c0b130290d 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -180,8 +180,7 @@ pub mod tests { use crate::{ ecc::tests::TestFixedBases, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaWithPrivateInitChip}, - merkle::chip::MerkleWithPrivateInitChip, + chip::SinsemillaChip, tests::{TestCommitDomain, TestHashDomain}, HashDomains, }, @@ -276,6 +275,7 @@ pub mod tests { fixed_y_q_1, lookup, range_check, + false, ); let config1 = MerkleChip::configure(meta, sinsemilla_config_1); @@ -286,6 +286,7 @@ pub mod tests { fixed_y_q_2, lookup, range_check, + false, ); let config2 = MerkleChip::configure(meta, sinsemilla_config_2); @@ -427,13 +428,13 @@ pub mod tests { } #[derive(Default)] - struct MyCircuit45B { + struct MyCircuitWithHashFromPrivatePoint { leaf: Value, leaf_pos: Value, merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, } - impl Circuit for MyCircuit45B { + impl Circuit for MyCircuitWithHashFromPrivatePoint { type Config = ( MerkleConfig< TestHashDomain, @@ -486,25 +487,27 @@ pub mod tests { let range_check = LookupRangeCheck45BConfig::configure(meta, advices[9], lookup.0); - let sinsemilla_config_1 = SinsemillaWithPrivateInitChip::configure( + let sinsemilla_config_1 = SinsemillaChip::configure( meta, advices[5..].try_into().unwrap(), advices[7], fixed_y_q_1, lookup, range_check, + true, ); - let config1 = MerkleWithPrivateInitChip::configure(meta, sinsemilla_config_1); + let config1 = MerkleChip::configure(meta, sinsemilla_config_1); - let sinsemilla_config_2 = SinsemillaWithPrivateInitChip::configure( + let sinsemilla_config_2 = SinsemillaChip::configure( meta, advices[..5].try_into().unwrap(), advices[2], fixed_y_q_2, lookup, range_check, + true, ); - let config2 = MerkleWithPrivateInitChip::configure(meta, sinsemilla_config_2); + let config2 = MerkleChip::configure(meta, sinsemilla_config_2); (config1, config2) } @@ -515,7 +518,7 @@ pub mod tests { mut layouter: impl Layouter, ) -> Result<(), Error> { // Load generator table (shared across both configs) for Sinsemilla45BChip - SinsemillaWithPrivateInitChip::< + SinsemillaChip::< TestHashDomain, TestCommitDomain, TestFixedBases, @@ -523,8 +526,8 @@ pub mod tests { >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; // Construct Merkle chips which will be placed side-by-side in the circuit. - let chip_1 = MerkleWithPrivateInitChip::construct(config.0.clone()); - let chip_2 = MerkleWithPrivateInitChip::construct(config.1.clone()); + let chip_1 = MerkleChip::construct(config.0.clone()); + let chip_2 = MerkleChip::construct(config.1.clone()); let leaf = chip_1.load_private( layouter.namespace(|| ""), @@ -593,7 +596,7 @@ pub mod tests { } } - fn generate_circuit_4_5_b() -> MyCircuit45B { + fn generate_circuit_4_5_b() -> MyCircuitWithHashFromPrivatePoint { let mut rng = OsRng; // Choose a random leaf and position @@ -606,14 +609,14 @@ pub mod tests { .collect(); // The root is provided as a public input in the Orchard circuit. - MyCircuit45B { + MyCircuitWithHashFromPrivatePoint { leaf: Value::known(leaf), leaf_pos: Value::known(pos), merkle_path: Value::known(path.try_into().unwrap()), } } #[test] - fn merkle_chip_4_5_b() { + fn merkle_with_hash_from_private_point_chip_4_5_b() { let circuit = generate_circuit_4_5_b(); let prover = MockProver::run(11, &circuit, vec![]).unwrap(); @@ -621,7 +624,7 @@ pub mod tests { } #[test] - fn test_against_stored_merkle_chip_4_5_b() { + fn test_against_stored_merkle_with_hash_from_private_point_chip_4_5_b() { let circuit = generate_circuit_4_5_b(); test_against_stored_circuit(circuit, "merkle_with_private_init_chip_4_5_b", 4160); @@ -629,7 +632,7 @@ pub mod tests { #[cfg(feature = "test-dev-graph")] #[test] - fn print_merkle_chip_4_5_b() { + fn print_merkle_with_hash_from_private_point_chip_4_5_b() { use plotters::prelude::*; let root = BitMapBackend::new( @@ -640,7 +643,7 @@ pub mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit45B::default(); + let circuit = MyCircuitWithHashFromPrivatePoint::default(); halo2_proofs::dev::CircuitLayout::default() .show_labels(true) .render(11, &circuit, &root) diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 6ec65fecad..f344202cc6 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -18,7 +18,7 @@ use crate::{ { ecc::FixedPoints, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig, SinsemillaWithPrivateInitChip}, + chip::{SinsemillaChip, SinsemillaConfig}, CommitDomains, HashDomains, SinsemillaInstructions, }, utilities::{ @@ -596,209 +596,20 @@ where chip.hash_to_point(layouter, Q, message) } - fn extract(point: &Self::NonIdentityPoint) -> Self::X { - SinsemillaChip::::extract(point) - } -} - -/// 'MerkleWithPrivateInitChip' Chip extends 'MerkleChip', supporting new methods -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct MerkleWithPrivateInitChip -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - base: MerkleChip, -} - -impl Chip - for MerkleWithPrivateInitChip -where - Hash: HashDomains, - Fixed: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - type Config = MerkleConfig; - type Loaded = (); - - fn config(&self) -> &Self::Config { - &self.base.config - } - - fn loaded(&self) -> &Self::Loaded { - &() - } -} - -impl MerkleWithPrivateInitChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - /// Configures the [`MerkleChip`]. - pub fn configure( - meta: &mut ConstraintSystem, - sinsemilla_config: SinsemillaConfig, - ) -> MerkleConfig { - MerkleChip::configure(meta, sinsemilla_config) - } - - /// Constructs a [`MerkleChip`] given a [`MerkleConfig`]. - pub fn construct(config: MerkleConfig) -> Self { - MerkleWithPrivateInitChip { - base: MerkleChip { config }, - } - } -} - -impl MerkleSinsemillaInstructions - for MerkleWithPrivateInitChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ -} - -impl UtilitiesInstructions - for MerkleWithPrivateInitChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - type Var = AssignedCell; -} - -impl CondSwapInstructions - for MerkleWithPrivateInitChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - #[allow(clippy::type_complexity)] - fn swap( - &self, - layouter: impl Layouter, - pair: (Self::Var, Value), - swap: Value, - ) -> Result<(Self::Var, Self::Var), Error> { - self.base.swap(layouter, pair, swap) - } - - fn mux( - &self, - layouter: &mut impl Layouter, - choice: Self::Var, - left: Self::Var, - right: Self::Var, - ) -> Result { - let config = self.config().cond_swap_config.clone(); - let chip = CondSwapChip::::construct(config); - chip.mux(layouter, choice, left, right) - } -} - -impl - SinsemillaInstructions - for MerkleWithPrivateInitChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ - type CellValue = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CellValue; - - type Message = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::Message; - type MessagePiece = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::MessagePiece; - type RunningSum = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::RunningSum; - - type X = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::X; - type NonIdentityPoint = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::NonIdentityPoint; - type FixedPoints = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::FixedPoints; - - type HashDomains = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::HashDomains; - type CommitDomains = - as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::CommitDomains; - - fn witness_message_piece( - &self, - layouter: impl Layouter, - value: Value, - num_words: usize, - ) -> Result { - let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaWithPrivateInitChip::::construct(config); - chip.witness_message_piece(layouter, value, num_words) - } - #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - fn hash_to_point( + fn hash_to_point_with_private_init( &self, layouter: impl Layouter, - Q: pallas::Affine, + Q: &Self::NonIdentityPoint, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec>), Error> { let config = self.config().sinsemilla_config.clone(); - let chip = SinsemillaWithPrivateInitChip::::construct(config); - chip.hash_to_point(layouter, Q, message) + let chip = SinsemillaChip::::construct(config); + chip.hash_to_point_with_private_init(layouter, Q, message) } fn extract(point: &Self::NonIdentityPoint) -> Self::X { - SinsemillaWithPrivateInitChip::::extract(point) + SinsemillaChip::::extract(point) } } diff --git a/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_with_private_init_chip_4_5_b.bin b/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_with_private_init_chip_4_5_b.bin index 2ad627e536ee98edda76c2f25f04383360cae100..219518b0e59c8ad05b3a4606cf3d3477cd913379 100644 GIT binary patch literal 4672 zcmc)K=OYvjz`$|)>~${ArnC1r*^*60XN$W~Mn?Q>GUK|)*&}--yKq)#JKG_9W`~fK zne{yX!}H?#{s*5o-%keWJN5;Bv=-ztNkMy6yQqabK;}OjzN_l`P)Rh-G zGJ?M=3RC$XO?{S261c9oBjtH5|7iW&nxK9sQlRp`6z9~LUu2*l(t6I?2cw#Pk}8Sx z{i7&+6^WrzZYZ}3i}42}2YK?>YsE@l@5YZ*5j0T|Ph3pu**rYiD+fBs;CY*NV0345 z?8maQ%_eRsD;;i)_E36=0Ht zOP`WG_fL+$@pU+cAtRBXk>d2p*8KS5uKqXEl^5a)`A^oRCO!oE+SPu}0d&75K&vJG zh==;<)-2#ahq41iz>GkboGWJ6WQuZyZ0wKTDq96Ca$-B+NZ;st>*&T*+m z&yw@)=eqM(E&XmJi*9gq(yQGUpQ}-yQ~GOzUiq;kbdi(dRXLp_%$w}k@o0z9PdztF zGHct$)7z>0R-)!89k$;g^Wx`ebgRCbu!dn|D(E@;Qmh8$;P>w3O>*dR14nuP_S+Xv}oaOUB~l_&9Mgi3Veu#zv76=Fy!A z%U{&nX?PtdfASP*-h8hS+}6CRCAxu>5WE~18dAZrXo%L{MBdW7RaX9z+l<*|@=Qzi zQ_XciD?<@oiVVbitmOiZ8co@7?QOc6NC`osJX=0o;wP`8vxZtr=sjE#faOW_2YJQf(MRD3oc{OKwC@-z`3L0f{00GTd`jCe2iQ-CONoJ*EN_?6 z*ozY0iTv}@%#v7jZJ-oP0#PNu;aaetWjJ)H8HnU0?$rYV78h%>?=CoK%!Y2?L6Hsx z&H`?lVjrpr8@cg!2@C;LO*$)57XycNg(Y%IIKo*g`kmhWbXP${ZmFRXtbq;~St{X- zpGDihP!f|RbS4>SH0d^4pE!K@?csa9>23;M>mtIP?Fqe!Y<~sj)CCx|Ox1i#H-YDS zrtkkTC_CWggFeIBAlAF9f7ef?L=LRJXUt@1CoL%(km*r{8bcurH|^m`&S=??%74=q4336$$ z$vg{+$q&v%&nqLKLV3BKOwkrCLeHT`HC`Yp6MMs+`tem$~tu;)v6DP;wv*?z6jG zQ5|UBO==Pfm>Z-;z$w%RIQkBlk2P|2kke<01*(QRWh`aOg#414|N22U*6X?*OukPX zf#VonwC6-OMNM?=D;b&+HXFrp>-(xzWA&k2`a(y-m>C#xuuwl`xwcqe!R4c1?IOy% zEUY_#BbX{Se{eTmppz4P2QRB{0=G>4^Doe3nipPh_C3mM)j{;aP2^5dP8q-3qC7XH z6RM=v>bX4Dh{#sAs08KAjjmZ%Yp-E^eao*q_SdBMvoa7ShhR1RA1v)BN?rvnvIWXb zUxu`+wPASm61K8VGKph>U=XXWjDu!l$8>C&@tg&>)=C2iaT+-@G zM*-BbSO0Pp)PKyA%!_)>a$mI6bX$(T?^puwF+!X>$cioQ`0jE9-Gj)dT6y#c_K;)# z{d>v3zC8B%^<8fHnkk-Bk=QqEa>{y^Szk;1jGfO(|WQ{ z=dISb!=OxGjkftEP`3nClq;ax)>|#XUEQ9kc6DPS&NF9C#YgQMOaV3mugl%n*N-$MZtA^L;?mmKqZf)66oR zv!ZT`Mcg<8`Cim~c;LGt&mfM@iJp01hQO!lREmD+*F_H_8r+ebTJK!hO`{bK47rgT zm3$*Tws)^?NZ^){iQ^m)E?63^n$ojU?xb$fVNZLO%x~%1rb3%GZAnj6N~PF3A$>*+ z$+2{*GaaSj*sEWJX;O4_qFIQKv$mwTxk%bAD%wj4%a4_M9;$b&!9DDLVcG-XUl>TcC7`g~&SS&I{47MW*`#~mxgVD)#zef#qb73fn`owJ3W{ivKtx{C!>JN(x^|pT z84M*Gx(qv`*O^!|H-~mUxT5{P@~=_)551<}k3i|9iX@e*P*jvIsSiZ+kI;&+`K|Ca z;*fykXHDcHo^o#WHSE6OUsuTi}%|5-4}efs5H z*871UXL7pW>S1`qD@W}^5_jS0d+GnY9;$-waLv3FBThn8D_+YLaebDUJw}u6=g^ay z)?LzC&>pfVib%_GKPCCkdvLhXWBu2tna?|pqr+%lmlhcj){}93BD3Oh;`Ou1z_3TB zzB8sZV{)ClK_9~M(-Zpwwy&FQ*RqqGvW z)oYbnoZ6J%?nFfQ+SYmWVT)aPqa7!yopGE}iWHoO#@gF0%?q_$XQE8GdGgpBYIh#x z9;!AP@zmc8*|m-gBy!(AZFy~G>Di_77H!#}Lob=zOshKP^)0bb(U~xd|NhOqXXeCD z`Ziib`pOG+`mJ=eMR5OMO458z@JD*#%P9Z!uW5$u0AO&1v4#%^vMP6SnGkSEFvmO2 z;-26qp_1iAs*jOM=eaqy4{0A;oSQ)amIUG{ew#eE7i>0p zbh;XmPUGG6*>oi7Mc>Y-38&%L8>bUfP--V6=(T``&PKV-m#9o$F|pB^$X`|3R3GIN zJdJ_3e1d7mYd^bjt?82?=g0zJG^c{2s|=|p6U*_A*U|D0VCOI1j<>JncWtz7=9`?M z_qg`W{tN2a-#V~4fYZ{DiYBJJDuNFd(%JO#udn(MTehTh9-TvMp(2Wm2ZWb>u#FB= zzA>mC4#va`3&*jLRGbYk8I;?wv%P5lz+t%d8GSe`4W#)~G4%cf4jys#gpzWI&zb9r&E z1Y)R-;erN*?QSuk+B)AAzVlu3ulN$@DtWJiVLdr3L#QQ-nwv41VJWMfR-S3kpZm8Y zE^3W#2wh3Uxo*Hc!}K70eM4Cd<$ZrMG1oKjfr(eZKw<>)jL}5)O}cWVLyrydc!7@M zw3{dAzbhdtxd&MiHa(aJRj1ukN31(~UWKa~i zEbM!Cpslj)?CC-lg{__wy7#o%QW+!qHe`n|g(Aj7zr$>xU6S2Dl#`8F1HOvbv>a|3 z(g^Z@0!lwmtY~(j;3Y^S|Ho?0bsv!(Fp~=r?Sl}PjpHVrLEU?6L<9vvi$B=&8n}5Y zPE%ktTTrFzthKe2{7BamfUpDNm-lw_`Vv*?eUv3n%O43Nes?Hqdp7BdN0O>`f43T| zmTYJ%0&?Q2IZ>`k$D=1U4zzi_GrM?*$75Nr0l{?JG z44N&yzo-1-N>@95L|>+den*A*%@e%|zTlAn%Wf@Qb8``&=9$YT-5*1+wVz2^3~@cX z8$?{VE`^3mNN4a?$neLs@{&S$Mn(HPlaBK{C=u^!S+1CuCr*>oCr~@5HPiuLRCi`( z%iup(*o4cpr4C+dRUxr2b20F^aa2>{7)|2b6X+KI8M&w175xwO-2kQ##(KnUpSaoc zIy?LsOPS~ud`jfdpS<0iZMTW3)tck0HuJL(t9-^+nV%kBjl^C!hQb*T4jZr7_v=KyV|OAVU=pGqMiol4qFx zGq7RfVdRg>5^1$^{tF+Ws+N-fkKpsI(#>;)&lo2U!P=;2dG}^sjM3rf`#DwVUKwND zjyk^_>>;A@x~{>R*(JO>RaZ33o6H|G`9zuiI6{B7HM0 z!A{-^=N zAW_4&+@S)2aiH7O-jX?rEt7xDv9$0*rH9`{Y3!!Q*?f;w?e*o8>&a1X;>mcNM5yIX zhp+g=d0T!q?`zU}LtcfxI0NMoIpqI3=3OP?H~1G7A(!DN1W3NRpdY{5eAmX9f-x4v z*66c-gwh8nklqB_TA3f+d#`sy1SkM@g&&qQ#P&07F%n};0>}26p^IaD_3>U$;@C!Q zMeP#<0poKoLIk%ibHNcZP8c02dck7(`VA%99;|s^eL8t0akOKOydCD`%GtFC#oi*L Vvc3R6@#|rnSf}foPnK}!{T~)goE888 literal 4672 zcmc(fC<&iclS0NrsHrrZ`zn{(`^$Ir(+nV+l}dt4bz<1;isGT{U6>B z@ADr#AD)MuG2cZVd(lvo&3t%S0XkT$G#%f@2PBlPsTs!|C6OG{(sk3!itB1G73RAu zmIR~=(~)|iC?FI-?sbf$t4u&vK9g*xEI})B)`fOlmftl{L2ANP5bbn!RJ}C+dk2|i zJ5bq#zKX;8QkbQw-CllvfXuY9%BfI}BHd?AMkvNcE)vv*+_@(kO&YZU{y3|qZi4)% zJ6`!^>%@LA-#jReb4D)rTpMMTfQ1Q>maUo>Npv5nxx~-k+-dkbO>ceB)xuYi7iBkL zEiW(^uFbUCBTw4!JWV8#xE3B`oKH|P+1VloFy3Lh9#;1u+uakK>ZZf_6hbzT=VkaQ zDUwLDLkV$%mPh)e;pRQz7(d91PW`aB)mO1FjzL?`AAhee0ir9%ea%9WB84d#|-K_5^){eT}|9t4oz$C zfBOz?;7QM!IH+%2IQ=-Rak{>sa>Q#bgY%VaXTI!I-@VO0G<8-r&S`p0#KMHg4fWq9 zE0nLie*9g49iQKKs-%=@orBZcuBOym9fOhua&hogacfwoe5Q#Q1P&-6|Lk%`J;xpw z$V-qoWKVY54Gx@kfsIR;TNjEf3?&*xUyH0y&ai|Flnv zEj&-F-WMk6C!z{huxiWK;r8pTamzBvuw5fiO%0icTl07|O=IyGNL`0zhjh_?cFvER zsIaBE5jAE{b0P1iIJa{-kVhN|&7>aIIP7#IPA73Ar~=fxPOELG#dD|Z$33|u(*ymQ17 zc3x9R4gBCuZc$KX<0&F(R8Jk`p7;GCByq7Pm+1i6N)!LhUEBdcnPso;`>#u*($Y+n zxPlAXcR9+y{YM;Z!9?+yXzi~$S zS-j)VR&!5HdA+UCkh*Rgckmc>7)_--xG}+pc%5-Jb;;++BKp1bku@Yti5FR?k5+*B z*T|{K!{|dOF8(W|b(Ef8i=QiDRz)u%1s(}Tx4R%UQ(YN8opWKujGJ3Y&2OXZxa_5f z!u*#UCH%<~F|S7q8rK`N-`el*-Ce2VRNkM0--UKEr3!v@j6R;6Y;OcJ-iSN*cVke_ z4CwW1WRR1aj_eZ$u+?6-8Z~7e4HV1}bp-nVt}pa}NNUXcJ*sr4=AU>-p?aSJF!PwB z9k@qujaBq3R(U3q-#lxv*jXN(FJb`DVf@Vcv#U!tH4~d4FQ`Y{gi`lA4}Al5fL>Xm zicp%J6T{S1?xC4+%Al11V=z3h>P|3bbJn__0dw(bwVWiA%m zQRsJk6N=V)E;qOZ{nTo0%doZ-27jEs{qZC3*F;V#w%K{R-Enw|kP~rW%5uS{AOcHL zKQ(3=TZ8G-v0F)^7I3ra8)@V|o-I;+XD;M_gE~7rvHya5VS#7At}Vr*vbsI`CXMd% z4G-)}O)f@ZBE1SFbolt?nJjM2dIF@+)VdSE>HqYp^Ko_!P3TLdTk_VRp9FAVI&rny zzd~*pb1L^bDye`LIEm5z@k)&9#~uEcVn-jaRcTDnzzws6dtuFH(L)jFoaQ-kBOWdR z3H^DwroI#|*Xx%8{>_-1YWaOw4q{qc#;o{nrqmY(12l=9jVYzKYX??|wh^ry@nN4k zp1-7&BM!DOFAAGHuv_&KppI13j_^%Q9x=S&o!I=fr1t>bo{I(oiiR;oh&ae(tz04K0(PaiU#?W#Lv$#&kZ$Ty z8@iZvl3;dy=U)>&o?BtR7n={{me985bpfy+}@W1$E@O+JU^GW_!_9c!z)IylD$vtpN6_6?=mB>ksYCGbjMEVA0oV|2ISUGXI0-noTnar*wp8?MDH?gPn4IY%$eHy3&8&(;AYExUWgUB|?3P_jYo09| zz1JC_Sr6bySW4rEqG?dmhhlaxheeJ_VFeKADI3eScOv_8AD_%O@l+k+EN9Nx_qdPW zd8>ElKPY_S3;4h4a{y}iNls8@-d(#3%xzG|(ruwe5aOvGf_%477slgoTr9EF1cz(?3NSz84S-}tc-A<L5IBze}l3g_1e&Egi2zB1efcB~wPoED{V-cxlW?TS2q$<{Bgyaxxs;$aY~Ei&0I! z-7yM(Qz9TEV#+p}eGy*%3ZtssI-;M)<=-7080QF1t&5dQ>b-=MF)UuG{U{7%ejpWM7T%Z#MyTgdYi(E5=o(%9Q>lySKt5yrs{EN4w z=~BZQIt9%Y-ccU`M^FAr;rR$;XUT7J#M+NwTww6A`C_*)J>JG4gJ!6M0-M=L>#|3D zlz=WB#K7z-EX*EhE1T2vh~ZL#)U;c|M@Y8K_iHc5g#W z@G44*7KLt5)Ata4_2-XEFyQ5&B8+s_;{E~kE!Kik?oTC=qJ+ZbId}e5!iJF4I6sFP z?$Js6{bzY+o40avOrpS&u5F zs?x41EvNh{u6{1yL*>JP+E=#|!s@>@W*~i>uYAl_QkYJ@P-WN*`@3)8zL#W)OnCEw zqSi_51C%;Z2>#_JS{LryGM09drclIv`d1X55@RbyD*Ft+F!xYqMx;wJ7BrWWj%^M9lKFVeJIm3{ zQxB-HXT|xBsNB=IPQ|0S!dIuK3|ZRyr9~ESK+P~33O2hW$iY%;OQOEXrA)4qew7Gm*@};hJgSnVa+7 zUod)W6sgb}Vk~`*=e=Soh$HGh2%si}Ma+8j>E3G4r_g&p#DSHtgJ>0RK*Uo59~G!Gj~cB@9?m=o(A-L@OPv4!eO zw}O=!)24HWXMZrM$V?%+{nmV+w-8H#pqhb)y3lfw>kW$HK~wS-n1*mW}ijHnbMZkwe&|UM+T}?FO0ek zB~y?AOZMkk4?wStSZ?ydD7~v6g1K3y#62o0t(s-t*7ul1Le0X@?nrA>W=)Fg>r=L7 zkNI2pgGSWvOmQ+BsG}7}F_u*#97de@Z|(w;86puT+TY@Tj5a?CGK_Bp^`^@%w0Qab z+#yn`2<%_R{f`G`dZ?rRiP*X&@<{+KKE1?!ffwd-pAqKO^7(#9rZey3*j|7EU^+!v zn8BVSpm%lzZ@&S@&>9vI$UHFE3&__QsWn%}B(OT9;gja!a21+ef`g)x`aE#Z399oL zk6Ci6Y?p;o_pM-EPnK zESvhZ$*u7Ujhz3d%Hhn_9Os5|;Rvki9@|_#8sTQ;-G9BXjaYPT*j8! z7dWlRq9PRs7JIQVbTf$WiZs`kkr^itD1A}VpXrPIch2mEb8|GavPaQpW4R$eF`#ETcMOOf4 zKSK;$W`MO94mBTk0dt7zL^Dn|dl~Vsn+Nl*3&Tvq^%{@S+&y%{&_cxvwso7&?qf@> zYcQP5iaXXh*b0vQFz~G?p@WESn&Gs)N#1dWCStOF7UjqC2#z6f4tPFVIjEfe&m^=N zPh{VWn`9^2M+GltgzHF^G!zheQT8@D*(F}}W#GXlmDi3-t&f#x8)fXcWa!d4Vb6Y^C^ySZXM0~_--5^Y=s{s+SJgmVA@ diff --git a/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5_b.rdata index 467fa7830c..a5c7971e8f 100644 --- a/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5_b.rdata +++ b/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5_b.rdata @@ -7170,7 +7170,7 @@ PinnedVerificationKey { ), Fixed { query_index: 4, - column_index: 3, + column_index: 2, rotation: Rotation( 0, ), @@ -7206,7 +7206,7 @@ PinnedVerificationKey { ), Fixed { query_index: 5, - column_index: 4, + column_index: 3, rotation: Rotation( 0, ), @@ -7265,7 +7265,7 @@ PinnedVerificationKey { ), Fixed { query_index: 6, - column_index: 5, + column_index: 4, rotation: Rotation( 0, ), @@ -7347,7 +7347,7 @@ PinnedVerificationKey { ), Fixed { query_index: 7, - column_index: 6, + column_index: 5, rotation: Rotation( 0, ), @@ -7452,7 +7452,7 @@ PinnedVerificationKey { ), Fixed { query_index: 8, - column_index: 7, + column_index: 6, rotation: Rotation( 0, ), @@ -7580,7 +7580,7 @@ PinnedVerificationKey { ), Fixed { query_index: 9, - column_index: 8, + column_index: 7, rotation: Rotation( 0, ), @@ -7731,7 +7731,7 @@ PinnedVerificationKey { ), Fixed { query_index: 10, - column_index: 9, + column_index: 8, rotation: Rotation( 0, ), @@ -7905,7 +7905,7 @@ PinnedVerificationKey { ), Fixed { query_index: 11, - column_index: 10, + column_index: 9, rotation: Rotation( 0, ), @@ -8057,7 +8057,7 @@ PinnedVerificationKey { ), Fixed { query_index: 4, - column_index: 3, + column_index: 2, rotation: Rotation( 0, ), @@ -8079,7 +8079,7 @@ PinnedVerificationKey { ), Fixed { query_index: 5, - column_index: 4, + column_index: 3, rotation: Rotation( 0, ), @@ -8110,7 +8110,7 @@ PinnedVerificationKey { ), Fixed { query_index: 6, - column_index: 5, + column_index: 4, rotation: Rotation( 0, ), @@ -8150,7 +8150,7 @@ PinnedVerificationKey { ), Fixed { query_index: 7, - column_index: 6, + column_index: 5, rotation: Rotation( 0, ), @@ -8199,7 +8199,7 @@ PinnedVerificationKey { ), Fixed { query_index: 8, - column_index: 7, + column_index: 6, rotation: Rotation( 0, ), @@ -8257,7 +8257,7 @@ PinnedVerificationKey { ), Fixed { query_index: 9, - column_index: 8, + column_index: 7, rotation: Rotation( 0, ), @@ -8324,7 +8324,7 @@ PinnedVerificationKey { ), Fixed { query_index: 10, - column_index: 9, + column_index: 8, rotation: Rotation( 0, ), @@ -8400,7 +8400,7 @@ PinnedVerificationKey { ), Fixed { query_index: 11, - column_index: 10, + column_index: 9, rotation: Rotation( 0, ), @@ -10921,7 +10921,7 @@ PinnedVerificationKey { ), ( Column { - index: 2, + index: 12, column_type: Fixed, }, Rotation( @@ -10939,7 +10939,7 @@ PinnedVerificationKey { ), ( Column { - index: 3, + index: 2, column_type: Fixed, }, Rotation( @@ -10948,7 +10948,7 @@ PinnedVerificationKey { ), ( Column { - index: 4, + index: 3, column_type: Fixed, }, Rotation( @@ -10957,7 +10957,7 @@ PinnedVerificationKey { ), ( Column { - index: 5, + index: 4, column_type: Fixed, }, Rotation( @@ -10966,7 +10966,7 @@ PinnedVerificationKey { ), ( Column { - index: 6, + index: 5, column_type: Fixed, }, Rotation( @@ -10975,7 +10975,7 @@ PinnedVerificationKey { ), ( Column { - index: 7, + index: 6, column_type: Fixed, }, Rotation( @@ -10984,7 +10984,7 @@ PinnedVerificationKey { ), ( Column { - index: 8, + index: 7, column_type: Fixed, }, Rotation( @@ -10993,7 +10993,7 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 8, column_type: Fixed, }, Rotation( @@ -11002,7 +11002,7 @@ PinnedVerificationKey { ), ( Column { - index: 10, + index: 9, column_type: Fixed, }, Rotation( @@ -11020,7 +11020,7 @@ PinnedVerificationKey { ), ( Column { - index: 11, + index: 10, column_type: Fixed, }, Rotation( @@ -11029,7 +11029,7 @@ PinnedVerificationKey { ), ( Column { - index: 12, + index: 11, column_type: Fixed, }, Rotation( @@ -11464,7 +11464,7 @@ PinnedVerificationKey { }, Fixed { query_index: 2, - column_index: 2, + column_index: 12, rotation: Rotation( 0, ), @@ -11714,14 +11714,14 @@ PinnedVerificationKey { }, Fixed { query_index: 13, - column_index: 11, + column_index: 10, rotation: Rotation( 0, ), }, Fixed { query_index: 14, - column_index: 12, + column_index: 11, rotation: Rotation( 0, ), @@ -11971,14 +11971,14 @@ PinnedVerificationKey { }, Fixed { query_index: 13, - column_index: 11, + column_index: 10, rotation: Rotation( 0, ), }, Fixed { query_index: 14, - column_index: 12, + column_index: 11, rotation: Rotation( 0, ), @@ -11997,7 +11997,6 @@ PinnedVerificationKey { fixed_commitments: [ (0x1f52e1e5a4228f86b85706beb3a38f9b8f83178b92572875e97e5d57526e59df, 0x2415bfeebebfed5e1766260161912596cc82afd7e6f6906257ae5ebb3b0ff1ef), (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), - (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x06f460c587c896f1f8284619af6d9cd7ed55ed416c6777336afab0facd2d9125, 0x0132b10308dfc29176a0ac2fd00846e89b4b098238b2f743d048460e5a853b07), (0x30e332088e023adfd8d0a9c54ca15a08d83f6e0d5516cb51f32e9bb956bbc3a7, 0x15bef2896e132c2c52ab59d768d48d3cf7dde3e2b643953823edc4bd9977b287), (0x3480efa9a7eaa4b42dfb9b2ce4dd7bc0a1e65ce9d04ac0b3471fcd6d5be7fdc8, 0x322895945a2c9b6fa91a2de6641244b71edeca0b11e324c086cc6fab3095c5b2), @@ -12008,6 +12007,7 @@ PinnedVerificationKey { (0x1076db76ed054a8ea26563331cfb04eb688169c04ca370d09f1aae0e6fbc8787, 0x0c87eca3dec43f90e5a64cbb22c1d38de880e1e8b7156fc378ffdc99e09f7c1f), (0x285e16cead69d5fef9441d4d4ac695fe8880120d209e1e631d8a4bc5f55e90e6, 0x3700fd2dfcfac5b2cb6d33c60ac79dfac3fb95518cd0aa97c75a51d62281f2c1), (0x2dc11f4f0000da15c59cd395ea5f32b4e79783d958c290c821c89e0bcb50eaf1, 0x2c53e12ce0a2022516ef31f0224b0bc1b119861078358f78d245ba5d2f180099), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x21f3275c835d322344502eedaf3c1e2ca34db968c3353b7de0eecff447a21be8, 0x278a7d6512910d39b926c80e89400e99255b5d587e2471107a88b24cc7c4ee6f), (0x3965d4503e0eed848f7c7ad1ae773a7de6b370bf62d4df90a6c058e2a476492c, 0x0e9b5713800ebced2820c9361a0c4640e79e3631a52952f76b479bc0f31883e7), (0x38a3ca5237cf04483e05dff22994bd83e45eb713563584f198750f1da538eeab, 0x38f39efa2eaa6dd41a613671e7801f703b210c66ef4fb7ede78e27ebf08bb9c1), diff --git a/halo2_proofs/src/plonk/error.rs b/halo2_proofs/src/plonk/error.rs index 6e3131e798..1830be3b2b 100644 --- a/halo2_proofs/src/plonk/error.rs +++ b/halo2_proofs/src/plonk/error.rs @@ -40,6 +40,8 @@ pub enum Error { ColumnNotInPermutation(Column), /// An error relating to a lookup table. TableError(TableError), + /// Try to hash from a private point when enable_hash_from_private_point is unset. + HashFromPrivatePoint, } impl From for Error { @@ -82,7 +84,11 @@ impl fmt::Display for Error { "Column {:?} must be included in the permutation. Help: try applying `meta.enable_equalty` on the column", column ), - Error::TableError(error) => write!(f, "{}", error) + Error::TableError(error) => write!(f, "{}", error), + Error::HashFromPrivatePoint => write!( + f, + "Hashing from private point is disabled" + ) } } } From 0d2512a121d30fbfdedef59ca53e81532d8afbe4 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 1 Jul 2024 21:59:00 +0200 Subject: [PATCH 107/121] Refactoring --- halo2_gadgets/src/ecc.rs | 57 +++++------ halo2_gadgets/src/ecc/chip.rs | 66 ++++++------- .../src/ecc/chip/mul_fixed/full_width.rs | 12 ++- halo2_gadgets/src/sinsemilla.rs | 76 +++++++-------- halo2_gadgets/src/sinsemilla/chip.rs | 97 ++----------------- .../src/sinsemilla/chip/hash_to_point.rs | 11 ++- 6 files changed, 125 insertions(+), 194 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 7b8139be9f..2da0c31952 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -60,6 +60,15 @@ pub trait EccInstructions: value: Value, ) -> Result; + /// Witnesses the given constant point as a private input to the circuit. + /// This allows the point to be the identity, mapped to (0, 0) in + /// affine coordinates. + fn witness_point_from_constant( + &self, + layouter: &mut impl Layouter, + value: C, + ) -> Result; + /// Witnesses the given point as a private input to the circuit. /// This returns an error if the point is the identity. fn witness_point_non_id( @@ -111,6 +120,15 @@ pub trait EccInstructions: b: &B, ) -> Result; + /// Performs variable-base sign-scalar multiplication, returning `[sign] point` + /// `sign` must be in {-1, 1}. + fn mul_sign( + &self, + layouter: &mut impl Layouter, + sign: &AssignedCell, + point: &Self::Point, + ) -> Result; + /// Performs variable-base scalar multiplication, returning `[scalar] base`. fn mul( &self, @@ -145,24 +163,6 @@ pub trait EccInstructions: base_field_elem: Self::Var, base: &>::Base, ) -> Result; - - /// Witnesses the given constant point as a private input to the circuit. - /// This allows the point to be the identity, mapped to (0, 0) in - /// affine coordinates. - fn witness_point_from_constant( - &self, - layouter: &mut impl Layouter, - value: C, - ) -> Result; - - /// Performs variable-base sign-scalar multiplication, returning `[sign] point` - /// `sign` must be in {-1, 1}. - fn mul_sign( - &self, - layouter: &mut impl Layouter, - sign: &AssignedCell, - point: &Self::Point, - ) -> Result; } /// Instructions that can be implemented for a curve whose base field fits into @@ -408,6 +408,17 @@ impl + Clone + Debug + Eq> Point, + value: C, + ) -> Result { + let point = chip.witness_point_from_constant(&mut layouter, value); + point.map(|inner| Point { chip, inner }) + } + /// Constrains this point to be equal in value to another point. pub fn constrain_equal> + Clone>( &self, @@ -451,16 +462,6 @@ impl + Clone + Debug + Eq> Point, - value: C, - ) -> Result { - let point = chip.witness_point_from_constant(&mut layouter, value); - point.map(|inner| Point { chip, inner }) - } - /// Returns `[sign] self`. /// `sign` must be in {-1, 1}. pub fn mul_sign( diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 32f026a415..2cdb5f63dc 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -465,6 +465,21 @@ where ) } + /// Witnesses the given constant point as a private input to the circuit. + /// This allows the point to be the identity, mapped to (0, 0) in + /// affine coordinates. + fn witness_point_from_constant( + &self, + layouter: &mut impl Layouter, + value: pallas::Affine, + ) -> Result { + let config = self.config().witness_point; + layouter.assign_region( + || "witness point (constant)", + |mut region| config.constant_point(value, 0, &mut region), + ) + } + fn witness_point_non_id( &self, layouter: &mut impl Layouter, @@ -544,6 +559,24 @@ where ) } + /// Performs variable-base sign-scalar multiplication, returning `[sign] point` + /// `sign` must be in {-1, 1}. + fn mul_sign( + &self, + layouter: &mut impl Layouter, + sign: &AssignedCell, + point: &Self::Point, + ) -> Result { + // Multiply point by sign, using the same gate as mul_fixed::short. + // This also constrains sign to be in {-1, 1}. + let config_short = self.config().mul_fixed_short.clone(); + config_short.assign_scalar_sign( + layouter.namespace(|| "variable-base sign-scalar mul"), + sign, + point, + ) + } + fn mul( &self, layouter: &mut impl Layouter, @@ -604,39 +637,6 @@ where base, ) } - - /// Witnesses the given constant point as a private input to the circuit. - /// This allows the point to be the identity, mapped to (0, 0) in - /// affine coordinates. - fn witness_point_from_constant( - &self, - layouter: &mut impl Layouter, - value: pallas::Affine, - ) -> Result { - let config = self.config().witness_point; - layouter.assign_region( - || "witness point (constant)", - |mut region| config.constant_point(value, 0, &mut region), - ) - } - - /// Performs variable-base sign-scalar multiplication, returning `[sign] point` - /// `sign` must be in {-1, 1}. - fn mul_sign( - &self, - layouter: &mut impl Layouter, - sign: &AssignedCell, - point: &Self::Point, - ) -> Result { - // Multiply point by sign, using the same gate as mul_fixed::short. - // This also constrains sign to be in {-1, 1}. - let config_short = self.config().mul_fixed_short.clone(); - config_short.assign_scalar_sign( - layouter.namespace(|| "variable-base sign-scalar mul"), - sign, - point, - ) - } } impl, Lookup: PallasLookupRangeCheck> diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs index f5cf9d3ce2..393f065206 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/full_width.rs @@ -187,12 +187,14 @@ pub mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - use crate::ecc::{ - chip::{EccChip, FixedPoint as _, H}, - tests::{FullWidth, TestFixedBases}, - FixedPoint, NonIdentityPoint, Point, ScalarFixed, + use crate::{ + ecc::{ + chip::{EccChip, FixedPoint as _, H}, + tests::{FullWidth, TestFixedBases}, + FixedPoint, NonIdentityPoint, Point, ScalarFixed, + }, + utilities::lookup_range_check::PallasLookupRangeCheck, }; - use crate::utilities::lookup_range_check::PallasLookupRangeCheck; pub(crate) fn test_mul_fixed( chip: EccChip, diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 76581cb9ae..d6dd82e4a6 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -441,44 +441,6 @@ where } } - #[allow(clippy::type_complexity)] - /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. - /// - /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit - pub fn commit( - &self, - mut layouter: impl Layouter, - message: Message, - r: ecc::ScalarFixed, - ) -> Result< - ( - ecc::Point, - Vec, - ), - Error, - > { - assert_eq!(self.M.sinsemilla_chip, message.chip); - let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; - let (p, zs) = self.M.hash_to_point(layouter.namespace(|| "M"), message)?; - let commitment = p.add(layouter.namespace(|| "M + [r] R"), &blind)?; - Ok((commitment, zs)) - } - - #[allow(clippy::type_complexity)] - /// $\mathsf{SinsemillaShortCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. - /// - /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit - pub fn short_commit( - &self, - mut layouter: impl Layouter, - message: Message, - r: ecc::ScalarFixed, - ) -> Result<(ecc::X, Vec), Error> { - assert_eq!(self.M.sinsemilla_chip, message.chip); - let (p, zs) = self.commit(layouter.namespace(|| "commit"), message, r)?; - Ok((p.extract_p(), zs)) - } - #[allow(non_snake_case)] #[allow(clippy::type_complexity)] /// Evaluates the Sinsemilla hash of `message` from the private initial point `Q`. @@ -517,6 +479,44 @@ where let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; Ok(blind) } + + #[allow(clippy::type_complexity)] + /// $\mathsf{SinsemillaCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. + /// + /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit + pub fn commit( + &self, + mut layouter: impl Layouter, + message: Message, + r: ecc::ScalarFixed, + ) -> Result< + ( + ecc::Point, + Vec, + ), + Error, + > { + assert_eq!(self.M.sinsemilla_chip, message.chip); + let (blind, _) = self.R.mul(layouter.namespace(|| "[r] R"), r)?; + let (p, zs) = self.M.hash_to_point(layouter.namespace(|| "M"), message)?; + let commitment = p.add(layouter.namespace(|| "M + [r] R"), &blind)?; + Ok((commitment, zs)) + } + + #[allow(clippy::type_complexity)] + /// $\mathsf{SinsemillaShortCommit}$ from [§ 5.4.8.4][concretesinsemillacommit]. + /// + /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit + pub fn short_commit( + &self, + mut layouter: impl Layouter, + message: Message, + r: ecc::ScalarFixed, + ) -> Result<(ecc::X, Vec), Error> { + assert_eq!(self.M.sinsemilla_chip, message.chip); + let (p, zs) = self.commit(layouter.namespace(|| "commit"), message, r)?; + Ok((p.extract_p(), zs)) + } } #[cfg(test)] diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 7af7924891..3dc70274cf 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -165,37 +165,6 @@ where lookup: (TableColumn, TableColumn, TableColumn), range_check: Lookup, enable_hash_from_private_point: bool, - ) -> >::Config { - // create SinsemillaConfig - let config = Self::create_config( - meta, - advices, - witness_pieces, - fixed_y_q, - lookup, - range_check, - enable_hash_from_private_point, - ); - - if enable_hash_from_private_point { - Self::create_initial_private_y_q_gate(meta, &config); - } else { - Self::create_initial_public_y_q_gate(meta, &config); - } - - Self::create_sinsemilla_gate(meta, &config); - - config - } - - pub(crate) fn create_config( - meta: &mut ConstraintSystem, - advices: [Column; 5], - witness_pieces: Column, - fixed_y_q: Column, - lookup: (TableColumn, TableColumn, TableColumn), - range_check: Lookup, - enable_hash_from_private_point: bool, ) -> >::Config { // Enable equality on all advice columns for advice in advices.iter() { @@ -228,46 +197,14 @@ where // Set up lookup argument GeneratorTableConfig::configure(meta, config.clone()); - config - } - - /// Assign y_q to a fixed column - #[allow(non_snake_case)] - fn create_initial_public_y_q_gate( - meta: &mut ConstraintSystem, - config: &SinsemillaConfig, - ) { let two = pallas::Base::from(2); - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) - let Y_A = |meta: &mut VirtualCells, rotation| { - config.double_and_add.Y_A(meta, rotation) + // Closures for expressions that are derived multiple times + // x_r = lambda_1^2 - x_a - x_p + let x_r = |meta: &mut VirtualCells, rotation| { + config.double_and_add.x_r(meta, rotation) }; - // Check that the initial x_A, x_P, lambda_1, lambda_2 are consistent with y_Q. - // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial - meta.create_gate("Initial y_Q", |meta| { - let q_s4 = meta.query_selector(config.q_sinsemilla4); - let y_q = meta.query_fixed(config.fixed_y_q); - - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) - let Y_A_cur = Y_A(meta, Rotation::cur()); - - // 2 * y_q - Y_{A,0} = 0 - let init_y_q_check = y_q * two - Y_A_cur; - - Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) - }); - } - - /// Assign y_q to an advice column - #[allow(non_snake_case)] - fn create_initial_private_y_q_gate( - meta: &mut ConstraintSystem, - config: &SinsemillaConfig, - ) { - let two = pallas::Base::from(2); - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) let Y_A = |meta: &mut VirtualCells, rotation| { config.double_and_add.Y_A(meta, rotation) @@ -277,7 +214,11 @@ where // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Initial y_Q", |meta| { let q_s4 = meta.query_selector(config.q_sinsemilla4); - let y_q = meta.query_advice(config.double_and_add.x_p, Rotation::prev()); + let y_q = if enable_hash_from_private_point { + meta.query_advice(config.double_and_add.x_p, Rotation::prev()) + } else { + meta.query_fixed(config.fixed_y_q) + }; // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) let Y_A_cur = Y_A(meta, Rotation::cur()); @@ -287,25 +228,6 @@ where Constraints::with_selector(q_s4, Some(("init_y_q_check", init_y_q_check))) }); - } - - #[allow(non_snake_case)] - pub(crate) fn create_sinsemilla_gate( - meta: &mut ConstraintSystem, - config: &SinsemillaConfig, - ) { - let two = pallas::Base::from(2); - - // Closures for expressions that are derived multiple times - // x_r = lambda_1^2 - x_a - x_p - let x_r = |meta: &mut VirtualCells, rotation| { - config.double_and_add.x_r(meta, rotation) - }; - - // Y_A = (lambda_1 + lambda_2) * (x_a - x_r) - let Y_A = |meta: &mut VirtualCells, rotation| { - config.double_and_add.Y_A(meta, rotation) - }; // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Sinsemilla gate", |meta| { @@ -351,6 +273,7 @@ where Constraints::with_selector(q_s1, [("Secant line", secant_line), ("y check", y_check)]) }); + config } } diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 03d7d6e82d..e6ce0e9d43 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -162,13 +162,18 @@ where } #[allow(non_snake_case)] - /// Assign the coordinates of the initial public point `Q` - /// - `x_Q` in a advice column, and - /// - `y_Q` in a fixed column. + /// Assign the coordinates of the initial public point `Q`. /// + /// If enable_hash_from_private_point is not set, /// | offset | x_A | q_sinsemilla4 | fixed_y_q | /// -------------------------------------- /// | 0 | x_Q | 1 | y_Q | + /// + /// If enable_hash_from_private_point is set, + /// | offset | x_A | x_P | q_sinsemilla4 | + /// -------------------------------------- + /// | 0 | | y_Q | | + /// | 1 | x_Q | | 1 | fn public_initialization( &self, region: &mut Region<'_, pallas::Base>, From e2c9e933fc6baf2a4e67742abfc520b105d5364c Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 2 Jul 2024 10:30:09 +0200 Subject: [PATCH 108/121] Refactor --- .../src/utilities/lookup_range_check.rs | 461 +++++++++--------- halo2_proofs/src/plonk/error.rs | 2 +- 2 files changed, 231 insertions(+), 232 deletions(-) diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 28ad379610..a7dde6f2e3 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -58,237 +58,6 @@ impl RangeConstrained> { } } -/// Configuration that provides methods for an efficient 4, 5, and 10-bit lookup range check. -#[derive(Eq, PartialEq, Debug, Clone, Copy)] -pub struct LookupRangeCheck45BConfig { - base: LookupRangeCheckConfig, - q_range_check_4: Selector, - q_range_check_5: Selector, - table_range_check_tag: TableColumn, -} - -impl LookupRangeCheck45BConfig { - /// The `running_sum` advice column breaks the field element into `K`-bit - /// words. It is used to construct the input expression to the lookup - /// argument. - /// - /// The `table_idx` fixed column contains values from [0..2^K). Looking up - /// a value in `table_idx` constrains it to be within this range. The table - /// can be loaded outside this helper. - /// - /// # Side-effects - /// - /// Both the `running_sum` and `constants` columns will be equality-enabled. - pub fn configure_with_tag( - meta: &mut ConstraintSystem, - running_sum: Column, - table_idx: TableColumn, - table_range_check_tag: TableColumn, - ) -> Self { - meta.enable_equality(running_sum); - - let q_lookup = meta.complex_selector(); - let q_running = meta.complex_selector(); - let q_bitshift = meta.selector(); - let q_range_check_4 = meta.complex_selector(); - let q_range_check_5 = meta.complex_selector(); - - // if the order of the creation makes a difference - let config = LookupRangeCheck45BConfig { - base: LookupRangeCheckConfig { - q_lookup, - q_running, - q_bitshift, - running_sum, - table_idx, - _marker: PhantomData, - }, - q_range_check_4, - q_range_check_5, - table_range_check_tag, - }; - - // https://p.z.cash/halo2-0.1:decompose-combined-lookup - meta.lookup(|meta| { - let q_lookup = meta.query_selector(config.base.q_lookup); - let q_running = meta.query_selector(config.base.q_running); - let q_range_check_4 = meta.query_selector(config.q_range_check_4); - let q_range_check_5 = meta.query_selector(config.q_range_check_5); - - let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); - let one = Expression::Constant(F::ONE); - - // In the case of a running sum decomposition, we recover the word from - // the difference of the running sums: - // z_i = 2^{K}⋅z_{i + 1} + a_i - // => a_i = z_i - 2^{K}⋅z_{i + 1} - let running_sum_lookup = { - let running_sum_word = { - let z_next = meta.query_advice(config.base.running_sum, Rotation::next()); - z_cur.clone() - z_next * F::from(1 << K) - }; - - q_running.clone() * running_sum_word - }; - - // In the short range check, the word is directly witnessed. - let short_lookup = { - let short_word = z_cur.clone(); - let q_short = one.clone() - q_running; - - q_short * short_word - }; - - // q_range_check is equal to - // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 - // - 0 otherwise - let q_range_check = one.clone() - - (one.clone() - q_range_check_4.clone()) * (one.clone() - q_range_check_5.clone()); - - // num_bits is equal to - // - 5 if q_range_check_5 = 1 - // - 4 if q_range_check_4 = 1 and q_range_check_5 = 0 - // - 0 otherwise - let num_bits = q_range_check_5.clone() * Expression::Constant(F::from(5_u64)) - + (one.clone() - q_range_check_5) - * q_range_check_4 - * Expression::Constant(F::from(4_u64)); - - // Combine the running sum, short lookups and optimized range checks: - vec![ - ( - q_lookup.clone() - * ((one - q_range_check.clone()) * (running_sum_lookup + short_lookup) - + q_range_check.clone() * z_cur), - config.base.table_idx, - ), - ( - q_lookup * q_range_check * num_bits, - config.table_range_check_tag, - ), - ] - }); - - // For short lookups, check that the word has been shifted by the correct number of bits. - // https://p.z.cash/halo2-0.1:decompose-short-lookup - meta.create_gate("Short lookup bitshift", |meta| { - let q_bitshift = meta.query_selector(config.base.q_bitshift); - let word = meta.query_advice(config.base.running_sum, Rotation::prev()); - let shifted_word = meta.query_advice(config.base.running_sum, Rotation::cur()); - let inv_two_pow_s = meta.query_advice(config.base.running_sum, Rotation::next()); - - let two_pow_k = F::from(1 << K); - - // shifted_word = word * 2^{K-s} - // = word * 2^K * inv_two_pow_s - Constraints::with_selector( - q_bitshift, - Some(word * two_pow_k * inv_two_pow_s - shifted_word), - ) - }); - - config - } -} - -impl LookupRangeCheck for LookupRangeCheck45BConfig { - fn config(&self) -> &LookupRangeCheckConfig { - &self.base - } - - fn configure( - meta: &mut ConstraintSystem, - running_sum: Column, - table_idx: TableColumn, - ) -> Self { - let table_range_check_tag = meta.lookup_table_column(); - Self::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) - } - - fn table_range_check_tag(&self) -> Option { - Some(self.table_range_check_tag) - } - - #[cfg(test)] - // Fill `table_idx` and `table_range_check_tag`. - // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table - // in the Orchard context. - fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { - layouter.assign_table( - || "table_idx", - |mut table| { - let mut assign_cells = - |offset: usize, table_size, value: u64| -> Result { - for index in 0..table_size { - let new_index = index + offset; - table.assign_cell( - || "table_idx", - self.base.table_idx, - new_index, - || Value::known(F::from(index as u64)), - )?; - table.assign_cell( - || "table_range_check_tag", - self.table_range_check_tag, - new_index, - || Value::known(F::from(value)), - )?; - } - Ok(offset + table_size) - }; - - // We generate the row values lazily (we only need them during keygen). - let mut offset = 0; - - //annotation: &'v (dyn Fn() -> String + 'v), - //column: TableColumn, - //offset: usize, - //to: &'v mut (dyn FnMut() -> Value> + 'v), - - offset = assign_cells(offset, 1 << K, 0)?; - offset = assign_cells(offset, 1 << 4, 4)?; - assign_cells(offset, 1 << 5, 5)?; - - Ok(()) - }, - ) - } - - /// Constrain `x` to be a NUM_BITS word. - /// - /// `element` must have been assigned to `self.running_sum` at offset 0. - fn short_range_check( - &self, - region: &mut Region<'_, F>, - element: AssignedCell, - num_bits: usize, - ) -> Result<(), Error> { - match num_bits { - 4 => { - self.base.q_lookup.enable(region, 0)?; - self.q_range_check_4.enable(region, 0)?; - Ok(()) - } - - 5 => { - self.base.q_lookup.enable(region, 0)?; - self.q_range_check_5.enable(region, 0)?; - Ok(()) - } - - _ => self.base.short_range_check(region, element, num_bits), - } - } -} - -/// In this crate, `LookupRangeCheck45BConfig` is always used with `pallas::Base` as the prime field -/// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, -/// we introduce this alias and use it instead of that long construction. -pub type PallasLookupRangeCheck45BConfig = - LookupRangeCheck45BConfig; - -impl PallasLookupRangeCheck for PallasLookupRangeCheck45BConfig {} - /// Configuration that provides methods for a 10-bit lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] pub struct LookupRangeCheckConfig { @@ -694,6 +463,236 @@ pub type PallasLookupRangeCheckConfig = LookupRangeCheckConfig { + base: LookupRangeCheckConfig, + q_range_check_4: Selector, + q_range_check_5: Selector, + table_range_check_tag: TableColumn, +} + +impl LookupRangeCheck45BConfig { + /// The `running_sum` advice column breaks the field element into `K`-bit + /// words. It is used to construct the input expression to the lookup + /// argument. + /// + /// The `table_idx` fixed column contains values from [0..2^K). Looking up + /// a value in `table_idx` constrains it to be within this range. The table + /// can be loaded outside this helper. + /// + /// # Side-effects + /// + /// Both the `running_sum` and `constants` columns will be equality-enabled. + pub fn configure_with_tag( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + table_range_check_tag: TableColumn, + ) -> Self { + meta.enable_equality(running_sum); + + let q_lookup = meta.complex_selector(); + let q_running = meta.complex_selector(); + let q_bitshift = meta.selector(); + let q_range_check_4 = meta.complex_selector(); + let q_range_check_5 = meta.complex_selector(); + + let config = LookupRangeCheck45BConfig { + base: LookupRangeCheckConfig { + q_lookup, + q_running, + q_bitshift, + running_sum, + table_idx, + _marker: PhantomData, + }, + q_range_check_4, + q_range_check_5, + table_range_check_tag, + }; + + // https://p.z.cash/halo2-0.1:decompose-combined-lookup + meta.lookup(|meta| { + let q_lookup = meta.query_selector(config.base.q_lookup); + let q_running = meta.query_selector(config.base.q_running); + let q_range_check_4 = meta.query_selector(config.q_range_check_4); + let q_range_check_5 = meta.query_selector(config.q_range_check_5); + + let z_cur = meta.query_advice(config.base.running_sum, Rotation::cur()); + let one = Expression::Constant(F::ONE); + + // In the case of a running sum decomposition, we recover the word from + // the difference of the running sums: + // z_i = 2^{K}⋅z_{i + 1} + a_i + // => a_i = z_i - 2^{K}⋅z_{i + 1} + let running_sum_lookup = { + let running_sum_word = { + let z_next = meta.query_advice(config.base.running_sum, Rotation::next()); + z_cur.clone() - z_next * F::from(1 << K) + }; + + q_running.clone() * running_sum_word + }; + + // In the short range check, the word is directly witnessed. + let short_lookup = { + let short_word = z_cur.clone(); + let q_short = one.clone() - q_running; + + q_short * short_word + }; + + // q_range_check is equal to + // - 1 if q_range_check_4 = 1 or q_range_check_5 = 1 + // - 0 otherwise + let q_range_check = one.clone() + - (one.clone() - q_range_check_4.clone()) * (one.clone() - q_range_check_5.clone()); + + // num_bits is equal to + // - 5 if q_range_check_5 = 1 + // - 4 if q_range_check_4 = 1 and q_range_check_5 = 0 + // - 0 otherwise + let num_bits = q_range_check_5.clone() * Expression::Constant(F::from(5_u64)) + + (one.clone() - q_range_check_5) + * q_range_check_4 + * Expression::Constant(F::from(4_u64)); + + // Combine the running sum, short lookups and optimized range checks: + vec![ + ( + q_lookup.clone() + * ((one - q_range_check.clone()) * (running_sum_lookup + short_lookup) + + q_range_check.clone() * z_cur), + config.base.table_idx, + ), + ( + q_lookup * q_range_check * num_bits, + config.table_range_check_tag, + ), + ] + }); + + // For short lookups, check that the word has been shifted by the correct number of bits. + // https://p.z.cash/halo2-0.1:decompose-short-lookup + meta.create_gate("Short lookup bitshift", |meta| { + let q_bitshift = meta.query_selector(config.base.q_bitshift); + let word = meta.query_advice(config.base.running_sum, Rotation::prev()); + let shifted_word = meta.query_advice(config.base.running_sum, Rotation::cur()); + let inv_two_pow_s = meta.query_advice(config.base.running_sum, Rotation::next()); + + let two_pow_k = F::from(1 << K); + + // shifted_word = word * 2^{K-s} + // = word * 2^K * inv_two_pow_s + Constraints::with_selector( + q_bitshift, + Some(word * two_pow_k * inv_two_pow_s - shifted_word), + ) + }); + + config + } +} + +impl LookupRangeCheck for LookupRangeCheck45BConfig { + fn config(&self) -> &LookupRangeCheckConfig { + &self.base + } + + fn configure( + meta: &mut ConstraintSystem, + running_sum: Column, + table_idx: TableColumn, + ) -> Self { + let table_range_check_tag = meta.lookup_table_column(); + Self::configure_with_tag(meta, running_sum, table_idx, table_range_check_tag) + } + + fn table_range_check_tag(&self) -> Option { + Some(self.table_range_check_tag) + } + + #[cfg(test)] + // Fill `table_idx` and `table_range_check_tag`. + // This is only used in testing for now, since the Sinsemilla chip provides a pre-loaded table + // in the Orchard context. + fn load(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table_idx", + |mut table| { + let mut assign_cells = + |offset: usize, table_size, value: u64| -> Result { + for index in 0..table_size { + let new_index = index + offset; + table.assign_cell( + || "table_idx", + self.base.table_idx, + new_index, + || Value::known(F::from(index as u64)), + )?; + table.assign_cell( + || "table_range_check_tag", + self.table_range_check_tag, + new_index, + || Value::known(F::from(value)), + )?; + } + Ok(offset + table_size) + }; + + // We generate the row values lazily (we only need them during keygen). + let mut offset = 0; + + //annotation: &'v (dyn Fn() -> String + 'v), + //column: TableColumn, + //offset: usize, + //to: &'v mut (dyn FnMut() -> Value> + 'v), + + offset = assign_cells(offset, 1 << K, 0)?; + offset = assign_cells(offset, 1 << 4, 4)?; + assign_cells(offset, 1 << 5, 5)?; + + Ok(()) + }, + ) + } + + /// Constrain `x` to be a NUM_BITS word. + /// + /// `element` must have been assigned to `self.running_sum` at offset 0. + fn short_range_check( + &self, + region: &mut Region<'_, F>, + element: AssignedCell, + num_bits: usize, + ) -> Result<(), Error> { + match num_bits { + 4 => { + self.base.q_lookup.enable(region, 0)?; + self.q_range_check_4.enable(region, 0)?; + Ok(()) + } + + 5 => { + self.base.q_lookup.enable(region, 0)?; + self.q_range_check_5.enable(region, 0)?; + Ok(()) + } + + _ => self.base.short_range_check(region, element, num_bits), + } + } +} + +/// In this crate, `LookupRangeCheck45BConfig` is always used with `pallas::Base` as the prime field +/// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, +/// we introduce this alias and use it instead of that long construction. +pub type PallasLookupRangeCheck45BConfig = + LookupRangeCheck45BConfig; + +impl PallasLookupRangeCheck for PallasLookupRangeCheck45BConfig {} + #[cfg(test)] mod tests { use super::super::lebs2ip; diff --git a/halo2_proofs/src/plonk/error.rs b/halo2_proofs/src/plonk/error.rs index 1830be3b2b..6ffed3a300 100644 --- a/halo2_proofs/src/plonk/error.rs +++ b/halo2_proofs/src/plonk/error.rs @@ -40,7 +40,7 @@ pub enum Error { ColumnNotInPermutation(Column), /// An error relating to a lookup table. TableError(TableError), - /// Try to hash from a private point when enable_hash_from_private_point is unset. + /// Try to hash from a private point when enable_hash_from_private_point is not set. HashFromPrivatePoint, } From 7f5c0babd61f8ca46c9165a1adfac298d3fd3a11 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 2 Jul 2024 14:13:42 +0200 Subject: [PATCH 109/121] Remove MerkleSinsemillaInstructions --- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 55 ++------------------- 1 file changed, 4 insertions(+), 51 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index f344202cc6..5cee5114ca 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -203,60 +203,13 @@ where } } -/// Defines the concrete types of `SinsemillaInstructions` required by the `MerkleCRH`. -pub(crate) trait MerkleSinsemillaInstructions -where - Self: SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - MessagePiece = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::MessagePiece, - RunningSum = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::RunningSum, - X = as SinsemillaInstructions< - pallas::Affine, - { sinsemilla::K }, - { sinsemilla::C }, - >>::X, - >, - Hash: HashDomains, - Commit: CommitDomains, - F: FixedPoints, - Lookup: PallasLookupRangeCheck, -{ -} - -impl MerkleSinsemillaInstructions - for MerkleChip -where - Hash: HashDomains, - F: FixedPoints, - Commit: CommitDomains, - Lookup: PallasLookupRangeCheck, -{ -} - -impl +impl MerkleInstructions - for InstructionsChip + for MerkleChip where - InstructionsChip: MerkleSinsemillaInstructions - + UtilitiesInstructions> - + CondSwapInstructions - + Chip> - + Eq - + Clone - + std::fmt::Debug, - Hash: HashDomains, + Hash: HashDomains + Eq, Fixed: FixedPoints, - Commit: CommitDomains, + Commit: CommitDomains + Eq, Lookup: PallasLookupRangeCheck, { #[allow(non_snake_case)] From 41c7d2e681bd060206dfe20f870828b51625cb46 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 5 Jul 2024 18:06:09 +0200 Subject: [PATCH 110/121] Restore code coverage --- .github/workflows/ci.yml | 55 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a182c0f209..7ed590bc01 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -127,33 +127,34 @@ jobs: - name: Test halo2 book run: mdbook test -L target/debug/deps book/ -# codecov: -# name: Code coverage -# runs-on: ubuntu-latest -# -# steps: -# - uses: actions/checkout@v3 -# # Use stable for this to ensure that cargo-tarpaulin can be built. -# - id: prepare -# uses: ./.github/actions/prepare -# with: -# toolchain: stable -# nightly-features: true -# - name: Install cargo-tarpaulin -# uses: actions-rs/cargo@v1 -# with: -# command: install -# args: cargo-tarpaulin -# - name: Generate coverage report -# uses: actions-rs/cargo@v1 -# with: -# command: tarpaulin -# args: > -# ${{ steps.prepare.outputs.feature-flags }} -# --timeout 600 -# --out Xml -# - name: Upload coverage to Codecov -# uses: codecov/codecov-action@v3.1.4 + codecov: + name: Code coverage + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + # Use stable for this to ensure that cargo-tarpaulin can be built. + - id: prepare + uses: ./.github/actions/prepare + with: + toolchain: stable + nightly-features: true + - name: Install cargo-tarpaulin + uses: actions-rs/cargo@v1 + with: + command: install + args: cargo-tarpaulin + - name: Generate coverage report + uses: actions-rs/cargo@v1 + with: + command: tarpaulin + # Extend the timeout to 3600 to ensure the code coverage test pass + args: > + ${{ steps.prepare.outputs.feature-flags }} + --timeout 3600 + --out Xml + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3.1.4 doc-links: name: Intra-doc links From 9c29f2768a99fa8f91d63a6c8d86c3d21a088c4c Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 5 Jul 2024 18:08:21 +0200 Subject: [PATCH 111/121] Refactor --- halo2_gadgets/src/ecc.rs | 2 +- halo2_gadgets/src/sinsemilla/merkle.rs | 2 +- halo2_gadgets/src/sinsemilla/primitives.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 2da0c31952..060ea32b60 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -972,7 +972,7 @@ pub(crate) mod tests { } #[test] - fn test_against_stored_ecc_chip() { + fn test_ecc_chip_against_stored_circuit() { let circuit: MyCircuit = MyCircuit { test_errors: false, _lookup_marker: PhantomData, diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index c0b130290d..1e1a2b667d 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -406,7 +406,7 @@ pub mod tests { } #[test] - fn test_against_stored_merkle_chip() { + fn test_merkle_chip_against_stored_circuit() { let circuit = generate_circuit(); test_against_stored_circuit(circuit, "merkle_chip", 4160); } diff --git a/halo2_gadgets/src/sinsemilla/primitives.rs b/halo2_gadgets/src/sinsemilla/primitives.rs index ad9e397b5e..215c09ff99 100644 --- a/halo2_gadgets/src/sinsemilla/primitives.rs +++ b/halo2_gadgets/src/sinsemilla/primitives.rs @@ -184,7 +184,6 @@ impl HashDomain { #[derive(Debug)] #[allow(non_snake_case)] pub struct CommitDomain { - /// A domain in which $\mathsf{SinsemillaHashToPoint}$ and $\mathsf{SinsemillaHash}$ can be used M: HashDomain, R: pallas::Point, } From 714fff05eb7cd6ea433ac2e98f7943dc3f97e43b Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Sun, 7 Jul 2024 16:17:40 +0200 Subject: [PATCH 112/121] Remove redundancy in Merkle tests --- halo2_gadgets/src/sinsemilla/merkle.rs | 290 +++++++++++-------------- 1 file changed, 124 insertions(+), 166 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 1e1a2b667d..27b00cb978 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -187,10 +187,7 @@ pub mod tests { tests::test_utils::test_against_stored_circuit, utilities::{ i2lebsp, - lookup_range_check::{ - LookupRangeCheck, LookupRangeCheck45BConfig, PallasLookupRangeCheck45BConfig, - PallasLookupRangeCheckConfig, - }, + lookup_range_check::{PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig}, UtilitiesInstructions, }, }; @@ -203,94 +200,101 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; + use crate::utilities::lookup_range_check::PallasLookupRangeCheck; use rand::{rngs::OsRng, RngCore}; + use std::marker::PhantomData; use std::{convert::TryInto, iter}; const MERKLE_DEPTH: usize = 32; #[derive(Default)] - struct MyCircuit { + struct MyCircuit { leaf: Value, leaf_pos: Value, merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, + _lookup_marker: PhantomData, } - impl Circuit for MyCircuit { - type Config = ( - MerkleConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - PallasLookupRangeCheckConfig, - >, - MerkleConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - PallasLookupRangeCheckConfig, - >, + type MyConfig = ( + MerkleConfig, + MerkleConfig, + ); + + fn configure( + meta: &mut ConstraintSystem, + enable_hash_from_private_point: bool, + ) -> MyConfig { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + // NB: In the actual Action circuit, these fixed columns will be reused + // by other chips. For this test, we are creating new fixed columns. + let fixed_y_q_1 = meta.fixed_column(); + let fixed_y_q_2 = meta.fixed_column(); + + // Fixed columns for the Sinsemilla generator lookup table + let lookup = ( + meta.lookup_table_column(), + meta.lookup_table_column(), + meta.lookup_table_column(), ); + + let range_check = Lookup::configure(meta, advices[9], lookup.0); + + let sinsemilla_config_1 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + fixed_y_q_1, + lookup, + range_check, + enable_hash_from_private_point, + ); + let config1 = MerkleChip::configure(meta, sinsemilla_config_1); + + let sinsemilla_config_2 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + fixed_y_q_2, + lookup, + range_check, + enable_hash_from_private_point, + ); + let config2 = MerkleChip::configure(meta, sinsemilla_config_2); + + (config1, config2) + } + + impl Circuit for MyCircuit { + type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - Self::default() + MyCircuit { + leaf: Value::default(), + leaf_pos: Value::default(), + merkle_path: Value::default(), + _lookup_marker: PhantomData, + } } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - // NB: In the actual Action circuit, these fixed columns will be reused - // by other chips. For this test, we are creating new fixed columns. - let fixed_y_q_1 = meta.fixed_column(); - let fixed_y_q_2 = meta.fixed_column(); - - // Fixed columns for the Sinsemilla generator lookup table - let lookup = ( - meta.lookup_table_column(), - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - - let range_check = PallasLookupRangeCheckConfig::configure(meta, advices[9], lookup.0); - - let sinsemilla_config_1 = SinsemillaChip::configure( - meta, - advices[5..].try_into().unwrap(), - advices[7], - fixed_y_q_1, - lookup, - range_check, - false, - ); - let config1 = MerkleChip::configure(meta, sinsemilla_config_1); - - let sinsemilla_config_2 = SinsemillaChip::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - fixed_y_q_2, - lookup, - range_check, - false, - ); - let config2 = MerkleChip::configure(meta, sinsemilla_config_2); - - (config1, config2) + configure::(meta, false) } fn synthesize( @@ -299,12 +303,10 @@ pub mod tests { mut layouter: impl Layouter, ) -> Result<(), Error> { // Load generator table (shared across both configs) - SinsemillaChip::< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - PallasLookupRangeCheckConfig, - >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; + SinsemillaChip::::load( + config.0.sinsemilla_config.clone(), + &mut layouter, + )?; // Construct Merkle chips which will be placed side-by-side in the circuit. let chip_1 = MerkleChip::construct(config.0.clone()); @@ -377,7 +379,7 @@ pub mod tests { } } - fn generate_circuit() -> MyCircuit { + fn generate_circuit() -> MyCircuit { let mut rng = OsRng; // Choose a random leaf and position @@ -394,12 +396,13 @@ pub mod tests { leaf: Value::known(leaf), leaf_pos: Value::known(pos), merkle_path: Value::known(path.try_into().unwrap()), + _lookup_marker: PhantomData, } } #[test] fn merkle_chip() { - let circuit = generate_circuit(); + let circuit: MyCircuit = generate_circuit(); let prover = MockProver::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) @@ -407,7 +410,7 @@ pub mod tests { #[test] fn test_merkle_chip_against_stored_circuit() { - let circuit = generate_circuit(); + let circuit: MyCircuit = generate_circuit(); test_against_stored_circuit(circuit, "merkle_chip", 4160); } @@ -420,7 +423,12 @@ pub mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit::default(); + let circuit: MyCircuit = MyCircuit { + leaf: Value::default(), + leaf_pos: Value::default(), + merkle_path: Value::default(), + _lookup_marker: PhantomData, + }; halo2_proofs::dev::CircuitLayout::default() .show_labels(true) .render(11, &circuit, &root) @@ -428,88 +436,30 @@ pub mod tests { } #[derive(Default)] - struct MyCircuitWithHashFromPrivatePoint { + struct MyCircuitWithHashFromPrivatePoint { leaf: Value, leaf_pos: Value, merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, + _lookup_marker: PhantomData, } - impl Circuit for MyCircuitWithHashFromPrivatePoint { - type Config = ( - MerkleConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheck45BConfig, - >, - MerkleConfig< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - LookupRangeCheck45BConfig, - >, - ); + impl Circuit + for MyCircuitWithHashFromPrivatePoint + { + type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - Self::default() + MyCircuitWithHashFromPrivatePoint { + leaf: Value::default(), + leaf_pos: Value::default(), + merkle_path: Value::default(), + _lookup_marker: PhantomData, + } } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Shared fixed column for loading constants - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - // NB: In the actual Action circuit, these fixed columns will be reused - // by other chips. For this test, we are creating new fixed columns. - let fixed_y_q_1 = meta.fixed_column(); - let fixed_y_q_2 = meta.fixed_column(); - - // Fixed columns for the Sinsemilla generator lookup table - let lookup = ( - meta.lookup_table_column(), - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - - let range_check = LookupRangeCheck45BConfig::configure(meta, advices[9], lookup.0); - - let sinsemilla_config_1 = SinsemillaChip::configure( - meta, - advices[5..].try_into().unwrap(), - advices[7], - fixed_y_q_1, - lookup, - range_check, - true, - ); - let config1 = MerkleChip::configure(meta, sinsemilla_config_1); - - let sinsemilla_config_2 = SinsemillaChip::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - fixed_y_q_2, - lookup, - range_check, - true, - ); - let config2 = MerkleChip::configure(meta, sinsemilla_config_2); - - (config1, config2) + configure(meta, true) } fn synthesize( @@ -517,13 +467,11 @@ pub mod tests { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - // Load generator table (shared across both configs) for Sinsemilla45BChip - SinsemillaChip::< - TestHashDomain, - TestCommitDomain, - TestFixedBases, - PallasLookupRangeCheck45BConfig, - >::load(config.0.sinsemilla_config.clone(), &mut layouter)?; + // Load generator table (shared across both configs) + SinsemillaChip::::load( + config.0.sinsemilla_config.clone(), + &mut layouter, + )?; // Construct Merkle chips which will be placed side-by-side in the circuit. let chip_1 = MerkleChip::construct(config.0.clone()); @@ -596,7 +544,8 @@ pub mod tests { } } - fn generate_circuit_4_5_b() -> MyCircuitWithHashFromPrivatePoint { + fn generate_circuit_4_5_b( + ) -> MyCircuitWithHashFromPrivatePoint { let mut rng = OsRng; // Choose a random leaf and position @@ -613,11 +562,13 @@ pub mod tests { leaf: Value::known(leaf), leaf_pos: Value::known(pos), merkle_path: Value::known(path.try_into().unwrap()), + _lookup_marker: PhantomData, } } #[test] fn merkle_with_hash_from_private_point_chip_4_5_b() { - let circuit = generate_circuit_4_5_b(); + let circuit: MyCircuitWithHashFromPrivatePoint = + generate_circuit_4_5_b(); let prover = MockProver::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) @@ -625,7 +576,8 @@ pub mod tests { #[test] fn test_against_stored_merkle_with_hash_from_private_point_chip_4_5_b() { - let circuit = generate_circuit_4_5_b(); + let circuit: MyCircuitWithHashFromPrivatePoint = + generate_circuit_4_5_b(); test_against_stored_circuit(circuit, "merkle_with_private_init_chip_4_5_b", 4160); } @@ -643,7 +595,13 @@ pub mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuitWithHashFromPrivatePoint::default(); + let circuit: MyCircuitWithHashFromPrivatePoint = + MyCircuitWithHashFromPrivatePoint { + leaf: Value::default(), + leaf_pos: Value::default(), + merkle_path: Value::default(), + _lookup_marker: PhantomData, + }; halo2_proofs::dev::CircuitLayout::default() .show_labels(true) .render(11, &circuit, &root) From 70af8098e98215dedbaf1597484158c1300a3e58 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Sun, 7 Jul 2024 16:36:37 +0200 Subject: [PATCH 113/121] Rename MyCircuit into MyMagnitudeSignCircuit on fixed_mul/short tests --- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 1cd2618f68..5f801fdf33 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -471,7 +471,7 @@ pub mod tests { } #[derive(Default)] - struct MyCircuit { + struct MyMagnitudeSignCircuit { magnitude: Value, sign: Value, // For test checking @@ -479,16 +479,18 @@ pub mod tests { _lookup_marker: PhantomData, } - impl UtilitiesInstructions for MyCircuit { + impl UtilitiesInstructions + for MyMagnitudeSignCircuit + { type Var = AssignedCell; } - impl Circuit for MyCircuit { + impl Circuit for MyMagnitudeSignCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit { + MyMagnitudeSignCircuit { magnitude: Value::unknown(), sign: Value::unknown(), magnitude_error: Value::unknown(), @@ -582,41 +584,41 @@ pub mod tests { } } - impl MyCircuit { + impl MyMagnitudeSignCircuit { fn test_invalid_magnitude_sign() { // Magnitude larger than 64 bits should fail { - let circuits: Vec> = vec![ + let circuits: Vec> = vec![ // 2^64 - MyCircuit:: { + MyMagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 64)), sign: Value::known(pallas::Base::one()), magnitude_error: Value::known(pallas::Base::from(1 << 1)), _lookup_marker: PhantomData, }, // -2^64 - MyCircuit:: { + MyMagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 64)), sign: Value::known(-pallas::Base::one()), magnitude_error: Value::known(pallas::Base::from(1 << 1)), _lookup_marker: PhantomData, }, // 2^66 - MyCircuit:: { + MyMagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 66)), sign: Value::known(pallas::Base::one()), magnitude_error: Value::known(pallas::Base::from(1 << 3)), _lookup_marker: PhantomData, }, // -2^66 - MyCircuit:: { + MyMagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 66)), sign: Value::known(-pallas::Base::one()), magnitude_error: Value::known(pallas::Base::from(1 << 3)), _lookup_marker: PhantomData, }, // 2^254 - MyCircuit:: { + MyMagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), sign: Value::known(pallas::Base::one()), magnitude_error: Value::known( @@ -625,7 +627,7 @@ pub mod tests { _lookup_marker: PhantomData, }, // -2^254 - MyCircuit:: { + MyMagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), sign: Value::known(-pallas::Base::one()), magnitude_error: Value::known( @@ -680,7 +682,7 @@ pub mod tests { // Sign that is not +/- 1 should fail { let magnitude_u64 = rand::random::(); - let circuit: MyCircuit = MyCircuit { + let circuit: MyMagnitudeSignCircuit = MyMagnitudeSignCircuit { magnitude: Value::known(pallas::Base::from(magnitude_u64)), sign: Value::known(pallas::Base::zero()), magnitude_error: Value::unknown(), @@ -743,12 +745,12 @@ pub mod tests { #[cfg(feature = "test-dev-graph")] #[test] fn invalid_magnitude_sign() { - MyCircuit::::test_invalid_magnitude_sign(); + MyMagnitudeSignCircuit::::test_invalid_magnitude_sign(); } #[test] fn invalid_magnitude_sign_4_5_b() { - MyCircuit::::test_invalid_magnitude_sign(); + MyMagnitudeSignCircuit::::test_invalid_magnitude_sign(); } pub(crate) fn test_mul_sign( From 68d65e0f33a247595528c49462503e834369a70e Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Sun, 7 Jul 2024 16:56:20 +0200 Subject: [PATCH 114/121] Refactor --- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 3 +- halo2_gadgets/src/sinsemilla.rs | 2 +- .../src/sinsemilla/chip/hash_to_point.rs | 156 +++++++++--------- halo2_gadgets/src/sinsemilla/merkle.rs | 9 +- .../src/utilities/lookup_range_check.rs | 57 +++++-- 5 files changed, 124 insertions(+), 103 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 5f801fdf33..d5ea2f07e4 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -588,7 +588,7 @@ pub mod tests { fn test_invalid_magnitude_sign() { // Magnitude larger than 64 bits should fail { - let circuits: Vec> = vec![ + let circuits = [ // 2^64 MyMagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 64)), @@ -742,7 +742,6 @@ pub mod tests { } } - #[cfg(feature = "test-dev-graph")] #[test] fn invalid_magnitude_sign() { MyMagnitudeSignCircuit::::test_invalid_magnitude_sign(); diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index d6dd82e4a6..6f56e35da3 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -835,7 +835,7 @@ pub(crate) mod tests { } #[test] - fn test_against_stored_sinsemilla_chip() { + fn test_sinsemilla_chip_against_stored_circuit() { let circuit: MyCircuit = MyCircuit { _lookup_marker: PhantomData, }; diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index e6ce0e9d43..ac81a5e485 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -50,7 +50,7 @@ where ), Error, > { - let (offset, x_a, y_a) = self.public_initialization(region, Q)?; + let (offset, x_a, y_a) = self.public_q_initialization(region, Q)?; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; @@ -80,87 +80,13 @@ where return Err(Error::HashFromPrivatePoint); } - let (offset, x_a, y_a) = self.private_initialization(region, Q)?; + let (offset, x_a, y_a) = self.private_q_initialization(region, Q)?; let (x_a, y_a, zs_sum) = self.hash_all_pieces(region, offset, message, x_a, y_a)?; self.check_hash_result(EccPointQ::PrivatePoint(Q), message, x_a, y_a, zs_sum) } - #[allow(unused_variables)] - #[allow(non_snake_case)] - #[allow(clippy::type_complexity)] - fn check_hash_result( - &self, - Q: EccPointQ, - message: &>::Message, - x_a: X, - y_a: AssignedCell, pallas::Base>, - zs_sum: Vec>>, - ) -> Result< - ( - NonIdentityEccPoint, - Vec>>, - ), - Error, - > { - #[cfg(test)] - // Check equivalence to result from primitives::sinsemilla::hash_to_point - { - use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; - - use group::{prime::PrimeCurveAffine, Curve}; - use pasta_curves::arithmetic::CurveExt; - - let field_elems: Value> = message - .iter() - .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) - .collect(); - - let value_Q = match Q { - EccPointQ::PublicPoint(p) => Value::known(p), - EccPointQ::PrivatePoint(p) => p.point(), - }; - - field_elems - .zip(x_a.value().zip(y_a.value())) - .zip(value_Q) - .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { - // Get message as a bitstring. - let bitstring: Vec = field_elems - .iter() - .flat_map(|(elem, num_words)| { - elem.to_le_bits().into_iter().take(K * num_words) - }) - .collect(); - - let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); - let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); - - // We can use complete addition here because it differs from - // incomplete addition with negligible probability. - let expected_point = bitstring - .chunks(K) - .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); - let actual_point = - pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); - expected_point.to_affine() == actual_point - }); - } - - x_a.value() - .zip(y_a.value()) - .error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?; - Ok(( - NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a), - zs_sum, - )) - } - #[allow(non_snake_case)] /// Assign the coordinates of the initial public point `Q`. /// @@ -174,7 +100,7 @@ where /// -------------------------------------- /// | 0 | | y_Q | | /// | 1 | x_Q | | 1 | - fn public_initialization( + fn public_q_initialization( &self, region: &mut Region<'_, pallas::Base>, Q: pallas::Affine, @@ -235,7 +161,7 @@ where /// -------------------------------------- /// | 0 | | y_Q | | /// | 1 | x_Q | | 1 | - fn private_initialization( + fn private_q_initialization( &self, region: &mut Region<'_, pallas::Base>, Q: &NonIdentityEccPoint, @@ -545,6 +471,80 @@ where Ok((x_a, y_a, zs)) } + + #[allow(unused_variables)] + #[allow(non_snake_case)] + #[allow(clippy::type_complexity)] + fn check_hash_result( + &self, + Q: EccPointQ, + message: &>::Message, + x_a: X, + y_a: AssignedCell, pallas::Base>, + zs_sum: Vec>>, + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { + #[cfg(test)] + // Check equivalence to result from primitives::sinsemilla::hash_to_point + { + use crate::sinsemilla::primitives::{K, S_PERSONALIZATION}; + + use group::{prime::PrimeCurveAffine, Curve}; + use pasta_curves::arithmetic::CurveExt; + + let field_elems: Value> = message + .iter() + .map(|piece| piece.field_elem().map(|elem| (elem, piece.num_words()))) + .collect(); + + let value_Q = match Q { + EccPointQ::PublicPoint(p) => Value::known(p), + EccPointQ::PrivatePoint(p) => p.point(), + }; + + field_elems + .zip(x_a.value().zip(y_a.value())) + .zip(value_Q) + .assert_if_known(|((field_elems, (x_a, y_a)), value_Q)| { + // Get message as a bitstring. + let bitstring: Vec = field_elems + .iter() + .flat_map(|(elem, num_words)| { + elem.to_le_bits().into_iter().take(K * num_words) + }) + .collect(); + + let hasher_S = pallas::Point::hash_to_curve(S_PERSONALIZATION); + let S = |chunk: &[bool]| hasher_S(&lebs2ip_k(chunk).to_le_bytes()); + + // We can use complete addition here because it differs from + // incomplete addition with negligible probability. + let expected_point = bitstring + .chunks(K) + .fold(value_Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); + let actual_point = + pallas::Affine::from_xy(x_a.evaluate(), y_a.evaluate()).unwrap(); + expected_point.to_affine() == actual_point + }); + } + + x_a.value() + .zip(y_a.value()) + .error_if_known_and(|(x_a, y_a)| x_a.is_zero_vartime() || y_a.is_zero_vartime())?; + Ok(( + NonIdentityEccPoint::from_coordinates_unchecked(x_a.0, y_a), + zs_sum, + )) + } } /// The x-coordinate of the accumulator in a Sinsemilla hash instance. diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index 27b00cb978..adf1f02b3b 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -187,7 +187,10 @@ pub mod tests { tests::test_utils::test_against_stored_circuit, utilities::{ i2lebsp, - lookup_range_check::{PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig}, + lookup_range_check::{ + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheckConfig, + }, UtilitiesInstructions, }, }; @@ -200,10 +203,8 @@ pub mod tests { plonk::{Circuit, ConstraintSystem, Error}, }; - use crate::utilities::lookup_range_check::PallasLookupRangeCheck; use rand::{rngs::OsRng, RngCore}; - use std::marker::PhantomData; - use std::{convert::TryInto, iter}; + use std::{convert::TryInto, iter, marker::PhantomData}; const MERKLE_DEPTH: usize = 32; diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index a7dde6f2e3..83ed67ee38 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -34,8 +34,8 @@ impl RangeConstrained> { /// # Panics /// /// Panics if `bitrange.len() >= K`. - pub fn witness_short>( - lookup_config: &L, + pub fn witness_short>( + lookup_config: &Lookup, layouter: impl Layouter, value: Value<&F>, bitrange: Range, @@ -817,6 +817,16 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); + } + + #[test] + fn test_lookup_range_check_against_stored_circuit() { + let circuit: MyLookupCircuit = + MyLookupCircuit { + num_words: 6, + _field_marker: PhantomData, + _lookup_marker: PhantomData, + }; test_against_stored_circuit(circuit, "lookup_range_check", 1888); } @@ -832,7 +842,16 @@ mod tests { let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); + } + #[test] + fn test_lookup_range_check_against_stored_circuit_4_5_b() { + let circuit: MyLookupCircuit = + MyLookupCircuit { + num_words: 6, + _field_marker: PhantomData, + _lookup_marker: PhantomData, + }; test_against_stored_circuit(circuit, "lookup_range_check_4_5_b", 2048); } @@ -907,6 +926,9 @@ mod tests { #[test] fn short_range_check() { + let proof_size_10_bits = 1888; + let proof_size_4_5_10_bits = 2048; + // Edge case: zero bits (case 0) let element = pallas::Base::ZERO; let num_bits = 0; @@ -915,14 +937,14 @@ mod tests { num_bits, &Ok(()), "short_range_check_case0", - 1888, + proof_size_10_bits, ); test_short_range_check::( element, num_bits, &Ok(()), "short_range_check_4_5_b_case0", - 2048, + proof_size_4_5_10_bits, ); // Edge case: K bits (case 1) @@ -933,14 +955,14 @@ mod tests { num_bits, &Ok(()), "short_range_check_case1", - 1888, + proof_size_10_bits, ); test_short_range_check::( element, num_bits, &Ok(()), "short_range_check_4_5_b_case1", - 2048, + proof_size_4_5_10_bits, ); // Element within `num_bits` (case 2) @@ -951,14 +973,14 @@ mod tests { num_bits, &Ok(()), "short_range_check_case2", - 1888, + proof_size_10_bits, ); test_short_range_check::( element, num_bits, &Ok(()), "short_range_check_4_5_b_case2", - 2048, + proof_size_4_5_10_bits, ); // Element larger than `num_bits` but within K bits @@ -976,14 +998,14 @@ mod tests { num_bits, &error, "not_saved", - 0, + proof_size_10_bits, ); test_short_range_check::( element, num_bits, &error, "not_saved", - 0, + proof_size_4_5_10_bits, ); // Element larger than K bits @@ -1010,18 +1032,17 @@ mod tests { num_bits, &error, "not_saved", - 0, + proof_size_10_bits, ); test_short_range_check::( element, num_bits, &error, "not_saved", - 0, + proof_size_4_5_10_bits, ); - // Element which is not within `num_bits`, but which has a shifted value within - // num_bits + // Element which is not within `num_bits`, but which has a shifted value within num_bits let num_bits = 6; let shifted = pallas::Base::from((1 << num_bits) - 1); // Recall that shifted = element * 2^{K-s} @@ -1042,14 +1063,14 @@ mod tests { num_bits as usize, &error, "not_saved", - 0, + proof_size_10_bits, ); test_short_range_check::( element, num_bits as usize, &error, "not_saved", - 0, + proof_size_4_5_10_bits, ); // Element within 4 bits @@ -1058,7 +1079,7 @@ mod tests { 4, &Ok(()), "short_range_check_4_5_b_case3", - 2048, + proof_size_4_5_10_bits, ); // Element larger than 5 bits @@ -1073,7 +1094,7 @@ mod tests { }, }]), "not_saved", - 0, + proof_size_4_5_10_bits, ); } } From a8832c9594740579ffe63361e9fa8747b71cfb91 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 16 Jul 2024 13:38:44 +0200 Subject: [PATCH 115/121] Make cond_swap_config public in merkle_config --- halo2_gadgets/src/sinsemilla/merkle/chip.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/halo2_gadgets/src/sinsemilla/merkle/chip.rs b/halo2_gadgets/src/sinsemilla/merkle/chip.rs index 5cee5114ca..c41ec86d53 100644 --- a/halo2_gadgets/src/sinsemilla/merkle/chip.rs +++ b/halo2_gadgets/src/sinsemilla/merkle/chip.rs @@ -40,7 +40,8 @@ where { advices: [Column; 5], q_decompose: Selector, - pub(super) cond_swap_config: CondSwapConfig, + /// Configuration for the `CondSwapChip` used by the `MerkleChip`. + pub cond_swap_config: CondSwapConfig, pub(super) sinsemilla_config: SinsemillaConfig, } From 8a2cbeef438597e08f03e8284966bfbfae9ceaa7 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Wed, 17 Jul 2024 10:21:07 +0200 Subject: [PATCH 116/121] Take into account Pablo's review --- halo2_gadgets/src/ecc.rs | 63 +++++++--------- halo2_gadgets/src/sinsemilla.rs | 51 +++++++------ .../src/sinsemilla/chip/hash_to_point.rs | 1 - halo2_gadgets/src/sinsemilla/merkle.rs | 70 +++++++++++------- .../src/utilities/lookup_range_check.rs | 72 ++++++++----------- 5 files changed, 123 insertions(+), 134 deletions(-) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 060ea32b60..e534ce10a6 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -625,14 +625,6 @@ pub(crate) mod tests { use group::{prime::PrimeCurveAffine, Curve, Group}; use std::marker::PhantomData; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use lazy_static::lazy_static; - use pasta_curves::pallas; - use super::{ chip::{ find_zs_and_us, BaseFieldElem, EccChip, EccConfig, FixedPoint, FullScalar, ShortScalar, @@ -646,6 +638,13 @@ pub(crate) mod tests { PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, }, }; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use lazy_static::lazy_static; + use pasta_curves::pallas; #[derive(Debug, Eq, PartialEq, Clone)] pub(crate) struct TestFixedBases; @@ -778,16 +777,22 @@ pub(crate) mod tests { _lookup_marker: PhantomData, } + impl MyCircuit { + fn new(test_errors: bool) -> Self { + Self { + test_errors, + _lookup_marker: PhantomData, + } + } + } + #[allow(non_snake_case)] impl Circuit for MyCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit { - test_errors: false, - _lookup_marker: PhantomData, - } + MyCircuit::new(false) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -962,21 +967,15 @@ pub(crate) mod tests { #[test] fn ecc_chip() { - let k = 11; - let circuit: MyCircuit = MyCircuit { - test_errors: true, - _lookup_marker: PhantomData, - }; + let k = 13; + let circuit = MyCircuit::::new(true); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] fn test_ecc_chip_against_stored_circuit() { - let circuit: MyCircuit = MyCircuit { - test_errors: false, - _lookup_marker: PhantomData, - }; + let circuit = MyCircuit::::new(false); test_against_stored_circuit(circuit, "ecc_chip", 3872); } @@ -989,10 +988,7 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit: MyCircuit = MyCircuit { - test_errors: false, - _lookup_marker: PhantomData, - }; + let circuit = MyCircuit::::new(false); halo2_proofs::dev::CircuitLayout::default() .render(13, &circuit, &root) .unwrap(); @@ -1000,11 +996,8 @@ pub(crate) mod tests { #[test] fn ecc_chip_4_5_b() { - let k = 11; - let circuit: MyCircuit = MyCircuit { - test_errors: true, - _lookup_marker: PhantomData, - }; + let k = 13; + let circuit = MyCircuit::::new(true); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) @@ -1012,10 +1005,7 @@ pub(crate) mod tests { #[test] fn test_against_stored_ecc_chip_4_5_b() { - let circuit: MyCircuit = MyCircuit { - test_errors: false, - _lookup_marker: PhantomData, - }; + let circuit = MyCircuit::::new(false); test_against_stored_circuit(circuit, "ecc_chip_4_5_b", 3968); } @@ -1029,10 +1019,7 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit: MyCircuit = MyCircuit { - test_errors: false, - _lookup_marker: PhantomData, - }; + let circuit = MyCircuit::::new(false); halo2_proofs::dev::CircuitLayout::default() .render(13, &circuit, &root) .unwrap(); diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 6f56e35da3..4d87fe757c 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -589,6 +589,14 @@ pub(crate) mod tests { _lookup_marker: PhantomData, } + impl MyCircuit { + fn new() -> Self { + Self { + _lookup_marker: PhantomData, + } + } + } + type MyConfig = ( EccConfig, SinsemillaConfig, @@ -805,9 +813,7 @@ pub(crate) mod tests { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit { - _lookup_marker: PhantomData, - } + MyCircuit::new() } #[allow(non_snake_case)] @@ -827,18 +833,14 @@ pub(crate) mod tests { #[test] fn sinsemilla_chip() { let k = 11; - let circuit: MyCircuit = MyCircuit { - _lookup_marker: PhantomData, - }; + let circuit = MyCircuit::::new(); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] fn test_sinsemilla_chip_against_stored_circuit() { - let circuit: MyCircuit = MyCircuit { - _lookup_marker: PhantomData, - }; + let circuit = MyCircuit::::new(); test_against_stored_circuit(circuit, "sinsemilla_chip", 4576); } @@ -852,9 +854,7 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); - let circuit: MyCircuit = MyCircuit { - _lookup_marker: PhantomData, - }; + let circuit = MyCircuit::::new(); halo2_proofs::dev::CircuitLayout::default() .render(11, &circuit, &root) .unwrap(); @@ -864,6 +864,14 @@ pub(crate) mod tests { _lookup_marker: PhantomData, } + impl MyCircuitWithHashFromPrivatePoint { + fn new() -> Self { + Self { + _lookup_marker: PhantomData, + } + } + } + impl Circuit for MyCircuitWithHashFromPrivatePoint { @@ -872,9 +880,7 @@ pub(crate) mod tests { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuitWithHashFromPrivatePoint { - _lookup_marker: PhantomData, - } + MyCircuitWithHashFromPrivatePoint::new() } #[allow(non_snake_case)] @@ -894,20 +900,14 @@ pub(crate) mod tests { #[test] fn sinsemilla_with_hash_from_private_point_chip_4_5_b() { let k = 11; - let circuit: MyCircuitWithHashFromPrivatePoint = - MyCircuitWithHashFromPrivatePoint { - _lookup_marker: PhantomData, - }; + let circuit = MyCircuitWithHashFromPrivatePoint::::new(); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] fn test_against_stored_sinsemilla_with_hash_from_private_point_chip_4_5_b() { - let circuit: MyCircuitWithHashFromPrivatePoint = - MyCircuitWithHashFromPrivatePoint { - _lookup_marker: PhantomData, - }; + let circuit = MyCircuitWithHashFromPrivatePoint::::new(); test_against_stored_circuit(circuit, "sinsemilla_with_private_init_chip_4_5_b", 4672); } @@ -924,10 +924,7 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); - let circuit: MyCircuitWithHashFromPrivatePoint = - MyCircuitWithHashFromPrivatePoint { - _lookup_marker: PhantomData, - }; + let circuit = MyCircuitWithHashFromPrivatePoint::::new(); halo2_proofs::dev::CircuitLayout::default() .render(11, &circuit, &root) .unwrap(); diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index ac81a5e485..c3d928ca69 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -471,7 +471,6 @@ where Ok((x_a, y_a, zs)) } - #[allow(unused_variables)] #[allow(non_snake_case)] #[allow(clippy::type_complexity)] diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index adf1f02b3b..e0e14afc38 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -216,6 +216,21 @@ pub mod tests { _lookup_marker: PhantomData, } + impl MyCircuit { + fn new( + leaf: Value, + leaf_pos: Value, + merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, + ) -> Self { + Self { + leaf, + leaf_pos, + merkle_path, + _lookup_marker: PhantomData, + } + } + } + type MyConfig = ( MerkleConfig, MerkleConfig, @@ -286,12 +301,7 @@ pub mod tests { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit { - leaf: Value::default(), - leaf_pos: Value::default(), - merkle_path: Value::default(), - _lookup_marker: PhantomData, - } + MyCircuit::new(Value::default(), Value::default(), Value::default()) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -393,12 +403,11 @@ pub mod tests { .collect(); // The root is provided as a public input in the Orchard circuit. - MyCircuit { - leaf: Value::known(leaf), - leaf_pos: Value::known(pos), - merkle_path: Value::known(path.try_into().unwrap()), - _lookup_marker: PhantomData, - } + MyCircuit::new( + Value::known(leaf), + Value::known(pos), + Value::known(path.try_into().unwrap()), + ) } #[test] @@ -444,6 +453,21 @@ pub mod tests { _lookup_marker: PhantomData, } + impl MyCircuitWithHashFromPrivatePoint { + fn new( + leaf: Value, + leaf_pos: Value, + merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, + ) -> Self { + Self { + leaf, + leaf_pos, + merkle_path, + _lookup_marker: PhantomData, + } + } + } + impl Circuit for MyCircuitWithHashFromPrivatePoint { @@ -451,12 +475,11 @@ pub mod tests { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuitWithHashFromPrivatePoint { - leaf: Value::default(), - leaf_pos: Value::default(), - merkle_path: Value::default(), - _lookup_marker: PhantomData, - } + MyCircuitWithHashFromPrivatePoint::new( + Value::default(), + Value::default(), + Value::default(), + ) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -559,12 +582,11 @@ pub mod tests { .collect(); // The root is provided as a public input in the Orchard circuit. - MyCircuitWithHashFromPrivatePoint { - leaf: Value::known(leaf), - leaf_pos: Value::known(pos), - merkle_path: Value::known(path.try_into().unwrap()), - _lookup_marker: PhantomData, - } + MyCircuitWithHashFromPrivatePoint::new( + Value::known(leaf), + Value::known(pos), + Value::known(path.try_into().unwrap()), + ) } #[test] fn merkle_with_hash_from_private_point_chip_4_5_b() { diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 83ed67ee38..784d80eb44 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -718,8 +718,16 @@ mod tests { #[derive(Clone, Copy)] struct MyLookupCircuit> { num_words: usize, - _field_marker: PhantomData, - _lookup_marker: PhantomData, + _marker: PhantomData<(F, Lookup)>, + } + + impl> MyLookupCircuit { + fn new(num_words: usize) -> Self { + MyLookupCircuit { + num_words, + _marker: PhantomData, + } + } } impl + std::clone::Clone> Circuit @@ -729,11 +737,7 @@ mod tests { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyLookupCircuit { - num_words: self.num_words, - _field_marker: PhantomData, - _lookup_marker: PhantomData, - } + MyLookupCircuit::new(self.num_words) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -808,50 +812,27 @@ mod tests { #[test] fn lookup_range_check() { - let circuit: MyLookupCircuit = - MyLookupCircuit { - num_words: 6, - _field_marker: PhantomData, - _lookup_marker: PhantomData, - }; - + let circuit = MyLookupCircuit::::new(6); let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); } #[test] fn test_lookup_range_check_against_stored_circuit() { - let circuit: MyLookupCircuit = - MyLookupCircuit { - num_words: 6, - _field_marker: PhantomData, - _lookup_marker: PhantomData, - }; - + let circuit = MyLookupCircuit::::new(6); test_against_stored_circuit(circuit, "lookup_range_check", 1888); } #[test] fn lookup_range_check_4_5_b() { - let circuit: MyLookupCircuit = - MyLookupCircuit { - num_words: 6, - _field_marker: PhantomData, - _lookup_marker: PhantomData, - }; - + let circuit = MyLookupCircuit::::new(6); let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); } #[test] fn test_lookup_range_check_against_stored_circuit_4_5_b() { - let circuit: MyLookupCircuit = - MyLookupCircuit { - num_words: 6, - _field_marker: PhantomData, - _lookup_marker: PhantomData, - }; + let circuit = MyLookupCircuit::::new(6); test_against_stored_circuit(circuit, "lookup_range_check_4_5_b", 2048); } @@ -862,6 +843,16 @@ mod tests { _lookup_marker: PhantomData, } + impl> MyShortRangeCheckCircuit { + fn new(element: Value, num_bits: usize) -> Self { + MyShortRangeCheckCircuit { + element, + num_bits, + _lookup_marker: PhantomData, + } + } + } + impl + std::clone::Clone> Circuit for MyShortRangeCheckCircuit { @@ -869,11 +860,7 @@ mod tests { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyShortRangeCheckCircuit { - element: Value::unknown(), - num_bits: self.num_bits, - _lookup_marker: PhantomData, - } + MyShortRangeCheckCircuit::new(Value::unknown(), self.num_bits) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -911,11 +898,8 @@ mod tests { circuit_name: &str, expected_proof_size: usize, ) { - let circuit: MyShortRangeCheckCircuit = MyShortRangeCheckCircuit { - element: Value::known(element), - num_bits, - _lookup_marker: PhantomData, - }; + let circuit = + MyShortRangeCheckCircuit::::new(Value::known(element), num_bits); let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), *proof_result); From 03dbe70dab4b359f658c9c3d0e2824dbe9713c6f Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 2 Aug 2024 10:01:42 +0200 Subject: [PATCH 117/121] Take into account Pablo's review --- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 1 - halo2_gadgets/src/sinsemilla.rs | 2 -- halo2_gadgets/src/sinsemilla/chip.rs | 22 ++++++++++++++----- .../src/sinsemilla/chip/hash_to_point.rs | 10 ++++----- halo2_gadgets/src/sinsemilla/merkle.rs | 11 +++++----- halo2_gadgets/src/utilities/cond_swap.rs | 22 ++++++++++++++----- 6 files changed, 43 insertions(+), 25 deletions(-) diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index d5ea2f07e4..0d72163887 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -890,7 +890,6 @@ pub mod tests { let column = config.advices[0]; - //let short_config = config.mul_fixed_short.clone(); let base = Point::new(chip, layouter.namespace(|| "load base"), self.base)?; let sign = self.load_private(layouter.namespace(|| "load sign"), column, self.sign)?; diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 4d87fe757c..35b27869d0 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -808,7 +808,6 @@ pub(crate) mod tests { } impl Circuit for MyCircuit { - #[allow(clippy::type_complexity)] type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; @@ -875,7 +874,6 @@ pub(crate) mod tests { impl Circuit for MyCircuitWithHashFromPrivatePoint { - #[allow(clippy::type_complexity)] type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 3dc70274cf..30b187ecc4 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -29,6 +29,10 @@ use generator_table::GeneratorTableConfig; mod hash_to_point; /// Configuration for the Sinsemilla hash chip +/// +/// If `init_from_private_point` is true, the chip can compute a hash from a private point. +/// However, compared to when `init_from_private_point` is set to false, +/// computing the hash from a public point will take one additional row. #[derive(Eq, PartialEq, Clone, Debug)] pub struct SinsemillaConfig where @@ -61,7 +65,9 @@ where /// An advice column configured to perform lookup range checks. lookup_config: Lookup, - enable_hash_from_private_point: bool, + /// If true, it is possible to compute a hash from a private point. + init_from_private_point: bool, + _marker: PhantomData<(Hash, Commit, F)>, } @@ -152,6 +158,12 @@ where .load(config.lookup_config.table_range_check_tag(), layouter) } + /// Creates the Sinsemilla chip + /// + /// If `init_from_private_point` is true, the chip can compute a hash from a private point. + /// However, compared to when `init_from_private_point` is set to false, + /// computing the hash from a public point will take one additional row. + /// /// # Side-effects /// /// All columns in `advices` and will be equality-enabled. @@ -164,7 +176,7 @@ where fixed_y_q: Column, lookup: (TableColumn, TableColumn, TableColumn), range_check: Lookup, - enable_hash_from_private_point: bool, + init_from_private_point: bool, ) -> >::Config { // Enable equality on all advice columns for advice in advices.iter() { @@ -190,7 +202,7 @@ where table_y: lookup.2, }, lookup_config: range_check, - enable_hash_from_private_point, + init_from_private_point, _marker: PhantomData, }; @@ -214,7 +226,7 @@ where // https://p.z.cash/halo2-0.1:sinsemilla-constraints?partial meta.create_gate("Initial y_Q", |meta| { let q_s4 = meta.query_selector(config.q_sinsemilla4); - let y_q = if enable_hash_from_private_point { + let y_q = if init_from_private_point { meta.query_advice(config.double_and_add.x_p, Rotation::prev()) } else { meta.query_fixed(config.fixed_y_q) @@ -345,7 +357,7 @@ where Q: &Self::NonIdentityPoint, message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec), Error> { - if !self.config().enable_hash_from_private_point { + if !self.config().init_from_private_point { return Err(Error::HashFromPrivatePoint); } diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index c3d928ca69..51d3c564a8 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -76,7 +76,7 @@ where ), Error, > { - if !self.config().enable_hash_from_private_point { + if !self.config().init_from_private_point { return Err(Error::HashFromPrivatePoint); } @@ -90,12 +90,12 @@ where #[allow(non_snake_case)] /// Assign the coordinates of the initial public point `Q`. /// - /// If enable_hash_from_private_point is not set, + /// If init_from_private_point is not set, /// | offset | x_A | q_sinsemilla4 | fixed_y_q | /// -------------------------------------- /// | 0 | x_Q | 1 | y_Q | /// - /// If enable_hash_from_private_point is set, + /// If init_from_private_point is set, /// | offset | x_A | x_P | q_sinsemilla4 | /// -------------------------------------- /// | 0 | | y_Q | | @@ -114,7 +114,7 @@ where // Constrain the initial x_a, lambda_1, lambda_2, x_p using the q_sinsemilla4 // selector. - let y_a: Y = if config.enable_hash_from_private_point { + let y_a: Y = if config.init_from_private_point { // Enable `q_sinsemilla4` on the second row. config.q_sinsemilla4.enable(region, 1)?; let y_a: AssignedCell, pallas::Base> = region @@ -168,7 +168,7 @@ where ) -> Result<(usize, X, Y), Error> { let config = self.config().clone(); - if !config.enable_hash_from_private_point { + if !config.init_from_private_point { return Err(Error::HashFromPrivatePoint); } diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index e0e14afc38..bad9672e2a 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -619,12 +619,11 @@ pub mod tests { let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); let circuit: MyCircuitWithHashFromPrivatePoint = - MyCircuitWithHashFromPrivatePoint { - leaf: Value::default(), - leaf_pos: Value::default(), - merkle_path: Value::default(), - _lookup_marker: PhantomData, - }; + MyCircuitWithHashFromPrivatePoint::new( + Value::default(), + Value::default(), + Value::default(), + ); halo2_proofs::dev::CircuitLayout::default() .show_labels(true) .render(11, &circuit, &root) diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 0cf6f3e181..c2be617851 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -435,17 +435,27 @@ mod tests { _lookup_marker: PhantomData, } + impl MyMuxCircuit { + fn new( + left_point: Value, + right_point: Value, + choice: Value, + ) -> Self { + MyMuxCircuit { + left_point, + right_point, + choice, + _lookup_marker: PhantomData, + } + } + } + impl Circuit for MyMuxCircuit { type Config = MyMuxConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyMuxCircuit:: { - left_point: Value::default(), - right_point: Value::default(), - choice: Value::default(), - _lookup_marker: PhantomData, - } + MyMuxCircuit::::new(Value::default(), Value::default(), Value::default()) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { From a34d146409c067a012ec3aef13f8a0c8454147f9 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 2 Aug 2024 10:26:56 +0200 Subject: [PATCH 118/121] Some renamings --- halo2_gadgets/src/ecc.rs | 33 ++++---- halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 50 +++++------ halo2_gadgets/src/sinsemilla.rs | 58 ++++++------- halo2_gadgets/src/sinsemilla/merkle.rs | 77 +++++++++-------- ...chip_4_5_b.bin => proof_ecc_chip_4_5b.bin} | Bin ....bin => proof_lookup_range_check_4_5b.bin} | Bin ...of_merkle_with_private_init_chip_4_5b.bin} | Bin ...=> proof_short_range_check_4_5b_case0.bin} | Bin ...=> proof_short_range_check_4_5b_case1.bin} | Bin ...=> proof_short_range_check_4_5b_case2.bin} | Bin ...=> proof_short_range_check_4_5b_case3.bin} | Bin ...insemilla_with_private_init_chip_4_5b.bin} | Bin ...hip_4_5_b.rdata => vk_ecc_chip_4_5b.rdata} | 0 ...rdata => vk_lookup_range_check_4_5b.rdata} | 0 ..._merkle_with_private_init_chip_4_5b.rdata} | 0 ... => vk_short_range_check_4_5b_case0.rdata} | 0 ... => vk_short_range_check_4_5b_case1.rdata} | 0 ... => vk_short_range_check_4_5b_case2.rdata} | 0 ... => vk_short_range_check_4_5b_case3.rdata} | 0 ...semilla_with_private_init_chip_4_5b.rdata} | 0 halo2_gadgets/src/utilities/cond_swap.rs | 34 ++++---- .../src/utilities/lookup_range_check.rs | 80 +++++++++--------- 22 files changed, 169 insertions(+), 163 deletions(-) rename halo2_gadgets/src/tests/circuit_data/{proof_ecc_chip_4_5_b.bin => proof_ecc_chip_4_5b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_lookup_range_check_4_5_b.bin => proof_lookup_range_check_4_5b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_merkle_with_private_init_chip_4_5_b.bin => proof_merkle_with_private_init_chip_4_5b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_4_5_b_case0.bin => proof_short_range_check_4_5b_case0.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_4_5_b_case1.bin => proof_short_range_check_4_5b_case1.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_4_5_b_case2.bin => proof_short_range_check_4_5b_case2.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_short_range_check_4_5_b_case3.bin => proof_short_range_check_4_5b_case3.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{proof_sinsemilla_with_private_init_chip_4_5_b.bin => proof_sinsemilla_with_private_init_chip_4_5b.bin} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_ecc_chip_4_5_b.rdata => vk_ecc_chip_4_5b.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_lookup_range_check_4_5_b.rdata => vk_lookup_range_check_4_5b.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_merkle_with_private_init_chip_4_5_b.rdata => vk_merkle_with_private_init_chip_4_5b.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_short_range_check_4_5_b_case0.rdata => vk_short_range_check_4_5b_case0.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_short_range_check_4_5_b_case1.rdata => vk_short_range_check_4_5b_case1.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_short_range_check_4_5_b_case2.rdata => vk_short_range_check_4_5b_case2.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_short_range_check_4_5_b_case3.rdata => vk_short_range_check_4_5b_case3.rdata} (100%) rename halo2_gadgets/src/tests/circuit_data/{vk_sinsemilla_with_private_init_chip_4_5_b.rdata => vk_sinsemilla_with_private_init_chip_4_5b.rdata} (100%) diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index e534ce10a6..78e3893952 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -635,7 +635,7 @@ pub(crate) mod tests { use crate::{ tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, PallasLookupRangeCheckConfig, }, }; use halo2_proofs::{ @@ -772,12 +772,12 @@ pub(crate) mod tests { type Base = BaseField; } - struct MyCircuit { + struct EccCircuit { test_errors: bool, _lookup_marker: PhantomData, } - impl MyCircuit { + impl EccCircuit { fn new(test_errors: bool) -> Self { Self { test_errors, @@ -787,12 +787,12 @@ pub(crate) mod tests { } #[allow(non_snake_case)] - impl Circuit for MyCircuit { + impl Circuit for EccCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit::new(false) + EccCircuit::new(false) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -968,14 +968,14 @@ pub(crate) mod tests { #[test] fn ecc_chip() { let k = 13; - let circuit = MyCircuit::::new(true); + let circuit = EccCircuit::::new(true); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] fn test_ecc_chip_against_stored_circuit() { - let circuit = MyCircuit::::new(false); + let circuit = EccCircuit::::new(false); test_against_stored_circuit(circuit, "ecc_chip", 3872); } @@ -988,38 +988,37 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit::::new(false); + let circuit = EccCircuit::::new(false); halo2_proofs::dev::CircuitLayout::default() .render(13, &circuit, &root) .unwrap(); } #[test] - fn ecc_chip_4_5_b() { + fn ecc_chip_4_5b() { let k = 13; - let circuit = MyCircuit::::new(true); + let circuit = EccCircuit::::new(true); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] - fn test_against_stored_ecc_chip_4_5_b() { - let circuit = MyCircuit::::new(false); - test_against_stored_circuit(circuit, "ecc_chip_4_5_b", 3968); + fn test_against_stored_ecc_chip_4_5b() { + let circuit = EccCircuit::::new(false); + test_against_stored_circuit(circuit, "ecc_chip_4_5b", 3968); } #[cfg(feature = "test-dev-graph")] #[test] - fn print_ecc_chip_4_5_b() { + fn print_ecc_chip_4_5b() { use plotters::prelude::*; - let root = - BitMapBackend::new("ecc-chip-4-5-b-layout.png", (1024, 7680)).into_drawing_area(); + let root = BitMapBackend::new("ecc-chip-4_5b-layout.png", (1024, 7680)).into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit::::new(false); + let circuit = EccCircuit::::new(false); halo2_proofs::dev::CircuitLayout::default() .render(13, &circuit, &root) .unwrap(); diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 0d72163887..d06049d3ff 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -325,7 +325,7 @@ pub mod tests { }, utilities::{ lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, PallasLookupRangeCheckConfig, }, UtilitiesInstructions, @@ -471,7 +471,7 @@ pub mod tests { } #[derive(Default)] - struct MyMagnitudeSignCircuit { + struct MagnitudeSignCircuit { magnitude: Value, sign: Value, // For test checking @@ -480,17 +480,17 @@ pub mod tests { } impl UtilitiesInstructions - for MyMagnitudeSignCircuit + for MagnitudeSignCircuit { type Var = AssignedCell; } - impl Circuit for MyMagnitudeSignCircuit { + impl Circuit for MagnitudeSignCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyMagnitudeSignCircuit { + MagnitudeSignCircuit { magnitude: Value::unknown(), sign: Value::unknown(), magnitude_error: Value::unknown(), @@ -584,41 +584,41 @@ pub mod tests { } } - impl MyMagnitudeSignCircuit { + impl MagnitudeSignCircuit { fn test_invalid_magnitude_sign() { // Magnitude larger than 64 bits should fail { let circuits = [ // 2^64 - MyMagnitudeSignCircuit:: { + MagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 64)), sign: Value::known(pallas::Base::one()), magnitude_error: Value::known(pallas::Base::from(1 << 1)), _lookup_marker: PhantomData, }, // -2^64 - MyMagnitudeSignCircuit:: { + MagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 64)), sign: Value::known(-pallas::Base::one()), magnitude_error: Value::known(pallas::Base::from(1 << 1)), _lookup_marker: PhantomData, }, // 2^66 - MyMagnitudeSignCircuit:: { + MagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 66)), sign: Value::known(pallas::Base::one()), magnitude_error: Value::known(pallas::Base::from(1 << 3)), _lookup_marker: PhantomData, }, // -2^66 - MyMagnitudeSignCircuit:: { + MagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 66)), sign: Value::known(-pallas::Base::one()), magnitude_error: Value::known(pallas::Base::from(1 << 3)), _lookup_marker: PhantomData, }, // 2^254 - MyMagnitudeSignCircuit:: { + MagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), sign: Value::known(pallas::Base::one()), magnitude_error: Value::known( @@ -627,7 +627,7 @@ pub mod tests { _lookup_marker: PhantomData, }, // -2^254 - MyMagnitudeSignCircuit:: { + MagnitudeSignCircuit:: { magnitude: Value::known(pallas::Base::from_u128(1 << 127).square()), sign: Value::known(-pallas::Base::one()), magnitude_error: Value::known( @@ -682,7 +682,7 @@ pub mod tests { // Sign that is not +/- 1 should fail { let magnitude_u64 = rand::random::(); - let circuit: MyMagnitudeSignCircuit = MyMagnitudeSignCircuit { + let circuit: MagnitudeSignCircuit = MagnitudeSignCircuit { magnitude: Value::known(pallas::Base::from(magnitude_u64)), sign: Value::known(pallas::Base::zero()), magnitude_error: Value::unknown(), @@ -744,12 +744,12 @@ pub mod tests { #[test] fn invalid_magnitude_sign() { - MyMagnitudeSignCircuit::::test_invalid_magnitude_sign(); + MagnitudeSignCircuit::::test_invalid_magnitude_sign(); } #[test] - fn invalid_magnitude_sign_4_5_b() { - MyMagnitudeSignCircuit::::test_invalid_magnitude_sign(); + fn invalid_magnitude_sign_4_5b() { + MagnitudeSignCircuit::::test_invalid_magnitude_sign(); } pub(crate) fn test_mul_sign( @@ -819,24 +819,24 @@ pub mod tests { } #[derive(Default)] - struct MyMulSignCircuit { + struct MulSignCircuit { base: Value, sign: Value, _lookup_marker: PhantomData, } impl UtilitiesInstructions - for MyMulSignCircuit + for MulSignCircuit { type Var = AssignedCell; } - impl Circuit for MyMulSignCircuit { + impl Circuit for MulSignCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyMulSignCircuit { + MulSignCircuit { base: Value::unknown(), sign: Value::unknown(), _lookup_marker: PhantomData, @@ -900,12 +900,12 @@ pub mod tests { } } - impl MyMulSignCircuit { + impl MulSignCircuit { fn test_invalid_magnitude_sign() { // Sign that is not +/- 1 should fail // Generate a random non-identity point let point = pallas::Point::random(rand::rngs::OsRng); - let circuit: MyMulSignCircuit = MyMulSignCircuit { + let circuit: MulSignCircuit = MulSignCircuit { base: Value::known(point.to_affine()), sign: Value::known(pallas::Base::zero()), _lookup_marker: PhantomData, @@ -954,10 +954,10 @@ pub mod tests { #[test] fn invalid_sign_in_mul_sign() { - MyMulSignCircuit::::test_invalid_magnitude_sign(); + MulSignCircuit::::test_invalid_magnitude_sign(); } #[test] - fn invalid_sign_in_mul_sign_4_5_b() { - MyMulSignCircuit::::test_invalid_magnitude_sign(); + fn invalid_sign_in_mul_sign_4_5b() { + MulSignCircuit::::test_invalid_magnitude_sign(); } } diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 35b27869d0..ee70342e32 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -542,7 +542,7 @@ pub(crate) mod tests { sinsemilla::primitives::{self as sinsemilla, K}, tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, PallasLookupRangeCheckConfig, }, }; @@ -585,11 +585,11 @@ pub(crate) mod tests { } } - struct MyCircuit { + struct SinsemillaCircuit { _lookup_marker: PhantomData, } - impl MyCircuit { + impl SinsemillaCircuit { fn new() -> Self { Self { _lookup_marker: PhantomData, @@ -597,7 +597,7 @@ pub(crate) mod tests { } } - type MyConfig = ( + type EccSinsemillaConfig = ( EccConfig, SinsemillaConfig, SinsemillaConfig, @@ -606,7 +606,7 @@ pub(crate) mod tests { fn configure( meta: &mut ConstraintSystem, enable_hash_from_private_point: bool, - ) -> MyConfig { + ) -> EccSinsemillaConfig { let advices = [ meta.advice_column(), meta.advice_column(), @@ -674,7 +674,7 @@ pub(crate) mod tests { } fn synthesize( - config: MyConfig, + config: EccSinsemillaConfig, mut layouter: impl Layouter, ) -> Result<(), Error> { let rng = OsRng; @@ -807,12 +807,12 @@ pub(crate) mod tests { } } - impl Circuit for MyCircuit { - type Config = MyConfig; + impl Circuit for SinsemillaCircuit { + type Config = EccSinsemillaConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit::new() + SinsemillaCircuit::new() } #[allow(non_snake_case)] @@ -832,14 +832,14 @@ pub(crate) mod tests { #[test] fn sinsemilla_chip() { let k = 11; - let circuit = MyCircuit::::new(); + let circuit = SinsemillaCircuit::::new(); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] fn test_sinsemilla_chip_against_stored_circuit() { - let circuit = MyCircuit::::new(); + let circuit = SinsemillaCircuit::::new(); test_against_stored_circuit(circuit, "sinsemilla_chip", 4576); } @@ -853,17 +853,17 @@ pub(crate) mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit::::new(); + let circuit = SinsemillaCircuit::::new(); halo2_proofs::dev::CircuitLayout::default() .render(11, &circuit, &root) .unwrap(); } - struct MyCircuitWithHashFromPrivatePoint { + struct SinsemillaCircuitWithHashFromPrivatePoint { _lookup_marker: PhantomData, } - impl MyCircuitWithHashFromPrivatePoint { + impl SinsemillaCircuitWithHashFromPrivatePoint { fn new() -> Self { Self { _lookup_marker: PhantomData, @@ -872,13 +872,13 @@ pub(crate) mod tests { } impl Circuit - for MyCircuitWithHashFromPrivatePoint + for SinsemillaCircuitWithHashFromPrivatePoint { - type Config = MyConfig; + type Config = EccSinsemillaConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuitWithHashFromPrivatePoint::new() + SinsemillaCircuitWithHashFromPrivatePoint::new() } #[allow(non_snake_case)] @@ -896,33 +896,33 @@ pub(crate) mod tests { } #[test] - fn sinsemilla_with_hash_from_private_point_chip_4_5_b() { + fn sinsemilla_with_hash_from_private_point_chip_4_5b() { let k = 11; - let circuit = MyCircuitWithHashFromPrivatePoint::::new(); + let circuit = + SinsemillaCircuitWithHashFromPrivatePoint::::new(); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] - fn test_against_stored_sinsemilla_with_hash_from_private_point_chip_4_5_b() { - let circuit = MyCircuitWithHashFromPrivatePoint::::new(); - test_against_stored_circuit(circuit, "sinsemilla_with_private_init_chip_4_5_b", 4672); + fn test_against_stored_sinsemilla_with_hash_from_private_point_chip_4_5b() { + let circuit = + SinsemillaCircuitWithHashFromPrivatePoint::::new(); + test_against_stored_circuit(circuit, "sinsemilla_with_private_init_chip_4_5b", 4672); } #[cfg(feature = "test-dev-graph")] #[test] - fn print_sinsemilla_with_hash_from_private_point_chip_4_5_b() { + fn print_sinsemilla_with_hash_from_private_point_chip_4_5b() { use plotters::prelude::*; - let root = BitMapBackend::new( - "sinsemilla-with-private-init-4-5-b-layout.png", - (1024, 7680), - ) - .into_drawing_area(); + let root = BitMapBackend::new("sinsemilla-with-private-init-4_5b-layout.png", (1024, 7680)) + .into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("SinsemillaHash", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuitWithHashFromPrivatePoint::::new(); + let circuit = + SinsemillaCircuitWithHashFromPrivatePoint::::new(); halo2_proofs::dev::CircuitLayout::default() .render(11, &circuit, &root) .unwrap(); diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index bad9672e2a..ae2f3883b2 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -188,7 +188,7 @@ pub mod tests { utilities::{ i2lebsp, lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, PallasLookupRangeCheckConfig, }, UtilitiesInstructions, @@ -209,14 +209,14 @@ pub mod tests { const MERKLE_DEPTH: usize = 32; #[derive(Default)] - struct MyCircuit { + struct MerkleCircuit { leaf: Value, leaf_pos: Value, merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, _lookup_marker: PhantomData, } - impl MyCircuit { + impl MerkleCircuit { fn new( leaf: Value, leaf_pos: Value, @@ -231,15 +231,14 @@ pub mod tests { } } - type MyConfig = ( - MerkleConfig, - MerkleConfig, - ); - + #[allow(clippy::type_complexity)] fn configure( meta: &mut ConstraintSystem, enable_hash_from_private_point: bool, - ) -> MyConfig { + ) -> ( + MerkleConfig, + MerkleConfig, + ) { let advices = [ meta.advice_column(), meta.advice_column(), @@ -296,12 +295,15 @@ pub mod tests { (config1, config2) } - impl Circuit for MyCircuit { - type Config = MyConfig; + impl Circuit for MerkleCircuit { + type Config = ( + MerkleConfig, + MerkleConfig, + ); type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit::new(Value::default(), Value::default(), Value::default()) + MerkleCircuit::new(Value::default(), Value::default(), Value::default()) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -390,7 +392,7 @@ pub mod tests { } } - fn generate_circuit() -> MyCircuit { + fn generate_circuit() -> MerkleCircuit { let mut rng = OsRng; // Choose a random leaf and position @@ -403,7 +405,7 @@ pub mod tests { .collect(); // The root is provided as a public input in the Orchard circuit. - MyCircuit::new( + MerkleCircuit::new( Value::known(leaf), Value::known(pos), Value::known(path.try_into().unwrap()), @@ -412,7 +414,7 @@ pub mod tests { #[test] fn merkle_chip() { - let circuit: MyCircuit = generate_circuit(); + let circuit: MerkleCircuit = generate_circuit(); let prover = MockProver::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) @@ -420,7 +422,7 @@ pub mod tests { #[test] fn test_merkle_chip_against_stored_circuit() { - let circuit: MyCircuit = generate_circuit(); + let circuit: MerkleCircuit = generate_circuit(); test_against_stored_circuit(circuit, "merkle_chip", 4160); } @@ -433,7 +435,7 @@ pub mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); - let circuit: MyCircuit = MyCircuit { + let circuit: MerkleCircuit = MerkleCircuit { leaf: Value::default(), leaf_pos: Value::default(), merkle_path: Value::default(), @@ -446,14 +448,14 @@ pub mod tests { } #[derive(Default)] - struct MyCircuitWithHashFromPrivatePoint { + struct MerkleCircuitWithHashFromPrivatePoint { leaf: Value, leaf_pos: Value, merkle_path: Value<[pallas::Base; MERKLE_DEPTH]>, _lookup_marker: PhantomData, } - impl MyCircuitWithHashFromPrivatePoint { + impl MerkleCircuitWithHashFromPrivatePoint { fn new( leaf: Value, leaf_pos: Value, @@ -469,13 +471,16 @@ pub mod tests { } impl Circuit - for MyCircuitWithHashFromPrivatePoint + for MerkleCircuitWithHashFromPrivatePoint { - type Config = MyConfig; + type Config = ( + MerkleConfig, + MerkleConfig, + ); type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuitWithHashFromPrivatePoint::new( + MerkleCircuitWithHashFromPrivatePoint::new( Value::default(), Value::default(), Value::default(), @@ -568,8 +573,8 @@ pub mod tests { } } - fn generate_circuit_4_5_b( - ) -> MyCircuitWithHashFromPrivatePoint { + fn generate_circuit_4_5b( + ) -> MerkleCircuitWithHashFromPrivatePoint { let mut rng = OsRng; // Choose a random leaf and position @@ -582,44 +587,44 @@ pub mod tests { .collect(); // The root is provided as a public input in the Orchard circuit. - MyCircuitWithHashFromPrivatePoint::new( + MerkleCircuitWithHashFromPrivatePoint::new( Value::known(leaf), Value::known(pos), Value::known(path.try_into().unwrap()), ) } #[test] - fn merkle_with_hash_from_private_point_chip_4_5_b() { - let circuit: MyCircuitWithHashFromPrivatePoint = - generate_circuit_4_5_b(); + fn merkle_with_hash_from_private_point_chip_4_5b() { + let circuit: MerkleCircuitWithHashFromPrivatePoint = + generate_circuit_4_5b(); let prover = MockProver::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } #[test] - fn test_against_stored_merkle_with_hash_from_private_point_chip_4_5_b() { - let circuit: MyCircuitWithHashFromPrivatePoint = - generate_circuit_4_5_b(); + fn test_against_stored_merkle_with_hash_from_private_point_chip_4_5b() { + let circuit: MerkleCircuitWithHashFromPrivatePoint = + generate_circuit_4_5b(); - test_against_stored_circuit(circuit, "merkle_with_private_init_chip_4_5_b", 4160); + test_against_stored_circuit(circuit, "merkle_with_private_init_chip_4_5b", 4160); } #[cfg(feature = "test-dev-graph")] #[test] - fn print_merkle_with_hash_from_private_point_chip_4_5_b() { + fn print_merkle_with_hash_from_private_point_chip_4_5b() { use plotters::prelude::*; let root = BitMapBackend::new( - "merkle-path-with-private-init-4-5-b-layout.png", + "merkle-with-private-init-chip-4_5b-layout.png", (1024, 7680), ) .into_drawing_area(); root.fill(&WHITE).unwrap(); let root = root.titled("MerkleCRH Path", ("sans-serif", 60)).unwrap(); - let circuit: MyCircuitWithHashFromPrivatePoint = - MyCircuitWithHashFromPrivatePoint::new( + let circuit: MerkleCircuitWithHashFromPrivatePoint = + MerkleCircuitWithHashFromPrivatePoint::new( Value::default(), Value::default(), Value::default(), diff --git a/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b.bin b/halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5_b.bin rename to halo2_gadgets/src/tests/circuit_data/proof_ecc_chip_4_5b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b.bin b/halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5_b.bin rename to halo2_gadgets/src/tests/circuit_data/proof_lookup_range_check_4_5b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_merkle_with_private_init_chip_4_5_b.bin b/halo2_gadgets/src/tests/circuit_data/proof_merkle_with_private_init_chip_4_5b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_merkle_with_private_init_chip_4_5_b.bin rename to halo2_gadgets/src/tests/circuit_data/proof_merkle_with_private_init_chip_4_5b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5b_case0.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case0.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5b_case0.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5b_case1.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case1.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5b_case1.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5b_case2.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case2.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5b_case2.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3.bin b/halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5b_case3.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5_b_case3.bin rename to halo2_gadgets/src/tests/circuit_data/proof_short_range_check_4_5b_case3.bin diff --git a/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_with_private_init_chip_4_5_b.bin b/halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_with_private_init_chip_4_5b.bin similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_with_private_init_chip_4_5_b.bin rename to halo2_gadgets/src/tests/circuit_data/proof_sinsemilla_with_private_init_chip_4_5b.bin diff --git a/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5b.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5_b.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_ecc_chip_4_5b.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5b.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5_b.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_lookup_range_check_4_5b.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_merkle_with_private_init_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_merkle_with_private_init_chip_4_5b.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_merkle_with_private_init_chip_4_5_b.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_merkle_with_private_init_chip_4_5b.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5b_case0.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case0.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5b_case0.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5b_case1.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case1.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5b_case1.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5b_case2.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case2.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5b_case2.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata b/halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5b_case3.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5_b_case3.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_short_range_check_4_5b_case3.rdata diff --git a/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5_b.rdata b/halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5b.rdata similarity index 100% rename from halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5_b.rdata rename to halo2_gadgets/src/tests/circuit_data/vk_sinsemilla_with_private_init_chip_4_5b.rdata diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index c2be617851..43a0f791c6 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -300,7 +300,7 @@ mod tests { use crate::utilities::{ cond_swap::{CondSwapChip, CondSwapConfig, CondSwapInstructions}, lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, PallasLookupRangeCheckConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, PallasLookupRangeCheckConfig, }, UtilitiesInstructions, }; @@ -317,13 +317,13 @@ mod tests { #[test] fn cond_swap() { #[derive(Default)] - struct MyCircuit { + struct CondSwapCircuit { a: Value, b: Value, swap: Value, } - impl Circuit for MyCircuit { + impl Circuit for CondSwapCircuit { type Config = CondSwapConfig; type FloorPlanner = SimpleFloorPlanner; @@ -380,7 +380,7 @@ mod tests { // Test swap case { - let circuit: MyCircuit = MyCircuit { + let circuit: CondSwapCircuit = CondSwapCircuit { a: Value::known(Base::random(rng)), b: Value::known(Base::random(rng)), swap: Value::known(true), @@ -391,7 +391,7 @@ mod tests { // Test non-swap case { - let circuit: MyCircuit = MyCircuit { + let circuit: CondSwapCircuit = CondSwapCircuit { a: Value::known(Base::random(rng)), b: Value::known(Base::random(rng)), swap: Value::known(false), @@ -420,7 +420,7 @@ mod tests { use rand::rngs::OsRng; #[derive(Clone, Debug)] - pub struct MyMuxConfig { + pub struct MuxConfig { primary: Column, advice: Column, cond_swap_config: CondSwapConfig, @@ -428,20 +428,20 @@ mod tests { } #[derive(Default)] - struct MyMuxCircuit { + struct MuxCircuit { left_point: Value, right_point: Value, choice: Value, _lookup_marker: PhantomData, } - impl MyMuxCircuit { + impl MuxCircuit { fn new( left_point: Value, right_point: Value, choice: Value, ) -> Self { - MyMuxCircuit { + MuxCircuit { left_point, right_point, choice, @@ -450,12 +450,12 @@ mod tests { } } - impl Circuit for MyMuxCircuit { - type Config = MyMuxConfig; + impl Circuit for MuxCircuit { + type Config = MuxConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyMuxCircuit::::new(Value::default(), Value::default(), Value::default()) + MuxCircuit::::new(Value::default(), Value::default(), Value::default()) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -506,7 +506,7 @@ mod tests { range_check, ); - MyMuxConfig { + MuxConfig { primary, advice: advices[0], cond_swap_config, @@ -597,7 +597,7 @@ mod tests { } } - impl MyMuxCircuit { + impl MuxCircuit { fn test_mux_circuits() { // Test different circuits let mut circuits = vec![]; @@ -610,7 +610,7 @@ mod tests { }; let left_point = pallas::Point::random(OsRng).to_affine(); let right_point = pallas::Point::random(OsRng).to_affine(); - circuits.push(MyMuxCircuit:: { + circuits.push(MuxCircuit:: { left_point: Value::known(left_point), right_point: Value::known(right_point), choice: Value::known(choice_value), @@ -638,7 +638,7 @@ mod tests { } } - MyMuxCircuit::::test_mux_circuits(); - MyMuxCircuit::::test_mux_circuits(); + MuxCircuit::::test_mux_circuits(); + MuxCircuit::::test_mux_circuits(); } } diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 784d80eb44..2a1715a330 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -465,14 +465,14 @@ impl PallasLookupRangeCheck for PallasLookupRangeCheckConfig {} /// Configuration that provides methods for an efficient 4, 5, and 10-bit lookup range check. #[derive(Eq, PartialEq, Debug, Clone, Copy)] -pub struct LookupRangeCheck45BConfig { +pub struct LookupRangeCheck4_5BConfig { base: LookupRangeCheckConfig, q_range_check_4: Selector, q_range_check_5: Selector, table_range_check_tag: TableColumn, } -impl LookupRangeCheck45BConfig { +impl LookupRangeCheck4_5BConfig { /// The `running_sum` advice column breaks the field element into `K`-bit /// words. It is used to construct the input expression to the lookup /// argument. @@ -498,7 +498,7 @@ impl LookupRangeCheck45BConfig { let q_range_check_4 = meta.complex_selector(); let q_range_check_5 = meta.complex_selector(); - let config = LookupRangeCheck45BConfig { + let config = LookupRangeCheck4_5BConfig { base: LookupRangeCheckConfig { q_lookup, q_running, @@ -595,7 +595,9 @@ impl LookupRangeCheck45BConfig { } } -impl LookupRangeCheck for LookupRangeCheck45BConfig { +impl LookupRangeCheck + for LookupRangeCheck4_5BConfig +{ fn config(&self) -> &LookupRangeCheckConfig { &self.base } @@ -685,13 +687,13 @@ impl LookupRangeCheck for LookupRangeCh } } -/// In this crate, `LookupRangeCheck45BConfig` is always used with `pallas::Base` as the prime field +/// In this crate, `LookupRangeCheck4_5BConfig` is always used with `pallas::Base` as the prime field /// and the constant `K` from the `sinsemilla` module. To reduce verbosity and improve readability, /// we introduce this alias and use it instead of that long construction. -pub type PallasLookupRangeCheck45BConfig = - LookupRangeCheck45BConfig; +pub type PallasLookupRangeCheck4_5BConfig = + LookupRangeCheck4_5BConfig; -impl PallasLookupRangeCheck for PallasLookupRangeCheck45BConfig {} +impl PallasLookupRangeCheck for PallasLookupRangeCheck4_5BConfig {} #[cfg(test)] mod tests { @@ -709,21 +711,21 @@ mod tests { sinsemilla::primitives::K, tests::test_utils::test_against_stored_circuit, utilities::lookup_range_check::{ - LookupRangeCheck, PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, + LookupRangeCheck, PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, PallasLookupRangeCheckConfig, }, }; use std::{convert::TryInto, marker::PhantomData}; #[derive(Clone, Copy)] - struct MyLookupCircuit> { + struct LookupCircuit> { num_words: usize, _marker: PhantomData<(F, Lookup)>, } - impl> MyLookupCircuit { + impl> LookupCircuit { fn new(num_words: usize) -> Self { - MyLookupCircuit { + LookupCircuit { num_words, _marker: PhantomData, } @@ -731,13 +733,13 @@ mod tests { } impl + std::clone::Clone> Circuit - for MyLookupCircuit + for LookupCircuit { type Config = Lookup; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyLookupCircuit::new(self.num_words) + LookupCircuit::new(self.num_words) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -812,40 +814,40 @@ mod tests { #[test] fn lookup_range_check() { - let circuit = MyLookupCircuit::::new(6); + let circuit = LookupCircuit::::new(6); let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); } #[test] fn test_lookup_range_check_against_stored_circuit() { - let circuit = MyLookupCircuit::::new(6); + let circuit = LookupCircuit::::new(6); test_against_stored_circuit(circuit, "lookup_range_check", 1888); } #[test] - fn lookup_range_check_4_5_b() { - let circuit = MyLookupCircuit::::new(6); + fn lookup_range_check_4_5b() { + let circuit = LookupCircuit::::new(6); let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); } #[test] - fn test_lookup_range_check_against_stored_circuit_4_5_b() { - let circuit = MyLookupCircuit::::new(6); - test_against_stored_circuit(circuit, "lookup_range_check_4_5_b", 2048); + fn test_lookup_range_check_against_stored_circuit_4_5b() { + let circuit = LookupCircuit::::new(6); + test_against_stored_circuit(circuit, "lookup_range_check_4_5b", 2048); } #[derive(Clone, Copy)] - struct MyShortRangeCheckCircuit> { + struct ShortRangeCheckCircuit> { element: Value, num_bits: usize, _lookup_marker: PhantomData, } - impl> MyShortRangeCheckCircuit { + impl> ShortRangeCheckCircuit { fn new(element: Value, num_bits: usize) -> Self { - MyShortRangeCheckCircuit { + ShortRangeCheckCircuit { element, num_bits, _lookup_marker: PhantomData, @@ -854,13 +856,13 @@ mod tests { } impl + std::clone::Clone> Circuit - for MyShortRangeCheckCircuit + for ShortRangeCheckCircuit { type Config = Lookup; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyShortRangeCheckCircuit::new(Value::unknown(), self.num_bits) + ShortRangeCheckCircuit::new(Value::unknown(), self.num_bits) } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -899,7 +901,7 @@ mod tests { expected_proof_size: usize, ) { let circuit = - MyShortRangeCheckCircuit::::new(Value::known(element), num_bits); + ShortRangeCheckCircuit::::new(Value::known(element), num_bits); let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), *proof_result); @@ -923,11 +925,11 @@ mod tests { "short_range_check_case0", proof_size_10_bits, ); - test_short_range_check::( + test_short_range_check::( element, num_bits, &Ok(()), - "short_range_check_4_5_b_case0", + "short_range_check_4_5b_case0", proof_size_4_5_10_bits, ); @@ -941,11 +943,11 @@ mod tests { "short_range_check_case1", proof_size_10_bits, ); - test_short_range_check::( + test_short_range_check::( element, num_bits, &Ok(()), - "short_range_check_4_5_b_case1", + "short_range_check_4_5b_case1", proof_size_4_5_10_bits, ); @@ -959,11 +961,11 @@ mod tests { "short_range_check_case2", proof_size_10_bits, ); - test_short_range_check::( + test_short_range_check::( element, num_bits, &Ok(()), - "short_range_check_4_5_b_case2", + "short_range_check_4_5b_case2", proof_size_4_5_10_bits, ); @@ -984,7 +986,7 @@ mod tests { "not_saved", proof_size_10_bits, ); - test_short_range_check::( + test_short_range_check::( element, num_bits, &error, @@ -1018,7 +1020,7 @@ mod tests { "not_saved", proof_size_10_bits, ); - test_short_range_check::( + test_short_range_check::( element, num_bits, &error, @@ -1049,7 +1051,7 @@ mod tests { "not_saved", proof_size_10_bits, ); - test_short_range_check::( + test_short_range_check::( element, num_bits as usize, &error, @@ -1058,16 +1060,16 @@ mod tests { ); // Element within 4 bits - test_short_range_check::( + test_short_range_check::( pallas::Base::from((1 << 4) - 1), 4, &Ok(()), - "short_range_check_4_5_b_case3", + "short_range_check_4_5b_case3", proof_size_4_5_10_bits, ); // Element larger than 5 bits - test_short_range_check::( + test_short_range_check::( pallas::Base::from(1 << 5), 5, &Err(vec![VerifyFailure::Lookup { From 9df4fb6f27c04203ae57078be470985c8d353817 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 8 Aug 2024 10:54:54 +0200 Subject: [PATCH 119/121] Replace enable_hash_from_private_point by init_from_private_point --- halo2_gadgets/src/sinsemilla.rs | 6 +++--- halo2_gadgets/src/sinsemilla/merkle.rs | 6 +++--- halo2_proofs/src/plonk/error.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index ee70342e32..14c9869ebf 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -605,7 +605,7 @@ pub(crate) mod tests { fn configure( meta: &mut ConstraintSystem, - enable_hash_from_private_point: bool, + init_from_private_point: bool, ) -> EccSinsemillaConfig { let advices = [ meta.advice_column(), @@ -659,7 +659,7 @@ pub(crate) mod tests { lagrange_coeffs[0], lookup, range_check, - enable_hash_from_private_point, + init_from_private_point, ); let config2 = SinsemillaChip::configure( meta, @@ -668,7 +668,7 @@ pub(crate) mod tests { lagrange_coeffs[1], lookup, range_check, - enable_hash_from_private_point, + init_from_private_point, ); (ecc_config, config1, config2) } diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index ae2f3883b2..e985209d83 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -234,7 +234,7 @@ pub mod tests { #[allow(clippy::type_complexity)] fn configure( meta: &mut ConstraintSystem, - enable_hash_from_private_point: bool, + init_from_private_point: bool, ) -> ( MerkleConfig, MerkleConfig, @@ -277,7 +277,7 @@ pub mod tests { fixed_y_q_1, lookup, range_check, - enable_hash_from_private_point, + init_from_private_point, ); let config1 = MerkleChip::configure(meta, sinsemilla_config_1); @@ -288,7 +288,7 @@ pub mod tests { fixed_y_q_2, lookup, range_check, - enable_hash_from_private_point, + init_from_private_point, ); let config2 = MerkleChip::configure(meta, sinsemilla_config_2); diff --git a/halo2_proofs/src/plonk/error.rs b/halo2_proofs/src/plonk/error.rs index 6ffed3a300..4478751fce 100644 --- a/halo2_proofs/src/plonk/error.rs +++ b/halo2_proofs/src/plonk/error.rs @@ -40,7 +40,7 @@ pub enum Error { ColumnNotInPermutation(Column), /// An error relating to a lookup table. TableError(TableError), - /// Try to hash from a private point when enable_hash_from_private_point is not set. + /// Try to hash from a private point when init_from_private_point is not set. HashFromPrivatePoint, } From 493bf53e5f7453708a98c5a1c43c79732daf4a20 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 8 Aug 2024 11:27:42 +0200 Subject: [PATCH 120/121] Remove unnecessary changes in CI --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ed590bc01..ce5cafc981 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,10 +52,8 @@ jobs: with: beta-features: ${{ matrix.stage == 'beta' }} nightly-features: ${{ matrix.stage == 'nightly' }} - - name: Update apt - run: sudo apt-get update - name: Install cross-platform support dependencies - run: sudo apt-get install gcc-multilib + run: sudo apt install gcc-multilib - run: rustup target add i686-unknown-linux-gnu - name: Run tests run: > From 46db5d45de09403305747fc796b967929d4ced2e Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 8 Aug 2024 11:32:41 +0200 Subject: [PATCH 121/121] Rename Error::HashFromPrivatePoint to Error::IllegalHashFromPrivatePoint --- halo2_gadgets/src/sinsemilla/chip.rs | 2 +- halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs | 4 ++-- halo2_proofs/src/plonk/error.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/halo2_gadgets/src/sinsemilla/chip.rs b/halo2_gadgets/src/sinsemilla/chip.rs index 30b187ecc4..ad2c54d4cc 100644 --- a/halo2_gadgets/src/sinsemilla/chip.rs +++ b/halo2_gadgets/src/sinsemilla/chip.rs @@ -358,7 +358,7 @@ where message: Self::Message, ) -> Result<(Self::NonIdentityPoint, Vec), Error> { if !self.config().init_from_private_point { - return Err(Error::HashFromPrivatePoint); + return Err(Error::IllegalHashFromPrivatePoint); } layouter.assign_region( diff --git a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs index 51d3c564a8..cda6434174 100644 --- a/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs +++ b/halo2_gadgets/src/sinsemilla/chip/hash_to_point.rs @@ -77,7 +77,7 @@ where Error, > { if !self.config().init_from_private_point { - return Err(Error::HashFromPrivatePoint); + return Err(Error::IllegalHashFromPrivatePoint); } let (offset, x_a, y_a) = self.private_q_initialization(region, Q)?; @@ -169,7 +169,7 @@ where let config = self.config().clone(); if !config.init_from_private_point { - return Err(Error::HashFromPrivatePoint); + return Err(Error::IllegalHashFromPrivatePoint); } // Assign `x_Q` and `y_Q` in the region and constrain the initial x_a, lambda_1, lambda_2, diff --git a/halo2_proofs/src/plonk/error.rs b/halo2_proofs/src/plonk/error.rs index 4478751fce..57d94b30a6 100644 --- a/halo2_proofs/src/plonk/error.rs +++ b/halo2_proofs/src/plonk/error.rs @@ -41,7 +41,7 @@ pub enum Error { /// An error relating to a lookup table. TableError(TableError), /// Try to hash from a private point when init_from_private_point is not set. - HashFromPrivatePoint, + IllegalHashFromPrivatePoint, } impl From for Error { @@ -85,7 +85,7 @@ impl fmt::Display for Error { column ), Error::TableError(error) => write!(f, "{}", error), - Error::HashFromPrivatePoint => write!( + Error::IllegalHashFromPrivatePoint => write!( f, "Hashing from private point is disabled" )