diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index f72d2916..f0cf0b33 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -16,17 +16,7 @@ pub mod chip; pub trait EccInstructions: Chip + UtilitiesInstructions + Clone + Debug + Eq { - /// Variable representing an element of the elliptic curve's base field, that - /// is used as a scalar in variable-base scalar mul. - /// - /// It is not true in general that a scalar field element fits in a curve's - /// base field, and in particular it is untrue for the Pallas curve, whose - /// scalar field `Fq` is larger than its base field `Fp`. - /// - /// However, the only use of variable-base scalar mul in the Orchard protocol - /// is in deriving diversified addresses `[ivk] g_d`, and `ivk` is guaranteed - /// to be in the base field of the curve. (See non-normative notes in - /// https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents.) + /// Variable representing a scalar used in variable-base scalar mul. type ScalarVar: Clone + Debug; /// Variable representing a full-width element of the elliptic curve's /// scalar field, to be used for fixed-base scalar mul. diff --git a/halo2_gadgets/src/ecc/chip.rs b/halo2_gadgets/src/ecc/chip.rs index 5454db62..44d39220 100644 --- a/halo2_gadgets/src/ecc/chip.rs +++ b/halo2_gadgets/src/ecc/chip.rs @@ -377,6 +377,26 @@ impl EccBaseFieldElemFixed { } } +/// An enumeration of the possible types of scalars used in variable-base +/// multiplication. +#[derive(Clone, Debug)] +pub enum ScalarVar { + /// An element of the elliptic curve's base field, that is used as a scalar + /// in variable-base scalar mul. + /// + /// It is not true in general that a scalar field element fits in a curve's + /// base field, and in particular it is untrue for the Pallas curve, whose + /// scalar field `Fq` is larger than its base field `Fp`. + /// + /// However, the only use of variable-base scalar mul in the Orchard protocol + /// is in deriving diversified addresses `[ivk] g_d`, and `ivk` is guaranteed + /// to be in the base field of the curve. (See non-normative notes in + /// https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents.) + BaseFieldElem(AssignedCell), + /// A full-width scalar. This is unimplemented for halo2_gadgets v0.1.0. + FullWidth, +} + impl> EccInstructions for EccChip where >::Base: @@ -388,7 +408,7 @@ where { type ScalarFixed = EccScalarFixed; type ScalarFixedShort = EccScalarFixedShort; - type ScalarVar = AssignedCell; + type ScalarVar = ScalarVar; type Point = EccPoint; type NonIdentityPoint = NonIdentityEccPoint; type X = AssignedCell; @@ -484,11 +504,16 @@ where base: &Self::NonIdentityPoint, ) -> Result<(Self::Point, Self::ScalarVar), Error> { let config = self.config().mul; - config.assign( - layouter.namespace(|| "variable-base scalar mul"), - scalar.clone(), - base, - ) + match scalar { + ScalarVar::BaseFieldElem(scalar) => config.assign( + layouter.namespace(|| "variable-base scalar mul"), + scalar.clone(), + base, + ), + ScalarVar::FullWidth => { + todo!() + } + } } fn mul_fixed( @@ -549,6 +574,6 @@ where _layouter: &mut impl Layouter, base: &Self::Var, ) -> Result { - Ok(base.clone()) + Ok(ScalarVar::BaseFieldElem(base.clone())) } } diff --git a/halo2_gadgets/src/ecc/chip/mul.rs b/halo2_gadgets/src/ecc/chip/mul.rs index 910a3d73..67387c5c 100644 --- a/halo2_gadgets/src/ecc/chip/mul.rs +++ b/halo2_gadgets/src/ecc/chip/mul.rs @@ -1,4 +1,4 @@ -use super::{add, EccPoint, NonIdentityEccPoint, T_Q}; +use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q}; use crate::{ primitives::sinsemilla, utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig, ternary}, @@ -167,7 +167,7 @@ impl Config { mut layouter: impl Layouter, alpha: AssignedCell, base: &NonIdentityEccPoint, - ) -> Result<(EccPoint, AssignedCell), Error> { + ) -> Result<(EccPoint, ScalarVar), Error> { let (result, zs): (EccPoint, Vec>) = layouter.assign_region( || "variable-base scalar mul", |mut region| { @@ -293,7 +293,7 @@ impl Config { &zs, )?; - Ok((result, alpha)) + Ok((result, ScalarVar::BaseFieldElem(alpha))) } /// Processes the final scalar bit `k_0`. @@ -483,7 +483,7 @@ pub mod tests { ecc::{ chip::{EccChip, EccPoint}, tests::TestFixedBases, - EccInstructions, NonIdentityPoint, Point, + BaseFitsInScalarInstructions, EccInstructions, NonIdentityPoint, Point, }, utilities::UtilitiesInstructions, }; @@ -525,6 +525,7 @@ pub mod tests { column, Some(scalar_val), )?; + let scalar = chip.scalar_var_from_base(&mut layouter, &scalar)?; p.mul(layouter.namespace(|| "random [a]B"), &scalar)? }; constrain_equal_non_id( @@ -543,6 +544,7 @@ pub mod tests { let (result, _) = { let scalar = chip.load_private(layouter.namespace(|| "zero"), column, Some(scalar_val))?; + let scalar = chip.scalar_var_from_base(&mut layouter, &scalar)?; p.mul(layouter.namespace(|| "[0]B"), &scalar)? }; if let Some(is_identity) = result.inner().is_identity() { @@ -556,6 +558,7 @@ pub mod tests { let (result, _) = { let scalar = chip.load_private(layouter.namespace(|| "-1"), column, Some(scalar_val))?; + let scalar = chip.scalar_var_from_base(&mut layouter, &scalar)?; p.mul(layouter.namespace(|| "[-1]B"), &scalar)? }; constrain_equal_non_id(