diff --git a/field/src/extension_field/quadratic.rs b/field/src/extension_field/quadratic.rs index e072d323..488304d2 100644 --- a/field/src/extension_field/quadratic.rs +++ b/field/src/extension_field/quadratic.rs @@ -95,10 +95,6 @@ impl> Field for QuadraticExtension { 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() } diff --git a/field/src/extension_field/quartic.rs b/field/src/extension_field/quartic.rs index 4e9cebf9..7b4a6950 100644 --- a/field/src/extension_field/quartic.rs +++ b/field/src/extension_field/quartic.rs @@ -107,14 +107,6 @@ impl> Field for QuarticExtension { ]) } - 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() } diff --git a/field/src/field_types.rs b/field/src/field_types.rs index 65d5bf21..95696475 100644 --- a/field/src/field_types.rs +++ b/field/src/field_types.rs @@ -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 { diff --git a/field/src/goldilocks_field.rs b/field/src/goldilocks_field.rs index a121b4d2..6c033bb2 100644 --- a/field/src/goldilocks_field.rs +++ b/field/src/goldilocks_field.rs @@ -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; diff --git a/field/src/inversion.rs b/field/src/inversion.rs index 10c02879..5eabc45c 100644 --- a/field/src/inversion.rs +++ b/field/src/inversion.rs @@ -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(x: &F) -> Option { +pub(crate) fn try_inverse_u64(x: &F) -> Option { let mut f = x.to_noncanonical_u64(); let mut g = F::ORDER; // NB: These two are very rarely such that their absolute diff --git a/field/src/prime_field_testing.rs b/field/src/prime_field_testing.rs index 772336e9..24d5e3c7 100644 --- a/field/src/prime_field_testing.rs +++ b/field/src/prime_field_testing.rs @@ -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 { /// word_bits)` and panic if the two resulting vectors differ. pub fn run_unaryop_test_cases(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(op: BinaryOp, expected_op: ExpectedOp) where - F: Field64, + F: PrimeField64, BinaryOp: Fn(F, F) -> F, ExpectedOp: Fn(u64, u64) -> u64, { diff --git a/field/src/secp256k1_base.rs b/field/src/secp256k1_base.rs index 23702420..1972aed7 100644 --- a/field/src/secp256k1_base.rs +++ b/field/src/secp256k1_base.rs @@ -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(&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()), + ) } } diff --git a/field/src/secp256k1_scalar.rs b/field/src/secp256k1_scalar.rs index f10892af..1e506426 100644 --- a/field/src/secp256k1_scalar.rs +++ b/field/src/secp256k1_scalar.rs @@ -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(&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()), + ) } } diff --git a/plonky2/src/curve/curve_msm.rs b/plonky2/src/curve/curve_msm.rs index 388c0321..4c274c1c 100644 --- a/plonky2/src/curve/curve_msm.rs +++ b/plonky2/src/curve/curve_msm.rs @@ -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(x: &C::ScalarField, w: usize) -> Vec { // 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(x: &C::ScalarField, w: usize) -> Vec { 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::(&x, 17), vec![ diff --git a/plonky2/src/curve/curve_multiplication.rs b/plonky2/src/curve/curve_multiplication.rs index 30da4973..c6fbbd83 100644 --- a/plonky2/src/curve/curve_multiplication.rs +++ b/plonky2/src/curve/curve_multiplication.rs @@ -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(x: &C::ScalarField) -> Vec { ); let digits_per_u64 = 64 / WINDOW_BITS; let mut digits = Vec::with_capacity(digits_per_scalar::()); - 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); } diff --git a/plonky2/src/curve/curve_types.rs b/plonky2/src/curve/curve_types.rs index 9599f6fe..0a9e8711 100644 --- a/plonky2/src/curve/curve_types.rs +++ b/plonky2/src/curve/curve_types.rs @@ -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(pub ::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 Neg for ProjectivePoint { } pub fn base_to_scalar(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(x: C::ScalarField) -> C::BaseField { - C::BaseField::from_biguint(x.to_biguint()) + C::BaseField::from_biguint(x.to_canonical_biguint()) } diff --git a/plonky2/src/curve/secp256k1.rs b/plonky2/src/curve/secp256k1.rs index d9039719..6a460735 100644 --- a/plonky2/src/curve/secp256k1.rs +++ b/plonky2/src/curve/secp256k1.rs @@ -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 { 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; diff --git a/plonky2/src/gadgets/nonnative.rs b/plonky2/src/gadgets/nonnative.rs index 245b0403..3f8d29e8 100644 --- a/plonky2/src/gadgets/nonnative.rs +++ b/plonky2/src/gadgets/nonnative.rs @@ -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, const D: usize> CircuitBuilder { x.value.clone() } - pub fn constant_nonnative(&mut self, x: FF) -> NonNativeTarget { - let x_biguint = self.constant_biguint(&x.to_biguint()); + pub fn constant_nonnative(&mut self, x: FF) -> NonNativeTarget { + let x_biguint = self.constant_biguint(&x.to_canonical_biguint()); self.biguint_to_nonnative(&x_biguint) } - pub fn zero_nonnative(&mut self) -> NonNativeTarget { + pub fn zero_nonnative(&mut self) -> NonNativeTarget { self.constant_nonnative(FF::ZERO) } @@ -62,7 +63,7 @@ impl, const D: usize> CircuitBuilder { } } - pub fn add_nonnative( + pub fn add_nonnative( &mut self, a: &NonNativeTarget, b: &NonNativeTarget, @@ -105,7 +106,7 @@ impl, const D: usize> CircuitBuilder { } } - pub fn add_many_nonnative( + pub fn add_many_nonnative( &mut self, to_add: &[NonNativeTarget], ) -> NonNativeTarget { @@ -149,7 +150,7 @@ impl, const D: usize> CircuitBuilder { } // Subtract two `NonNativeTarget`s. - pub fn sub_nonnative( + pub fn sub_nonnative( &mut self, a: &NonNativeTarget, b: &NonNativeTarget, @@ -177,7 +178,7 @@ impl, const D: usize> CircuitBuilder { diff } - pub fn mul_nonnative( + pub fn mul_nonnative( &mut self, a: &NonNativeTarget, b: &NonNativeTarget, @@ -208,7 +209,7 @@ impl, const D: usize> CircuitBuilder { prod } - pub fn mul_many_nonnative( + pub fn mul_many_nonnative( &mut self, to_mul: &[NonNativeTarget], ) -> NonNativeTarget { @@ -223,14 +224,20 @@ impl, const D: usize> CircuitBuilder { accumulator } - pub fn neg_nonnative(&mut self, x: &NonNativeTarget) -> NonNativeTarget { + pub fn neg_nonnative( + &mut self, + x: &NonNativeTarget, + ) -> NonNativeTarget { 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(&mut self, x: &NonNativeTarget) -> NonNativeTarget { + pub fn inv_nonnative( + &mut self, + x: &NonNativeTarget, + ) -> NonNativeTarget { 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, const D: usize> CircuitBuilder { } #[derive(Debug)] -struct NonNativeAdditionGenerator, const D: usize, FF: Field> { +struct NonNativeAdditionGenerator, const D: usize, FF: PrimeField> { a: NonNativeTarget, b: NonNativeTarget, sum: NonNativeTarget, @@ -315,7 +322,7 @@ struct NonNativeAdditionGenerator, const D: usize, _phantom: PhantomData, } -impl, const D: usize, FF: Field> SimpleGenerator +impl, const D: usize, FF: PrimeField> SimpleGenerator for NonNativeAdditionGenerator { fn dependencies(&self) -> Vec { @@ -332,8 +339,8 @@ impl, const D: usize, FF: Field> SimpleGenerator fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { 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, const D: usize, FF: Field> SimpleGenerator } #[derive(Debug)] -struct NonNativeMultipleAddsGenerator, const D: usize, FF: Field> { +struct NonNativeMultipleAddsGenerator, const D: usize, FF: PrimeField> +{ summands: Vec>, sum: NonNativeTarget, overflow: U32Target, _phantom: PhantomData, } -impl, const D: usize, FF: Field> SimpleGenerator +impl, const D: usize, FF: PrimeField> SimpleGenerator for NonNativeMultipleAddsGenerator { fn dependencies(&self) -> Vec { @@ -373,7 +381,7 @@ impl, const D: usize, FF: Field> SimpleGenerator .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, const D: usiz _phantom: PhantomData, } -impl, const D: usize, FF: Field> SimpleGenerator +impl, const D: usize, FF: PrimeField> SimpleGenerator for NonNativeSubtractionGenerator { fn dependencies(&self) -> Vec { @@ -415,8 +423,8 @@ impl, const D: usize, FF: Field> SimpleGenerator fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { 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, const D: u _phantom: PhantomData, } -impl, const D: usize, FF: Field> SimpleGenerator +impl, const D: usize, FF: PrimeField> SimpleGenerator for NonNativeMultiplicationGenerator { fn dependencies(&self) -> Vec { @@ -456,8 +464,8 @@ impl, const D: usize, FF: Field> SimpleGenerator fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { 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, const D: usize, FF: Field> SimpleGenerator } #[derive(Debug)] -struct NonNativeInverseGenerator, const D: usize, FF: Field> { +struct NonNativeInverseGenerator, const D: usize, FF: PrimeField> { x: NonNativeTarget, inv: BigUintTarget, div: BigUintTarget, _phantom: PhantomData, } -impl, const D: usize, FF: Field> SimpleGenerator +impl, const D: usize, FF: PrimeField> SimpleGenerator for NonNativeInverseGenerator { fn dependencies(&self) -> Vec { @@ -488,8 +496,8 @@ impl, const D: usize, FF: Field> SimpleGenerator 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, const D: usize, FF: Field> SimpleGenerator #[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; diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index c087a963..cec7274b 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -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; diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index bc3e69b9..b1cf7b98 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -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; diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index 80bc03ed..b1e4d84f 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -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; diff --git a/plonky2/src/hash/hash_types.rs b/plonky2/src/hash/hash_types.rs index ed6fca43..0a1cedd0 100644 --- a/plonky2/src/hash/hash_types.rs +++ b/plonky2/src/hash/hash_types.rs @@ -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 {} diff --git a/plonky2/src/hash/poseidon.rs b/plonky2/src/hash/poseidon.rs index 08c2851a..09c5d2fc 100644 --- a/plonky2/src/hash/poseidon.rs +++ b/plonky2/src/hash/poseidon.rs @@ -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((n_lo, n_hi): (u128, u32)) -> F { +fn reduce_u160((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; diff --git a/plonky2/src/hash/poseidon_goldilocks.rs b/plonky2/src/hash/poseidon_goldilocks.rs index ab886847..7b82bb01 100644 --- a/plonky2/src/hash/poseidon_goldilocks.rs +++ b/plonky2/src/hash/poseidon_goldilocks.rs @@ -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}; diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index 73978f5c..1569e889 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -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 GeneratedValues { } } - pub fn set_nonnative_target(&mut self, target: NonNativeTarget, value: FF) { - self.set_biguint_target(target.value, value.to_biguint()) + pub fn set_nonnative_target(&mut self, target: NonNativeTarget, value: FF) { + self.set_biguint_target(target.value, value.to_canonical_biguint()) } pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { diff --git a/plonky2/src/iop/witness.rs b/plonky2/src/iop/witness.rs index 43dc752d..e1bdf06e 100644 --- a/plonky2/src/iop/witness.rs +++ b/plonky2/src/iop/witness.rs @@ -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 { 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(&self, target: NonNativeTarget) -> FF { + fn get_nonnative_target(&self, target: NonNativeTarget) -> FF + where + F: PrimeField, + { let val = self.get_biguint_target(target.value); FF::from_biguint(val) } diff --git a/plonky2/src/util/serialization.rs b/plonky2/src/util/serialization.rs index adc8baee..d0326073 100644 --- a/plonky2/src/util/serialization.rs +++ b/plonky2/src/util/serialization.rs @@ -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(&mut self, x: F) -> Result<()> { + fn write_field(&mut self, x: F) -> Result<()> { self.0.write_all(&x.to_canonical_u64().to_le_bytes()) } fn read_field(&mut self) -> Result { @@ -116,7 +116,7 @@ impl Buffer { )) } - pub fn write_field_vec(&mut self, v: &[F]) -> Result<()> { + pub fn write_field_vec(&mut self, v: &[F]) -> Result<()> { for &a in v { self.write_field(a)?; } diff --git a/waksman/src/sorting.rs b/waksman/src/sorting.rs index b154436e..286205b1 100644 --- a/waksman/src/sorting.rs +++ b/waksman/src/sorting.rs @@ -183,7 +183,7 @@ impl, const D: usize> SimpleGenerator #[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};