From 22f57005a98035807e239e4bc57f477f8c932d07 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 15:59:29 -0500 Subject: [PATCH] mul::incomplete: Refactor incomplete::Config. This is only used in chip::mul::Config. In a subsequent commit, this will be configured from mul::Config instead of from ecc::chip::Config. This commit does not result in circuit changes. --- src/circuit/gadget/ecc/chip.rs | 17 +++- src/circuit/gadget/ecc/chip/mul.rs | 31 ++++-- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 94 +++++++------------ 3 files changed, 67 insertions(+), 75 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 9c875abf..0ce5f6bd 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -145,9 +145,9 @@ pub struct EccConfig { add: add::Config, /// Variable-base scalar multiplication (hi half) - pub q_mul_hi: (Selector, Selector, Selector), + mul_hi: mul::incomplete::Config<{ mul::INCOMPLETE_HI_LEN }>, /// Variable-base scalar multiplication (lo half) - pub q_mul_lo: (Selector, Selector, Selector), + mul_lo: mul::incomplete::Config<{ mul::INCOMPLETE_LO_LEN }>, /// Selector used to enforce boolean decomposition in variable-base scalar mul pub q_mul_decompose_var: Selector, /// Selector used to enforce switching logic on LSB in variable-base scalar mul @@ -253,14 +253,23 @@ impl EccChip { advices[6], advices[7], advices[8], ); + // Components of mul::Config + // TODO: Move this into mul::Config. + let mul_hi = mul::incomplete::Config::configure( + meta, advices[9], advices[3], advices[0], advices[1], advices[4], advices[5], + ); + let mul_lo = mul::incomplete::Config::configure( + meta, advices[6], advices[7], advices[0], advices[1], advices[8], advices[2], + ); + let config = EccConfig { advices, lagrange_coeffs, fixed_z: meta.fixed_column(), add_incomplete, add, - q_mul_hi: (meta.selector(), meta.selector(), meta.selector()), - q_mul_lo: (meta.selector(), meta.selector(), meta.selector()), + mul_hi, + mul_lo, q_mul_decompose_var: meta.selector(), q_mul_overflow: meta.selector(), q_mul_lsb: meta.selector(), diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index e2f02445..a95e0831 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -17,7 +17,8 @@ use halo2::{ use pasta_curves::pallas; mod complete; -mod incomplete; +// TODO: Undo this pub(crate). +pub(crate) mod incomplete; mod overflow; /// Number of bits for which complete addition needs to be used in variable-base @@ -33,10 +34,12 @@ const INCOMPLETE_RANGE: Range = 0..INCOMPLETE_LEN; // (It is a coincidence that k_{130} matches the boundary of the // overflow check described in [the book](https://zcash.github.io/halo2/design/gadgets/ecc/var-base-scalar-mul.html#overflow-check).) const INCOMPLETE_HI_RANGE: Range = 0..(INCOMPLETE_LEN / 2); +pub const INCOMPLETE_HI_LEN: usize = INCOMPLETE_LEN / 2; // Bits k_{254} to k_{4} inclusive are used in incomplete addition. // The `lo` half is k_{129} to k_{4} inclusive (length 126 bits). const INCOMPLETE_LO_RANGE: Range = (INCOMPLETE_LEN / 2)..INCOMPLETE_LEN; +pub const INCOMPLETE_LO_LEN: usize = (INCOMPLETE_LEN / 2) + 1; // Bits k_{3} to k_{1} inclusive are used in complete addition. // Bit k_{0} is handled separately. @@ -48,9 +51,9 @@ pub struct Config { // Configuration used in complete addition add_config: add::Config, // Configuration used for `hi` bits of the scalar - hi_config: incomplete::HiConfig, + hi_config: incomplete::Config, // Configuration used for `lo` bits of the scalar - lo_config: incomplete::LoConfig, + lo_config: incomplete::Config, // Configuration used for complete addition part of double-and-add algorithm complete_config: complete::Config, // Configuration used to check for overflow @@ -62,8 +65,8 @@ impl From<&EccConfig> for Config { let config = Self { q_mul_lsb: ecc_config.q_mul_lsb, add_config: ecc_config.add, - hi_config: ecc_config.into(), - lo_config: ecc_config.into(), + hi_config: ecc_config.mul_hi, + lo_config: ecc_config.mul_lo, complete_config: ecc_config.into(), overflow_config: ecc_config.into(), }; @@ -81,13 +84,23 @@ impl From<&EccConfig> for Config { // z and lambda1 are assigned on the same row as the add_config output. // Therefore, z and lambda1 must not overlap with add_config.x_qr, add_config.y_qr. let add_config_outputs = config.add_config.output_columns(); - for config in [&(*config.hi_config), &(*config.lo_config)].iter() { + { assert!( - !add_config_outputs.contains(&config.z), + !add_config_outputs.contains(&config.hi_config.z), "incomplete config z cannot overlap with complete addition columns." ); assert!( - !add_config_outputs.contains(&config.lambda1), + !add_config_outputs.contains(&config.hi_config.lambda1), + "incomplete config lambda1 cannot overlap with complete addition columns." + ); + } + { + assert!( + !add_config_outputs.contains(&config.lo_config.z), + "incomplete config z cannot overlap with complete addition columns." + ); + assert!( + !add_config_outputs.contains(&config.lo_config.lambda1), "incomplete config lambda1 cannot overlap with complete addition columns." ); } @@ -98,8 +111,6 @@ impl From<&EccConfig> for Config { impl Config { pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { - self.hi_config.create_gate(meta); - self.lo_config.create_gate(meta); self.complete_config.create_gate(meta); self.overflow_config.create_gate(meta); diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index 4ddac353..63e6919d 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -1,7 +1,5 @@ -use std::ops::Deref; - -use super::super::{copy, CellValue, EccConfig, NonIdentityEccPoint, Var}; -use super::{INCOMPLETE_HI_RANGE, INCOMPLETE_LO_RANGE, X, Y, Z}; +use super::super::{copy, CellValue, NonIdentityEccPoint, Var}; +use super::{X, Y, Z}; use crate::circuit::gadget::utilities::bool_check; use ff::Field; use halo2::{ @@ -12,10 +10,8 @@ use halo2::{ use pasta_curves::{arithmetic::FieldExt, pallas}; -#[derive(Copy, Clone)] -pub(super) struct Config { - // Number of bits covered by this incomplete range. - num_bits: usize, +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub(crate) struct Config { // Selectors used to constrain the cells used in incomplete addition. pub(super) q_mul: (Selector, Selector, Selector), // Cumulative sum used to decompose the scalar. @@ -32,61 +28,37 @@ pub(super) struct Config { pub(super) lambda2: Column, } -// Columns used in processing the `hi` bits of the scalar. -// `x_p, y_p` are shared across the `hi` and `lo` halves. -pub(super) struct HiConfig(Config); -impl From<&EccConfig> for HiConfig { - fn from(ecc_config: &EccConfig) -> Self { - let config = Config { - num_bits: INCOMPLETE_HI_RANGE.len(), - q_mul: ecc_config.q_mul_hi, - x_p: ecc_config.advices[0], - y_p: ecc_config.advices[1], - z: ecc_config.advices[9], - x_a: ecc_config.advices[3], - lambda1: ecc_config.advices[4], - lambda2: ecc_config.advices[5], +impl Config { + // TODO: Make this pub(super). + pub(crate) fn configure( + meta: &mut ConstraintSystem, + z: Column, + x_a: Column, + x_p: Column, + y_p: Column, + lambda1: Column, + lambda2: Column, + ) -> Self { + meta.enable_equality(z.into()); + meta.enable_equality(lambda1.into()); + + let config = Self { + q_mul: (meta.selector(), meta.selector(), meta.selector()), + z, + x_a, + x_p, + y_p, + lambda1, + lambda2, }; - Self(config) - } -} -impl Deref for HiConfig { - type Target = Config; - fn deref(&self) -> &Config { - &self.0 - } -} + config.create_gate(meta); -// Columns used in processing the `lo` bits of the scalar. -// `x_p, y_p` are shared across the `hi` and `lo` halves. -pub(super) struct LoConfig(Config); -impl From<&EccConfig> for LoConfig { - fn from(ecc_config: &EccConfig) -> Self { - let config = Config { - num_bits: INCOMPLETE_LO_RANGE.len(), - q_mul: ecc_config.q_mul_lo, - x_p: ecc_config.advices[0], - y_p: ecc_config.advices[1], - z: ecc_config.advices[6], - x_a: ecc_config.advices[7], - lambda1: ecc_config.advices[8], - lambda2: ecc_config.advices[2], - }; - Self(config) + config } -} -impl Deref for LoConfig { - type Target = Config; - fn deref(&self) -> &Config { - &self.0 - } -} - -impl Config { // Gate for incomplete addition part of variable-base scalar multiplication. - pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { + fn create_gate(&self, meta: &mut ConstraintSystem) { // Closure to compute x_{R,i} = λ_{1,i}^2 - x_{A,i} - x_{P,i} let x_r = |meta: &mut VirtualCells, rotation: Rotation| { let x_a = meta.query_advice(self.x_a, rotation); @@ -216,7 +188,7 @@ impl Config { acc: (X, Y, Z), ) -> Result<(X, Y, Vec>), Error> { // Check that we have the correct number of bits for this double-and-add. - assert_eq!(bits.len(), self.num_bits); + assert_eq!(bits.len(), NUM_BITS); // Handle exceptional cases let (x_p, y_p) = (base.x.value(), base.y.value()); @@ -241,12 +213,12 @@ impl Config { let offset = offset + 1; // q_mul_2 = 1 on all rows after offset 0, excluding the last row. - for idx in 0..(self.num_bits - 1) { + for idx in 0..(NUM_BITS - 1) { self.q_mul.1.enable(region, offset + idx)?; } // q_mul_3 = 1 on the last row. - self.q_mul.2.enable(region, offset + self.num_bits - 1)?; + self.q_mul.2.enable(region, offset + NUM_BITS - 1)?; } // Initialise double-and-add @@ -361,7 +333,7 @@ impl Config { let cell = region.assign_advice( || "y_a", self.lambda1, - offset + self.num_bits, + offset + NUM_BITS, || y_a.ok_or(Error::Synthesis), )?; CellValue::new(cell, y_a)