Add PrimeField, PrimeField64 traits (#457)

* Add PrimeField, PrimeField64 traits

* fix

* fixes

* fix

* `to_biguint` -> `to_canonical_biguint`
This commit is contained in:
Daniel Lubarov 2022-02-09 21:50:18 -08:00 committed by GitHub
parent fe89fa949e
commit cfe52ad604
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 159 additions and 135 deletions

View File

@ -95,10 +95,6 @@ impl<F: Extendable<2>> Field for QuadraticExtension<F> {
Self([F::from_biguint(low), F::from_biguint(high)])
}
fn to_biguint(&self) -> BigUint {
self.0[0].to_biguint() + F::order() * self.0[1].to_biguint()
}
fn from_canonical_u64(n: u64) -> Self {
F::from_canonical_u64(n).into()
}

View File

@ -107,14 +107,6 @@ impl<F: Extendable<4>> Field for QuarticExtension<F> {
])
}
fn to_biguint(&self) -> BigUint {
let mut result = self.0[3].to_biguint();
result = result * F::order() + self.0[2].to_biguint();
result = result * F::order() + self.0[1].to_biguint();
result = result * F::order() + self.0[0].to_biguint();
result
}
fn from_canonical_u64(n: u64) -> Self {
F::from_canonical_u64(n).into()
}

View File

@ -268,9 +268,6 @@ pub trait Field:
// Rename to `from_noncanonical_biguint` and have it return `n % Self::characteristic()`.
fn from_biguint(n: BigUint) -> Self;
// TODO: Move to a new `PrimeField` trait.
fn to_biguint(&self) -> BigUint;
/// Returns `n`. Assumes that `n` is already in canonical form, i.e. `n < Self::order()`.
// TODO: Should probably be unsafe.
fn from_canonical_u64(n: u64) -> Self;
@ -407,16 +404,14 @@ pub trait Field:
}
}
pub trait PrimeField: Field {
fn to_canonical_biguint(&self) -> BigUint;
}
/// A finite field of order less than 2^64.
pub trait Field64: Field {
const ORDER: u64;
// TODO: Only well-defined for prime 64-bit fields. Move to a new PrimeField64 trait?
fn to_canonical_u64(&self) -> u64;
// TODO: Only well-defined for prime 64-bit fields. Move to a new PrimeField64 trait?
fn to_noncanonical_u64(&self) -> u64;
/// Returns `x % Self::CHARACTERISTIC`.
// TODO: Move to `Field`.
fn from_noncanonical_u64(n: u64) -> Self;
@ -456,6 +451,13 @@ pub trait Field64: Field {
}
}
/// A finite field of prime order less than 2^64.
pub trait PrimeField64: PrimeField + Field64 {
fn to_canonical_u64(&self) -> u64;
fn to_noncanonical_u64(&self) -> u64;
}
/// An iterator over the powers of a certain base element `b`: `b^0, b^1, b^2, ...`.
#[derive(Clone)]
pub struct Powers<F: Field> {

View File

@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
use crate::extension_field::quadratic::QuadraticExtension;
use crate::extension_field::quartic::QuarticExtension;
use crate::extension_field::{Extendable, Frobenius};
use crate::field_types::{Field, Field64};
use crate::field_types::{Field, Field64, PrimeField, PrimeField64};
use crate::inversion::try_inverse_u64;
const EPSILON: u64 = (1 << 32) - 1;
@ -98,10 +98,6 @@ impl Field for GoldilocksField {
Self(n.mod_floor(&Self::order()).to_u64_digits()[0])
}
fn to_biguint(&self) -> BigUint {
self.to_canonical_u64().into()
}
#[inline]
fn from_canonical_u64(n: u64) -> Self {
debug_assert!(n < Self::ORDER);
@ -123,23 +119,15 @@ impl Field for GoldilocksField {
}
}
impl PrimeField for GoldilocksField {
fn to_canonical_biguint(&self) -> BigUint {
self.to_canonical_u64().into()
}
}
impl Field64 for GoldilocksField {
const ORDER: u64 = 0xFFFFFFFF00000001;
#[inline]
fn to_canonical_u64(&self) -> u64 {
let mut c = self.0;
// We only need one condition subtraction, since 2 * ORDER would not fit in a u64.
if c >= Self::ORDER {
c -= Self::ORDER;
}
c
}
fn to_noncanonical_u64(&self) -> u64 {
self.0
}
#[inline]
fn from_noncanonical_u64(n: u64) -> Self {
Self(n)
@ -160,6 +148,22 @@ impl Field64 for GoldilocksField {
}
}
impl PrimeField64 for GoldilocksField {
#[inline]
fn to_canonical_u64(&self) -> u64 {
let mut c = self.0;
// We only need one condition subtraction, since 2 * ORDER would not fit in a u64.
if c >= Self::ORDER {
c -= Self::ORDER;
}
c
}
fn to_noncanonical_u64(&self) -> u64 {
self.0
}
}
impl Neg for GoldilocksField {
type Output = Self;

View File

@ -1,4 +1,4 @@
use crate::field_types::Field64;
use crate::field_types::PrimeField64;
/// This is a 'safe' iteration for the modular inversion algorithm. It
/// is safe in the sense that it will produce the right answer even
@ -63,7 +63,7 @@ unsafe fn unsafe_iteration(f: &mut u64, g: &mut u64, c: &mut i128, d: &mut i128,
/// Elliptic and Hyperelliptic Cryptography, Algorithms 11.6
/// and 11.12.
#[allow(clippy::many_single_char_names)]
pub(crate) fn try_inverse_u64<F: Field64>(x: &F) -> Option<F> {
pub(crate) fn try_inverse_u64<F: PrimeField64>(x: &F) -> Option<F> {
let mut f = x.to_noncanonical_u64();
let mut g = F::ORDER;
// NB: These two are very rarely such that their absolute

View File

@ -1,4 +1,4 @@
use crate::field_types::Field64;
use crate::field_types::PrimeField64;
/// Generates a series of non-negative integers less than `modulus` which cover a range of
/// interesting test values.
@ -19,7 +19,7 @@ pub fn test_inputs(modulus: u64) -> Vec<u64> {
/// word_bits)` and panic if the two resulting vectors differ.
pub fn run_unaryop_test_cases<F, UnaryOp, ExpectedOp>(op: UnaryOp, expected_op: ExpectedOp)
where
F: Field64,
F: PrimeField64,
UnaryOp: Fn(F) -> F,
ExpectedOp: Fn(u64) -> u64,
{
@ -43,7 +43,7 @@ where
/// Apply the binary functions `op` and `expected_op` to each pair of inputs.
pub fn run_binaryop_test_cases<F, BinaryOp, ExpectedOp>(op: BinaryOp, expected_op: ExpectedOp)
where
F: Field64,
F: PrimeField64,
BinaryOp: Fn(F, F) -> F,
ExpectedOp: Fn(u64, u64) -> u64,
{

View File

@ -10,7 +10,7 @@ use num::{Integer, One};
use rand::Rng;
use serde::{Deserialize, Serialize};
use crate::field_types::Field;
use crate::field_types::{Field, PrimeField};
/// The base field of the secp256k1 elliptic curve.
///
@ -42,7 +42,7 @@ impl Default for Secp256K1Base {
impl PartialEq for Secp256K1Base {
fn eq(&self, other: &Self) -> bool {
self.to_biguint() == other.to_biguint()
self.to_canonical_biguint() == other.to_canonical_biguint()
}
}
@ -50,19 +50,19 @@ impl Eq for Secp256K1Base {}
impl Hash for Secp256K1Base {
fn hash<H: Hasher>(&self, state: &mut H) {
self.to_biguint().hash(state)
self.to_canonical_biguint().hash(state)
}
}
impl Display for Secp256K1Base {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.to_biguint(), f)
Display::fmt(&self.to_canonical_biguint(), f)
}
}
impl Debug for Secp256K1Base {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.to_biguint(), f)
Debug::fmt(&self.to_canonical_biguint(), f)
}
}
@ -107,14 +107,6 @@ impl Field for Secp256K1Base {
Some(self.exp_biguint(&(Self::order() - BigUint::one() - BigUint::one())))
}
fn to_biguint(&self) -> BigUint {
let mut result = biguint_from_array(self.0);
if result >= Self::order() {
result -= Self::order();
}
result
}
fn from_biguint(val: BigUint) -> Self {
Self(
val.to_u64_digits()
@ -146,6 +138,16 @@ impl Field for Secp256K1Base {
}
}
impl PrimeField for Secp256K1Base {
fn to_canonical_biguint(&self) -> BigUint {
let mut result = biguint_from_array(self.0);
if result >= Self::order() {
result -= Self::order();
}
result
}
}
impl Neg for Secp256K1Base {
type Output = Self;
@ -154,7 +156,7 @@ impl Neg for Secp256K1Base {
if self.is_zero() {
Self::ZERO
} else {
Self::from_biguint(Self::order() - self.to_biguint())
Self::from_biguint(Self::order() - self.to_canonical_biguint())
}
}
}
@ -164,7 +166,7 @@ impl Add for Secp256K1Base {
#[inline]
fn add(self, rhs: Self) -> Self {
let mut result = self.to_biguint() + rhs.to_biguint();
let mut result = self.to_canonical_biguint() + rhs.to_canonical_biguint();
if result >= Self::order() {
result -= Self::order();
}
@ -207,7 +209,9 @@ impl Mul for Secp256K1Base {
#[inline]
fn mul(self, rhs: Self) -> Self {
Self::from_biguint((self.to_biguint() * rhs.to_biguint()).mod_floor(&Self::order()))
Self::from_biguint(
(self.to_canonical_biguint() * rhs.to_canonical_biguint()).mod_floor(&Self::order()),
)
}
}

View File

@ -11,7 +11,7 @@ use num::{Integer, One};
use rand::Rng;
use serde::{Deserialize, Serialize};
use crate::field_types::Field;
use crate::field_types::{Field, PrimeField};
/// The base field of the secp256k1 elliptic curve.
///
@ -45,7 +45,7 @@ impl Default for Secp256K1Scalar {
impl PartialEq for Secp256K1Scalar {
fn eq(&self, other: &Self) -> bool {
self.to_biguint() == other.to_biguint()
self.to_canonical_biguint() == other.to_canonical_biguint()
}
}
@ -53,19 +53,19 @@ impl Eq for Secp256K1Scalar {}
impl Hash for Secp256K1Scalar {
fn hash<H: Hasher>(&self, state: &mut H) {
self.to_biguint().hash(state)
self.to_canonical_biguint().hash(state)
}
}
impl Display for Secp256K1Scalar {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.to_biguint(), f)
Display::fmt(&self.to_canonical_biguint(), f)
}
}
impl Debug for Secp256K1Scalar {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.to_biguint(), f)
Debug::fmt(&self.to_canonical_biguint(), f)
}
}
@ -116,14 +116,6 @@ impl Field for Secp256K1Scalar {
Some(self.exp_biguint(&(Self::order() - BigUint::one() - BigUint::one())))
}
fn to_biguint(&self) -> BigUint {
let mut result = biguint_from_array(self.0);
if result >= Self::order() {
result -= Self::order();
}
result
}
fn from_biguint(val: BigUint) -> Self {
Self(
val.to_u64_digits()
@ -155,6 +147,16 @@ impl Field for Secp256K1Scalar {
}
}
impl PrimeField for Secp256K1Scalar {
fn to_canonical_biguint(&self) -> BigUint {
let mut result = biguint_from_array(self.0);
if result >= Self::order() {
result -= Self::order();
}
result
}
}
impl Neg for Secp256K1Scalar {
type Output = Self;
@ -163,7 +165,7 @@ impl Neg for Secp256K1Scalar {
if self.is_zero() {
Self::ZERO
} else {
Self::from_biguint(Self::order() - self.to_biguint())
Self::from_biguint(Self::order() - self.to_canonical_biguint())
}
}
}
@ -173,7 +175,7 @@ impl Add for Secp256K1Scalar {
#[inline]
fn add(self, rhs: Self) -> Self {
let mut result = self.to_biguint() + rhs.to_biguint();
let mut result = self.to_canonical_biguint() + rhs.to_canonical_biguint();
if result >= Self::order() {
result -= Self::order();
}
@ -216,7 +218,9 @@ impl Mul for Secp256K1Scalar {
#[inline]
fn mul(self, rhs: Self) -> Self {
Self::from_biguint((self.to_biguint() * rhs.to_biguint()).mod_floor(&Self::order()))
Self::from_biguint(
(self.to_canonical_biguint() * rhs.to_canonical_biguint()).mod_floor(&Self::order()),
)
}
}

View File

@ -1,5 +1,6 @@
use itertools::Itertools;
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField;
use rayon::prelude::*;
use crate::curve::curve_summation::affine_multisummation_best;
@ -160,7 +161,7 @@ pub(crate) fn to_digits<C: Curve>(x: &C::ScalarField, w: usize) -> Vec<usize> {
// Convert x to a bool array.
let x_canonical: Vec<_> = x
.to_biguint()
.to_canonical_biguint()
.to_u64_digits()
.iter()
.cloned()
@ -187,6 +188,7 @@ pub(crate) fn to_digits<C: Curve>(x: &C::ScalarField, w: usize) -> Vec<usize> {
mod tests {
use num::BigUint;
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField;
use plonky2_field::secp256k1_scalar::Secp256K1Scalar;
use crate::curve::curve_msm::{msm_execute, msm_precompute, to_digits};
@ -206,7 +208,7 @@ mod tests {
0b11111111111111111111111111111111,
];
let x = Secp256K1Scalar::from_biguint(BigUint::from_slice(&x_canonical));
assert_eq!(x.to_biguint().to_u32_digits(), x_canonical);
assert_eq!(x.to_canonical_biguint().to_u32_digits(), x_canonical);
assert_eq!(
to_digits::<Secp256K1>(&x, 17),
vec![

View File

@ -1,6 +1,7 @@
use std::ops::Mul;
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField;
use crate::curve::curve_types::{Curve, CurveScalar, ProjectivePoint};
@ -88,7 +89,7 @@ fn to_digits<C: Curve>(x: &C::ScalarField) -> Vec<u64> {
);
let digits_per_u64 = 64 / WINDOW_BITS;
let mut digits = Vec::with_capacity(digits_per_scalar::<C>());
for limb in x.to_biguint().to_u64_digits() {
for limb in x.to_canonical_biguint().to_u64_digits() {
for j in 0..digits_per_u64 {
digits.push((limb >> (j * WINDOW_BITS) as u64) % BASE as u64);
}

View File

@ -1,7 +1,7 @@
use std::fmt::Debug;
use std::ops::Neg;
use plonky2_field::field_types::Field;
use plonky2_field::field_types::{Field, PrimeField};
use plonky2_field::ops::Square;
// To avoid implementation conflicts from associated types,
@ -10,8 +10,8 @@ pub struct CurveScalar<C: Curve>(pub <C as Curve>::ScalarField);
/// A short Weierstrass curve.
pub trait Curve: 'static + Sync + Sized + Copy + Debug {
type BaseField: Field;
type ScalarField: Field;
type BaseField: PrimeField;
type ScalarField: PrimeField;
const A: Self::BaseField;
const B: Self::BaseField;
@ -261,9 +261,9 @@ impl<C: Curve> Neg for ProjectivePoint<C> {
}
pub fn base_to_scalar<C: Curve>(x: C::BaseField) -> C::ScalarField {
C::ScalarField::from_biguint(x.to_biguint())
C::ScalarField::from_biguint(x.to_canonical_biguint())
}
pub fn scalar_to_base<C: Curve>(x: C::ScalarField) -> C::BaseField {
C::BaseField::from_biguint(x.to_biguint())
C::BaseField::from_biguint(x.to_canonical_biguint())
}

View File

@ -40,6 +40,7 @@ const SECP256K1_GENERATOR_Y: Secp256K1Base = Secp256K1Base([
mod tests {
use num::BigUint;
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField;
use plonky2_field::secp256k1_scalar::Secp256K1Scalar;
use crate::curve::curve_types::{AffinePoint, Curve, ProjectivePoint};
@ -86,7 +87,7 @@ mod tests {
) -> ProjectivePoint<Secp256K1> {
let mut g = rhs;
let mut sum = ProjectivePoint::ZERO;
for limb in lhs.to_biguint().to_u64_digits().iter() {
for limb in lhs.to_canonical_biguint().to_u64_digits().iter() {
for j in 0..64 {
if (limb >> j & 1u64) != 0u64 {
sum = sum + g;

View File

@ -1,6 +1,7 @@
use std::marker::PhantomData;
use num::{BigUint, Integer, One, Zero};
use plonky2_field::field_types::PrimeField;
use plonky2_field::{extension_field::Extendable, field_types::Field};
use plonky2_util::ceil_div_usize;
@ -34,12 +35,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
x.value.clone()
}
pub fn constant_nonnative<FF: Field>(&mut self, x: FF) -> NonNativeTarget<FF> {
let x_biguint = self.constant_biguint(&x.to_biguint());
pub fn constant_nonnative<FF: PrimeField>(&mut self, x: FF) -> NonNativeTarget<FF> {
let x_biguint = self.constant_biguint(&x.to_canonical_biguint());
self.biguint_to_nonnative(&x_biguint)
}
pub fn zero_nonnative<FF: Field>(&mut self) -> NonNativeTarget<FF> {
pub fn zero_nonnative<FF: PrimeField>(&mut self) -> NonNativeTarget<FF> {
self.constant_nonnative(FF::ZERO)
}
@ -62,7 +63,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
pub fn add_nonnative<FF: Field>(
pub fn add_nonnative<FF: PrimeField>(
&mut self,
a: &NonNativeTarget<FF>,
b: &NonNativeTarget<FF>,
@ -105,7 +106,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
pub fn add_many_nonnative<FF: Field>(
pub fn add_many_nonnative<FF: PrimeField>(
&mut self,
to_add: &[NonNativeTarget<FF>],
) -> NonNativeTarget<FF> {
@ -149,7 +150,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
// Subtract two `NonNativeTarget`s.
pub fn sub_nonnative<FF: Field>(
pub fn sub_nonnative<FF: PrimeField>(
&mut self,
a: &NonNativeTarget<FF>,
b: &NonNativeTarget<FF>,
@ -177,7 +178,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
diff
}
pub fn mul_nonnative<FF: Field>(
pub fn mul_nonnative<FF: PrimeField>(
&mut self,
a: &NonNativeTarget<FF>,
b: &NonNativeTarget<FF>,
@ -208,7 +209,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
prod
}
pub fn mul_many_nonnative<FF: Field>(
pub fn mul_many_nonnative<FF: PrimeField>(
&mut self,
to_mul: &[NonNativeTarget<FF>],
) -> NonNativeTarget<FF> {
@ -223,14 +224,20 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
accumulator
}
pub fn neg_nonnative<FF: Field>(&mut self, x: &NonNativeTarget<FF>) -> NonNativeTarget<FF> {
pub fn neg_nonnative<FF: PrimeField>(
&mut self,
x: &NonNativeTarget<FF>,
) -> NonNativeTarget<FF> {
let zero_target = self.constant_biguint(&BigUint::zero());
let zero_ff = self.biguint_to_nonnative(&zero_target);
self.sub_nonnative(&zero_ff, x)
}
pub fn inv_nonnative<FF: Field>(&mut self, x: &NonNativeTarget<FF>) -> NonNativeTarget<FF> {
pub fn inv_nonnative<FF: PrimeField>(
&mut self,
x: &NonNativeTarget<FF>,
) -> NonNativeTarget<FF> {
let num_limbs = x.value.num_limbs();
let inv_biguint = self.add_virtual_biguint_target(num_limbs);
let div = self.add_virtual_biguint_target(num_limbs);
@ -307,7 +314,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
#[derive(Debug)]
struct NonNativeAdditionGenerator<F: RichField + Extendable<D>, const D: usize, FF: Field> {
struct NonNativeAdditionGenerator<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> {
a: NonNativeTarget<FF>,
b: NonNativeTarget<FF>,
sum: NonNativeTarget<FF>,
@ -315,7 +322,7 @@ struct NonNativeAdditionGenerator<F: RichField + Extendable<D>, const D: usize,
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F>
for NonNativeAdditionGenerator<F, D, FF>
{
fn dependencies(&self) -> Vec<Target> {
@ -332,8 +339,8 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let a = witness.get_nonnative_target(self.a.clone());
let b = witness.get_nonnative_target(self.b.clone());
let a_biguint = a.to_biguint();
let b_biguint = b.to_biguint();
let a_biguint = a.to_canonical_biguint();
let b_biguint = b.to_canonical_biguint();
let sum_biguint = a_biguint + b_biguint;
let modulus = FF::order();
let (overflow, sum_reduced) = if sum_biguint > modulus {
@ -348,14 +355,15 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
}
#[derive(Debug)]
struct NonNativeMultipleAddsGenerator<F: RichField + Extendable<D>, const D: usize, FF: Field> {
struct NonNativeMultipleAddsGenerator<F: RichField + Extendable<D>, const D: usize, FF: PrimeField>
{
summands: Vec<NonNativeTarget<FF>>,
sum: NonNativeTarget<FF>,
overflow: U32Target,
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F>
for NonNativeMultipleAddsGenerator<F, D, FF>
{
fn dependencies(&self) -> Vec<Target> {
@ -373,7 +381,7 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
.collect();
let summand_biguints: Vec<_> = summands
.iter()
.map(|summand| summand.to_biguint())
.map(|summand| summand.to_canonical_biguint())
.collect();
let sum_biguint = summand_biguints
@ -398,7 +406,7 @@ struct NonNativeSubtractionGenerator<F: RichField + Extendable<D>, const D: usiz
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F>
for NonNativeSubtractionGenerator<F, D, FF>
{
fn dependencies(&self) -> Vec<Target> {
@ -415,8 +423,8 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let a = witness.get_nonnative_target(self.a.clone());
let b = witness.get_nonnative_target(self.b.clone());
let a_biguint = a.to_biguint();
let b_biguint = b.to_biguint();
let a_biguint = a.to_canonical_biguint();
let b_biguint = b.to_canonical_biguint();
let modulus = FF::order();
let (diff_biguint, overflow) = if a_biguint > b_biguint {
@ -439,7 +447,7 @@ struct NonNativeMultiplicationGenerator<F: RichField + Extendable<D>, const D: u
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F>
for NonNativeMultiplicationGenerator<F, D, FF>
{
fn dependencies(&self) -> Vec<Target> {
@ -456,8 +464,8 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let a = witness.get_nonnative_target(self.a.clone());
let b = witness.get_nonnative_target(self.b.clone());
let a_biguint = a.to_biguint();
let b_biguint = b.to_biguint();
let a_biguint = a.to_canonical_biguint();
let b_biguint = b.to_canonical_biguint();
let prod_biguint = a_biguint * b_biguint;
@ -470,14 +478,14 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
}
#[derive(Debug)]
struct NonNativeInverseGenerator<F: RichField + Extendable<D>, const D: usize, FF: Field> {
struct NonNativeInverseGenerator<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> {
x: NonNativeTarget<FF>,
inv: BigUintTarget,
div: BigUintTarget,
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerator<F>
for NonNativeInverseGenerator<F, D, FF>
{
fn dependencies(&self) -> Vec<Target> {
@ -488,8 +496,8 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
let x = witness.get_nonnative_target(self.x.clone());
let inv = x.inverse();
let x_biguint = x.to_biguint();
let inv_biguint = inv.to_biguint();
let x_biguint = x.to_canonical_biguint();
let inv_biguint = inv.to_canonical_biguint();
let prod = x_biguint * &inv_biguint;
let modulus = FF::order();
let (div, _rem) = prod.div_rem(&modulus);
@ -502,7 +510,7 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: Field> SimpleGenerator<F>
#[cfg(test)]
mod tests {
use anyhow::Result;
use plonky2_field::field_types::Field;
use plonky2_field::field_types::{Field, PrimeField};
use plonky2_field::secp256k1_base::Secp256K1Base;
use crate::iop::witness::PartialWitness;
@ -587,7 +595,7 @@ mod tests {
let x_ff = FF::rand();
let mut y_ff = FF::rand();
while y_ff.to_biguint() > x_ff.to_biguint() {
while y_ff.to_canonical_biguint() > x_ff.to_canonical_biguint() {
y_ff = FF::rand();
}
let diff_ff = x_ff - y_ff;

View File

@ -455,7 +455,8 @@ mod tests {
use anyhow::Result;
use plonky2_field::extension_field::quartic::QuarticExtension;
use plonky2_field::field_types::{Field, Field64};
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField64;
use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;

View File

@ -520,7 +520,8 @@ mod tests {
use std::marker::PhantomData;
use anyhow::Result;
use plonky2_field::field_types::{Field, Field64};
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField64;
use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;

View File

@ -338,7 +338,8 @@ mod tests {
use anyhow::Result;
use plonky2_field::extension_field::quartic::QuarticExtension;
use plonky2_field::field_types::{Field, Field64};
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField64;
use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;

View File

@ -1,4 +1,4 @@
use plonky2_field::field_types::{Field, Field64};
use plonky2_field::field_types::{Field, PrimeField64};
use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
@ -8,7 +8,7 @@ use crate::iop::target::Target;
use crate::plonk::config::GenericHashOut;
/// A prime order field with the features we need to use it as a base field in our argument system.
pub trait RichField: Field64 + Poseidon {}
pub trait RichField: PrimeField64 + Poseidon {}
impl RichField for GoldilocksField {}

View File

@ -2,7 +2,7 @@
//! https://eprint.iacr.org/2019/458.pdf
use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::field_types::{Field, Field64};
use plonky2_field::field_types::{Field, PrimeField64};
use unroll::unroll_for_loops;
use crate::gates::gate::Gate;
@ -35,7 +35,7 @@ fn add_u160_u128((x_lo, x_hi): (u128, u32), y: u128) -> (u128, u32) {
}
#[inline(always)]
fn reduce_u160<F: Field64>((n_lo, n_hi): (u128, u32)) -> F {
fn reduce_u160<F: PrimeField64>((n_lo, n_hi): (u128, u32)) -> F {
let n_lo_hi = (n_lo >> 64) as u64;
let n_lo_lo = n_lo as u64;
let reduced_hi: u64 = F::from_noncanonical_u96((n_lo_hi, n_hi)).to_noncanonical_u64();
@ -148,7 +148,7 @@ pub const ALL_ROUND_CONSTANTS: [u64; MAX_WIDTH * N_ROUNDS] = [
];
const WIDTH: usize = SPONGE_WIDTH;
pub trait Poseidon: Field64 {
pub trait Poseidon: PrimeField64 {
// Total number of round constants required: width of the input
// times number of rounds.
const N_ROUND_CONSTANTS: usize = WIDTH * N_ROUNDS;

View File

@ -270,7 +270,8 @@ impl Poseidon for GoldilocksField {
#[cfg(test)]
mod tests {
use plonky2_field::field_types::{Field, Field64};
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField64;
use plonky2_field::goldilocks_field::GoldilocksField as F;
use crate::hash::poseidon::test_helpers::{check_consistency, check_test_vectors};

View File

@ -3,7 +3,7 @@ use std::marker::PhantomData;
use num::BigUint;
use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::field_types::Field;
use plonky2_field::field_types::{Field, PrimeField};
use crate::gadgets::arithmetic_u32::U32Target;
use crate::gadgets::biguint::BigUintTarget;
@ -180,8 +180,8 @@ impl<F: Field> GeneratedValues<F> {
}
}
pub fn set_nonnative_target<FF: Field>(&mut self, target: NonNativeTarget<FF>, value: FF) {
self.set_biguint_target(target.value, value.to_biguint())
pub fn set_nonnative_target<FF: PrimeField>(&mut self, target: NonNativeTarget<FF>, value: FF) {
self.set_biguint_target(target.value, value.to_canonical_biguint())
}
pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut<F>) {

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use itertools::Itertools;
use num::{BigUint, FromPrimitive, Zero};
use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::field_types::Field;
use plonky2_field::field_types::{Field, PrimeField};
use crate::fri::witness_util::set_fri_proof_target;
use crate::gadgets::arithmetic_u32::U32Target;
@ -62,20 +62,26 @@ pub trait Witness<F: Field> {
panic!("not a bool")
}
fn get_biguint_target(&self, target: BigUintTarget) -> BigUint {
fn get_biguint_target(&self, target: BigUintTarget) -> BigUint
where
F: PrimeField,
{
let mut result = BigUint::zero();
let limb_base = BigUint::from_u64(1 << 32u64).unwrap();
for i in (0..target.num_limbs()).rev() {
let limb = target.get_limb(i);
result *= &limb_base;
result += self.get_target(limb.0).to_biguint();
result += self.get_target(limb.0).to_canonical_biguint();
}
result
}
fn get_nonnative_target<FF: Field>(&self, target: NonNativeTarget<FF>) -> FF {
fn get_nonnative_target<FF: PrimeField>(&self, target: NonNativeTarget<FF>) -> FF
where
F: PrimeField,
{
let val = self.get_biguint_target(target.value);
FF::from_biguint(val)
}

View File

@ -3,7 +3,7 @@ use std::io::Cursor;
use std::io::{Read, Result, Write};
use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::field_types::Field64;
use plonky2_field::field_types::{Field64, PrimeField64};
use plonky2_field::polynomial::PolynomialCoeffs;
use crate::fri::proof::{
@ -53,7 +53,7 @@ impl Buffer {
Ok(u32::from_le_bytes(buf))
}
fn write_field<F: Field64>(&mut self, x: F) -> Result<()> {
fn write_field<F: PrimeField64>(&mut self, x: F) -> Result<()> {
self.0.write_all(&x.to_canonical_u64().to_le_bytes())
}
fn read_field<F: Field64>(&mut self) -> Result<F> {
@ -116,7 +116,7 @@ impl Buffer {
))
}
pub fn write_field_vec<F: Field64>(&mut self, v: &[F]) -> Result<()> {
pub fn write_field_vec<F: PrimeField64>(&mut self, v: &[F]) -> Result<()> {
for &a in v {
self.write_field(a)?;
}

View File

@ -183,7 +183,7 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
#[cfg(test)]
mod tests {
use anyhow::Result;
use plonky2::field::field_types::{Field, Field64};
use plonky2::field::field_types::{Field, PrimeField64};
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};