From 5569c6dbab90bc4d13a195b3ad1f9b4bfc04c686 Mon Sep 17 00:00:00 2001 From: Conghao Shen Date: Sat, 5 Mar 2022 18:49:32 -0800 Subject: [PATCH 1/8] Support scalar mul of arkworks curve using precomputed table. --- manta-crypto/src/ecc.rs | 14 -------------- manta-pay/src/crypto/ecc/arkworks.rs | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/manta-crypto/src/ecc.rs b/manta-crypto/src/ecc.rs index b4d26027d..07dbd3fb9 100644 --- a/manta-crypto/src/ecc.rs +++ b/manta-crypto/src/ecc.rs @@ -145,20 +145,6 @@ pub trait PreprocessedScalarMul: ScalarMul + Sized { ) -> Self::Output; } -impl PreprocessedScalarMul for G -where - G: ScalarMul, -{ - #[inline] - fn preprocessed_scalar_mul( - table: &[Self; 1], - scalar: &Self::Scalar, - compiler: &mut COM, - ) -> Self::Output { - table[0].scalar_mul(scalar, compiler) - } -} - /// Elliptic Curve Group pub trait Group: PointAdd + PointDouble + ScalarMul {} diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index 8d7fa37b0..f148f0baa 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -406,6 +406,31 @@ where } } +impl ecc::PreprocessedScalarMul, N> for GroupVar where + C: ProjectiveCurve, + CV: CurveVar> { + /// Performs the scalar multiplication against a pre-computed table. + /// + /// The pre-computed table is a list of power-of-two multiples of `scalar`, such that + /// `table[i] = scalar * 2^i`. + fn preprocessed_scalar_mul(table: &[Self; N], scalar: &Self::Scalar, compiler: &mut Compiler) -> Self::Output { + // Computes the standard little-endian double-and-add algorithm + // (Algorithm 3.26, Guide to Elliptic Curve Cryptography) + // adapted from https://github.com/arkworks-rs/r1cs-std/blob/50ab8ee5ba8c09637044718eceac38e98e0ea67c/src/groups/mod.rs#L110-L139 + + let _ = compiler; + let mut result: CV = CV::zero(); + let scalar_bits = scalar.0.to_bits_le().expect("Bit decomposition is not allowed to fail."); + debug_assert_eq!(scalar_bits.len(), N, "Scalar is expected to have N bits."); + for (bit, base) in scalar_bits.into_iter().zip(table.iter()){ + // compute `self + 2^i * scalar` + let scalar_plus_base = result.clone() + base.0.clone(); + result = bit.select(&scalar_plus_base, &result).expect("Conditional select is not allowed to fail. "); + } + Self(result, PhantomData) + } +} + impl Equal> for GroupVar where C: ProjectiveCurve, From 5359a0a7aaa5a90af75ee84a5e87f4ab9fb01e7e Mon Sep 17 00:00:00 2001 From: Conghao Shen Date: Fri, 18 Mar 2022 00:31:33 -0700 Subject: [PATCH 2/8] implement processed scalar mul only for the correct MODULAR_BITS and 1 --- manta-crypto/src/ecc.rs | 17 +++++++++ manta-pay/src/crypto/ecc/arkworks.rs | 57 +++++++++++++++++----------- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/manta-crypto/src/ecc.rs b/manta-crypto/src/ecc.rs index 07dbd3fb9..0c5811511 100644 --- a/manta-crypto/src/ecc.rs +++ b/manta-crypto/src/ecc.rs @@ -137,6 +137,9 @@ pub trait ScalarMul { /// Elliptic Curve Pre-processed Scalar Multiplication Operation pub trait PreprocessedScalarMul: ScalarMul + Sized { /// Performs the scalar multiplication against a pre-computed table. + /// + /// The pre-computed table is a list of power-of-two multiples of `scalar`, such that + /// `table[i] = scalar * 2^i`. #[must_use] fn preprocessed_scalar_mul( table: &[Self; N], @@ -145,6 +148,20 @@ pub trait PreprocessedScalarMul: ScalarMul + Sized { ) -> Self::Output; } +impl PreprocessedScalarMul for G +where + G: ScalarMul, +{ + #[inline] + fn preprocessed_scalar_mul( + table: &[Self; 1], + scalar: &Self::Scalar, + compiler: &mut COM, + ) -> Self::Output { + table[0].scalar_mul(scalar, compiler) + } +} + /// Elliptic Curve Group pub trait Group: PointAdd + PointDouble + ScalarMul {} diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index f148f0baa..49195ed3c 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -35,6 +35,7 @@ use manta_util::codec; use manta_util::serde::{Deserialize, Serialize, Serializer}; pub use ark_ec::{AffineCurve, ProjectiveCurve}; +use ark_ed_on_bls12_381::EdwardsProjective; pub use ark_r1cs_std::groups::CurveVar; /// Constraint Field Type @@ -406,31 +407,43 @@ where } } -impl ecc::PreprocessedScalarMul, N> for GroupVar where - C: ProjectiveCurve, - CV: CurveVar> { - /// Performs the scalar multiplication against a pre-computed table. - /// - /// The pre-computed table is a list of power-of-two multiples of `scalar`, such that - /// `table[i] = scalar * 2^i`. - fn preprocessed_scalar_mul(table: &[Self; N], scalar: &Self::Scalar, compiler: &mut Compiler) -> Self::Output { - // Computes the standard little-endian double-and-add algorithm - // (Algorithm 3.26, Guide to Elliptic Curve Cryptography) - // adapted from https://github.com/arkworks-rs/r1cs-std/blob/50ab8ee5ba8c09637044718eceac38e98e0ea67c/src/groups/mod.rs#L110-L139 - - let _ = compiler; - let mut result: CV = CV::zero(); - let scalar_bits = scalar.0.to_bits_le().expect("Bit decomposition is not allowed to fail."); - debug_assert_eq!(scalar_bits.len(), N, "Scalar is expected to have N bits."); - for (bit, base) in scalar_bits.into_iter().zip(table.iter()){ - // compute `self + 2^i * scalar` - let scalar_plus_base = result.clone() + base.0.clone(); - result = bit.select(&scalar_plus_base, &result).expect("Conditional select is not allowed to fail. "); +macro_rules! impl_processed_scalar_mul { + ($curve: ty, $N: expr) => { + impl ecc::PreprocessedScalarMul, $N> for GroupVar<$curve, CV> + where + CV: CurveVar<$curve, ConstraintField>, + { + fn preprocessed_scalar_mul( + table: &[Self; $N], + scalar: &Self::Scalar, + compiler: &mut Compiler, + ) -> Self::Output { + // Computes the standard little-endian double-and-add algorithm + // (Algorithm 3.26, Guide to Elliptic Curve Cryptography) + // adapted from https://github.com/arkworks-rs/r1cs-std/blob/50ab8ee5ba8c09637044718eceac38e98e0ea67c/src/groups/mod.rs#L110-L139 + + let _ = compiler; + let mut result: CV = CV::zero(); + let scalar_bits = scalar + .0 + .to_bits_le() + .expect("Bit decomposition is not allowed to fail."); + debug_assert_eq!(scalar_bits.len(), $N, "Scalar is expected to have N bits."); + for (bit, base) in scalar_bits.into_iter().zip(table.iter()) { + // compute `self + 2^i * scalar` + let scalar_plus_base = result.clone() + base.0.clone(); + result = bit + .select(&scalar_plus_base, &result) + .expect("Conditional select is not allowed to fail. "); + } + Self(result, PhantomData) + } } - Self(result, PhantomData) - } + }; } +impl_processed_scalar_mul!(EdwardsProjective, 252); + impl Equal> for GroupVar where C: ProjectiveCurve, From 160f170b45240555d1b1aa8f7a7f62ceb224a4f0 Mon Sep 17 00:00:00 2001 From: Conghao Shen Date: Sun, 20 Mar 2022 15:56:12 -0700 Subject: [PATCH 3/8] better macro implementation, remove unnecessary comments --- manta-crypto/src/ecc.rs | 11 ++--- manta-pay/src/crypto/ecc/arkworks.rs | 74 ++++++++++++++++------------ 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/manta-crypto/src/ecc.rs b/manta-crypto/src/ecc.rs index 0c5811511..a0da48dff 100644 --- a/manta-crypto/src/ecc.rs +++ b/manta-crypto/src/ecc.rs @@ -138,8 +138,8 @@ pub trait ScalarMul { pub trait PreprocessedScalarMul: ScalarMul + Sized { /// Performs the scalar multiplication against a pre-computed table. /// - /// The pre-computed table is a list of power-of-two multiples of `scalar`, such that - /// `table[i] = scalar * 2^i`. + /// The pre-computed table is powers of two of `scalar`, such that + /// `table[i] = 2^i * G`. #[must_use] fn preprocessed_scalar_mul( table: &[Self; N], @@ -165,7 +165,7 @@ where /// Elliptic Curve Group pub trait Group: PointAdd + PointDouble + ScalarMul {} -/// Pre-processed Scalar Multiplication Table +/// Pre-processed Scalar Multiplication Table, represented as powers of two of `scalar`. #[cfg_attr( feature = "serde", derive(Deserialize, Serialize), @@ -183,17 +183,16 @@ pub struct PreprocessedScalarMulTable { } impl PreprocessedScalarMulTable { - /// Builds a new [`PreprocessedScalarMulTable`] collection from `base`. + /// Builds a new [`PreprocessedScalarMulTable`] collection from `base`, such that `table[i] = 2^i * base`. #[inline] pub fn from_base(mut base: G, compiler: &mut COM) -> Self where G: Clone + PointAdd + PointDouble, { let mut powers = Vec::with_capacity(N); - let double = base.double(compiler); for _ in 0..N { powers.push(base.clone()); - base.add_assign(&double, compiler); + base.double_assign(compiler); } Self::from_powers_unchecked( powers diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index 49195ed3c..e1a73e5ff 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -35,7 +35,6 @@ use manta_util::codec; use manta_util::serde::{Deserialize, Serialize, Serializer}; pub use ark_ec::{AffineCurve, ProjectiveCurve}; -use ark_ed_on_bls12_381::EdwardsProjective; pub use ark_r1cs_std::groups::CurveVar; /// Constraint Field Type @@ -408,41 +407,54 @@ where } macro_rules! impl_processed_scalar_mul { - ($curve: ty, $N: expr) => { - impl ecc::PreprocessedScalarMul, $N> for GroupVar<$curve, CV> - where - CV: CurveVar<$curve, ConstraintField>, + ($curve: ty) => { +impl + ecc::PreprocessedScalarMul< + Compiler<$curve>, { - fn preprocessed_scalar_mul( - table: &[Self; $N], - scalar: &Self::Scalar, - compiler: &mut Compiler, - ) -> Self::Output { - // Computes the standard little-endian double-and-add algorithm - // (Algorithm 3.26, Guide to Elliptic Curve Cryptography) - // adapted from https://github.com/arkworks-rs/r1cs-std/blob/50ab8ee5ba8c09637044718eceac38e98e0ea67c/src/groups/mod.rs#L110-L139 - - let _ = compiler; - let mut result: CV = CV::zero(); - let scalar_bits = scalar - .0 - .to_bits_le() - .expect("Bit decomposition is not allowed to fail."); - debug_assert_eq!(scalar_bits.len(), $N, "Scalar is expected to have N bits."); - for (bit, base) in scalar_bits.into_iter().zip(table.iter()) { - // compute `self + 2^i * scalar` - let scalar_plus_base = result.clone() + base.0.clone(); - result = bit - .select(&scalar_plus_base, &result) - .expect("Conditional select is not allowed to fail. "); - } - Self(result, PhantomData) - } + <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS + as usize + }, + > for GroupVar<$curve, CV> +where + CV: CurveVar<$curve, ConstraintField<$curve>>, +{ + #[inline] + fn preprocessed_scalar_mul( + table: &[Self; { + <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS + as usize + }], + scalar: &Self::Scalar, + compiler: &mut Compiler<$curve>, + ) -> Self::Output { + let _ = compiler; + let mut result = CV::zero(); + let scalar_bits = scalar + .0 + .to_bits_le() + .expect("Bit decomposition is not allowed to fail."); + debug_assert_eq!( + scalar_bits.len(), + { + <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS + as usize + }, + "Scalar is expected to have N bits." + ); + // TODO: Add `+` implementations, `conditional_add` to avoid unnecessary clones. + for (bit, base) in scalar_bits.into_iter().zip(table.iter()) { + result = bit + .select(&(result.clone() + &base.0), &result) + .expect("Conditional select is not allowed to fail. "); } + Self(result, PhantomData) + } +} }; } -impl_processed_scalar_mul!(EdwardsProjective, 252); +impl_processed_scalar_mul!(ark_ed_on_bls12_381::EdwardsProjective); impl Equal> for GroupVar where From c40897a88c3a4a9f8953de1cc62d272f20b48daf Mon Sep 17 00:00:00 2001 From: Conghao Shen Date: Mon, 21 Mar 2022 21:25:23 -0700 Subject: [PATCH 4/8] add/double trait impl for GroupVar, tests --- manta-pay/Cargo.toml | 2 +- manta-pay/src/crypto/ecc/arkworks.rs | 153 ++++++++++++++++++++------- 2 files changed, 113 insertions(+), 42 deletions(-) diff --git a/manta-pay/Cargo.toml b/manta-pay/Cargo.toml index c5eb43650..d2f1c6403 100644 --- a/manta-pay/Cargo.toml +++ b/manta-pay/Cargo.toml @@ -78,7 +78,7 @@ simulation = [ std = ["manta-accounting/std", "manta-util/std"] # Testing Frameworks -test = ["manta-accounting/test", "manta-crypto/test"] +test = ["manta-accounting/test", "manta-crypto/test", "manta-crypto/getrandom"] # Wallet wallet = ["bip32", "manta-crypto/getrandom", "std"] diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index e1a73e5ff..17380f774 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -36,6 +36,7 @@ use manta_util::serde::{Deserialize, Serialize, Serializer}; pub use ark_ec::{AffineCurve, ProjectiveCurve}; pub use ark_r1cs_std::groups::CurveVar; +use manta_crypto::ecc::{PointAdd, PointDouble}; /// Constraint Field Type type ConstraintField = <::BaseField as Field>::BasePrimeField; @@ -363,6 +364,7 @@ where } /// Elliptic Curve Group Element Variable +#[derive(Clone)] pub struct GroupVar(pub(crate) CV, PhantomData) where C: ProjectiveCurve, @@ -408,49 +410,41 @@ where macro_rules! impl_processed_scalar_mul { ($curve: ty) => { -impl - ecc::PreprocessedScalarMul< - Compiler<$curve>, + impl + ecc::PreprocessedScalarMul< + Compiler<$curve>, + { + <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS + as usize + }, + > for GroupVar<$curve, CV> + where + CV: CurveVar<$curve, ConstraintField<$curve>>, { - <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS - as usize - }, - > for GroupVar<$curve, CV> -where - CV: CurveVar<$curve, ConstraintField<$curve>>, -{ - #[inline] - fn preprocessed_scalar_mul( - table: &[Self; { - <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS - as usize - }], - scalar: &Self::Scalar, - compiler: &mut Compiler<$curve>, - ) -> Self::Output { - let _ = compiler; - let mut result = CV::zero(); - let scalar_bits = scalar - .0 - .to_bits_le() - .expect("Bit decomposition is not allowed to fail."); - debug_assert_eq!( - scalar_bits.len(), - { - <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS - as usize - }, - "Scalar is expected to have N bits." - ); - // TODO: Add `+` implementations, `conditional_add` to avoid unnecessary clones. - for (bit, base) in scalar_bits.into_iter().zip(table.iter()) { - result = bit - .select(&(result.clone() + &base.0), &result) - .expect("Conditional select is not allowed to fail. "); + #[inline] + fn preprocessed_scalar_mul( + table: &[Self; { + <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS + as usize + }], + scalar: &Self::Scalar, + compiler: &mut Compiler<$curve>, + ) -> Self::Output { + let _ = compiler; + let mut result = CV::zero(); + let scalar_bits = scalar + .0 + .to_bits_le() + .expect("Bit decomposition is not allowed to fail."); + // TODO: Add `+` implementations, `conditional_add` to avoid unnecessary clones. + for (bit, base) in scalar_bits.into_iter().zip(table.iter()) { + result = bit + .select(&(result.clone() + &base.0), &result) + .expect("Conditional select is not allowed to fail. "); + } + Self(result, PhantomData) + } } - Self(result, PhantomData) - } -} }; } @@ -545,3 +539,80 @@ where ) } } + +impl PointAdd> for GroupVar +where + C: ProjectiveCurve, + CV: CurveVar>, +{ + type Output = Self; + + fn add(&self, rhs: &Self, compiler: &mut Compiler) -> Self::Output { + let _ = compiler; + let mut result = self.0.clone(); + result += &rhs.0; + Self::new(result) + } +} + +impl PointDouble> for GroupVar +where + C: ProjectiveCurve, + CV: CurveVar>, +{ + type Output = Self; + + fn double(&self, compiler: &mut Compiler) -> Self::Output { + let _ = compiler; + Self::new(self.0.double().expect("Doubling is not allowed to fail.")) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ark_ec::ProjectiveCurve; + use ark_ed_on_bls12_381::constraints::EdwardsVar; + use ark_ed_on_bls12_381::EdwardsProjective; + use manta_crypto::constraint::ConstraintSystem; + use manta_crypto::ecc::{PreprocessedScalarMulTable, ScalarMul}; + use manta_crypto::rand::OsRng; + fn preprocessed_scalar_mul_test_template(rng: &mut OsRng) + where + C: ProjectiveCurve, + CV: CurveVar>, + GroupVar: ecc::PreprocessedScalarMul< + Compiler, + N, + Scalar = ScalarVar, + Output = GroupVar, + >, + { + const NUM_TRIALS: usize = 5; + + let mut cs = R1CS::for_known(); + + for _ in 0..NUM_TRIALS { + let base = Group::::gen(rng); + let base_var = as Variable>::new_known(&base, &mut cs); + + let scalar = Scalar::::gen(rng); + let scalar_var = scalar.as_known::>(&mut cs); + + let expected = ScalarMul::scalar_mul(&base_var, &scalar_var, &mut cs); + + let table = PreprocessedScalarMulTable::<_, N>::from_base(base_var, &mut cs); + let actual = table.scalar_mul(&scalar_var, &mut cs); + + cs.assert_eq(&expected, &actual); + } + + assert!(cs.cs.is_satisfied().unwrap()); + } + + #[test] + fn preprocessed_scalar_mul_test() { + let mut rng = OsRng::default(); + preprocessed_scalar_mul_test_template::(&mut rng); + } +} From e32b10ef695ec69e5a10f5d866a218e7ba2c38ce Mon Sep 17 00:00:00 2001 From: Conghao Shen Date: Mon, 21 Mar 2022 21:29:44 -0700 Subject: [PATCH 5/8] fmt --- manta-pay/src/crypto/ecc/arkworks.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index 17380f774..108c9ef77 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -572,11 +572,12 @@ where mod tests { use super::*; use ark_ec::ProjectiveCurve; - use ark_ed_on_bls12_381::constraints::EdwardsVar; - use ark_ed_on_bls12_381::EdwardsProjective; - use manta_crypto::constraint::ConstraintSystem; - use manta_crypto::ecc::{PreprocessedScalarMulTable, ScalarMul}; - use manta_crypto::rand::OsRng; + use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; + use manta_crypto::{ + constraint::ConstraintSystem, + ecc::{PreprocessedScalarMulTable, ScalarMul}, + rand::OsRng, + }; fn preprocessed_scalar_mul_test_template(rng: &mut OsRng) where C: ProjectiveCurve, From 8ce8318545adcc17d75ffdca7cd54cebc7316750 Mon Sep 17 00:00:00 2001 From: Conghao Shen Date: Mon, 21 Mar 2022 21:37:01 -0700 Subject: [PATCH 6/8] better support for tests on various curves --- manta-pay/src/crypto/ecc/arkworks.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index 108c9ef77..993d82038 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -578,6 +578,7 @@ mod tests { ecc::{PreprocessedScalarMulTable, ScalarMul}, rand::OsRng, }; + fn preprocessed_scalar_mul_test_template(rng: &mut OsRng) where C: ProjectiveCurve, @@ -613,7 +614,19 @@ mod tests { #[test] fn preprocessed_scalar_mul_test() { + macro_rules! test_on_curve { + ($curve: ty, $var: ty, $rng: expr) => { + preprocessed_scalar_mul_test_template::< + $curve, + $var, + { + <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS as usize + }, + >($rng) + } + } + let mut rng = OsRng::default(); - preprocessed_scalar_mul_test_template::(&mut rng); + test_on_curve!(EdwardsProjective, EdwardsVar, &mut rng); } } From 9856f1fc64189f2bbde556b0d49eef2835c819c1 Mon Sep 17 00:00:00 2001 From: Conghao Shen Date: Thu, 24 Mar 2022 21:55:01 -0700 Subject: [PATCH 7/8] nit --- manta-pay/Cargo.toml | 3 +- .../src/crypto/constraint/arkworks/mod.rs | 8 +++ manta-pay/src/crypto/ecc/arkworks.rs | 56 +++++++++---------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/manta-pay/Cargo.toml b/manta-pay/Cargo.toml index d2f1c6403..c57c2244a 100644 --- a/manta-pay/Cargo.toml +++ b/manta-pay/Cargo.toml @@ -78,7 +78,7 @@ simulation = [ std = ["manta-accounting/std", "manta-util/std"] # Testing Frameworks -test = ["manta-accounting/test", "manta-crypto/test", "manta-crypto/getrandom"] +test = ["manta-accounting/test", "manta-crypto/test"] # Wallet wallet = ["bip32", "manta-crypto/getrandom", "std"] @@ -120,3 +120,4 @@ tungstenite = { version = "0.17.2", optional = true, default-features = false, f [dev-dependencies] manta-pay = { path = ".", features = ["groth16", "test"] } +manta-crypto = { path = "../manta-crypto", default-features = false, features = ["getrandom"] } diff --git a/manta-pay/src/crypto/constraint/arkworks/mod.rs b/manta-pay/src/crypto/constraint/arkworks/mod.rs index e00b16b94..a6fc17ea2 100644 --- a/manta-pay/src/crypto/constraint/arkworks/mod.rs +++ b/manta-pay/src/crypto/constraint/arkworks/mod.rs @@ -276,6 +276,14 @@ where cs.set_optimization_goal(ark_r1cs::OptimizationGoal::Constraints); Self { cs } } + + /// Check if all constraints are satisfied. + #[inline] + pub fn is_satisfied(&self) -> bool { + self.cs + .is_satisfied() + .expect("is_satisfied is not allowed to fail") + } } impl ConstraintSystem for R1CS diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index 993d82038..270014357 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -23,9 +23,11 @@ use ark_r1cs_std::ToBitsGadget; use ark_relations::ns; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError}; use core::marker::PhantomData; +use derivative::Derivative; use manta_crypto::{ constraint::{Allocator, Constant, Equal, Public, Secret, ValueSource, Variable}, ecc, + ecc::{PointAdd, PointDouble}, key::kdf, rand::{CryptoRng, RngCore, Sample, Standard}, }; @@ -36,7 +38,6 @@ use manta_util::serde::{Deserialize, Serialize, Serializer}; pub use ark_ec::{AffineCurve, ProjectiveCurve}; pub use ark_r1cs_std::groups::CurveVar; -use manta_crypto::ecc::{PointAdd, PointDouble}; /// Constraint Field Type type ConstraintField = <::BaseField as Field>::BasePrimeField; @@ -44,6 +45,9 @@ type ConstraintField = <::BaseField as Field>::BasePrim /// Compiler Type type Compiler = R1CS>; +/// Curve Scalar Parameter +type ScalarParam = <::ScalarField as PrimeField>::Params; + /// Scalar Field Element pub type Scalar = Fp<::ScalarField>; @@ -364,7 +368,8 @@ where } /// Elliptic Curve Group Element Variable -#[derive(Clone)] +#[derive(Derivative)] +#[derivative(Clone)] pub struct GroupVar(pub(crate) CV, PhantomData) where C: ProjectiveCurve, @@ -423,10 +428,7 @@ macro_rules! impl_processed_scalar_mul { { #[inline] fn preprocessed_scalar_mul( - table: &[Self; { - <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS - as usize - }], + table: &[Self; ScalarParam::<$curve>::MODULUS_BITS as usize], scalar: &Self::Scalar, compiler: &mut Compiler<$curve>, ) -> Self::Output { @@ -547,6 +549,7 @@ where { type Output = Self; + #[inline] fn add(&self, rhs: &Self, compiler: &mut Compiler) -> Self::Output { let _ = compiler; let mut result = self.0.clone(); @@ -562,6 +565,7 @@ where { type Output = Self; + #[inline] fn double(&self, compiler: &mut Compiler) -> Self::Output { let _ = compiler; Self::new(self.0.double().expect("Doubling is not allowed to fail.")) @@ -573,17 +577,19 @@ mod tests { use super::*; use ark_ec::ProjectiveCurve; use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; + use ecc::PreprocessedScalarMul; use manta_crypto::{ constraint::ConstraintSystem, ecc::{PreprocessedScalarMulTable, ScalarMul}, rand::OsRng, }; + /// Tests preprocessed scalar multiplication on curve `C`. fn preprocessed_scalar_mul_test_template(rng: &mut OsRng) where C: ProjectiveCurve, CV: CurveVar>, - GroupVar: ecc::PreprocessedScalarMul< + GroupVar: PreprocessedScalarMul< Compiler, N, Scalar = ScalarVar, @@ -595,38 +601,28 @@ mod tests { let mut cs = R1CS::for_known(); for _ in 0..NUM_TRIALS { - let base = Group::::gen(rng); - let base_var = as Variable>::new_known(&base, &mut cs); + let base = Group::<_>::gen(rng).as_known::>(&mut cs); - let scalar = Scalar::::gen(rng); - let scalar_var = scalar.as_known::>(&mut cs); + let scalar = Scalar::::gen(rng).as_known::(&mut cs); - let expected = ScalarMul::scalar_mul(&base_var, &scalar_var, &mut cs); + let expected = ScalarMul::scalar_mul(&base, &scalar, &mut cs); - let table = PreprocessedScalarMulTable::<_, N>::from_base(base_var, &mut cs); - let actual = table.scalar_mul(&scalar_var, &mut cs); + let table = PreprocessedScalarMulTable::<_, N>::from_base(base, &mut cs); + let actual = table.scalar_mul(&scalar, &mut cs); cs.assert_eq(&expected, &actual); } - assert!(cs.cs.is_satisfied().unwrap()); + assert!(cs.is_satisfied()); } + /// Tests preprocessed scalar multiplication on different curves. #[test] - fn preprocessed_scalar_mul_test() { - macro_rules! test_on_curve { - ($curve: ty, $var: ty, $rng: expr) => { - preprocessed_scalar_mul_test_template::< - $curve, - $var, - { - <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS as usize - }, - >($rng) - } - } - - let mut rng = OsRng::default(); - test_on_curve!(EdwardsProjective, EdwardsVar, &mut rng); + fn preprocessed_scalar_mul() { + preprocessed_scalar_mul_test_template::< + EdwardsProjective, + EdwardsVar, + { ScalarParam::::MODULUS_BITS as usize }, + >(&mut OsRng); } } From eb57ecd4f5aa5224350a9dbfa35be97299661a7f Mon Sep 17 00:00:00 2001 From: Conghao Shen Date: Fri, 25 Mar 2022 12:45:21 -0700 Subject: [PATCH 8/8] nit --- manta-crypto/src/ecc.rs | 4 +++- manta-pay/src/crypto/ecc/arkworks.rs | 16 ++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/manta-crypto/src/ecc.rs b/manta-crypto/src/ecc.rs index a0da48dff..f5376878f 100644 --- a/manta-crypto/src/ecc.rs +++ b/manta-crypto/src/ecc.rs @@ -165,7 +165,9 @@ where /// Elliptic Curve Group pub trait Group: PointAdd + PointDouble + ScalarMul {} -/// Pre-processed Scalar Multiplication Table, represented as powers of two of `scalar`. +/// Pre-processed Scalar Multiplication Table. +/// +/// This table contains power-of-two multiples of a fixed base group element. #[cfg_attr( feature = "serde", derive(Deserialize, Serialize), diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index 270014357..8463003bc 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -23,11 +23,9 @@ use ark_r1cs_std::ToBitsGadget; use ark_relations::ns; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError}; use core::marker::PhantomData; -use derivative::Derivative; use manta_crypto::{ constraint::{Allocator, Constant, Equal, Public, Secret, ValueSource, Variable}, - ecc, - ecc::{PointAdd, PointDouble}, + ecc::{self, PointAdd, PointDouble}, key::kdf, rand::{CryptoRng, RngCore, Sample, Standard}, }; @@ -368,7 +366,7 @@ where } /// Elliptic Curve Group Element Variable -#[derive(Derivative)] +#[derive(derivative::Derivative)] #[derivative(Clone)] pub struct GroupVar(pub(crate) CV, PhantomData) where @@ -573,7 +571,7 @@ where } #[cfg(test)] -mod tests { +mod test { use super::*; use ark_ec::ProjectiveCurve; use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; @@ -599,20 +597,14 @@ mod tests { const NUM_TRIALS: usize = 5; let mut cs = R1CS::for_known(); - for _ in 0..NUM_TRIALS { let base = Group::<_>::gen(rng).as_known::>(&mut cs); - let scalar = Scalar::::gen(rng).as_known::(&mut cs); - - let expected = ScalarMul::scalar_mul(&base, &scalar, &mut cs); - + let expected = base.scalar_mul(&scalar, &mut cs); let table = PreprocessedScalarMulTable::<_, N>::from_base(base, &mut cs); let actual = table.scalar_mul(&scalar, &mut cs); - cs.assert_eq(&expected, &actual); } - assert!(cs.is_satisfied()); }