ff: Remove PrimeFieldRepr trait

The ff::PrimeField::Repr associated type now has the minimal necessary
bounds, which can be satisfied by a newtype around a byte array.
This commit is contained in:
Jack Grigg
2020-04-23 17:32:04 +12:00
parent 1fe3e3784c
commit 49f119fb03
35 changed files with 1705 additions and 3634 deletions

View File

@@ -313,12 +313,12 @@ pub fn field_into_allocated_bits_le<E: ScalarEngine, CS: ConstraintSystem<E>, F:
// Deconstruct in big-endian bit order
let values = match value {
Some(ref value) => {
let mut field_char = BitIterator::<u64, _>::new(F::char());
let mut field_char = BitIterator::<u8, _>::new(F::char());
let mut tmp = Vec::with_capacity(F::NUM_BITS as usize);
let mut found_one = false;
for b in BitIterator::<u64, _>::new(value.into_repr()) {
for b in BitIterator::<u8, _>::new(value.into_repr()) {
// Skip leading bits
found_one |= field_char.next().unwrap();
if !found_one {

View File

@@ -1,6 +1,6 @@
//! Gadgets representing numbers in the scalar field of the underlying curve.
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, ScalarEngine};
use ff::{BitIterator, Field, PrimeField, ScalarEngine};
use std::ops::{AddAssign, MulAssign};
use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable};
@@ -103,11 +103,8 @@ impl<E: ScalarEngine> AllocatedNum<E> {
// We want to ensure that the bit representation of a is
// less than or equal to r - 1.
let mut a = self
.value
.map(|e| BitIterator::<u64, _>::new(e.into_repr()));
let mut b = E::Fr::char();
b.sub_noborrow(&1.into());
let mut a = self.value.map(|e| BitIterator::<u8, _>::new(e.into_repr()));
let b = (-E::Fr::one()).into_repr();
let mut result = vec![];
@@ -117,7 +114,7 @@ impl<E: ScalarEngine> AllocatedNum<E> {
let mut found_one = false;
let mut i = 0;
for b in BitIterator::<u64, _>::new(b) {
for b in BitIterator::<u8, _>::new(b) {
let a_bit = a.as_mut().map(|e| e.next().unwrap());
// Skip over unset bits at the beginning
@@ -560,7 +557,7 @@ mod test {
assert!(cs.is_satisfied());
for (b, a) in BitIterator::<u64, _>::new(r.into_repr())
for (b, a) in BitIterator::<u8, _>::new(r.into_repr())
.skip(1)
.zip(bits.iter().rev())
{

View File

@@ -1,6 +1,6 @@
//! Helpers for testing circuit implementations.
use ff::{Field, PowVartime, PrimeField, PrimeFieldRepr, ScalarEngine};
use ff::{Field, PowVartime, PrimeField, ScalarEngine};
use crate::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable};
@@ -106,7 +106,12 @@ fn hash_lc<E: ScalarEngine>(terms: &[(Variable, E::Fr)], h: &mut Blake2sState) {
}
}
coeff.into_repr().write_be(&mut buf[9..]).unwrap();
// BLS12-381's Fr is canonically serialized in little-endian, but the hasher
// writes its coefficients in big endian. For now, we flip the endianness
// manually, which is not necessarily correct for circuits using other curves.
// TODO: Fix this in a standalone commit, and document the no-op change.
let coeff_be: Vec<_> = coeff.into_repr().as_ref().iter().cloned().rev().collect();
buf[9..].copy_from_slice(&coeff_be[..]);
h.update(&buf);
}

View File

@@ -4,7 +4,7 @@ use std::sync::Arc;
use futures::Future;
use ff::{Field, PrimeField};
use ff::Field;
use group::{CurveAffine, CurveProjective};
use pairing::Engine;
@@ -229,26 +229,14 @@ where
let a_len = a.len() - 1;
a.truncate(a_len);
// TODO: parallelize if it's even helpful
let a = Arc::new(a.into_iter().map(|s| s.0.into_repr()).collect::<Vec<_>>());
let a = Arc::new(a.into_iter().map(|s| s.0).collect::<Vec<_>>());
multiexp(&worker, params.get_h(a.len())?, FullDensity, a)
};
// TODO: parallelize if it's even helpful
let input_assignment = Arc::new(
prover
.input_assignment
.into_iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>(),
);
let aux_assignment = Arc::new(
prover
.aux_assignment
.into_iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>(),
);
let input_assignment = Arc::new(prover.input_assignment);
let aux_assignment = Arc::new(prover.aux_assignment);
let l = multiexp(
&worker,

View File

@@ -1,6 +1,4 @@
use ff::{
Field, PowVartime, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField,
};
use ff::{Field, PowVartime, PrimeField, ScalarEngine, SqrtField};
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use pairing::{Engine, PairingCurveAffine};
@@ -259,86 +257,35 @@ impl SqrtField for Fr {
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct FrRepr([u64; 1]);
impl Ord for FrRepr {
fn cmp(&self, other: &FrRepr) -> Ordering {
(self.0)[0].cmp(&(other.0)[0])
}
}
impl PartialOrd for FrRepr {
fn partial_cmp(&self, other: &FrRepr) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl fmt::Display for FrRepr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", (self.0)[0])
}
}
impl From<u64> for FrRepr {
fn from(v: u64) -> FrRepr {
FrRepr([v])
}
}
pub struct FrRepr([u8; 8]);
impl From<Fr> for FrRepr {
fn from(v: Fr) -> FrRepr {
FrRepr([(v.0).0 as u64])
FrRepr::from(&v)
}
}
impl AsMut<[u64]> for FrRepr {
fn as_mut(&mut self) -> &mut [u64] {
impl<'a> From<&'a Fr> for FrRepr {
fn from(v: &'a Fr) -> FrRepr {
FrRepr(((v.0).0 as u64).to_le_bytes())
}
}
impl AsMut<[u8]> for FrRepr {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0[..]
}
}
impl AsRef<[u64]> for FrRepr {
fn as_ref(&self) -> &[u64] {
impl AsRef<[u8]> for FrRepr {
fn as_ref(&self) -> &[u8] {
&self.0[..]
}
}
impl Default for FrRepr {
fn default() -> FrRepr {
FrRepr::from(0u64)
}
}
impl PrimeFieldRepr for FrRepr {
fn sub_noborrow(&mut self, other: &Self) {
self.0[0] = self.0[0].wrapping_sub(other.0[0]);
}
fn add_nocarry(&mut self, other: &Self) {
self.0[0] = self.0[0].wrapping_add(other.0[0]);
}
fn num_bits(&self) -> u32 {
64 - self.0[0].leading_zeros()
}
fn is_zero(&self) -> bool {
self.0[0] == 0
}
fn is_odd(&self) -> bool {
!self.is_even()
}
fn is_even(&self) -> bool {
self.0[0] % 2 == 0
}
fn div2(&mut self) {
self.shr(1)
}
fn shr(&mut self, amt: u32) {
self.0[0] >>= amt;
}
fn mul2(&mut self) {
self.shl(1)
}
fn shl(&mut self, amt: u32) {
self.0[0] <<= amt;
FrRepr([0; 8])
}
}
@@ -349,11 +296,12 @@ impl PrimeField for Fr {
const CAPACITY: u32 = 15;
const S: u32 = 10;
fn from_repr(repr: FrRepr) -> Result<Self, PrimeFieldDecodingError> {
if repr.0[0] >= (MODULUS_R.0 as u64) {
Err(PrimeFieldDecodingError::NotInField)
fn from_repr(repr: FrRepr) -> Option<Self> {
let v = u64::from_le_bytes(repr.0);
if v >= (MODULUS_R.0 as u64) {
None
} else {
Ok(Fr(Wrapping(repr.0[0] as u32)))
Some(Fr(Wrapping(v as u32)))
}
}
@@ -464,7 +412,7 @@ impl CurveProjective for Fr {
*self
}
fn recommended_wnaf_for_scalar(_: &<Self::Scalar as PrimeField>::Repr) -> usize {
fn recommended_wnaf_for_scalar(_: &Self::Scalar) -> usize {
3
}

View File

@@ -1,6 +1,6 @@
use super::multicore::Worker;
use bit_vec::{self, BitVec};
use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine};
use ff::{Field, PrimeField, ScalarEngine};
use futures::Future;
use group::{CurveAffine, CurveProjective};
use std::io;
@@ -154,7 +154,7 @@ fn multiexp_inner<Q, D, G, S>(
pool: &Worker,
bases: S,
density_map: D,
exponents: Arc<Vec<<<G::Engine as ScalarEngine>::Fr as PrimeField>::Repr>>,
exponents: Arc<Vec<<G::Engine as ScalarEngine>::Fr>>,
mut skip: u32,
c: u32,
handle_trivial: bool,
@@ -181,13 +181,12 @@ where
// Create space for the buckets
let mut buckets = vec![G::zero(); (1 << c) - 1];
let zero = <G::Engine as ScalarEngine>::Fr::zero().into_repr();
let one = <G::Engine as ScalarEngine>::Fr::one().into_repr();
let one = <G::Engine as ScalarEngine>::Fr::one();
// Sort the bases into buckets
for (&exp, density) in exponents.iter().zip(density_map.as_ref().iter()) {
if density {
if exp == zero {
if exp.is_zero() {
bases.skip(1)?;
} else if exp == one {
if handle_trivial {
@@ -196,9 +195,8 @@ where
bases.skip(1)?;
}
} else {
let mut exp = exp;
exp.shr(skip);
let exp = exp.as_ref()[0] % (1 << c);
let exp = exp >> skip;
let exp = exp & ((1 << c) - 1);
if exp != 0 {
(&mut buckets[(exp - 1) as usize])
@@ -261,7 +259,7 @@ pub fn multiexp<Q, D, G, S>(
pool: &Worker,
bases: S,
density_map: D,
exponents: Arc<Vec<<<G::Engine as ScalarEngine>::Fr as PrimeField>::Repr>>,
exponents: Arc<Vec<<G::Engine as ScalarEngine>::Fr>>,
) -> Box<dyn Future<Item = G, Error = SynthesisError>>
where
for<'a> &'a Q: QueryDensity,
@@ -290,14 +288,14 @@ where
fn test_with_bls12() {
fn naive_multiexp<G: CurveProjective>(
bases: Arc<Vec<<G as CurveProjective>::Affine>>,
exponents: Arc<Vec<<G::Scalar as PrimeField>::Repr>>,
exponents: Arc<Vec<G::Scalar>>,
) -> G {
assert_eq!(bases.len(), exponents.len());
let mut acc = G::zero();
for (base, exp) in bases.iter().zip(exponents.iter()) {
AddAssign::<&G>::add_assign(&mut acc, &base.mul(*exp));
AddAssign::<&G>::add_assign(&mut acc, &base.mul(exp.into_repr()));
}
acc
@@ -311,7 +309,7 @@ fn test_with_bls12() {
let rng = &mut rand::thread_rng();
let v = Arc::new(
(0..SAMPLES)
.map(|_| <Bls12 as ScalarEngine>::Fr::random(rng).into_repr())
.map(|_| <Bls12 as ScalarEngine>::Fr::random(rng))
.collect::<Vec<_>>(),
);
let g = Arc::new(