ecc::chip: Introduce ScalarVar enum.

This commit is contained in:
therealyingtong 2022-03-22 15:20:16 +08:00
parent 6f2fc57b3c
commit 1c877f3caf
3 changed files with 40 additions and 22 deletions

View File

@ -16,17 +16,7 @@ pub mod chip;
pub trait EccInstructions<C: CurveAffine>: pub trait EccInstructions<C: CurveAffine>:
Chip<C::Base> + UtilitiesInstructions<C::Base> + Clone + Debug + Eq Chip<C::Base> + UtilitiesInstructions<C::Base> + Clone + Debug + Eq
{ {
/// Variable representing an element of the elliptic curve's base field, that /// Variable representing a scalar used in variable-base scalar mul.
/// 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.)
type ScalarVar: Clone + Debug; type ScalarVar: Clone + Debug;
/// Variable representing a full-width element of the elliptic curve's /// Variable representing a full-width element of the elliptic curve's
/// scalar field, to be used for fixed-base scalar mul. /// scalar field, to be used for fixed-base scalar mul.

View File

@ -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<pallas::Base, pallas::Base>),
/// A full-width scalar. This is unimplemented for halo2_gadgets v0.1.0.
FullWidth,
}
impl<Fixed: FixedPoints<pallas::Affine>> EccInstructions<pallas::Affine> for EccChip<Fixed> impl<Fixed: FixedPoints<pallas::Affine>> EccInstructions<pallas::Affine> for EccChip<Fixed>
where where
<Fixed as FixedPoints<pallas::Affine>>::Base: <Fixed as FixedPoints<pallas::Affine>>::Base:
@ -388,7 +408,7 @@ where
{ {
type ScalarFixed = EccScalarFixed; type ScalarFixed = EccScalarFixed;
type ScalarFixedShort = EccScalarFixedShort; type ScalarFixedShort = EccScalarFixedShort;
type ScalarVar = AssignedCell<pallas::Base, pallas::Base>; type ScalarVar = ScalarVar;
type Point = EccPoint; type Point = EccPoint;
type NonIdentityPoint = NonIdentityEccPoint; type NonIdentityPoint = NonIdentityEccPoint;
type X = AssignedCell<pallas::Base, pallas::Base>; type X = AssignedCell<pallas::Base, pallas::Base>;
@ -484,11 +504,16 @@ where
base: &Self::NonIdentityPoint, base: &Self::NonIdentityPoint,
) -> Result<(Self::Point, Self::ScalarVar), Error> { ) -> Result<(Self::Point, Self::ScalarVar), Error> {
let config = self.config().mul; let config = self.config().mul;
config.assign( match scalar {
layouter.namespace(|| "variable-base scalar mul"), ScalarVar::BaseFieldElem(scalar) => config.assign(
scalar.clone(), layouter.namespace(|| "variable-base scalar mul"),
base, scalar.clone(),
) base,
),
ScalarVar::FullWidth => {
todo!()
}
}
} }
fn mul_fixed( fn mul_fixed(
@ -549,6 +574,6 @@ where
_layouter: &mut impl Layouter<pallas::Base>, _layouter: &mut impl Layouter<pallas::Base>,
base: &Self::Var, base: &Self::Var,
) -> Result<Self::ScalarVar, Error> { ) -> Result<Self::ScalarVar, Error> {
Ok(base.clone()) Ok(ScalarVar::BaseFieldElem(base.clone()))
} }
} }

View File

@ -1,4 +1,4 @@
use super::{add, EccPoint, NonIdentityEccPoint, T_Q}; use super::{add, EccPoint, NonIdentityEccPoint, ScalarVar, T_Q};
use crate::{ use crate::{
primitives::sinsemilla, primitives::sinsemilla,
utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig, ternary}, utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig, ternary},
@ -167,7 +167,7 @@ impl Config {
mut layouter: impl Layouter<pallas::Base>, mut layouter: impl Layouter<pallas::Base>,
alpha: AssignedCell<pallas::Base, pallas::Base>, alpha: AssignedCell<pallas::Base, pallas::Base>,
base: &NonIdentityEccPoint, base: &NonIdentityEccPoint,
) -> Result<(EccPoint, AssignedCell<pallas::Base, pallas::Base>), Error> { ) -> Result<(EccPoint, ScalarVar), Error> {
let (result, zs): (EccPoint, Vec<Z<pallas::Base>>) = layouter.assign_region( let (result, zs): (EccPoint, Vec<Z<pallas::Base>>) = layouter.assign_region(
|| "variable-base scalar mul", || "variable-base scalar mul",
|mut region| { |mut region| {
@ -293,7 +293,7 @@ impl Config {
&zs, &zs,
)?; )?;
Ok((result, alpha)) Ok((result, ScalarVar::BaseFieldElem(alpha)))
} }
/// Processes the final scalar bit `k_0`. /// Processes the final scalar bit `k_0`.
@ -483,7 +483,7 @@ pub mod tests {
ecc::{ ecc::{
chip::{EccChip, EccPoint}, chip::{EccChip, EccPoint},
tests::TestFixedBases, tests::TestFixedBases,
EccInstructions, NonIdentityPoint, Point, BaseFitsInScalarInstructions, EccInstructions, NonIdentityPoint, Point,
}, },
utilities::UtilitiesInstructions, utilities::UtilitiesInstructions,
}; };
@ -525,6 +525,7 @@ pub mod tests {
column, column,
Some(scalar_val), Some(scalar_val),
)?; )?;
let scalar = chip.scalar_var_from_base(&mut layouter, &scalar)?;
p.mul(layouter.namespace(|| "random [a]B"), &scalar)? p.mul(layouter.namespace(|| "random [a]B"), &scalar)?
}; };
constrain_equal_non_id( constrain_equal_non_id(
@ -543,6 +544,7 @@ pub mod tests {
let (result, _) = { let (result, _) = {
let scalar = let scalar =
chip.load_private(layouter.namespace(|| "zero"), column, Some(scalar_val))?; 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)? p.mul(layouter.namespace(|| "[0]B"), &scalar)?
}; };
if let Some(is_identity) = result.inner().is_identity() { if let Some(is_identity) = result.inner().is_identity() {
@ -556,6 +558,7 @@ pub mod tests {
let (result, _) = { let (result, _) = {
let scalar = let scalar =
chip.load_private(layouter.namespace(|| "-1"), column, Some(scalar_val))?; 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)? p.mul(layouter.namespace(|| "[-1]B"), &scalar)?
}; };
constrain_equal_non_id( constrain_equal_non_id(