diff --git a/Cargo.toml b/Cargo.toml index 7cd9d62..d60b76c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ backtrace = { version = "0.3", optional = true } subtle = "2.3" crossbeam-utils = "0.8" ff = "0.9" +group = "0.9" metrics = "0.14.2" num_cpus = "1.13" rand = "0.8" diff --git a/benches/hashtocurve.rs b/benches/hashtocurve.rs index cd3e987..7e6af30 100644 --- a/benches/hashtocurve.rs +++ b/benches/hashtocurve.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use halo2::arithmetic::Curve; +use halo2::arithmetic::CurveExt; use halo2::pasta::{pallas, vesta}; fn criterion_benchmark(c: &mut Criterion) { diff --git a/examples/performance_model.rs b/examples/performance_model.rs index 5f03efb..8cd9c53 100644 --- a/examples/performance_model.rs +++ b/examples/performance_model.rs @@ -1,5 +1,6 @@ +use group::Curve; use halo2::{ - arithmetic::{Curve, FieldExt}, + arithmetic::FieldExt, model::ModelRecorder, pasta::{EqAffine, Fp}, plonk::*, diff --git a/src/arithmetic.rs b/src/arithmetic.rs index bee2b04..31c972b 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -3,6 +3,7 @@ use crossbeam_utils::thread; pub use ff::Field; +use group::Group as _; mod curves; mod fields; diff --git a/src/arithmetic/curves.rs b/src/arithmetic/curves.rs index 21da4f7..97a9527 100644 --- a/src/arithmetic/curves.rs +++ b/src/arithmetic/curves.rs @@ -2,8 +2,8 @@ //! write code that generalizes over a pair of groups. use core::cmp; -use core::fmt::Debug; -use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use core::ops::{Add, Sub}; +use group::prime::{PrimeCurve, PrimeCurveAffine}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use super::{FieldExt, Group}; @@ -13,66 +13,26 @@ use std::io::{self, Read, Write}; /// This trait is a common interface for dealing with elements of an elliptic /// curve group in a "projective" form, where that arithmetic is usually more /// efficient. -pub trait Curve: - Sized +pub trait CurveExt: + PrimeCurve + + group::Group::ScalarExt> + Default - + Copy - + Clone - + Send - + Sync - + 'static - + Debug - + Add - + Sub - + Mul<::Scalar, Output = Self> - + Neg - + for<'a> Add<&'a Self, Output = Self> - + for<'a> Sub<&'a Self, Output = Self> - + MulAssign<::Scalar> - + AddAssign - + SubAssign - + for<'a> AddAssign<&'a Self> - + for<'a> SubAssign<&'a Self> - + AddAssign<::Affine> - + SubAssign<::Affine> + PartialEq + cmp::Eq + ConditionallySelectable + ConstantTimeEq - + From<::Affine> - + Group::Scalar> + + From<::Affine> + + Group::Scalar> { - /// The representation of a point on this curve in the affine coordinate space. - type Affine: CurveAffine::Scalar, Base = ::Base> - + Add - + Sub - + Mul<::Scalar, Output = Self> - + Neg::Affine> - + From; /// The scalar field of this elliptic curve. - type Scalar: FieldExt; + type ScalarExt: FieldExt; /// The base field over which this elliptic curve is constructed. type Base: FieldExt; - /// Obtains the additive identity. - fn identity() -> Self; - - /// Obtains the base point of the curve. - fn generator() -> Self; - - /// Doubles this element. - fn double(&self) -> Self; - - /// Returns whether or not this element is the identity. - fn is_identity(&self) -> Choice; - /// Apply the curve endomorphism by multiplying the x-coordinate /// by an element of multiplicative order 3. fn endo(&self) -> Self; - /// Converts this element into its affine form. - fn to_affine(&self) -> Self::Affine; - /// Return the Jacobian coordinates of this point. fn jacobian_coordinates(&self) -> (Self::Base, Self::Base, Self::Base); @@ -84,10 +44,10 @@ pub trait Curve: /// # Example /// /// ``` - /// use halo2::arithmetic::Curve; - /// fn pedersen_commitment( - /// x: ::Scalar, - /// r: ::Scalar, + /// use halo2::arithmetic::CurveExt; + /// fn pedersen_commitment( + /// x: C::ScalarExt, + /// r: C::ScalarExt, /// ) -> C::Affine { /// let hasher = C::hash_to_curve("z.cash:example_pedersen_commitment"); /// let g = hasher(b"g"); @@ -101,10 +61,6 @@ pub trait Curve: /// always be true unless an "unchecked" API was used. fn is_on_curve(&self) -> Choice; - /// Converts many elements into their affine form. Panics if the - /// sizes of the slices are different. - fn batch_normalize(v: &[Self], target: &mut [Self::Affine]); - /// Returns the curve constant a. fn a() -> Self::Base; @@ -119,36 +75,16 @@ pub trait Curve: /// This trait is the affine counterpart to `Curve` and is used for /// serialization, storage in memory, and inspection of $x$ and $y$ coordinates. pub trait CurveAffine: - Sized + PrimeCurveAffine::ScalarExt> + Default - + Copy - + Clone - + Send - + Sync - + 'static - + Debug - + Add::Curve> - + Sub::Curve> - + Mul<::Scalar, Output = ::Curve> - + Neg - + PartialEq - + cmp::Eq + + Add::Curve> + + Sub::Curve> + ConditionallySelectable + ConstantTimeEq - + From<::Curve> + + From<::Curve> { - /// The representation of a point on this curve in the projective coordinate space. - type Curve: Curve< - Affine = Self, - Scalar = ::Scalar, - Base = ::Base, - > + Mul<::Scalar, Output = ::Curve> - + MulAssign<::Scalar> - + AddAssign - + SubAssign - + From; /// The scalar field of this elliptic curve. - type Scalar: FieldExt; + type ScalarExt: FieldExt; /// The base field over which this elliptic curve is constructed. type Base: FieldExt; @@ -159,18 +95,6 @@ pub trait CurveAffine: /// CURVE_ID used for hash-to-curve. const CURVE_ID: &'static str; - /// Obtains the additive identity. - fn identity() -> Self; - - /// Obtains the base point of the curve. - fn generator() -> Self; - - /// Returns whether or not this element is the identity. - fn is_identity(&self) -> Choice; - - /// Converts this element into its projective form. - fn to_curve(&self) -> Self::Curve; - /// Gets the $(x, y)$ coordinates of this point. fn get_xy(&self) -> CtOption<(Self::Base, Self::Base)>; @@ -182,27 +106,19 @@ pub trait CurveAffine: /// always be true unless an "unchecked" API was used. fn is_on_curve(&self) -> Choice; - /// Attempts to obtain a group element from its compressed 32-byte little - /// endian representation. - fn from_bytes(bytes: &[u8; 32]) -> CtOption; - /// Reads a compressed element from the buffer and attempts to parse it /// using `from_bytes`. fn read(reader: &mut R) -> io::Result { - let mut compressed = [0u8; 32]; - reader.read_exact(&mut compressed[..])?; + let mut compressed = Self::Repr::default(); + reader.read_exact(compressed.as_mut())?; Option::from(Self::from_bytes(&compressed)) .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof")) } - /// Obtains the compressed, 32-byte little endian representation of this - /// element. - fn to_bytes(&self) -> [u8; 32]; - /// Writes an element in compressed form to the buffer. fn write(&self, writer: &mut W) -> io::Result<()> { let compressed = self.to_bytes(); - writer.write_all(&compressed[..]) + writer.write_all(compressed.as_ref()) } /// Attempts to obtain a group element from its uncompressed 64-byte little diff --git a/src/pasta.rs b/src/pasta.rs index 3046bf4..4f170c6 100644 --- a/src/pasta.rs +++ b/src/pasta.rs @@ -15,7 +15,8 @@ pub use fields::*; #[test] fn test_endo_consistency() { - use crate::arithmetic::{Curve, FieldExt}; + use crate::arithmetic::{CurveExt, FieldExt}; + use group::Group; let a = pallas::Point::generator(); assert_eq!(a * pallas::Scalar::ZETA, a.endo()); diff --git a/src/pasta/curves.rs b/src/pasta/curves.rs index fe266cc..552944e 100644 --- a/src/pasta/curves.rs +++ b/src/pasta/curves.rs @@ -3,12 +3,18 @@ use core::cmp; use core::fmt::Debug; +use core::iter::Sum; use core::ops::{Add, Mul, Neg, Sub}; use ff::Field; +use group::{ + prime::{PrimeCurve, PrimeCurveAffine, PrimeGroup}, + Curve as _, Group as _, GroupEncoding, +}; +use rand::RngCore; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use super::{Fp, Fq}; -use crate::arithmetic::{Curve, CurveAffine, FieldExt, Group}; +use crate::arithmetic::{CurveAffine, CurveExt, FieldExt, Group}; macro_rules! new_curve_impl { (($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident, $blake2b_personalization:literal, @@ -50,10 +56,21 @@ macro_rules! new_curve_impl { } } - impl Curve for $name { - type Affine = $name_affine; + impl group::Group for $name { type Scalar = $scalar; - type Base = $base; + + fn random(mut rng: impl RngCore) -> Self { + loop { + let mut buf = [0; 64]; + rng.fill_bytes(&mut buf); + let p: Option<$name_affine> = $name_affine::from_bytes_wide(&buf).into(); + if let Some(p) = p { + if !bool::from(p.is_identity()) { + break p.to_curve(); + } + } + } + } impl_projective_curve_specific!($name, $base, $curve_type); @@ -68,22 +85,11 @@ macro_rules! new_curve_impl { fn is_identity(&self) -> Choice { self.z.ct_is_zero() } + } - fn to_affine(&self) -> Self::Affine { - let zinv = self.z.invert().unwrap_or($base::zero()); - let zinv2 = zinv.square(); - let x = self.x * zinv2; - let zinv3 = zinv2 * zinv; - let y = self.y * zinv3; - - let tmp = $name_affine { - x, - y, - infinity: Choice::from(0u8), - }; - - $name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.ct_is_zero()) - } + impl CurveExt for $name { + type ScalarExt = $scalar; + type Base = $base; impl_projective_curve_ext!($name, $name_affine, $iso, $base, $curve_type); @@ -115,8 +121,12 @@ macro_rules! new_curve_impl { .ct_eq(&(z6 * $name::curve_constant_b())) | self.z.ct_is_zero() } + } - fn batch_normalize(p: &[Self], q: &mut [Self::Affine]) { + impl group::Curve for $name { + type AffineRepr = $name_affine; + + fn batch_normalize(p: &[Self], q: &mut [Self::AffineRepr]) { assert_eq!(p.len(), q.len()); let mut acc = $base::one(); @@ -153,6 +163,45 @@ macro_rules! new_curve_impl { *q = $name_affine::conditional_select(&q, &$name_affine::identity(), skip); } } + + fn to_affine(&self) -> Self::AffineRepr { + let zinv = self.z.invert().unwrap_or($base::zero()); + let zinv2 = zinv.square(); + let x = self.x * zinv2; + let zinv3 = zinv2 * zinv; + let y = self.y * zinv3; + + let tmp = $name_affine { + x, + y, + infinity: Choice::from(0u8), + }; + + $name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.ct_is_zero()) + } + } + + impl PrimeGroup for $name {} + + impl PrimeCurve for $name { + type Affine = $name_affine; + } + + impl GroupEncoding for $name { + type Repr = [u8; 32]; + + fn from_bytes(bytes: &Self::Repr) -> CtOption { + $name_affine::from_bytes(bytes).map(Self::from) + } + + fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption { + // We can't avoid curve checks when parsing a compressed encoding. + $name_affine::from_bytes(bytes).map(Self::from) + } + + fn to_bytes(&self) -> Self::Repr { + $name_affine::from(self).to_bytes() + } } impl<'a> From<&'a $name_affine> for $name { @@ -233,6 +282,18 @@ macro_rules! new_curve_impl { } } + impl Sum for $name + where + T: core::borrow::Borrow<$name>, + { + fn sum(iter: I) -> Self + where + I: Iterator, + { + iter.fold(Self::identity(), |acc, item| acc + item.borrow()) + } + } + impl<'a, 'b> Add<&'a $name> for &'b $name { type Output = $name; @@ -473,13 +534,9 @@ macro_rules! new_curve_impl { } } - impl CurveAffine for $name_affine { + impl PrimeCurveAffine for $name_affine { type Curve = $name; type Scalar = $scalar; - type Base = $base; - - const BLAKE2B_PERSONALIZATION: &'static [u8; 16] = $blake2b_personalization; - const CURVE_ID: &'static str = $curve_id; impl_affine_curve_specific!($name, $base, $curve_type); @@ -495,12 +552,6 @@ macro_rules! new_curve_impl { self.infinity } - fn is_on_curve(&self) -> Choice { - // y^2 - x^3 - ax ?= b - (self.y.square() - (self.x.square() + &$name::curve_constant_a()) * self.x).ct_eq(&$name::curve_constant_b()) - | self.infinity - } - fn to_curve(&self) -> Self::Curve { $name { x: self.x, @@ -508,17 +559,10 @@ macro_rules! new_curve_impl { z: $base::conditional_select(&$base::one(), &$base::zero(), self.infinity), } } + } - fn get_xy(&self) -> CtOption<(Self::Base, Self::Base)> { - CtOption::new((self.x, self.y), !self.is_identity()) - } - - fn from_xy(x: Self::Base, y: Self::Base) -> CtOption { - let p = $name_affine { - x, y, infinity: 0u8.into() - }; - CtOption::new(p, p.is_on_curve()) - } + impl GroupEncoding for $name_affine { + type Repr = [u8; 32]; fn from_bytes(bytes: &[u8; 32]) -> CtOption { let mut tmp = *bytes; @@ -546,6 +590,11 @@ macro_rules! new_curve_impl { }) } + fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption { + // We can't avoid curve checks when parsing a compressed encoding. + Self::from_bytes(bytes) + } + fn to_bytes(&self) -> [u8; 32] { // TODO: not constant time if bool::from(self.is_identity()) { @@ -558,6 +607,31 @@ macro_rules! new_curve_impl { xbytes } } + } + + impl CurveAffine for $name_affine { + type ScalarExt = $scalar; + type Base = $base; + + const BLAKE2B_PERSONALIZATION: &'static [u8; 16] = $blake2b_personalization; + const CURVE_ID: &'static str = $curve_id; + + fn is_on_curve(&self) -> Choice { + // y^2 - x^3 - ax ?= b + (self.y.square() - (self.x.square() + &$name::curve_constant_a()) * self.x).ct_eq(&$name::curve_constant_b()) + | self.infinity + } + + fn get_xy(&self) -> CtOption<(Self::Base, Self::Base)> { + CtOption::new((self.x, self.y), !self.is_identity()) + } + + fn from_xy(x: Self::Base, y: Self::Base) -> CtOption { + let p = $name_affine { + x, y, infinity: 0u8.into() + }; + CtOption::new(p, p.is_on_curve()) + } fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption { let mut xbytes = [0u8; 32]; diff --git a/src/pasta/hashtocurve.rs b/src/pasta/hashtocurve.rs index d3acfe8..3fae7b8 100644 --- a/src/pasta/hashtocurve.rs +++ b/src/pasta/hashtocurve.rs @@ -3,7 +3,7 @@ use subtle::ConstantTimeEq; -use crate::arithmetic::{Curve, FieldExt}; +use crate::arithmetic::{CurveExt, FieldExt}; /// Hashes over a message and writes the output to all of `buf`. pub fn hash_to_field( @@ -72,7 +72,7 @@ pub fn hash_to_field( } /// Implements a degree 3 isogeny map. -pub fn iso_map, I: Curve>( +pub fn iso_map, I: CurveExt>( p: &I, iso: &[C::Base; 13], ) -> C { @@ -99,7 +99,7 @@ pub fn iso_map, I: Curve>( C::new_jacobian(xo, yo, zo).unwrap() } -pub fn map_to_curve_simple_swu, I: Curve>( +pub fn map_to_curve_simple_swu, I: CurveExt>( u: &F, theta: F, z: F, diff --git a/src/pasta/pallas.rs b/src/pasta/pallas.rs index 729b264..c3094ef 100644 --- a/src/pasta/pallas.rs +++ b/src/pasta/pallas.rs @@ -16,7 +16,8 @@ pub type Affine = EpAffine; #[test] fn test_iso_map() { - use crate::arithmetic::Curve; + use crate::arithmetic::CurveExt; + use group::Group; // This is a regression test (it's the same input to iso_map as for hash_to_curve // with domain prefix "z.cash:test", Shake128, and input b"hello"). We don't @@ -64,7 +65,8 @@ fn test_iso_map() { #[test] fn test_iso_map_identity() { - use crate::arithmetic::Curve; + use crate::arithmetic::CurveExt; + use group::Group; let r = super::IsoEp::new_jacobian( Base::from_raw([ @@ -97,7 +99,7 @@ fn test_iso_map_identity() { #[test] fn test_map_to_curve_simple_swu() { - use crate::arithmetic::Curve; + use crate::arithmetic::CurveExt; use crate::pasta::curves::IsoEp; use crate::pasta::hashtocurve::map_to_curve_simple_swu; @@ -131,7 +133,8 @@ fn test_map_to_curve_simple_swu() { #[test] fn test_hash_to_curve() { - use crate::arithmetic::Curve; + use crate::arithmetic::CurveExt; + use group::Group; // This test vector is chosen so that the first map_to_curve_simple_swu takes the gx1 square // "branch" and the second takes the gx1 non-square "branch" (opposite to the Vesta test vector). diff --git a/src/pasta/vesta.rs b/src/pasta/vesta.rs index d41d60f..c958804 100644 --- a/src/pasta/vesta.rs +++ b/src/pasta/vesta.rs @@ -16,7 +16,7 @@ pub type Affine = EqAffine; #[test] fn test_map_to_curve_simple_swu() { - use crate::arithmetic::Curve; + use crate::arithmetic::CurveExt; use crate::pasta::curves::IsoEq; use crate::pasta::hashtocurve::map_to_curve_simple_swu; @@ -50,7 +50,7 @@ fn test_map_to_curve_simple_swu() { #[test] fn test_hash_to_curve() { - use crate::arithmetic::Curve; + use crate::arithmetic::CurveExt; // This test vector is chosen so that the first map_to_curve_simple_swu takes the gx1 non-square // "branch" and the second takes the gx1 square "branch" (opposite to the Pallas test vector). diff --git a/src/plonk.rs b/src/plonk.rs index bb9fd31..95719c4 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -44,7 +44,7 @@ impl VerifyingKey { /// Writes a verifying key to a buffer. pub fn write(&self, writer: &mut W) -> io::Result<()> { for commitment in &self.fixed_commitments { - writer.write_all(&commitment.to_bytes())?; + writer.write_all(commitment.to_bytes().as_ref())?; } for permutation in &self.permutations { permutation.write(writer)?; @@ -190,7 +190,7 @@ type ChallengeX = ChallengeScalar; #[test] fn test_proving() { - use crate::arithmetic::{Curve, FieldExt}; + use crate::arithmetic::FieldExt; use crate::dev::MockProver; use crate::pasta::{EqAffine, Fp}; use crate::poly::{ @@ -199,6 +199,7 @@ fn test_proving() { }; use crate::transcript::{Blake2bRead, Blake2bWrite}; use circuit::{Advice, Column, Fixed}; + use group::Curve; use std::marker::PhantomData; const K: u32 = 5; diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs index a206913..18cbafb 100644 --- a/src/plonk/keygen.rs +++ b/src/plonk/keygen.rs @@ -1,10 +1,11 @@ use ff::Field; +use group::Curve; use super::{ circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed}, permutation, Error, LagrangeCoeff, Polynomial, ProvingKey, VerifyingKey, }; -use crate::arithmetic::{Curve, CurveAffine}; +use crate::arithmetic::CurveAffine; use crate::poly::{ commitment::{Blind, Params}, EvaluationDomain, Rotation, diff --git a/src/plonk/lookup/prover.rs b/src/plonk/lookup/prover.rs index 1eee099..76693dc 100644 --- a/src/plonk/lookup/prover.rs +++ b/src/plonk/lookup/prover.rs @@ -4,7 +4,7 @@ use super::super::{ }; use super::Argument; use crate::{ - arithmetic::{eval_polynomial, parallelize, BatchInvert, Curve, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, parallelize, BatchInvert, CurveAffine, FieldExt}, poly::{ commitment::{Blind, Params}, multiopen::ProverQuery, @@ -13,6 +13,7 @@ use crate::{ transcript::TranscriptWrite, }; use ff::Field; +use group::Curve; use std::{ collections::BTreeMap, iter, @@ -86,7 +87,7 @@ impl Argument { transcript: &mut T, ) -> Result, Error> where - C: CurveAffine, + C: CurveAffine, C::Curve: Mul + MulAssign, { // Closure to get values of expressions and compress them diff --git a/src/plonk/permutation/keygen.rs b/src/plonk/permutation/keygen.rs index 072f6c5..dfc1f55 100644 --- a/src/plonk/permutation/keygen.rs +++ b/src/plonk/permutation/keygen.rs @@ -1,8 +1,9 @@ use ff::Field; +use group::Curve; use super::{Argument, ProvingKey, VerifyingKey}; use crate::{ - arithmetic::{Curve, CurveAffine, FieldExt}, + arithmetic::{CurveAffine, FieldExt}, plonk::{circuit::ConstraintSystem, Error}, poly::{ commitment::{Blind, Params}, diff --git a/src/plonk/permutation/prover.rs b/src/plonk/permutation/prover.rs index b0a3f30..eca39a2 100644 --- a/src/plonk/permutation/prover.rs +++ b/src/plonk/permutation/prover.rs @@ -1,10 +1,11 @@ use ff::Field; +use group::Curve; use std::iter; use super::super::circuit::Any; use super::{Argument, ProvingKey}; use crate::{ - arithmetic::{eval_polynomial, parallelize, BatchInvert, Curve, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, parallelize, BatchInvert, CurveAffine, FieldExt}, plonk::{self, ChallengeBeta, ChallengeGamma, ChallengeX, Error}, poly::{ commitment::{Blind, Params}, diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index f9f1e3a..e919fd9 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -1,4 +1,5 @@ use ff::Field; +use group::Curve; use std::iter; use super::{ @@ -6,7 +7,7 @@ use super::{ lookup, permutation, vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, ChallengeY, Error, ProvingKey, }; -use crate::arithmetic::{eval_polynomial, Curve, CurveAffine, FieldExt}; +use crate::arithmetic::{eval_polynomial, CurveAffine, FieldExt}; use crate::poly::{ commitment::{Blind, Params}, multiopen::{self, ProverQuery}, diff --git a/src/plonk/vanishing/prover.rs b/src/plonk/vanishing/prover.rs index bf8094e..441615e 100644 --- a/src/plonk/vanishing/prover.rs +++ b/src/plonk/vanishing/prover.rs @@ -1,6 +1,8 @@ +use group::Curve; + use super::Argument; use crate::{ - arithmetic::{eval_polynomial, Curve, CurveAffine, FieldExt}, + arithmetic::{eval_polynomial, CurveAffine, FieldExt}, plonk::{ChallengeX, ChallengeY, Error}, poly::{ commitment::{Blind, Params}, diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index 5bbc350..7ed1ac3 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -6,10 +6,10 @@ use blake2b_simd::{Params as Blake2bParams, State as Blake2bState}; use super::{Coeff, LagrangeCoeff, Polynomial}; -use crate::arithmetic::{best_fft, best_multiexp, parallelize, Curve, CurveAffine, FieldExt}; +use crate::arithmetic::{best_fft, best_multiexp, parallelize, CurveAffine, FieldExt, Group}; use ff::{Field, PrimeField}; -use std::convert::TryInto; +use group::{prime::PrimeCurveAffine, Curve}; use std::ops::{Add, AddAssign, Mul, MulAssign}; mod msm; @@ -36,7 +36,10 @@ pub struct Params { impl Params { /// Initializes parameters for the curve, given a random oracle to draw /// points from. - pub fn new(k: u32) -> Self { + pub fn new(k: u32) -> Self + where + ::Curve: Group, + { // This is usually a limitation on the curve, but we also want 32-bit // architectures to be supported. assert!(k < 32); @@ -50,7 +53,9 @@ impl Params { loop { let mut hasher = hasher.clone(); hasher.update(&(trial.to_le_bytes())[..]); - let p = C::from_bytes(&hasher.finalize().as_bytes().try_into().unwrap()); + let mut repr = C::Repr::default(); + repr.as_mut().copy_from_slice(hasher.finalize().as_bytes()); + let p = C::from_bytes(&repr); if bool::from(p.is_some()) { break p.unwrap(); } @@ -83,7 +88,7 @@ impl Params { // Let's evaluate all of the Lagrange basis polynomials // using an inverse FFT. - let mut alpha_inv = C::Scalar::ROOT_OF_UNITY_INV; + let mut alpha_inv = <::Curve as Group>::Scalar::ROOT_OF_UNITY_INV; for _ in k..C::Scalar::S { alpha_inv = alpha_inv.square(); } @@ -191,13 +196,13 @@ impl Params { pub fn write(&self, writer: &mut W) -> io::Result<()> { writer.write_all(&self.k.to_le_bytes())?; for g_element in &self.g { - writer.write_all(&g_element.to_bytes())?; + writer.write_all(g_element.to_bytes().as_ref())?; } for g_lagrange_element in &self.g_lagrange { - writer.write_all(&g_lagrange_element.to_bytes())?; + writer.write_all(g_lagrange_element.to_bytes().as_ref())?; } - writer.write_all(&self.h.to_bytes())?; - writer.write_all(&self.u.to_bytes())?; + writer.write_all(self.h.to_bytes().as_ref())?; + writer.write_all(self.u.to_bytes().as_ref())?; Ok(()) } diff --git a/src/poly/commitment/msm.rs b/src/poly/commitment/msm.rs index 090fbb9..91184a1 100644 --- a/src/poly/commitment/msm.rs +++ b/src/poly/commitment/msm.rs @@ -1,6 +1,7 @@ use super::Params; -use crate::arithmetic::{best_multiexp, parallelize, Curve, CurveAffine}; +use crate::arithmetic::{best_multiexp, parallelize, CurveAffine}; use ff::Field; +use group::Group; /// A multiscalar multiplication in the polynomial commitment scheme #[derive(Debug, Clone)] diff --git a/src/poly/commitment/prover.rs b/src/poly/commitment/prover.rs index 71995b5..db3e97c 100644 --- a/src/poly/commitment/prover.rs +++ b/src/poly/commitment/prover.rs @@ -3,10 +3,11 @@ use ff::Field; use super::super::{Coeff, Polynomial}; use super::{Blind, Params}; use crate::arithmetic::{ - best_multiexp, compute_inner_product, eval_polynomial, parallelize, Curve, CurveAffine, - FieldExt, + best_multiexp, compute_inner_product, eval_polynomial, parallelize, CurveAffine, FieldExt, }; use crate::transcript::{Challenge, ChallengeScalar, TranscriptWrite}; + +use group::Curve; use std::io; /// Create a polynomial commitment opening proof for the polynomial defined diff --git a/src/poly/commitment/verifier.rs b/src/poly/commitment/verifier.rs index da057fd..2665223 100644 --- a/src/poly/commitment/verifier.rs +++ b/src/poly/commitment/verifier.rs @@ -1,10 +1,11 @@ use ff::Field; +use group::Curve; use super::super::Error; use super::{Params, MSM}; use crate::transcript::{Challenge, ChallengeScalar, TranscriptRead}; -use crate::arithmetic::{best_multiexp, BatchInvert, Curve, CurveAffine}; +use crate::arithmetic::{best_multiexp, BatchInvert, CurveAffine}; /// A guard returned by the verifier #[derive(Debug, Clone)] diff --git a/src/poly/multiopen.rs b/src/poly/multiopen.rs index c5937e4..2ed4ee7 100644 --- a/src/poly/multiopen.rs +++ b/src/poly/multiopen.rs @@ -206,8 +206,10 @@ where #[test] fn test_roundtrip() { + use group::Curve; + use super::commitment::{Blind, Params}; - use crate::arithmetic::{eval_polynomial, Curve, FieldExt}; + use crate::arithmetic::{eval_polynomial, FieldExt}; use crate::pasta::{EqAffine, Fp}; const K: u32 = 4; diff --git a/src/poly/multiopen/prover.rs b/src/poly/multiopen/prover.rs index 7cf4703..9dbb647 100644 --- a/src/poly/multiopen/prover.rs +++ b/src/poly/multiopen/prover.rs @@ -7,10 +7,11 @@ use super::{ Query, }; -use crate::arithmetic::{eval_polynomial, kate_division, Curve, CurveAffine, FieldExt}; +use crate::arithmetic::{eval_polynomial, kate_division, CurveAffine, FieldExt}; use crate::transcript::TranscriptWrite; use ff::Field; +use group::Curve; use std::io; use std::marker::PhantomData; diff --git a/src/transcript.rs b/src/transcript.rs index 86052b6..c3da9a9 100644 --- a/src/transcript.rs +++ b/src/transcript.rs @@ -69,8 +69,8 @@ impl Blake2bRead { impl TranscriptRead for Blake2bRead { fn read_point(&mut self) -> io::Result { - let mut compressed = [0u8; 32]; - self.reader.read_exact(&mut compressed[..])?; + let mut compressed = C::Repr::default(); + self.reader.read_exact(compressed.as_mut())?; let point: C = Option::from(C::from_bytes(&compressed)).ok_or_else(|| { io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof") })?; @@ -154,7 +154,7 @@ impl TranscriptWrite for Blake2bWrite { fn write_point(&mut self, point: C) -> io::Result<()> { self.common_point(point)?; let compressed = point.to_bytes(); - self.writer.write_all(&compressed[..]) + self.writer.write_all(compressed.as_ref()) } fn write_scalar(&mut self, scalar: C::Scalar) -> io::Result<()> { self.common_scalar(scalar)?;