Migrate to group traits

The `Curve` trait is now `CurveExt: group::prime::PrimeCurve`, and
`CurveAffine` is now `CurveAffine: group::prime::PrimeCurveAffine`.

There is no `CurveAffine` trait in `group`, and it's a widely-used
trait in this crate, so we don't rename it to `CurveAffineExt`.
This commit is contained in:
Jack Grigg 2021-02-22 19:02:53 +00:00
parent 55fb581f17
commit b4ed5295fe
24 changed files with 200 additions and 184 deletions

View file

@ -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"

View file

@ -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) {

View file

@ -1,5 +1,6 @@
use group::Curve;
use halo2::{
arithmetic::{Curve, FieldExt},
arithmetic::FieldExt,
model::ModelRecorder,
pasta::{EqAffine, Fp},
plonk::*,

View file

@ -3,6 +3,7 @@
use crossbeam_utils::thread;
pub use ff::Field;
use group::Group as _;
mod curves;
mod fields;

View file

@ -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<Scalar = <Self as CurveExt>::ScalarExt>
+ Default
+ Copy
+ Clone
+ Send
+ Sync
+ 'static
+ Debug
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<<Self as Curve>::Scalar, Output = Self>
+ Neg<Output = Self>
+ for<'a> Add<&'a Self, Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ MulAssign<<Self as Curve>::Scalar>
+ AddAssign
+ SubAssign
+ for<'a> AddAssign<&'a Self>
+ for<'a> SubAssign<&'a Self>
+ AddAssign<<Self as Curve>::Affine>
+ SubAssign<<Self as Curve>::Affine>
+ PartialEq
+ cmp::Eq
+ ConditionallySelectable
+ ConstantTimeEq
+ From<<Self as Curve>::Affine>
+ Group<Scalar = <Self as Curve>::Scalar>
+ From<<Self as PrimeCurve>::Affine>
+ Group<Scalar = <Self as group::Group>::Scalar>
{
/// The representation of a point on this curve in the affine coordinate space.
type Affine: CurveAffine<Curve = Self, Scalar = <Self as Curve>::Scalar, Base = <Self as Curve>::Base>
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<<Self as Curve>::Scalar, Output = Self>
+ Neg<Output = <Self as Curve>::Affine>
+ From<Self>;
/// 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<C: Curve>(
/// x: <C as Curve>::Scalar,
/// r: <C as Curve>::Scalar,
/// use halo2::arithmetic::CurveExt;
/// fn pedersen_commitment<C: CurveExt>(
/// 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<Scalar = <Self as CurveAffine>::ScalarExt>
+ Default
+ Copy
+ Clone
+ Send
+ Sync
+ 'static
+ Debug
+ Add<Output = <Self as CurveAffine>::Curve>
+ Sub<Output = <Self as CurveAffine>::Curve>
+ Mul<<Self as CurveAffine>::Scalar, Output = <Self as CurveAffine>::Curve>
+ Neg<Output = Self>
+ PartialEq
+ cmp::Eq
+ Add<Output = <Self as PrimeCurveAffine>::Curve>
+ Sub<Output = <Self as PrimeCurveAffine>::Curve>
+ ConditionallySelectable
+ ConstantTimeEq
+ From<<Self as CurveAffine>::Curve>
+ From<<Self as PrimeCurveAffine>::Curve>
{
/// The representation of a point on this curve in the projective coordinate space.
type Curve: Curve<
Affine = Self,
Scalar = <Self as CurveAffine>::Scalar,
Base = <Self as CurveAffine>::Base,
> + Mul<<Self as CurveAffine>::Scalar, Output = <Self as CurveAffine>::Curve>
+ MulAssign<<Self as CurveAffine>::Scalar>
+ AddAssign<Self>
+ SubAssign<Self>
+ From<Self>;
/// 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<Self>;
/// Reads a compressed element from the buffer and attempts to parse it
/// using `from_bytes`.
fn read<R: Read>(reader: &mut R) -> io::Result<Self> {
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<W: 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

View file

@ -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());

View file

@ -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<Self> {
$name_affine::from_bytes(bytes).map(Self::from)
}
fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
// 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<T> Sum<T> for $name
where
T: core::borrow::Borrow<$name>,
{
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = T>,
{
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<Self> {
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<Self> {
let mut tmp = *bytes;
@ -546,6 +590,11 @@ macro_rules! new_curve_impl {
})
}
fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
// 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<Self> {
let p = $name_affine {
x, y, infinity: 0u8.into()
};
CtOption::new(p, p.is_on_curve())
}
fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption<Self> {
let mut xbytes = [0u8; 32];

View file

@ -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<F: FieldExt>(
@ -72,7 +72,7 @@ pub fn hash_to_field<F: FieldExt>(
}
/// Implements a degree 3 isogeny map.
pub fn iso_map<F: FieldExt, C: Curve<Base = F>, I: Curve<Base = F>>(
pub fn iso_map<F: FieldExt, C: CurveExt<Base = F>, I: CurveExt<Base = F>>(
p: &I,
iso: &[C::Base; 13],
) -> C {
@ -99,7 +99,7 @@ pub fn iso_map<F: FieldExt, C: Curve<Base = F>, I: Curve<Base = F>>(
C::new_jacobian(xo, yo, zo).unwrap()
}
pub fn map_to_curve_simple_swu<F: FieldExt, C: Curve<Base = F>, I: Curve<Base = F>>(
pub fn map_to_curve_simple_swu<F: FieldExt, C: CurveExt<Base = F>, I: CurveExt<Base = F>>(
u: &F,
theta: F,
z: F,

View file

@ -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).

View file

@ -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).

View file

@ -44,7 +44,7 @@ impl<C: CurveAffine> VerifyingKey<C> {
/// Writes a verifying key to a buffer.
pub fn write<W: io::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<F> = ChallengeScalar<F, X>;
#[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;

View file

@ -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,

View file

@ -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<F: FieldExt> Argument<F> {
transcript: &mut T,
) -> Result<Permuted<C>, Error>
where
C: CurveAffine<Scalar = F>,
C: CurveAffine<ScalarExt = F>,
C::Curve: Mul<F, Output = C::Curve> + MulAssign<F>,
{
// Closure to get values of expressions and compress them

View file

@ -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},

View file

@ -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},

View file

@ -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},

View file

@ -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},

View file

@ -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<C: CurveAffine> {
impl<C: CurveAffine> Params<C> {
/// 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
<C as PrimeCurveAffine>::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<C: CurveAffine> Params<C> {
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<C: CurveAffine> Params<C> {
// 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 = <<C as PrimeCurveAffine>::Curve as Group>::Scalar::ROOT_OF_UNITY_INV;
for _ in k..C::Scalar::S {
alpha_inv = alpha_inv.square();
}
@ -191,13 +196,13 @@ impl<C: CurveAffine> Params<C> {
pub fn write<W: io::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(())
}

View file

@ -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)]

View file

@ -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

View file

@ -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)]

View file

@ -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;

View file

@ -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;

View file

@ -69,8 +69,8 @@ impl<R: Read, C: CurveAffine> Blake2bRead<R, C> {
impl<R: Read, C: CurveAffine> TranscriptRead<C> for Blake2bRead<R, C> {
fn read_point(&mut self) -> io::Result<C> {
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<W: Write, C: CurveAffine> TranscriptWrite<C> for Blake2bWrite<W, C> {
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)?;