mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-08 08:43:06 +00:00
Add PrimeField, PrimeField64 traits (#457)
* Add PrimeField, PrimeField64 traits * fix * fixes * fix * `to_biguint` -> `to_canonical_biguint`
This commit is contained in:
parent
fe89fa949e
commit
cfe52ad604
@ -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()
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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> {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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![
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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 {}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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};
|
||||
|
||||
@ -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>) {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)?;
|
||||
}
|
||||
|
||||
@ -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};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user