From 0d2512a121d30fbfdedef59ca53e81532d8afbe4 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 1 Jul 2024 21:59:00 +0200 Subject: [PATCH] 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 7b8139be9..2da0c3195 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 32f026a41..2cdb5f63d 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 f5cf9d3ce..393f06520 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 76581cb9a..d6dd82e4a 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 7af792489..3dc70274c 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 03d7d6e82..e6ce0e9d4 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>,