diff --git a/src/circuit.rs b/src/circuit.rs index 6034e739..d4f8a045 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -62,6 +62,8 @@ use gadget::{ use std::convert::TryInto; +use self::gadget::utilities::lookup_range_check::LookupRangeCheckConfig; + pub(crate) mod gadget; /// Size of the Orchard circuit. @@ -221,9 +223,13 @@ impl plonk::Circuit for Circuit { let rc_a = lagrange_coeffs[2..5].try_into().unwrap(); let rc_b = lagrange_coeffs[5..8].try_into().unwrap(); + // We have a lot of free space in the right-most advice columns; use one of them + // for all of our range checks. + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + // Configuration for curve point operations. // This uses 10 advice columns and spans the whole circuit. - let ecc_config = EccChip::configure(meta, advices, table_idx, lagrange_coeffs); + let ecc_config = EccChip::configure(meta, advices, lagrange_coeffs, range_check.clone()); // Configuration for the Poseidon hash. let poseidon_config = PoseidonChip::configure( @@ -243,8 +249,12 @@ impl plonk::Circuit for Circuit { // Since the Sinsemilla config uses only 5 advice columns, // we can fit two instances side-by-side. let (sinsemilla_config_1, merkle_config_1) = { - let sinsemilla_config_1 = - SinsemillaChip::configure(meta, advices[..5].try_into().unwrap(), lookup); + let sinsemilla_config_1 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + lookup, + range_check.clone(), + ); let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone()); (sinsemilla_config_1, merkle_config_1) @@ -255,8 +265,12 @@ impl plonk::Circuit for Circuit { // Since the Sinsemilla config uses only 5 advice columns, // we can fit two instances side-by-side. let (sinsemilla_config_2, merkle_config_2) = { - let sinsemilla_config_2 = - SinsemillaChip::configure(meta, advices[5..].try_into().unwrap(), lookup); + let sinsemilla_config_2 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + lookup, + range_check, + ); let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone()); (sinsemilla_config_2, merkle_config_2) diff --git a/src/circuit/gadget/ecc.rs b/src/circuit/gadget/ecc.rs index 497ef101..b561c45e 100644 --- a/src/circuit/gadget/ecc.rs +++ b/src/circuit/gadget/ecc.rs @@ -407,6 +407,7 @@ mod tests { use pasta_curves::pallas; use super::chip::{EccChip, EccConfig}; + use crate::circuit::gadget::utilities::lookup_range_check::LookupRangeCheckConfig; struct MyCircuit {} @@ -447,7 +448,8 @@ mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - EccChip::configure(meta, advices, lookup_table, lagrange_coeffs) + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup_table); + EccChip::configure(meta, advices, lagrange_coeffs, range_check) } fn synthesize( diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index fe0981fc..c96dc16e 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -152,8 +152,8 @@ impl EccChip { pub fn configure( meta: &mut ConstraintSystem, advices: [Column; 10], - lookup_table: Column, lagrange_coeffs: [Column; 8], + range_check: LookupRangeCheckConfig, ) -> >::Config { // The following columns need to be equality-enabled for their use in sub-configs: // @@ -186,8 +186,6 @@ impl EccChip { meta.enable_equality((*column).into()); } - let lookup_config = LookupRangeCheckConfig::configure(meta, advices[9], lookup_table); - let q_mul_fixed_running_sum = meta.selector(); let running_sum_config = RunningSumConfig::configure(meta, q_mul_fixed_running_sum, advices[4]); @@ -208,7 +206,7 @@ impl EccChip { q_mul_fixed_base_field: meta.selector(), q_mul_fixed_running_sum, q_point: meta.selector(), - lookup_config, + lookup_config: range_check, running_sum_config, }; diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index defc3961..4c663ac7 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -247,7 +247,7 @@ pub mod tests { use crate::circuit::gadget::{ ecc::{chip::EccChip, FixedPointShort, Point}, - utilities::{CellValue, UtilitiesInstructions}, + utilities::{lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions}, }; use crate::constants::load::ValueCommitV; @@ -420,7 +420,8 @@ pub mod tests { let constants = meta.fixed_column(); meta.enable_constant(constants); - EccChip::configure(meta, advices, lookup_table, lagrange_coeffs) + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup_table); + EccChip::configure(meta, advices, lagrange_coeffs, range_check) } fn synthesize( diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index 996e30e9..e2e56bb2 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -416,9 +416,12 @@ mod tests { }; use crate::{ - circuit::gadget::ecc::{ - chip::{EccChip, EccConfig}, - Point, + circuit::gadget::{ + ecc::{ + chip::{EccChip, EccConfig}, + Point, + }, + utilities::lookup_range_check::LookupRangeCheckConfig, }, constants::{COMMIT_IVK_PERSONALIZATION, MERKLE_CRH_PERSONALIZATION}, primitives::sinsemilla::{self, K}, @@ -473,10 +476,23 @@ mod tests { // Fixed columns for the Sinsemilla generator lookup table let lookup = (table_idx, meta.fixed_column(), meta.fixed_column()); - let ecc_config = EccChip::configure(meta, advices, table_idx, lagrange_coeffs); + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); - let config1 = SinsemillaChip::configure(meta, advices[..5].try_into().unwrap(), lookup); - let config2 = SinsemillaChip::configure(meta, advices[5..].try_into().unwrap(), lookup); + let ecc_config = + EccChip::configure(meta, advices, lagrange_coeffs, range_check.clone()); + + let config1 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + lookup, + range_check.clone(), + ); + let config2 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + lookup, + range_check, + ); (ecc_config, config1, config2) } diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index 749366f5..5ef88d11 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -56,12 +56,8 @@ pub struct SinsemillaConfig { /// 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, - /// Configure each advice column to be able to perform lookup range checks. - pub(super) lookup_config_0: LookupRangeCheckConfig, - pub(super) lookup_config_1: LookupRangeCheckConfig, - pub(super) lookup_config_2: LookupRangeCheckConfig, - pub(super) lookup_config_3: LookupRangeCheckConfig, - pub(super) lookup_config_4: LookupRangeCheckConfig, + /// An advice column configured to perform lookup range checks. + pub(super) lookup_config: LookupRangeCheckConfig, } impl SinsemillaConfig { @@ -111,16 +107,8 @@ impl SinsemillaChip { meta: &mut ConstraintSystem, advices: [Column; 5], lookup: (Column, Column, Column), + range_check: LookupRangeCheckConfig, ) -> >::Config { - // This chip requires all advice columns and the `constants` fixed columns to be - // equality-enabled. The advice columns and the first five `constants` columns - // are equality-enabled by the calls to LookupRangeCheckConfig::configure. - let lookup_config_0 = LookupRangeCheckConfig::configure(meta, advices[0], lookup.0); - let lookup_config_1 = LookupRangeCheckConfig::configure(meta, advices[1], lookup.0); - let lookup_config_2 = LookupRangeCheckConfig::configure(meta, advices[2], lookup.0); - let lookup_config_3 = LookupRangeCheckConfig::configure(meta, advices[3], lookup.0); - let lookup_config_4 = LookupRangeCheckConfig::configure(meta, advices[4], lookup.0); - let config = SinsemillaConfig { q_sinsemilla1: meta.selector(), q_sinsemilla2: meta.fixed_column(), @@ -135,11 +123,7 @@ impl SinsemillaChip { table_x: lookup.1, table_y: lookup.2, }, - lookup_config_0, - lookup_config_1, - lookup_config_2, - lookup_config_3, - lookup_config_4, + lookup_config: range_check, }; // Set up lookup argument diff --git a/src/circuit/gadget/sinsemilla/commit_ivk.rs b/src/circuit/gadget/sinsemilla/commit_ivk.rs index 94a2364c..44caff6f 100644 --- a/src/circuit/gadget/sinsemilla/commit_ivk.rs +++ b/src/circuit/gadget/sinsemilla/commit_ivk.rs @@ -263,13 +263,13 @@ impl CommitIvkConfig { }); // Constrain b_0 to be 4 bits. - let b_0 = self.sinsemilla_config.lookup_config_0.witness_short_check( + let b_0 = self.sinsemilla_config.lookup_config.witness_short_check( layouter.namespace(|| "b_0 is 4 bits"), b_0, 4, )?; // Constrain b_2 to be 5 bits. - let b_2 = self.sinsemilla_config.lookup_config_1.witness_short_check( + let b_2 = self.sinsemilla_config.lookup_config.witness_short_check( layouter.namespace(|| "b_2 is 5 bits"), b_2, 5, @@ -307,7 +307,7 @@ impl CommitIvkConfig { .map(|(d_0, d_1)| d_0 + d_1 * pallas::Base::from_u64(1 << 9)); // Constrain d_0 to be 9 bits. - let d_0 = self.sinsemilla_config.lookup_config_2.witness_short_check( + let d_0 = self.sinsemilla_config.lookup_config.witness_short_check( layouter.namespace(|| "d_0 is 9 bits"), d_0, 9, @@ -400,7 +400,7 @@ impl CommitIvkConfig { let t_p = pallas::Base::from_u128(T_P); a + two_pow_130 - t_p }); - let (a_prime, zs) = self.sinsemilla_config.lookup_config_3.witness_check( + let (a_prime, zs) = self.sinsemilla_config.lookup_config.witness_check( layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"), a_prime, 13, @@ -436,7 +436,7 @@ impl CommitIvkConfig { let t_p = pallas::Base::from_u128(T_P); b_2 + c * two_pow_5 + two_pow_140 - t_p }); - let (b2_c_prime, zs) = self.sinsemilla_config.lookup_config_4.witness_check( + let (b2_c_prime, zs) = self.sinsemilla_config.lookup_config.witness_check( layouter.namespace(|| "Decompose low 140 bits of (b_2 + c * 2^5 + 2^140 - t_P)"), b2_c_prime, 14, @@ -629,7 +629,9 @@ mod tests { circuit::gadget::{ ecc::chip::{EccChip, EccConfig}, sinsemilla::chip::SinsemillaChip, - utilities::{CellValue, UtilitiesInstructions}, + utilities::{ + lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, + }, }, constants::T_Q, }; @@ -696,12 +698,18 @@ mod tests { meta.fixed_column(), ]; - let sinsemilla_config = - SinsemillaChip::configure(meta, advices[..5].try_into().unwrap(), lookup); + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let sinsemilla_config = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + lookup, + range_check.clone(), + ); + let commit_ivk_config = CommitIvkConfig::configure(meta, advices, sinsemilla_config); - let ecc_config = EccChip::configure(meta, advices, table_idx, lagrange_coeffs); + let ecc_config = EccChip::configure(meta, advices, lagrange_coeffs, range_check); (commit_ivk_config, ecc_config) } diff --git a/src/circuit/gadget/sinsemilla/merkle.rs b/src/circuit/gadget/sinsemilla/merkle.rs index 4c1341d7..0a691f2a 100644 --- a/src/circuit/gadget/sinsemilla/merkle.rs +++ b/src/circuit/gadget/sinsemilla/merkle.rs @@ -139,7 +139,7 @@ pub mod tests { use crate::{ circuit::gadget::{ sinsemilla::chip::{SinsemillaChip, SinsemillaHashDomains}, - utilities::{UtilitiesInstructions, Var}, + utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions, Var}, }, constants::{L_ORCHARD_BASE, MERKLE_CRH_PERSONALIZATION, MERKLE_DEPTH_ORCHARD}, primitives::sinsemilla::HashDomain, @@ -198,12 +198,22 @@ pub mod tests { meta.fixed_column(), ); - let sinsemilla_config_1 = - SinsemillaChip::configure(meta, advices[5..].try_into().unwrap(), lookup); + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], lookup.0); + + let sinsemilla_config_1 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + lookup, + range_check.clone(), + ); let config1 = MerkleChip::configure(meta, sinsemilla_config_1); - let sinsemilla_config_2 = - SinsemillaChip::configure(meta, advices[..5].try_into().unwrap(), lookup); + let sinsemilla_config_2 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + lookup, + range_check, + ); let config2 = MerkleChip::configure(meta, sinsemilla_config_2); (config1, config2) diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index 9b41f97f..54b73131 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -214,10 +214,11 @@ impl MerkleInstructions