diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 73f0c5758..91a6f7924 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -33,6 +33,9 @@ jobs: - name: Linux Tests in parallel, with nextest profile ci and cargo profile dev-ci run: | cargo nextest run --profile ci --workspace --cargo-profile dev-ci + - name: Run test_pp_digest with the asm feature + run: | + cargo nextest run --profile ci --workspace --cargo-profile dev-ci --features "asm" -E 'test(test_pp_digest)' check-lurk-compiles: if: github.event_name == 'pull_request' diff --git a/Cargo.toml b/Cargo.toml index 7756cb68e..963ceceb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,7 @@ harness = false [features] default = [] +asm = ["halo2curves/asm"] # Compiles in portable mode, w/o ISA extensions => binary can be executed on all systems. portable = ["pasta-msm/portable"] cuda = ["neptune/cuda", "neptune/pasta", "neptune/arity24"] diff --git a/src/lib.rs b/src/lib.rs index 2d0c99d61..4878a9011 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -942,10 +942,14 @@ type CE = ::CE; #[cfg(test)] mod tests { - use crate::provider::bn256_grumpkin::{bn256, grumpkin}; - use crate::provider::secp_secq::{secp256k1, secq256k1}; - use crate::traits::evaluation::EvaluationEngineTrait; - use crate::traits::snark::default_ck_hint; + use crate::{ + provider::{ + bn256_grumpkin::{bn256, grumpkin}, + secp_secq::{secp256k1, secq256k1}, + GroupExt, + }, + traits::{evaluation::EvaluationEngineTrait, snark::default_ck_hint}, + }; use core::fmt::Write; use super::*; @@ -1014,8 +1018,8 @@ mod tests { fn test_pp_digest_with(circuit1: &T1, circuit2: &T2, _expected: &str) where - G1: Group::Scalar>, - G2: Group::Scalar>, + G1: Group::Scalar> + GroupExt, + G2: Group::Scalar> + GroupExt, T1: StepCircuit, T2: StepCircuit, E1: EvaluationEngineTrait, @@ -1065,11 +1069,28 @@ mod tests { let trivial_circuit2_grumpkin = TrivialCircuit::<::Scalar>::default(); let cubic_circuit1_grumpkin = CubicCircuit::<::Scalar>::default(); + // These tests should not need be different on the "asm" feature for bn256. + // See https://github.com/privacy-scaling-explorations/halo2curves/issues/100 for why they are - closing the issue there + // should eliminate the discrepancy here. + #[cfg(feature = "asm")] + test_pp_digest_with::, EE<_>>( + &trivial_circuit1_grumpkin, + &trivial_circuit2_grumpkin, + "c4ecd363a6c1473de7e0d24fc1dbb660f563556e2e13fb4614acdff04cab7701", + ); + #[cfg(feature = "asm")] + test_pp_digest_with::, EE<_>>( + &cubic_circuit1_grumpkin, + &trivial_circuit2_grumpkin, + "4853a6463b6309f6ae76442934d0a423f51f1e10abaddd0d39bf5644ed589100", + ); + #[cfg(not(feature = "asm"))] test_pp_digest_with::, EE<_>>( &trivial_circuit1_grumpkin, &trivial_circuit2_grumpkin, "c26cc841d42c19bf98bc2482e66cd30903922f2a923927b85d66f375a821f101", ); + #[cfg(not(feature = "asm"))] test_pp_digest_with::, EE<_>>( &cubic_circuit1_grumpkin, &trivial_circuit2_grumpkin, diff --git a/src/provider/bn256_grumpkin.rs b/src/provider/bn256_grumpkin.rs index 4a2cbbe94..fc1eddfe4 100644 --- a/src/provider/bn256_grumpkin.rs +++ b/src/provider/bn256_grumpkin.rs @@ -6,8 +6,9 @@ use crate::{ keccak::Keccak256Transcript, pedersen::CommitmentEngine, poseidon::{PoseidonRO, PoseidonROCircuit}, + CompressedGroup, GroupExt, }, - traits::{CompressedGroup, Group, PrimeFieldExt, TranscriptReprTrait}, + traits::{Group, PrimeFieldExt, TranscriptReprTrait}, }; use digest::{ExtendableOutput, Update}; use ff::{FromUniformBytes, PrimeField}; @@ -41,24 +42,13 @@ pub mod grumpkin { }; } -impl TranscriptReprTrait for grumpkin::Base { - fn to_transcript_bytes(&self) -> Vec { - self.to_repr().to_vec() - } -} - -impl TranscriptReprTrait for grumpkin::Scalar { - fn to_transcript_bytes(&self) -> Vec { - self.to_repr().to_vec() - } -} - impl_traits!( bn256, Bn256Compressed, Bn256Point, Bn256Affine, - "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001" + "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001", + "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47" ); impl_traits!( @@ -66,7 +56,8 @@ impl_traits!( GrumpkinCompressed, GrumpkinPoint, GrumpkinAffine, - "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47" + "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47", + "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001" ); #[cfg(test)] @@ -94,7 +85,7 @@ mod tests { for n in [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1021, ] { - let ck_par = ::from_label(label, n); + let ck_par = ::from_label(label, n); let ck_ser = from_label_serial(label, n); assert_eq!(ck_par.len(), n); assert_eq!(ck_ser.len(), n); diff --git a/src/provider/ipa_pc.rs b/src/provider/ipa_pc.rs index d4c731e7b..3025e162b 100644 --- a/src/provider/ipa_pc.rs +++ b/src/provider/ipa_pc.rs @@ -1,7 +1,7 @@ //! This module implements `EvaluationEngine` using an IPA-based polynomial commitment scheme use crate::{ errors::NovaError, - provider::pedersen::CommitmentKeyExtTrait, + provider::{pedersen::CommitmentKeyExtTrait, GroupExt}, spartan::polys::eq::EqPolynomial, traits::{ commitment::{CommitmentEngineTrait, CommitmentTrait}, @@ -42,7 +42,7 @@ pub struct EvaluationEngine { impl EvaluationEngineTrait for EvaluationEngine where - G: Group, + G: GroupExt, CommitmentKey: CommitmentKeyExtTrait, { type ProverKey = ProverKey; @@ -164,7 +164,7 @@ pub struct InnerProductArgument { impl InnerProductArgument where - G: Group, + G: GroupExt, CommitmentKey: CommitmentKeyExtTrait, { const fn protocol_name() -> &'static [u8] { diff --git a/src/provider/keccak.rs b/src/provider/keccak.rs index 1f7b0a7ac..26139eb91 100644 --- a/src/provider/keccak.rs +++ b/src/provider/keccak.rs @@ -155,7 +155,7 @@ mod tests { fn test_keccak_example() { let mut hasher = Keccak256::new(); hasher.update(0xffffffff_u32.to_le_bytes()); - let output: [u8; 32] = hasher.finalize().try_into().unwrap(); + let output: [u8; 32] = hasher.finalize().into(); assert_eq!( hex::encode(output), "29045a592007d0c246ef02c2223570da9522d0cf0f73282c79a1bc8f0bb2c238" diff --git a/src/provider/mod.rs b/src/provider/mod.rs index 3387fe3a8..b27e35deb 100644 --- a/src/provider/mod.rs +++ b/src/provider/mod.rs @@ -3,6 +3,96 @@ //! `Group` with pasta curves and BN256/Grumpkin //! `RO` traits with Poseidon //! `EvaluationEngine` with an IPA-based polynomial evaluation argument +use crate::traits::{commitment::ScalarMul, Group, TranscriptReprTrait}; +use core::{ + fmt::Debug, + ops::{Add, AddAssign, Sub, SubAssign}, +}; +use serde::{Deserialize, Serialize}; + +/// Represents a compressed version of a group element +pub trait CompressedGroup: + Clone + + Copy + + Debug + + Eq + + Send + + Sync + + TranscriptReprTrait + + Serialize + + for<'de> Deserialize<'de> + + 'static +{ + /// A type that holds the decompressed version of the compressed group element + type GroupElement: Group; + + /// Decompresses the compressed group element + fn decompress(&self) -> Option; +} + +/// A helper trait for types with a group operation. +pub trait GroupOps: + Add + Sub + AddAssign + SubAssign +{ +} + +impl GroupOps for T where + T: Add + Sub + AddAssign + SubAssign +{ +} + +/// A helper trait for references with a group operation. +pub trait GroupOpsOwned: for<'r> GroupOps<&'r Rhs, Output> {} +impl GroupOpsOwned for T where T: for<'r> GroupOps<&'r Rhs, Output> {} + +/// A helper trait for references implementing group scalar multiplication. +pub trait ScalarMulOwned: for<'r> ScalarMul<&'r Rhs, Output> {} +impl ScalarMulOwned for T where T: for<'r> ScalarMul<&'r Rhs, Output> {} + +/// A trait that defines extensions to the Group trait +pub trait GroupExt: + Group + + Serialize + + for<'de> Deserialize<'de> + + GroupOps + + GroupOpsOwned + + ScalarMul<::Scalar> + + ScalarMulOwned<::Scalar> +{ + /// A type representing the compressed version of the group element + type CompressedGroupElement: CompressedGroup; + + /// A type representing preprocessed group element + type PreprocessedGroupElement: Clone + + Debug + + PartialEq + + Eq + + Send + + Sync + + Serialize + + for<'de> Deserialize<'de>; + + /// A method to compute a multiexponentation + fn vartime_multiscalar_mul( + scalars: &[Self::Scalar], + bases: &[Self::PreprocessedGroupElement], + ) -> Self; + + /// Produce a vector of group elements using a static label + fn from_label(label: &'static [u8], n: usize) -> Vec; + + /// Compresses the group element + fn compress(&self) -> Self::CompressedGroupElement; + + /// Produces a preprocessed element + fn preprocessed(&self) -> Self::PreprocessedGroupElement; + + /// Returns an element that is the additive identity of the group + fn zero() -> Self; + + /// Returns the affine coordinates (x, y, infinty) for the point + fn to_coordinates(&self) -> (Self::Base, Self::Base, bool); +} pub mod bn256_grumpkin; pub mod ipa_pc; @@ -135,18 +225,31 @@ macro_rules! impl_traits { $name_compressed:ident, $name_curve:ident, $name_curve_affine:ident, - $order_str:literal + $order_str:literal, + $base_str:literal ) => { impl Group for $name::Point { type Base = $name::Base; type Scalar = $name::Scalar; - type CompressedGroupElement = $name_compressed; - type PreprocessedGroupElement = $name::Affine; type RO = PoseidonRO; type ROCircuit = PoseidonROCircuit; type TE = Keccak256Transcript; type CE = CommitmentEngine; + fn get_curve_params() -> (Self::Base, Self::Base, BigInt, BigInt) { + let A = $name::Point::a(); + let B = $name::Point::b(); + let order = BigInt::from_str_radix($order_str, 16).unwrap(); + let base = BigInt::from_str_radix($base_str, 16).unwrap(); + + (A, B, order, base) + } + } + + impl GroupExt for $name::Point { + type CompressedGroupElement = $name_compressed; + type PreprocessedGroupElement = $name::Affine; + fn vartime_multiscalar_mul( scalars: &[Self::Scalar], bases: &[Self::PreprocessedGroupElement], @@ -208,33 +311,21 @@ macro_rules! impl_traits { } } + fn zero() -> Self { + $name::Point::identity() + } + fn to_coordinates(&self) -> (Self::Base, Self::Base, bool) { // see: grumpkin implementation at src/provider/bn256_grumpkin.rs let coordinates = self.to_affine().coordinates(); if coordinates.is_some().unwrap_u8() == 1 - && (Self::PreprocessedGroupElement::identity() != self.to_affine()) + && ($name_curve_affine::identity() != self.to_affine()) { (*coordinates.unwrap().x(), *coordinates.unwrap().y(), false) } else { (Self::Base::zero(), Self::Base::zero(), true) } } - - fn get_curve_params() -> (Self::Base, Self::Base, BigInt) { - let A = $name::Point::a(); - let B = $name::Point::b(); - let order = BigInt::from_str_radix($order_str, 16).unwrap(); - - (A, B, order) - } - - fn zero() -> Self { - $name::Point::identity() - } - - fn get_generator() -> Self { - $name::Point::generator() - } } impl PrimeFieldExt for $name::Scalar { @@ -257,6 +348,12 @@ macro_rules! impl_traits { Some($name_curve::from_bytes(&self).unwrap()) } } + + impl TranscriptReprTrait for $name::Scalar { + fn to_transcript_bytes(&self) -> Vec { + self.to_repr().to_vec() + } + } }; } diff --git a/src/provider/pasta.rs b/src/provider/pasta.rs index 5e357adf7..dc1663f59 100644 --- a/src/provider/pasta.rs +++ b/src/provider/pasta.rs @@ -5,8 +5,9 @@ use crate::{ keccak::Keccak256Transcript, pedersen::CommitmentEngine, poseidon::{PoseidonRO, PoseidonROCircuit}, + CompressedGroup, GroupExt, }, - traits::{CompressedGroup, Group, PrimeFieldExt, TranscriptReprTrait}, + traits::{Group, PrimeFieldExt, TranscriptReprTrait}, }; use digest::{ExtendableOutput, Update}; use ff::{FromUniformBytes, PrimeField}; @@ -55,18 +56,31 @@ macro_rules! impl_traits { $name_compressed:ident, $name_curve:ident, $name_curve_affine:ident, - $order_str:literal + $order_str:literal, + $base_str:literal ) => { impl Group for $name::Point { type Base = $name::Base; type Scalar = $name::Scalar; - type CompressedGroupElement = $name_compressed; - type PreprocessedGroupElement = $name::Affine; type RO = PoseidonRO; type ROCircuit = PoseidonROCircuit; type TE = Keccak256Transcript; type CE = CommitmentEngine; + fn get_curve_params() -> (Self::Base, Self::Base, BigInt, BigInt) { + let A = $name::Point::a(); + let B = $name::Point::b(); + let order = BigInt::from_str_radix($order_str, 16).unwrap(); + let base = BigInt::from_str_radix($base_str, 16).unwrap(); + + (A, B, order, base) + } + } + + impl GroupExt for $name::Point { + type CompressedGroupElement = $name_compressed; + type PreprocessedGroupElement = $name::Affine; + #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] #[tracing::instrument( skip_all, @@ -92,14 +106,14 @@ macro_rules! impl_traits { cpu_best_multiexp(scalars, bases) } - fn preprocessed(&self) -> Self::PreprocessedGroupElement { - self.to_affine() - } - fn compress(&self) -> Self::CompressedGroupElement { $name_compressed::new(self.to_bytes()) } + fn preprocessed(&self) -> Self::PreprocessedGroupElement { + self.to_affine() + } + fn from_label(label: &'static [u8], n: usize) -> Vec { let mut shake = Shake256::default(); shake.update(label); @@ -146,6 +160,10 @@ macro_rules! impl_traits { } } + fn zero() -> Self { + $name::Point::identity() + } + fn to_coordinates(&self) -> (Self::Base, Self::Base, bool) { let coordinates = self.to_affine().coordinates(); if coordinates.is_some().unwrap_u8() == 1 { @@ -154,22 +172,6 @@ macro_rules! impl_traits { (Self::Base::zero(), Self::Base::zero(), true) } } - - fn get_curve_params() -> (Self::Base, Self::Base, BigInt) { - let A = $name::Point::a(); - let B = $name::Point::b(); - let order = BigInt::from_str_radix($order_str, 16).unwrap(); - - (A, B, order) - } - - fn zero() -> Self { - $name::Point::identity() - } - - fn get_generator() -> Self { - $name::Point::generator() - } } impl PrimeFieldExt for $name::Scalar { @@ -192,19 +194,13 @@ macro_rules! impl_traits { Some($name_curve::from_bytes(&self.repr).unwrap()) } } - }; -} -impl TranscriptReprTrait for pallas::Base { - fn to_transcript_bytes(&self) -> Vec { - self.to_repr().to_vec() - } -} - -impl TranscriptReprTrait for pallas::Scalar { - fn to_transcript_bytes(&self) -> Vec { - self.to_repr().to_vec() - } + impl TranscriptReprTrait for $name::Scalar { + fn to_transcript_bytes(&self) -> Vec { + self.to_repr().to_vec() + } + } + }; } impl_traits!( @@ -212,7 +208,8 @@ impl_traits!( PallasCompressedElementWrapper, Ep, EpAffine, - "40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001" + "40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + "40000000000000000000000000000000224698fc094cf91b992d30ed00000001" ); impl_traits!( @@ -220,7 +217,8 @@ impl_traits!( VestaCompressedElementWrapper, Eq, EqAffine, - "40000000000000000000000000000000224698fc094cf91b992d30ed00000001" + "40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + "40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001" ); #[cfg(test)] @@ -248,7 +246,7 @@ mod tests { for n in [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1021, ] { - let ck_par = ::from_label(label, n); + let ck_par = ::from_label(label, n); let ck_ser = from_label_serial(label, n); assert_eq!(ck_par.len(), n); assert_eq!(ck_ser.len(), n); diff --git a/src/provider/pedersen.rs b/src/provider/pedersen.rs index b9e5dfa74..d22f50609 100644 --- a/src/provider/pedersen.rs +++ b/src/provider/pedersen.rs @@ -1,9 +1,10 @@ //! This module provides an implementation of a commitment engine use crate::{ errors::NovaError, + provider::{CompressedGroup, GroupExt}, traits::{ commitment::{CommitmentEngineTrait, CommitmentTrait, Len}, - AbsorbInROTrait, CompressedGroup, Group, ROTrait, TranscriptReprTrait, + AbsorbInROTrait, Group, ROTrait, TranscriptReprTrait, }, }; use abomonation_derive::Abomonation; @@ -19,13 +20,13 @@ use serde::{Deserialize, Serialize}; /// A type that holds commitment generators #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Abomonation)] #[abomonation_omit_bounds] -pub struct CommitmentKey { +pub struct CommitmentKey { #[abomonate_with(Vec<[u64; 8]>)] // this is a hack; we just assume the size of the element. ck: Vec, } /// [CommitmentKey]s are often large, and this helps with cloning bottlenecks -impl Clone for CommitmentKey { +impl Clone for CommitmentKey { fn clone(&self) -> Self { Self { ck: self.ck.par_iter().cloned().collect(), @@ -33,7 +34,7 @@ impl Clone for CommitmentKey { } } -impl Len for CommitmentKey { +impl Len for CommitmentKey { fn length(&self) -> usize { self.ck.len() } @@ -43,7 +44,7 @@ impl Len for CommitmentKey { #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Abomonation)] #[serde(bound = "")] #[abomonation_omit_bounds] -pub struct Commitment { +pub struct Commitment { #[abomonate_with(Vec<[u64; 12]>)] // this is a hack; we just assume the size of the element. pub(crate) comm: G, } @@ -51,11 +52,11 @@ pub struct Commitment { /// A type that holds a compressed commitment #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(bound = "")] -pub struct CompressedCommitment { +pub struct CompressedCommitment { comm: G::CompressedGroupElement, } -impl CommitmentTrait for Commitment { +impl CommitmentTrait for Commitment { type CompressedCommitment = CompressedCommitment; fn compress(&self) -> Self::CompressedCommitment { @@ -69,7 +70,7 @@ impl CommitmentTrait for Commitment { } fn decompress(c: &Self::CompressedCommitment) -> Result { - let comm = c.comm.decompress(); + let comm = ::CompressedGroupElement::decompress(&c.comm); if comm.is_none() { return Err(NovaError::DecompressionError); } @@ -79,13 +80,13 @@ impl CommitmentTrait for Commitment { } } -impl Default for Commitment { +impl Default for Commitment { fn default() -> Self { Commitment { comm: G::zero() } } } -impl TranscriptReprTrait for Commitment { +impl TranscriptReprTrait for Commitment { fn to_transcript_bytes(&self) -> Vec { let (x, y, is_infinity) = self.comm.to_coordinates(); let is_infinity_byte = (!is_infinity).into(); @@ -98,7 +99,7 @@ impl TranscriptReprTrait for Commitment { } } -impl AbsorbInROTrait for Commitment { +impl AbsorbInROTrait for Commitment { fn absorb_in_ro(&self, ro: &mut G::RO) { let (x, y, is_infinity) = self.comm.to_coordinates(); ro.absorb(x); @@ -111,20 +112,20 @@ impl AbsorbInROTrait for Commitment { } } -impl TranscriptReprTrait for CompressedCommitment { +impl TranscriptReprTrait for CompressedCommitment { fn to_transcript_bytes(&self) -> Vec { self.comm.to_transcript_bytes() } } -impl MulAssign for Commitment { +impl MulAssign for Commitment { fn mul_assign(&mut self, scalar: G::Scalar) { let result = (self as &Commitment).comm * scalar; *self = Commitment { comm: result }; } } -impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a Commitment { +impl<'a, 'b, G: GroupExt> Mul<&'b G::Scalar> for &'a Commitment { type Output = Commitment; fn mul(self, scalar: &'b G::Scalar) -> Commitment { Commitment { @@ -133,7 +134,7 @@ impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a Commitment { } } -impl Mul for Commitment { +impl Mul for Commitment { type Output = Commitment; fn mul(self, scalar: G::Scalar) -> Commitment { @@ -143,14 +144,14 @@ impl Mul for Commitment { } } -impl<'b, G: Group> AddAssign<&'b Commitment> for Commitment { +impl<'b, G: GroupExt> AddAssign<&'b Commitment> for Commitment { fn add_assign(&mut self, other: &'b Commitment) { let result = (self as &Commitment).comm + other.comm; *self = Commitment { comm: result }; } } -impl<'a, 'b, G: Group> Add<&'b Commitment> for &'a Commitment { +impl<'a, 'b, G: GroupExt> Add<&'b Commitment> for &'a Commitment { type Output = Commitment; fn add(self, other: &'b Commitment) -> Commitment { Commitment { @@ -194,16 +195,16 @@ macro_rules! define_add_assign_variants { }; } -define_add_assign_variants!(G = Group, LHS = Commitment, RHS = Commitment); -define_add_variants!(G = Group, LHS = Commitment, RHS = Commitment, Output = Commitment); +define_add_assign_variants!(G = GroupExt, LHS = Commitment, RHS = Commitment); +define_add_variants!(G = GroupExt, LHS = Commitment, RHS = Commitment, Output = Commitment); /// Provides a commitment engine #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct CommitmentEngine { +pub struct CommitmentEngine { _p: PhantomData, } -impl CommitmentEngineTrait for CommitmentEngine { +impl CommitmentEngineTrait for CommitmentEngine { type CommitmentKey = CommitmentKey; type Commitment = Commitment; @@ -222,7 +223,7 @@ impl CommitmentEngineTrait for CommitmentEngine { } /// A trait listing properties of a commitment key that can be managed in a divide-and-conquer fashion -pub trait CommitmentKeyExtTrait { +pub trait CommitmentKeyExtTrait { /// Splits the commitment key into two pieces at a specified point fn split_at(&self, n: usize) -> (Self, Self) where @@ -245,7 +246,7 @@ pub trait CommitmentKeyExtTrait { Self: Sized; } -impl>> CommitmentKeyExtTrait for CommitmentKey { +impl> + GroupExt> CommitmentKeyExtTrait for CommitmentKey { fn split_at(&self, n: usize) -> (CommitmentKey, CommitmentKey) { ( CommitmentKey { diff --git a/src/provider/secp_secq.rs b/src/provider/secp_secq.rs index bd604d25b..13f2c1cf8 100644 --- a/src/provider/secp_secq.rs +++ b/src/provider/secp_secq.rs @@ -6,8 +6,9 @@ use crate::{ keccak::Keccak256Transcript, pedersen::CommitmentEngine, poseidon::{PoseidonRO, PoseidonROCircuit}, + CompressedGroup, GroupExt, }, - traits::{CompressedGroup, Group, PrimeFieldExt, TranscriptReprTrait}, + traits::{Group, PrimeFieldExt, TranscriptReprTrait}, }; use digest::{ExtendableOutput, Update}; use ff::{FromUniformBytes, PrimeField}; @@ -38,24 +39,13 @@ pub mod secq256k1 { }; } -impl TranscriptReprTrait for secp256k1::Base { - fn to_transcript_bytes(&self) -> Vec { - self.to_repr().to_vec() - } -} - -impl TranscriptReprTrait for secp256k1::Scalar { - fn to_transcript_bytes(&self) -> Vec { - self.to_repr().to_vec() - } -} - impl_traits!( secp256k1, Secp256k1Compressed, Secp256k1, Secp256k1Affine, - "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" + "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" ); impl_traits!( @@ -63,7 +53,8 @@ impl_traits!( Secq256k1Compressed, Secq256k1, Secq256k1Affine, - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" ); #[cfg(test)] @@ -91,7 +82,7 @@ mod tests { for n in [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1021, ] { - let ck_par = ::from_label(label, n); + let ck_par = ::from_label(label, n); let ck_ser = from_label_serial(label, n); assert_eq!(ck_par.len(), n); assert_eq!(ck_ser.len(), n); diff --git a/src/spartan/polys/multilinear.rs b/src/spartan/polys/multilinear.rs index 4933c852c..5cbbb7d91 100644 --- a/src/spartan/polys/multilinear.rs +++ b/src/spartan/polys/multilinear.rs @@ -60,7 +60,7 @@ impl MultilinearPolynomial { /// Bounds the polynomial's top variable using the given scalar. /// /// This operation modifies the polynomial in-place. - pub fn bound_poly_var_top(&mut self, r: &Scalar) { + pub fn bind_poly_var_top(&mut self, r: &Scalar) { let n = self.len() / 2; let (left, right) = self.Z.split_at_mut(n); diff --git a/src/spartan/ppsnark.rs b/src/spartan/ppsnark.rs index c67e9c621..b3a83e092 100644 --- a/src/spartan/ppsnark.rs +++ b/src/spartan/ppsnark.rs @@ -570,7 +570,7 @@ impl SumcheckEngine for MemorySumcheckInstance { &mut self.poly_eq, ] .par_iter_mut() - .for_each(|poly| poly.bound_poly_var_top(r)); + .for_each(|poly| poly.bind_poly_var_top(r)); } fn final_claims(&self) -> Vec> { @@ -686,7 +686,7 @@ impl SumcheckEngine for OuterSumcheckInstance { &mut self.poly_Mz, ] .par_iter_mut() - .for_each(|poly| poly.bound_poly_var_top(r)); + .for_each(|poly| poly.bind_poly_var_top(r)); } fn final_claims(&self) -> Vec> { @@ -736,7 +736,7 @@ impl SumcheckEngine for InnerSumcheckInstance { &mut self.poly_val, ] .par_iter_mut() - .for_each(|poly| poly.bound_poly_var_top(r)); + .for_each(|poly| poly.bind_poly_var_top(r)); } fn final_claims(&self) -> Vec> { diff --git a/src/spartan/sumcheck.rs b/src/spartan/sumcheck.rs index 2c3c9d28c..6c9f13d8e 100644 --- a/src/spartan/sumcheck.rs +++ b/src/spartan/sumcheck.rs @@ -125,8 +125,8 @@ impl SumcheckProof { // bound all tables to the verifier's challenege rayon::join( - || poly_A.bound_poly_var_top(&r_i), - || poly_B.bound_poly_var_top(&r_i), + || poly_A.bind_poly_var_top(&r_i), + || poly_B.bind_poly_var_top(&r_i), ); } @@ -181,8 +181,8 @@ impl SumcheckProof { .zip(poly_B_vec.par_iter_mut()) .for_each(|(poly_A, poly_B)| { let _ = rayon::join( - || poly_A.bound_poly_var_top(&r_i), - || poly_B.bound_poly_var_top(&r_i), + || poly_A.bind_poly_var_top(&r_i), + || poly_B.bind_poly_var_top(&r_i), ); }); @@ -339,14 +339,14 @@ impl SumcheckProof { rayon::join( || { rayon::join( - || poly_A.bound_poly_var_top(&r_i), - || poly_B.bound_poly_var_top(&r_i), + || poly_A.bind_poly_var_top(&r_i), + || poly_B.bind_poly_var_top(&r_i), ) }, || { rayon::join( - || poly_C.bound_poly_var_top(&r_i), - || poly_D.bound_poly_var_top(&r_i), + || poly_C.bind_poly_var_top(&r_i), + || poly_D.bind_poly_var_top(&r_i), ) }, ); diff --git a/src/traits/commitment.rs b/src/traits/commitment.rs index e13726735..70f05f9c0 100644 --- a/src/traits/commitment.rs +++ b/src/traits/commitment.rs @@ -7,11 +7,15 @@ use crate::{ use abomonation::Abomonation; use core::{ fmt::Debug, - ops::{Add, AddAssign}, + ops::{Add, AddAssign, Mul, MulAssign}, }; use serde::{Deserialize, Serialize}; -use super::ScalarMul; +/// A helper trait for types implementing scalar multiplication. +pub trait ScalarMul: Mul + MulAssign {} + +impl ScalarMul for T where T: Mul + MulAssign +{} /// Defines basic operations on commitments pub trait CommitmentOps: diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 9970a0d5e..6ac2812cf 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -2,10 +2,7 @@ use crate::errors::NovaError; use abomonation::Abomonation; use bellpepper_core::{boolean::AllocatedBit, num::AllocatedNum, ConstraintSystem, SynthesisError}; -use core::{ - fmt::Debug, - ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, -}; +use core::fmt::Debug; use ff::{PrimeField, PrimeFieldBits}; use num_bigint::BigInt; use serde::{Deserialize, Serialize}; @@ -16,20 +13,7 @@ use commitment::CommitmentEngineTrait; /// Represents an element of a group /// This is currently tailored for an elliptic curve group -pub trait Group: - Clone - + Copy - + Debug - + Eq - + GroupOps - + GroupOpsOwned - + ScalarMul<::Scalar> - + ScalarMulOwned<::Scalar> - + Send - + Sync - + Serialize - + for<'de> Deserialize<'de> -{ +pub trait Group: Clone + Copy + Debug + Send + Sync + Sized + Eq + PartialEq { /// A type representing an element of the base field of the group type Base: PrimeFieldBits + TranscriptReprTrait + Serialize + for<'de> Deserialize<'de>; @@ -42,18 +26,6 @@ pub trait Group: + Serialize + for<'de> Deserialize<'de>; - /// A type representing the compressed version of the group element - type CompressedGroupElement: CompressedGroup; - - /// A type representing preprocessed group element - type PreprocessedGroupElement: Clone - + PartialEq - + Debug - + Send - + Sync - + Serialize - + for<'de> Deserialize<'de>; - /// A type that represents a circuit-friendly sponge that consumes elements /// from the base field and squeezes out elements of the scalar field type RO: ROTrait; @@ -67,52 +39,8 @@ pub trait Group: /// A type that defines a commitment engine over scalars in the group type CE: CommitmentEngineTrait; - /// A method to compute a multiexponentation - fn vartime_multiscalar_mul( - scalars: &[Self::Scalar], - bases: &[Self::PreprocessedGroupElement], - ) -> Self; - - /// Compresses the group element - fn compress(&self) -> Self::CompressedGroupElement; - - /// Produces a preprocessed element - fn preprocessed(&self) -> Self::PreprocessedGroupElement; - - /// Produce a vector of group elements using a static label - fn from_label(label: &'static [u8], n: usize) -> Vec; - - /// Returns the affine coordinates (x, y, infinty) for the point - fn to_coordinates(&self) -> (Self::Base, Self::Base, bool); - - /// Returns an element that is the additive identity of the group - fn zero() -> Self; - - /// Returns the generator of the group - fn get_generator() -> Self; - - /// Returns A, B, and the order of the group as a big integer - fn get_curve_params() -> (Self::Base, Self::Base, BigInt); -} - -/// Represents a compressed version of a group element -pub trait CompressedGroup: - Clone - + Copy - + Debug - + Eq - + Send - + Sync - + TranscriptReprTrait - + Serialize - + for<'de> Deserialize<'de> - + 'static -{ - /// A type that holds the decompressed version of the compressed group element - type GroupElement: Group; - - /// Decompresses the compressed group element - fn decompress(&self) -> Option; + /// Returns A, B, the order of the group, the size of the base field as big integers + fn get_curve_params() -> (Self::Base, Self::Base, BigInt, BigInt); } /// A helper trait to absorb different objects in RO @@ -181,31 +109,6 @@ pub type ROConstants = pub type ROConstantsCircuit = <::ROCircuit as ROCircuitTrait<::Base>>::Constants; -/// A helper trait for types with a group operation. -pub trait GroupOps: - Add + Sub + AddAssign + SubAssign -{ -} - -impl GroupOps for T where - T: Add + Sub + AddAssign + SubAssign -{ -} - -/// A helper trait for references with a group operation. -pub trait GroupOpsOwned: for<'r> GroupOps<&'r Rhs, Output> {} -impl GroupOpsOwned for T where T: for<'r> GroupOps<&'r Rhs, Output> {} - -/// A helper trait for types implementing group scalar multiplication. -pub trait ScalarMul: Mul + MulAssign {} - -impl ScalarMul for T where T: Mul + MulAssign -{} - -/// A helper trait for references implementing group scalar multiplication. -pub trait ScalarMulOwned: for<'r> ScalarMul<&'r Rhs, Output> {} -impl ScalarMulOwned for T where T: for<'r> ScalarMul<&'r Rhs, Output> {} - /// This trait allows types to implement how they want to be added to `TranscriptEngine` pub trait TranscriptReprTrait: Send + Sync { /// returns a byte representation of self to be added to the transcript