Move some Field members to a Field64 subtrait (#213)

* Move some Field members to a Field64 subtrait

I.e. move anything specific to 64-bit fields.

Also, relatedly,
- Tweak a bunch of prover code to require `Field64`, since 64-bit stuff is used in a couple places, like the FRI proof-of-work
- Remove `bits()`, which was unused and assumed a 64-bit field
- Rename a couple methods to reflect that they're u64 variants

There are no functional changes.

* Field64 -> PrimeField

* Remove `exp_u32`, `kth_root_u32`

* PrimeField: PrimeField

* Move `to_canonical_biguint` as well

* Add back from_noncanonical_u128
This commit is contained in:
Daniel Lubarov 2021-09-05 10:27:11 -07:00 committed by GitHub
parent ba4b03e487
commit 236a143abf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 317 additions and 339 deletions

View File

@ -3,7 +3,7 @@ use env_logger::Env;
use log::info;
use plonky2::field::crandall_field::CrandallField;
use plonky2::field::extension_field::Extendable;
use plonky2::field::field_types::Field;
use plonky2::field::field_types::PrimeField;
use plonky2::fri::FriConfig;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
@ -19,7 +19,7 @@ fn main() -> Result<()> {
bench_prove::<CrandallField, 4>()
}
fn bench_prove<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
fn bench_prove<F: PrimeField + Extendable<D>, const D: usize>() -> Result<()> {
let config = CircuitConfig {
num_wires: 126,
num_routed_wires: 33,

View File

@ -12,9 +12,7 @@ use serde::{Deserialize, Serialize};
use crate::field::extension_field::quadratic::QuadraticCrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::{Extendable, Frobenius};
use crate::field::field_types::Field;
const FIELD_ORDER: u64 = 18446744071293632513;
use crate::field::field_types::{Field, PrimeField};
/// EPSILON = 9 * 2**28 - 1
const EPSILON: u64 = 2415919103;
@ -152,16 +150,16 @@ impl Field for CrandallField {
const ZERO: Self = Self(0);
const ONE: Self = Self(1);
const TWO: Self = Self(2);
const NEG_ONE: Self = Self(FIELD_ORDER - 1);
const NEG_ONE: Self = Self(Self::ORDER - 1);
const CHARACTERISTIC: u64 = FIELD_ORDER;
const CHARACTERISTIC: u64 = Self::ORDER;
const TWO_ADICITY: usize = 28;
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self(5);
const POWER_OF_TWO_GENERATOR: Self = Self(10281950781551402419);
fn order() -> BigUint {
BigUint::from(FIELD_ORDER)
BigUint::from(Self::ORDER)
}
#[inline]
@ -183,7 +181,7 @@ impl Field for CrandallField {
// Based on Algorithm 16 of "Efficient Software-Implementation of Finite Fields with
// Applications to Cryptography".
let p = FIELD_ORDER;
let p = Self::ORDER;
let mut u = self.to_canonical_u64();
let mut v = p;
let mut b = 1u64;
@ -240,18 +238,12 @@ impl Field for CrandallField {
}
#[inline]
fn to_noncanonical_u64(&self) -> u64 {
self.0
fn from_canonical_u64(n: u64) -> Self {
Self(n)
}
#[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 >= FIELD_ORDER {
c -= FIELD_ORDER;
}
c
fn from_canonical_biguint(n: BigUint) -> Self {
Self(n.iter_u64_digits().next().unwrap_or(0))
}
#[inline]
@ -259,21 +251,8 @@ impl Field for CrandallField {
reduce128(n)
}
#[inline]
fn from_canonical_u64(n: u64) -> Self {
Self(n)
}
fn to_canonical_biguint(&self) -> BigUint {
BigUint::from(self.to_canonical_u64())
}
fn from_canonical_biguint(n: BigUint) -> Self {
Self(n.iter_u64_digits().next().unwrap_or(0))
}
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
Self::from_canonical_u64(rng.gen_range(0..FIELD_ORDER))
Self::from_canonical_u64(rng.gen_range(0..Self::ORDER))
}
fn cube_root(&self) -> Self {
@ -365,6 +344,29 @@ impl Field for CrandallField {
}
}
impl PrimeField for CrandallField {
const ORDER: u64 = 18446744071293632513;
#[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
}
#[inline]
fn to_noncanonical_u64(&self) -> u64 {
self.0
}
fn to_canonical_biguint(&self) -> BigUint {
BigUint::from(self.to_canonical_u64())
}
}
impl Neg for CrandallField {
type Output = Self;
@ -373,7 +375,7 @@ impl Neg for CrandallField {
if self.is_zero() {
Self::ZERO
} else {
Self(FIELD_ORDER - self.to_canonical_u64())
Self(Self::ORDER - self.to_canonical_u64())
}
}
}
@ -385,7 +387,7 @@ impl Add for CrandallField {
#[allow(clippy::suspicious_arithmetic_impl)]
fn add(self, rhs: Self) -> Self {
let (sum, over) = self.0.overflowing_add(rhs.to_canonical_u64());
Self(sum.overflowing_sub((over as u64) * FIELD_ORDER).0)
Self(sum.overflowing_sub((over as u64) * Self::ORDER).0)
}
}
@ -408,7 +410,7 @@ impl Sub for CrandallField {
#[allow(clippy::suspicious_arithmetic_impl)]
fn sub(self, rhs: Self) -> Self {
let (diff, under) = self.0.overflowing_sub(rhs.to_canonical_u64());
Self(diff.overflowing_add((under as u64) * FIELD_ORDER).0)
Self(diff.overflowing_add((under as u64) * Self::ORDER).0)
}
}
@ -464,7 +466,7 @@ impl Extendable<4> for CrandallField {
type Extension = QuarticCrandallField;
}
/// Faster addition for when we know that lhs.0 + rhs.0 < 2^64 + FIELD_ORDER. If this is the case,
/// Faster addition for when we know that lhs.0 + rhs.0 < 2^64 + Self::ORDER. If this is the case,
/// then the .to_canonical_u64() that addition usually performs is unnecessary. Omitting it saves
/// three instructions.
/// This function is marked unsafe because it may yield incorrect result if the condition is not
@ -472,7 +474,7 @@ impl Extendable<4> for CrandallField {
#[inline]
unsafe fn add_no_canonicalize(lhs: CrandallField, rhs: CrandallField) -> CrandallField {
let (sum, over) = lhs.0.overflowing_add(rhs.0);
CrandallField(sum.overflowing_sub((over as u64) * FIELD_ORDER).0)
CrandallField(sum.overflowing_sub((over as u64) * CrandallField::ORDER).0)
}
/// Reduces to a 64-bit value. The result might not be in canonical form; it could be in between the
@ -489,8 +491,8 @@ fn reduce128(x: u128) -> CrandallField {
let lo_3 = hi_2 * EPSILON;
unsafe {
// This is safe to do because lo_2 + lo_3 < 2^64 + FIELD_ORDER. Notice that hi_2 <=
// 2^32 - 1. Then lo_3 = hi_2 * EPSILON <= (2^32 - 1) * EPSILON < FIELD_ORDER.
// This is safe to do because lo_2 + lo_3 < 2^64 + Self::ORDER. Notice that hi_2 <=
// 2^32 - 1. Then lo_3 = hi_2 * EPSILON <= (2^32 - 1) * EPSILON < Self::ORDER.
// Use of standard addition here would make multiplication 20% more expensive.
add_no_canonicalize(CrandallField(lo_2), CrandallField(lo_3))
}

View File

@ -89,31 +89,10 @@ impl Field for QuadraticCrandallField {
))
}
fn to_canonical_u64(&self) -> u64 {
//panic!("Can't convert extension field element to a u64.");
self.0[0].to_canonical_u64()
}
fn to_noncanonical_u64(&self) -> u64 {
panic!("Can't convert extension field element to a u64.");
}
fn from_noncanonical_u128(n: u128) -> Self {
<Self as FieldExtension<2>>::BaseField::from_noncanonical_u128(n).into()
}
fn from_canonical_u64(n: u64) -> Self {
<Self as FieldExtension<2>>::BaseField::from_canonical_u64(n).into()
}
fn to_canonical_biguint(&self) -> BigUint {
let first = self.0[0].to_canonical_biguint();
let second = self.0[1].to_canonical_biguint();
let combined = second * Self::CHARACTERISTIC + first;
combined
}
fn from_canonical_biguint(n: BigUint) -> Self {
let smaller = n.clone() % Self::CHARACTERISTIC;
let larger = n.clone() / Self::CHARACTERISTIC;
@ -124,6 +103,10 @@ impl Field for QuadraticCrandallField {
])
}
fn from_noncanonical_u128(n: u128) -> Self {
<Self as FieldExtension<2>>::BaseField::from_noncanonical_u128(n).into()
}
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
Self([
<Self as FieldExtension<2>>::BaseField::rand_from_rng(rng),
@ -288,7 +271,8 @@ mod tests {
type F = QuadraticCrandallField;
let x = F::rand();
assert_eq!(
x.exp(18446744071293632512).exp(18446744071293632514),
x.exp_u64(18446744071293632512)
.exp_u64(18446744071293632514),
F::ONE
);
}
@ -299,13 +283,13 @@ mod tests {
// F::order() = 2^29 * 2762315674048163 * 229454332791453 + 1
assert_eq!(
F::MULTIPLICATIVE_GROUP_GENERATOR
.exp(2762315674048163)
.exp(229454332791453),
.exp_u64(2762315674048163)
.exp_u64(229454332791453),
F::POWER_OF_TWO_GENERATOR
);
assert_eq!(
F::POWER_OF_TWO_GENERATOR
.exp(1 << (F::TWO_ADICITY - <F as FieldExtension<2>>::BaseField::TWO_ADICITY)),
.exp_u64(1 << (F::TWO_ADICITY - <F as FieldExtension<2>>::BaseField::TWO_ADICITY)),
<F as FieldExtension<2>>::BaseField::POWER_OF_TWO_GENERATOR.into()
);
}

View File

@ -122,40 +122,10 @@ impl Field for QuarticCrandallField {
))
}
fn to_canonical_u64(&self) -> u64 {
//panic!("Can't convert extension field element to a u64.");
self.0[0].to_canonical_u64()
}
fn to_noncanonical_u64(&self) -> u64 {
panic!("Can't convert extension field element to a u64.");
}
fn from_noncanonical_u128(n: u128) -> Self {
<Self as FieldExtension<4>>::BaseField::from_noncanonical_u128(n).into()
}
fn from_canonical_u64(n: u64) -> Self {
<Self as FieldExtension<4>>::BaseField::from_canonical_u64(n).into()
}
fn to_canonical_biguint(&self) -> BigUint {
let first = self.0[0].to_canonical_biguint();
let second = self.0[1].to_canonical_biguint();
let third = self.0[2].to_canonical_biguint();
let fourth = self.0[3].to_canonical_biguint();
let mut combined = fourth;
combined *= Self::CHARACTERISTIC;
combined += third;
combined *= Self::CHARACTERISTIC;
combined += second;
combined *= Self::CHARACTERISTIC;
combined += first;
combined
}
fn from_canonical_biguint(n: BigUint) -> Self {
let first = &n % Self::CHARACTERISTIC;
let mut remaining = &n / Self::CHARACTERISTIC;
@ -173,6 +143,10 @@ impl Field for QuarticCrandallField {
])
}
fn from_noncanonical_u128(n: u128) -> Self {
<Self as FieldExtension<4>>::BaseField::from_noncanonical_u128(n).into()
}
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
Self([
<Self as FieldExtension<4>>::BaseField::rand_from_rng(rng),
@ -399,7 +373,7 @@ mod tests {
);
assert_eq!(
F::POWER_OF_TWO_GENERATOR
.exp(1 << (F::TWO_ADICITY - <F as FieldExtension<4>>::BaseField::TWO_ADICITY)),
.exp_u64(1 << (F::TWO_ADICITY - <F as FieldExtension<4>>::BaseField::TWO_ADICITY)),
<F as FieldExtension<4>>::BaseField::POWER_OF_TWO_GENERATOR.into()
);
}

View File

@ -3,7 +3,7 @@ use std::ops::Range;
use crate::field::extension_field::algebra::ExtensionAlgebra;
use crate::field::extension_field::{Extendable, FieldExtension, OEF};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -16,11 +16,14 @@ impl<const D: usize> ExtensionTarget<D> {
self.0
}
pub fn frobenius<F: Extendable<D>>(&self, builder: &mut CircuitBuilder<F, D>) -> Self {
pub fn frobenius<F: PrimeField + Extendable<D>>(
&self,
builder: &mut CircuitBuilder<F, D>,
) -> Self {
self.repeated_frobenius(1, builder)
}
pub fn repeated_frobenius<F: Extendable<D>>(
pub fn repeated_frobenius<F: PrimeField + Extendable<D>>(
&self,
count: usize,
builder: &mut CircuitBuilder<F, D>,
@ -71,7 +74,7 @@ impl<const D: usize> ExtensionAlgebraTarget<D> {
}
}
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn constant_extension(&mut self, c: F::Extension) -> ExtensionTarget<D> {
let c_parts = c.to_basefield_array();
let mut parts = [self.zero(); D];

View File

@ -1,6 +1,6 @@
use num::{bigint::BigUint, Zero};
use crate::field::field_types::Field;
use crate::field::field_types::PrimeField;
use crate::util::ceil_div_usize;
/// Generates a series of non-negative integers less than
@ -67,7 +67,7 @@ pub fn run_unaryop_test_cases<F, UnaryOp, ExpectedOp>(
op: UnaryOp,
expected_op: ExpectedOp,
) where
F: Field,
F: PrimeField,
UnaryOp: Fn(F) -> F,
ExpectedOp: Fn(BigUint) -> BigUint,
{
@ -99,7 +99,7 @@ pub fn run_binaryop_test_cases<F, BinaryOp, ExpectedOp>(
op: BinaryOp,
expected_op: ExpectedOp,
) where
F: Field,
F: PrimeField,
BinaryOp: Fn(F, F) -> F,
ExpectedOp: Fn(BigUint, BigUint) -> BigUint,
{
@ -192,36 +192,26 @@ macro_rules! test_field_arithmetic {
}
}
#[test]
fn bits() {
assert_eq!(<$field>::ZERO.bits(), 0);
assert_eq!(<$field>::ONE.bits(), 1);
assert_eq!(<$field>::TWO.bits(), 2);
assert_eq!(<$field>::from_canonical_u64(3).bits(), 2);
assert_eq!(<$field>::from_canonical_u64(4).bits(), 3);
assert_eq!(<$field>::from_canonical_u64(5).bits(), 3);
}
#[test]
fn exponentiation() {
type F = $field;
assert_eq!(F::ZERO.exp_u32(0), <F>::ONE);
assert_eq!(F::ONE.exp_u32(0), <F>::ONE);
assert_eq!(F::TWO.exp_u32(0), <F>::ONE);
assert_eq!(F::ZERO.exp_u64(0), <F>::ONE);
assert_eq!(F::ONE.exp_u64(0), <F>::ONE);
assert_eq!(F::TWO.exp_u64(0), <F>::ONE);
assert_eq!(F::ZERO.exp_u32(1), <F>::ZERO);
assert_eq!(F::ONE.exp_u32(1), <F>::ONE);
assert_eq!(F::TWO.exp_u32(1), <F>::TWO);
assert_eq!(F::ZERO.exp_u64(1), <F>::ZERO);
assert_eq!(F::ONE.exp_u64(1), <F>::ONE);
assert_eq!(F::TWO.exp_u64(1), <F>::TWO);
assert_eq!(F::ZERO.kth_root_u32(1), <F>::ZERO);
assert_eq!(F::ONE.kth_root_u32(1), <F>::ONE);
assert_eq!(F::TWO.kth_root_u32(1), <F>::TWO);
assert_eq!(F::ZERO.kth_root_u64(1), <F>::ZERO);
assert_eq!(F::ONE.kth_root_u64(1), <F>::ONE);
assert_eq!(F::TWO.kth_root_u64(1), <F>::TWO);
for power in 1..10 {
if F::is_monomial_permutation(power) {
if F::is_monomial_permutation_u64(power) {
let x = F::rand();
assert_eq!(x.exp(power).kth_root(power), x);
assert_eq!(x.exp_u64(power).kth_root_u64(power), x);
}
}
}
@ -251,7 +241,7 @@ macro_rules! test_field_arithmetic {
let v = <F as Field>::PrimeField::TWO_ADICITY;
for e in [0, 1, 2, 3, 4, v - 2, v - 1, v, v + 1, v + 2, 123 * v] {
let x = F::TWO.exp(e as u64).inverse();
let x = F::TWO.exp_u64(e as u64).inverse();
let y = F::inverse_2exp(e);
assert_eq!(x, y);
}

View File

@ -13,7 +13,7 @@ use serde::Serialize;
use crate::field::extension_field::Frobenius;
use crate::util::bits_u64;
/// A finite field with prime order less than 2^64.
/// A finite field.
pub trait Field:
'static
+ Copy
@ -38,7 +38,7 @@ pub trait Field:
+ Serialize
+ DeserializeOwned
{
type PrimeField: Field;
type PrimeField: PrimeField;
const ZERO: Self;
const ONE: Self;
@ -133,7 +133,7 @@ pub trait Field:
// In the general case we compute 1/2 = (p+1)/2 and then exponentiate
// by exp to get 1/2^exp. Costs about log_2(exp) operations.
let half = Self::from_canonical_u64((p + 1) >> 1);
half.exp(exp as u64)
half.exp_u64(exp as u64)
// TODO: Faster to combine several high powers of 1/2 using multiple
// applications of the trick above. E.g. if the 2-adicity is v, then
@ -180,15 +180,6 @@ pub trait Field:
subgroup.into_iter().map(|x| x * shift).collect()
}
// Converting to u64 only makes sense in a prime field, not in
// an extension; probably means these two functions don't belong
// the Field trait...
fn to_canonical_u64(&self) -> u64;
fn to_noncanonical_u64(&self) -> u64;
fn from_noncanonical_u128(n: u128) -> Self;
fn from_canonical_u64(n: u64) -> Self;
fn from_canonical_u32(n: u32) -> Self {
@ -203,15 +194,12 @@ pub trait Field:
Self::from_canonical_u64(b as u64)
}
fn to_canonical_biguint(&self) -> BigUint;
fn from_canonical_biguint(n: BigUint) -> Self;
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self;
/// Returns `n % Self::CHARACTERISTIC`.
fn from_noncanonical_u128(n: u128) -> Self;
fn bits(&self) -> usize {
bits_u64(self.to_canonical_u64())
}
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self;
fn exp_power_of_2(&self, power_log: usize) -> Self {
let mut res = *self;
@ -221,7 +209,7 @@ pub trait Field:
res
}
fn exp(&self, power: u64) -> Self {
fn exp_u64(&self, power: u64) -> Self {
let mut current = *self;
let mut product = Self::ONE;
@ -234,27 +222,17 @@ pub trait Field:
product
}
fn exp_u32(&self, power: u32) -> Self {
self.exp(power as u64)
}
fn exp_biguint(&self, power: &BigUint) -> Self {
let digits = power.to_u32_digits();
let radix = 1u64 << 32;
let mut result = Self::ONE;
for (radix_power, &digit) in digits.iter().enumerate() {
let mut current = self.exp_u32(digit);
for _ in 0..radix_power {
current = current.exp(radix);
}
result *= current;
for &digit in power.to_u64_digits().iter().rev() {
result = result.exp_power_of_2(64);
result *= self.exp_u64(digit);
}
result
}
/// Returns whether `x^power` is a permutation of this field.
fn is_monomial_permutation(power: u64) -> bool {
fn is_monomial_permutation_u64(power: u64) -> bool {
match power {
0 => false,
1 => true,
@ -262,11 +240,11 @@ pub trait Field:
}
}
fn kth_root(&self, k: u64) -> Self {
fn kth_root_u64(&self, k: u64) -> Self {
let p = Self::order().clone();
let p_minus_1 = &p - 1u32;
debug_assert!(
Self::is_monomial_permutation(k),
Self::is_monomial_permutation_u64(k),
"Not a permutation of this field"
);
@ -289,12 +267,8 @@ pub trait Field:
);
}
fn kth_root_u32(&self, k: u32) -> Self {
self.kth_root(k as u64)
}
fn cube_root(&self) -> Self {
self.kth_root(3)
self.kth_root_u64(3)
}
fn powers(&self) -> Powers<Self> {
@ -347,6 +321,17 @@ pub trait Field:
}
}
/// A finite field of prime order less than 2^64.
pub trait PrimeField: Field {
const ORDER: u64;
fn to_canonical_u64(&self) -> u64;
fn to_noncanonical_u64(&self) -> u64;
fn to_canonical_biguint(&self) -> BigUint;
}
/// 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

@ -2,7 +2,7 @@ use rayon::prelude::*;
use crate::field::extension_field::Extendable;
use crate::field::fft::DEFAULT_STRATEGY;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::fri::proof::FriProof;
use crate::fri::prover::fri_proof;
use crate::hash::merkle_tree::MerkleTree;
@ -20,7 +20,7 @@ use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place, transp
pub const SALT_SIZE: usize = 2;
/// Represents a batch FRI based commitment to a list of polynomials.
pub struct PolynomialBatchCommitment<F: Field> {
pub struct PolynomialBatchCommitment<F: PrimeField> {
pub polynomials: Vec<PolynomialCoeffs<F>>,
pub merkle_tree: MerkleTree<F>,
pub degree_log: usize,
@ -28,7 +28,7 @@ pub struct PolynomialBatchCommitment<F: Field> {
pub blinding: bool,
}
impl<F: Field> PolynomialBatchCommitment<F> {
impl<F: PrimeField> PolynomialBatchCommitment<F> {
/// Creates a list polynomial commitment for the polynomials interpolating the values in `values`.
pub(crate) fn from_values(
values: Vec<PolynomialValues<F>>,
@ -125,7 +125,7 @@ impl<F: Field> PolynomialBatchCommitment<F> {
timing: &mut TimingTree,
) -> (FriProof<F, D>, OpeningSet<F, D>)
where
F: Extendable<D>,
F: PrimeField + Extendable<D>,
{
let config = &common_data.config;
assert!(D > 1, "Not implemented for D=1.");
@ -133,7 +133,7 @@ impl<F: Field> PolynomialBatchCommitment<F> {
let g = F::Extension::primitive_root_of_unity(degree_log);
for p in &[zeta, g * zeta] {
assert_ne!(
p.exp(1 << degree_log as u64),
p.exp_u64(1 << degree_log as u64),
F::Extension::ONE,
"Opening point is in the subgroup."
);
@ -273,14 +273,15 @@ mod tests {
let degree = 1 << degree_log;
let mut point = F::Extension::rand();
while point.exp(degree as u64).is_one() {
while point.exp_u64(degree as u64).is_one() {
point = F::Extension::rand();
}
point
}
fn check_batch_polynomial_commitment<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
fn check_batch_polynomial_commitment<F: PrimeField + Extendable<D>, const D: usize>(
) -> Result<()> {
let ks = [10, 2, 10, 8];
let degree_bits = 11;
let fri_config = FriConfig {

View File

@ -1,7 +1,7 @@
use rayon::prelude::*;
use crate::field::extension_field::{flatten, unflatten, Extendable};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound, FriQueryStep};
use crate::fri::FriConfig;
use crate::hash::hash_types::HashOut;
@ -16,7 +16,7 @@ use crate::util::reverse_index_bits_in_place;
use crate::util::timing::TimingTree;
/// Builds a FRI proof.
pub fn fri_proof<F: Field + Extendable<D>, const D: usize>(
pub fn fri_proof<F: PrimeField + Extendable<D>, const D: usize>(
initial_merkle_trees: &[&MerkleTree<F>],
// Coefficients of the polynomial on which the LDT is performed. Only the first `1/rate` coefficients are non-zero.
lde_polynomial_coeffs: PolynomialCoeffs<F::Extension>,
@ -99,7 +99,7 @@ fn fri_committed_trees<F: Field + Extendable<D>, const D: usize>(
.map(|chunk| reduce_with_powers(chunk, beta))
.collect::<Vec<_>>(),
);
shift = shift.exp_u32(arity as u32);
shift = shift.exp_u64(arity as u64);
values = coeffs.coset_fft(shift.into())
}
@ -110,7 +110,7 @@ fn fri_committed_trees<F: Field + Extendable<D>, const D: usize>(
(trees, coeffs)
}
fn fri_proof_of_work<F: Field>(current_hash: HashOut<F>, config: &FriConfig) -> F {
fn fri_proof_of_work<F: PrimeField>(current_hash: HashOut<F>, config: &FriConfig) -> F {
(0..=F::NEG_ONE.to_canonical_u64())
.into_par_iter()
.find_any(|&i| {
@ -131,7 +131,7 @@ fn fri_proof_of_work<F: Field>(current_hash: HashOut<F>, config: &FriConfig) ->
.expect("Proof of work failed. This is highly unlikely!")
}
fn fri_prover_query_rounds<F: Field + Extendable<D>, const D: usize>(
fn fri_prover_query_rounds<F: PrimeField + Extendable<D>, const D: usize>(
initial_merkle_trees: &[&MerkleTree<F>],
trees: &[MerkleTree<F>],
challenger: &mut Challenger<F>,
@ -143,7 +143,7 @@ fn fri_prover_query_rounds<F: Field + Extendable<D>, const D: usize>(
.collect()
}
fn fri_prover_query_round<F: Field + Extendable<D>, const D: usize>(
fn fri_prover_query_round<F: PrimeField + Extendable<D>, const D: usize>(
initial_merkle_trees: &[&MerkleTree<F>],
trees: &[MerkleTree<F>],
challenger: &mut Challenger<F>,

View File

@ -1,6 +1,6 @@
use crate::field::extension_field::target::{flatten_target, ExtensionTarget};
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget};
use crate::fri::FriConfig;
use crate::hash::hash_types::MerkleCapTarget;
@ -14,7 +14,7 @@ use crate::util::reducing::ReducingFactorTarget;
use crate::util::{log2_strict, reverse_index_bits_in_place};
use crate::with_context;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity
/// and P' is the FRI reduced polynomial.
fn compute_evaluation(
@ -29,7 +29,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
debug_assert_eq!(evals.len(), arity);
let g = F::primitive_root_of_unity(arity_bits);
let g_inv = g.exp((arity as u64) - 1);
let g_inv = g.exp_u64((arity as u64) - 1);
let g_inv_t = self.constant(g_inv);
// The evaluation vector needs to be reordered first.
@ -394,7 +394,7 @@ struct PrecomputedReducedEvalsTarget<const D: usize> {
}
impl<const D: usize> PrecomputedReducedEvalsTarget<D> {
fn from_os_and_alpha<F: Extendable<D>>(
fn from_os_and_alpha<F: PrimeField + Extendable<D>>(
os: &OpeningSetTarget<D>,
alpha: ExtensionTarget<D>,
degree_log: usize,

View File

@ -1,7 +1,7 @@
use anyhow::{ensure, Result};
use crate::field::extension_field::{flatten, Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::field::interpolation::{barycentric_weights, interpolate, interpolate2};
use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound};
use crate::fri::FriConfig;
@ -33,7 +33,7 @@ fn compute_evaluation<F: Field + Extendable<D>, const D: usize>(
let mut evals = evals.to_vec();
reverse_index_bits_in_place(&mut evals);
let rev_x_index_within_coset = reverse_bits(x_index_within_coset, arity_bits);
let coset_start = x * g.exp((arity - rev_x_index_within_coset) as u64);
let coset_start = x * g.exp_u64((arity - rev_x_index_within_coset) as u64);
// The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta.
let points = g
.powers()
@ -44,7 +44,7 @@ fn compute_evaluation<F: Field + Extendable<D>, const D: usize>(
interpolate(&points, beta, &barycentric_weights)
}
fn fri_verify_proof_of_work<F: Field + Extendable<D>, const D: usize>(
fn fri_verify_proof_of_work<F: PrimeField + Extendable<D>, const D: usize>(
proof: &FriProof<F, D>,
challenger: &mut Challenger<F>,
config: &FriConfig,
@ -68,7 +68,7 @@ fn fri_verify_proof_of_work<F: Field + Extendable<D>, const D: usize>(
Ok(())
}
pub fn verify_fri_proof<F: Field + Extendable<D>, const D: usize>(
pub fn verify_fri_proof<F: PrimeField + Extendable<D>, const D: usize>(
// Openings of the PLONK polynomials.
os: &OpeningSet<F, D>,
// Point at which the PLONK polynomials are opened.
@ -179,7 +179,7 @@ impl<F: Extendable<D>, const D: usize> PrecomputedReducedEvals<F, D> {
}
}
fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
fn fri_combine_initial<F: PrimeField + Extendable<D>, const D: usize>(
proof: &FriInitialTreeProof<F>,
alpha: F::Extension,
zeta: F::Extension,
@ -244,7 +244,7 @@ fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
sum
}
fn fri_verifier_query_round<F: Field + Extendable<D>, const D: usize>(
fn fri_verifier_query_round<F: PrimeField + Extendable<D>, const D: usize>(
zeta: F::Extension,
alpha: F::Extension,
precomputed_reduced_evals: PrecomputedReducedEvals<F, D>,
@ -267,7 +267,7 @@ fn fri_verifier_query_round<F: Field + Extendable<D>, const D: usize>(
// `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
let log_n = log2_strict(n);
let mut subgroup_x = F::MULTIPLICATIVE_GROUP_GENERATOR
* F::primitive_root_of_unity(log_n).exp(reverse_bits(x_index, log_n) as u64);
* F::primitive_root_of_unity(log_n).exp_u64(reverse_bits(x_index, log_n) as u64);
// old_eval is the last derived evaluation; it will be checked for consistency with its
// committed "parent" value in the next iteration.

View File

@ -1,11 +1,12 @@
use std::borrow::Borrow;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::gates::exponentiation::ExponentiationGate;
use crate::iop::target::{BoolTarget, Target};
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Computes `-x`.
pub fn neg(&mut self, x: Target) -> Target {
let neg_one = self.neg_one();

View File

@ -3,7 +3,7 @@ use std::convert::TryInto;
use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget};
use crate::field::extension_field::FieldExtension;
use crate::field::extension_field::{Extendable, OEF};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS};
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::Target;
@ -11,7 +11,7 @@ use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::util::bits_u64;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Finds the last available arithmetic gate with the given constants or add one if there aren't any.
/// Returns `(g,i)` such that there is an arithmetic gate with the given constants at index
/// `g` and the gate's `i`-th operation is available.
@ -440,7 +440,9 @@ struct QuotientGeneratorExtension<const D: usize> {
quotient: ExtensionTarget<D>,
}
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for QuotientGeneratorExtension<D> {
impl<F: PrimeField + Extendable<D>, const D: usize> SimpleGenerator<F>
for QuotientGeneratorExtension<D>
{
fn dependencies(&self) -> Vec<Target> {
let mut deps = self.numerator.to_target_array().to_vec();
deps.extend(&self.denominator.to_target_array());
@ -463,7 +465,7 @@ pub struct PowersTarget<const D: usize> {
}
impl<const D: usize> PowersTarget<D> {
pub fn next<F: Extendable<D>>(
pub fn next<F: PrimeField + Extendable<D>>(
&mut self,
builder: &mut CircuitBuilder<F, D>,
) -> ExtensionTarget<D> {
@ -472,7 +474,7 @@ impl<const D: usize> PowersTarget<D> {
result
}
pub fn repeated_frobenius<F: Extendable<D>>(
pub fn repeated_frobenius<F: PrimeField + Extendable<D>>(
self,
k: usize,
builder: &mut CircuitBuilder<F, D>,
@ -485,7 +487,7 @@ impl<const D: usize> PowersTarget<D> {
}
}
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn powers(&mut self, base: ExtensionTarget<D>) -> PowersTarget<D> {
PowersTarget {
base,

View File

@ -1,6 +1,7 @@
use std::convert::TryInto;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::gates::gmimc::GMiMCGate;
use crate::hash::hashing::GMIMC_ROUNDS;
use crate::iop::target::Target;
@ -8,7 +9,7 @@ use crate::iop::wire::Wire;
use crate::plonk::circuit_builder::CircuitBuilder;
// TODO: Move to be next to native `permute`?
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] {
let zero = self.zero();
let gate_type = GMiMCGate::<F, D, GMIMC_ROUNDS>::new_automatic_constants();

View File

@ -1,10 +1,11 @@
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::gates::insertion::InsertionGate;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Inserts a `Target` in a vector at a non-deterministic index.
/// Note: `index` is not range-checked.
pub fn insert(

View File

@ -1,10 +1,11 @@
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::gates::interpolation::InterpolationGate;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Interpolate a list of point/evaluation pairs at a given point.
/// Returns the evaluation of the interpolated polynomial at `evaluation_point`.
pub fn interpolate(

View File

@ -1,5 +1,6 @@
use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget};
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::util::reducing::ReducingFactorTarget;
@ -11,7 +12,7 @@ impl<const D: usize> PolynomialCoeffsExtTarget<D> {
self.0.len()
}
pub fn eval_scalar<F: Extendable<D>>(
pub fn eval_scalar<F: PrimeField + Extendable<D>>(
&self,
builder: &mut CircuitBuilder<F, D>,
point: Target,
@ -21,7 +22,7 @@ impl<const D: usize> PolynomialCoeffsExtTarget<D> {
point.reduce(&self.0, builder)
}
pub fn eval<F: Extendable<D>>(
pub fn eval<F: PrimeField + Extendable<D>>(
&self,
builder: &mut CircuitBuilder<F, D>,
point: ExtensionTarget<D>,
@ -40,7 +41,7 @@ impl<const D: usize> PolynomialCoeffsExtAlgebraTarget<D> {
point: ExtensionTarget<D>,
) -> ExtensionAlgebraTarget<D>
where
F: Extendable<D>,
F: PrimeField + Extendable<D>,
{
let mut acc = builder.zero_ext_algebra();
for &c in self.0.iter().rev() {
@ -55,7 +56,7 @@ impl<const D: usize> PolynomialCoeffsExtAlgebraTarget<D> {
point: ExtensionAlgebraTarget<D>,
) -> ExtensionAlgebraTarget<D>
where
F: Extendable<D>,
F: PrimeField + Extendable<D>,
{
let mut acc = builder.zero_ext_algebra();
for &c in self.0.iter().rev() {

View File

@ -1,10 +1,11 @@
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::gates::random_access::RandomAccessGate;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Checks that a `Target` matches a vector at a non-deterministic index.
/// Note: `index` is not range-checked.
pub fn random_access(

View File

@ -1,12 +1,12 @@
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::PrimeField;
use crate::gates::base_sum::BaseSumGate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Checks that `x < 2^n_log` using a `BaseSumGate`.
pub fn range_check(&mut self, x: Target, n_log: usize) {
let gate = self.add_gate(BaseSumGate::<2>::new(n_log), vec![]);
@ -51,7 +51,7 @@ struct LowHighGenerator {
high: Target,
}
impl<F: Field> SimpleGenerator<F> for LowHighGenerator {
impl<F: PrimeField> SimpleGenerator<F> for LowHighGenerator {
fn dependencies(&self) -> Vec<Target> {
vec![self.integer]
}

View File

@ -1,9 +1,10 @@
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::iop::target::{BoolTarget, Target};
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Selects `x` or `y` based on `b`, i.e., this returns `if b { x } else { y }`.
pub fn select_ext(
&mut self,

View File

@ -1,14 +1,14 @@
use std::borrow::Borrow;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::base_sum::BaseSumGate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Split the given element into a list of targets, where each one represents a
/// base-B limb of the element, with little-endian ordering.
pub fn split_le_base<const B: usize>(&mut self, x: Target, num_limbs: usize) -> Vec<Target> {

View File

@ -1,5 +1,5 @@
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::PrimeField;
use crate::gates::base_sum::BaseSumGate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target};
@ -7,7 +7,7 @@ use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::util::ceil_div_usize;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Split the given integer into a list of wires, where each one represents a
/// bit of the integer, with little-endian ordering.
/// Verifies that the decomposition is correct by using `k` `BaseSum<2>` gates
@ -63,7 +63,7 @@ struct SplitGenerator {
bits: Vec<Target>,
}
impl<F: Field> SimpleGenerator<F> for SplitGenerator {
impl<F: PrimeField> SimpleGenerator<F> for SplitGenerator {
fn dependencies(&self) -> Vec<Target> {
vec![self.integer]
}
@ -91,7 +91,7 @@ struct WireSplitGenerator {
num_limbs: usize,
}
impl<F: Field> SimpleGenerator<F> for WireSplitGenerator {
impl<F: PrimeField> SimpleGenerator<F> for WireSplitGenerator {
fn dependencies(&self) -> Vec<Target> {
vec![self.integer]
}

View File

@ -3,6 +3,7 @@ use std::ops::Range;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::extension_field::FieldExtension;
use crate::field::field_types::PrimeField;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
@ -32,7 +33,7 @@ impl<const D: usize> ArithmeticExtensionGate<D> {
}
}
impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D> {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D> {
fn id(&self) -> String {
format!("{:?}", self)
}
@ -139,14 +140,16 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
}
#[derive(Clone, Debug)]
struct ArithmeticExtensionGenerator<F: Extendable<D>, const D: usize> {
struct ArithmeticExtensionGenerator<F: PrimeField + Extendable<D>, const D: usize> {
gate_index: usize,
const_0: F,
const_1: F,
i: usize,
}
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensionGenerator<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> SimpleGenerator<F>
for ArithmeticExtensionGenerator<F, D>
{
fn dependencies(&self) -> Vec<Target> {
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(self.i)
.chain(ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(

View File

@ -2,7 +2,7 @@ use std::ops::Range;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
@ -31,7 +31,7 @@ impl<const B: usize> BaseSumGate<B> {
}
}
impl<F: Extendable<D>, const D: usize, const B: usize> Gate<F, D> for BaseSumGate<B> {
impl<F: PrimeField + Extendable<D>, const D: usize, const B: usize> Gate<F, D> for BaseSumGate<B> {
fn id(&self) -> String {
format!("{:?} + Base: {}", self, B)
}
@ -134,7 +134,7 @@ pub struct BaseSplitGenerator<const B: usize> {
num_limbs: usize,
}
impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B> {
impl<F: PrimeField, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B> {
fn dependencies(&self) -> Vec<Target> {
vec![Target::wire(self.gate_index, BaseSumGate::<B>::WIRE_SUM)]
}

View File

@ -1,6 +1,6 @@
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
@ -18,7 +18,7 @@ impl ConstantGate {
pub const WIRE_OUTPUT: usize = 0;
}
impl<F: Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
fn id(&self) -> String {
"ConstantGate".into()
}

View File

@ -2,7 +2,7 @@ use std::marker::PhantomData;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
@ -14,12 +14,12 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
/// A gate for raising a value to a power.
#[derive(Clone, Debug)]
pub(crate) struct ExponentiationGate<F: Extendable<D>, const D: usize> {
pub(crate) struct ExponentiationGate<F: PrimeField + Extendable<D>, const D: usize> {
pub num_power_bits: usize,
pub _phantom: PhantomData<F>,
}
impl<F: Extendable<D>, const D: usize> ExponentiationGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> ExponentiationGate<F, D> {
pub fn new(config: CircuitConfig) -> Self {
let num_power_bits = Self::max_power_bits(config.num_wires, config.num_routed_wires);
Self {
@ -55,7 +55,7 @@ impl<F: Extendable<D>, const D: usize> ExponentiationGate<F, D> {
}
}
impl<F: Extendable<D>, const D: usize> Gate<F, D> for ExponentiationGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for ExponentiationGate<F, D> {
fn id(&self) -> String {
format!("{:?}<D={}>", self, D)
}
@ -201,12 +201,14 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ExponentiationGate<F, D> {
}
#[derive(Debug)]
struct ExponentiationGenerator<F: Extendable<D>, const D: usize> {
struct ExponentiationGenerator<F: PrimeField + Extendable<D>, const D: usize> {
gate_index: usize,
gate: ExponentiationGate<F, D>,
}
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ExponentiationGenerator<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> SimpleGenerator<F>
for ExponentiationGenerator<F, D>
{
fn dependencies(&self) -> Vec<Target> {
let local_target = |input| Target::wire(self.gate_index, input);

View File

@ -4,14 +4,14 @@ use std::sync::Arc;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate_tree::Tree;
use crate::iop::generator::WitnessGenerator;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
/// A custom gate.
pub trait Gate<F: Extendable<D>, const D: usize>: 'static + Send + Sync {
pub trait Gate<F: PrimeField + Extendable<D>, const D: usize>: 'static + Send + Sync {
fn id(&self) -> String;
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension>;
@ -108,48 +108,48 @@ pub trait Gate<F: Extendable<D>, const D: usize>: 'static + Send + Sync {
/// A wrapper around an `Rc<Gate>` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs.
#[derive(Clone)]
pub struct GateRef<F: Extendable<D>, const D: usize>(pub(crate) Arc<dyn Gate<F, D>>);
pub struct GateRef<F: PrimeField + Extendable<D>, const D: usize>(pub(crate) Arc<dyn Gate<F, D>>);
impl<F: Extendable<D>, const D: usize> GateRef<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> GateRef<F, D> {
pub fn new<G: Gate<F, D>>(gate: G) -> GateRef<F, D> {
GateRef(Arc::new(gate))
}
}
impl<F: Extendable<D>, const D: usize> PartialEq for GateRef<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> PartialEq for GateRef<F, D> {
fn eq(&self, other: &Self) -> bool {
self.0.id() == other.0.id()
}
}
impl<F: Extendable<D>, const D: usize> Hash for GateRef<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> Hash for GateRef<F, D> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.id().hash(state)
}
}
impl<F: Extendable<D>, const D: usize> Eq for GateRef<F, D> {}
impl<F: PrimeField + Extendable<D>, const D: usize> Eq for GateRef<F, D> {}
impl<F: Extendable<D>, const D: usize> Debug for GateRef<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> Debug for GateRef<F, D> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(f, "{}", self.0.id())
}
}
/// A gate along with any constants used to configure it.
pub struct GateInstance<F: Extendable<D>, const D: usize> {
pub struct GateInstance<F: PrimeField + Extendable<D>, const D: usize> {
pub gate_ref: GateRef<F, D>,
pub constants: Vec<F>,
}
/// Map each gate to a boolean prefix used to construct the gate's selector polynomial.
#[derive(Debug, Clone)]
pub struct PrefixedGate<F: Extendable<D>, const D: usize> {
pub struct PrefixedGate<F: PrimeField + Extendable<D>, const D: usize> {
pub gate: GateRef<F, D>,
pub prefix: Vec<bool>,
}
impl<F: Extendable<D>, const D: usize> PrefixedGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> PrefixedGate<F, D> {
pub fn from_tree(tree: Tree<GateRef<F, D>>) -> Vec<Self> {
tree.traversal()
.into_iter()
@ -174,7 +174,7 @@ fn compute_filter<K: Field>(prefix: &[bool], constants: &[K]) -> K {
.product()
}
fn compute_filter_recursively<F: Extendable<D>, const D: usize>(
fn compute_filter_recursively<F: PrimeField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
prefix: &[bool],
constants: &[ExtensionTarget<D>],

View File

@ -1,7 +1,7 @@
use anyhow::{ensure, Result};
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::Gate;
use crate::hash::hash_types::HashOut;
use crate::iop::witness::{PartialWitness, Witness};
@ -17,7 +17,9 @@ const WITNESS_DEGREE: usize = WITNESS_SIZE - 1;
/// Tests that the constraints imposed by the given gate are low-degree by applying them to random
/// low-degree witness polynomials.
pub(crate) fn test_low_degree<F: Extendable<D>, G: Gate<F, D>, const D: usize>(gate: G) {
pub(crate) fn test_low_degree<F: PrimeField + Extendable<D>, G: Gate<F, D>, const D: usize>(
gate: G,
) {
let rate_bits = log2_ceil(gate.degree() + 1);
let wire_ldes = random_low_degree_matrix::<F::Extension>(gate.num_wires(), rate_bits);
@ -82,7 +84,7 @@ fn random_low_degree_values<F: Field>(rate_bits: usize) -> Vec<F> {
.values
}
pub(crate) fn test_eval_fns<F: Extendable<D>, G: Gate<F, D>, const D: usize>(
pub(crate) fn test_eval_fns<F: PrimeField + Extendable<D>, G: Gate<F, D>, const D: usize>(
gate: G,
) -> Result<()> {
// Test that `eval_unfiltered` and `eval_unfiltered_base` are coherent.

View File

@ -1,6 +1,7 @@
use log::info;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::gates::gate::GateRef;
/// A binary tree where leaves hold some type `T` and other nodes are empty.
@ -50,7 +51,7 @@ impl<T: Clone> Tree<T> {
}
}
impl<F: Extendable<D>, const D: usize> Tree<GateRef<F, D>> {
impl<F: PrimeField + Extendable<D>, const D: usize> Tree<GateRef<F, D>> {
/// The binary gate tree influences the degree `D` of the constraint polynomial and the number `C`
/// of constant wires in the circuit. We want to construct a tree minimizing both values. To do so
/// we iterate over possible values of `(D, C)` and try to construct a tree with these values.

View File

@ -2,7 +2,7 @@ use std::sync::Arc;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::Gate;
use crate::hash::gmimc::gmimc_automatic_constants;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
@ -23,11 +23,11 @@ const W: usize = 12;
/// sibling digests. It also has an accumulator that computes the weighted sum of these flags, for
/// computing the index of the leaf based on these swap bits.
#[derive(Debug)]
pub struct GMiMCGate<F: Extendable<D>, const D: usize, const R: usize> {
pub struct GMiMCGate<F: PrimeField + Extendable<D>, const D: usize, const R: usize> {
constants: Arc<[F; R]>,
}
impl<F: Extendable<D>, const D: usize, const R: usize> GMiMCGate<F, D, R> {
impl<F: PrimeField + Extendable<D>, const D: usize, const R: usize> GMiMCGate<F, D, R> {
pub fn new(constants: Arc<[F; R]>) -> Self {
Self { constants }
}
@ -62,7 +62,9 @@ impl<F: Extendable<D>, const D: usize, const R: usize> GMiMCGate<F, D, R> {
}
}
impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> for GMiMCGate<F, D, R> {
impl<F: PrimeField + Extendable<D>, const D: usize, const R: usize> Gate<F, D>
for GMiMCGate<F, D, R>
{
fn id(&self) -> String {
format!("<R={}> {:?}", R, self)
}
@ -238,12 +240,12 @@ impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> for GMiMCGate<
}
#[derive(Debug)]
struct GMiMCGenerator<F: Extendable<D>, const D: usize, const R: usize> {
struct GMiMCGenerator<F: PrimeField + Extendable<D>, const D: usize, const R: usize> {
gate_index: usize,
constants: Arc<[F; R]>,
}
impl<F: Extendable<D>, const D: usize, const R: usize> SimpleGenerator<F>
impl<F: PrimeField + Extendable<D>, const D: usize, const R: usize> SimpleGenerator<F>
for GMiMCGenerator<F, D, R>
{
fn dependencies(&self) -> Vec<Target> {

View File

@ -4,7 +4,7 @@ use std::ops::Range;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
@ -15,12 +15,12 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
/// A gate for inserting a value into a list at a non-deterministic location.
#[derive(Clone, Debug)]
pub(crate) struct InsertionGate<F: Extendable<D>, const D: usize> {
pub(crate) struct InsertionGate<F: PrimeField + Extendable<D>, const D: usize> {
pub vec_size: usize,
_phantom: PhantomData<F>,
}
impl<F: Extendable<D>, const D: usize> InsertionGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> InsertionGate<F, D> {
pub fn new(vec_size: usize) -> Self {
Self {
vec_size,
@ -70,7 +70,7 @@ impl<F: Extendable<D>, const D: usize> InsertionGate<F, D> {
}
}
impl<F: Extendable<D>, const D: usize> Gate<F, D> for InsertionGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for InsertionGate<F, D> {
fn id(&self) -> String {
format!("{:?}<D={}>", self, D)
}
@ -241,12 +241,14 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for InsertionGate<F, D> {
}
#[derive(Debug)]
struct InsertionGenerator<F: Extendable<D>, const D: usize> {
struct InsertionGenerator<F: PrimeField + Extendable<D>, const D: usize> {
gate_index: usize,
gate: InsertionGate<F, D>,
}
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for InsertionGenerator<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> SimpleGenerator<F>
for InsertionGenerator<F, D>
{
fn dependencies(&self) -> Vec<Target> {
let local_target = |input| Target::wire(self.gate_index, input);

View File

@ -5,6 +5,7 @@ use std::ops::Range;
use crate::field::extension_field::algebra::PolynomialCoeffsAlgebra;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::PrimeField;
use crate::field::interpolation::interpolant;
use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget;
use crate::gates::gate::Gate;
@ -22,12 +23,12 @@ use crate::polynomial::polynomial::PolynomialCoeffs;
/// to evaluate the interpolant at. It computes the interpolant and outputs its evaluation at the
/// given point.
#[derive(Clone, Debug)]
pub(crate) struct InterpolationGate<F: Extendable<D>, const D: usize> {
pub(crate) struct InterpolationGate<F: PrimeField + Extendable<D>, const D: usize> {
pub num_points: usize,
_phantom: PhantomData<F>,
}
impl<F: Extendable<D>, const D: usize> InterpolationGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> InterpolationGate<F, D> {
pub fn new(num_points: usize) -> Self {
Self {
num_points,
@ -93,7 +94,7 @@ impl<F: Extendable<D>, const D: usize> InterpolationGate<F, D> {
}
}
impl<F: Extendable<D>, const D: usize> Gate<F, D> for InterpolationGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for InterpolationGate<F, D> {
fn id(&self) -> String {
format!("{:?}<D={}>", self, D)
}
@ -214,13 +215,15 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for InterpolationGate<F, D> {
}
#[derive(Debug)]
struct InterpolationGenerator<F: Extendable<D>, const D: usize> {
struct InterpolationGenerator<F: PrimeField + Extendable<D>, const D: usize> {
gate_index: usize,
gate: InterpolationGate<F, D>,
_phantom: PhantomData<F>,
}
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for InterpolationGenerator<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> SimpleGenerator<F>
for InterpolationGenerator<F, D>
{
fn dependencies(&self) -> Vec<Target> {
let local_target = |input| {
Target::Wire(Wire {

View File

@ -1,5 +1,6 @@
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::gates::gate::Gate;
use crate::iop::generator::WitnessGenerator;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -8,7 +9,7 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
/// A gate which does nothing.
pub struct NoopGate;
impl<F: Extendable<D>, const D: usize> Gate<F, D> for NoopGate {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for NoopGate {
fn id(&self) -> String {
"NoopGate".into()
}

View File

@ -2,6 +2,7 @@ use std::ops::Range;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::gates::gate::Gate;
use crate::iop::generator::WitnessGenerator;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -16,7 +17,7 @@ impl PublicInputGate {
}
}
impl<F: Extendable<D>, const D: usize> Gate<F, D> for PublicInputGate {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for PublicInputGate {
fn id(&self) -> String {
"PublicInputGate".into()
}

View File

@ -3,7 +3,7 @@ use std::ops::Range;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
@ -14,12 +14,12 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
/// A gate for checking that a particular element of a list matches a given value.
#[derive(Clone, Debug)]
pub(crate) struct RandomAccessGate<F: Extendable<D>, const D: usize> {
pub(crate) struct RandomAccessGate<F: PrimeField + Extendable<D>, const D: usize> {
pub vec_size: usize,
_phantom: PhantomData<F>,
}
impl<F: Extendable<D>, const D: usize> RandomAccessGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> RandomAccessGate<F, D> {
pub fn new(vec_size: usize) -> Self {
Self {
vec_size,
@ -61,7 +61,7 @@ impl<F: Extendable<D>, const D: usize> RandomAccessGate<F, D> {
}
}
impl<F: Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGate<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGate<F, D> {
fn id(&self) -> String {
format!("{:?}<D={}>", self, D)
}
@ -188,12 +188,14 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGate<F, D> {
}
#[derive(Debug)]
struct RandomAccessGenerator<F: Extendable<D>, const D: usize> {
struct RandomAccessGenerator<F: PrimeField + Extendable<D>, const D: usize> {
gate_index: usize,
gate: RandomAccessGate<F, D>,
}
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for RandomAccessGenerator<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> SimpleGenerator<F>
for RandomAccessGenerator<F, D>
{
fn dependencies(&self) -> Vec<Target> {
let local_target = |input| Target::wire(self.gate_index, input);

View File

@ -3,6 +3,7 @@ use std::ops::Range;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::extension_field::FieldExtension;
use crate::field::field_types::PrimeField;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
@ -50,7 +51,7 @@ impl<const D: usize> ReducingGate<D> {
}
}
impl<F: Extendable<D>, const D: usize> Gate<F, D> for ReducingGate<D> {
impl<F: PrimeField + Extendable<D>, const D: usize> Gate<F, D> for ReducingGate<D> {
fn id(&self) -> String {
format!("{:?}", self)
}

View File

@ -2,7 +2,7 @@ use std::marker::PhantomData;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
@ -14,12 +14,15 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
/// A gate for conditionally swapping input values based on a boolean.
#[derive(Clone, Debug)]
pub(crate) struct SwitchGate<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> {
pub(crate) struct SwitchGate<F: PrimeField + Extendable<D>, const D: usize, const CHUNK_SIZE: usize>
{
num_copies: usize,
_phantom: PhantomData<F>,
}
impl<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> SwitchGate<F, D, CHUNK_SIZE> {
impl<F: PrimeField + Extendable<D>, const D: usize, const CHUNK_SIZE: usize>
SwitchGate<F, D, CHUNK_SIZE>
{
pub fn new(config: CircuitConfig) -> Self {
let num_copies = Self::max_num_copies(config.num_routed_wires);
Self {
@ -62,7 +65,7 @@ impl<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> SwitchGate<F, D,
}
}
impl<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> Gate<F, D>
impl<F: PrimeField + Extendable<D>, const D: usize, const CHUNK_SIZE: usize> Gate<F, D>
for SwitchGate<F, D, CHUNK_SIZE>
{
fn id(&self) -> String {
@ -187,12 +190,12 @@ impl<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> Gate<F, D>
}
#[derive(Debug)]
struct SwitchGenerator<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> {
struct SwitchGenerator<F: PrimeField + Extendable<D>, const D: usize, const CHUNK_SIZE: usize> {
gate_index: usize,
gate: SwitchGate<F, D, CHUNK_SIZE>,
}
impl<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> SimpleGenerator<F>
impl<F: PrimeField + Extendable<D>, const D: usize, const CHUNK_SIZE: usize> SimpleGenerator<F>
for SwitchGenerator<F, D, CHUNK_SIZE>
{
fn dependencies(&self) -> Vec<Target> {

View File

@ -1,7 +1,7 @@
//! Concrete instantiation of a hash function.
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::hash::gmimc::gmimc_permute_array;
use crate::hash::hash_types::{HashOut, HashOutTarget};
use crate::iop::target::Target;
@ -127,7 +127,7 @@ pub fn hash_or_noop<F: Field>(inputs: Vec<F>) -> HashOut<F> {
}
}
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn hash_or_noop(&mut self, inputs: Vec<Target>) -> HashOutTarget {
let zero = self.zero();
if inputs.len() <= 4 {

View File

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gmimc::GMiMCGate;
use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget};
use crate::hash::hashing::{compress, hash_or_noop, GMIMC_ROUNDS};
@ -54,7 +54,7 @@ pub(crate) fn verify_merkle_proof<F: Field>(
Ok(())
}
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Verifies that the given leaf data is present at the given index in the Merkle tree with the
/// given cap. The index is given by it's little-endian bits.
/// Note: Works only for D=4.

View File

@ -4,7 +4,7 @@
use unroll::unroll_for_loops;
use crate::field::crandall_field::CrandallField;
use crate::field::field_types::Field;
use crate::field::field_types::PrimeField;
// The number of full rounds and partial rounds is given by the
// calc_round_numbers.py script. They happen to be the same for both
@ -116,7 +116,7 @@ const ALL_ROUND_CONSTANTS: [u64; MAX_WIDTH * N_ROUNDS] = [
0x4543d9df72c4831d, 0xf172d73e69f20739, 0xdfd1c4ff1eb3d868, 0xbc8dfb62d26376f7,
];
pub trait PoseidonInterface<const WIDTH: usize>: Field
pub trait PoseidonInterface<const WIDTH: usize>: PrimeField
where
// magic to get const generic expressions to work
[(); WIDTH - 1]: ,

View File

@ -2,7 +2,7 @@ use std::convert::TryInto;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget};
use crate::hash::hashing::{permute, SPONGE_RATE, SPONGE_WIDTH};
use crate::hash::merkle_tree::MerkleCap;
@ -183,7 +183,7 @@ pub struct RecursiveChallenger {
}
impl RecursiveChallenger {
pub(crate) fn new<F: Extendable<D>, const D: usize>(
pub(crate) fn new<F: PrimeField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
) -> Self {
let zero = builder.zero();
@ -250,7 +250,7 @@ impl RecursiveChallenger {
}
}
pub(crate) fn get_challenge<F: Extendable<D>, const D: usize>(
pub(crate) fn get_challenge<F: PrimeField + Extendable<D>, const D: usize>(
&mut self,
builder: &mut CircuitBuilder<F, D>,
) -> Target {
@ -267,7 +267,7 @@ impl RecursiveChallenger {
.expect("Output buffer should be non-empty")
}
pub(crate) fn get_n_challenges<F: Extendable<D>, const D: usize>(
pub(crate) fn get_n_challenges<F: PrimeField + Extendable<D>, const D: usize>(
&mut self,
builder: &mut CircuitBuilder<F, D>,
n: usize,
@ -275,7 +275,7 @@ impl RecursiveChallenger {
(0..n).map(|_| self.get_challenge(builder)).collect()
}
pub fn get_hash<F: Extendable<D>, const D: usize>(
pub fn get_hash<F: PrimeField + Extendable<D>, const D: usize>(
&mut self,
builder: &mut CircuitBuilder<F, D>,
) -> HashOutTarget {
@ -289,7 +289,7 @@ impl RecursiveChallenger {
}
}
pub fn get_extension_challenge<F: Extendable<D>, const D: usize>(
pub fn get_extension_challenge<F: PrimeField + Extendable<D>, const D: usize>(
&mut self,
builder: &mut CircuitBuilder<F, D>,
) -> ExtensionTarget<D> {
@ -297,7 +297,7 @@ impl RecursiveChallenger {
}
/// Absorb any buffered inputs. After calling this, the input buffer will be empty.
fn absorb_buffered_inputs<F: Extendable<D>, const D: usize>(
fn absorb_buffered_inputs<F: PrimeField + Extendable<D>, const D: usize>(
&mut self,
builder: &mut CircuitBuilder<F, D>,
) {

View File

@ -44,12 +44,14 @@ pub trait Witness<F: Field> {
}
fn get_bool_target(&self, target: BoolTarget) -> bool {
let value = self.get_target(target.target).to_canonical_u64();
match value {
0 => false,
1 => true,
_ => panic!("not a bool"),
let value = self.get_target(target.target);
if value.is_zero() {
return false;
}
if value.is_one() {
return true;
}
panic!("not a bool")
}
fn get_hash_target(&self, ht: HashOutTarget) -> HashOut<F> {

View File

@ -7,6 +7,7 @@ use log::{info, Level};
use crate::field::cosets::get_unique_coset_shifts;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::PrimeField;
use crate::fri::commitment::PolynomialBatchCommitment;
use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS};
use crate::gates::constant::ConstantGate;
@ -33,7 +34,7 @@ use crate::util::partial_products::num_partial_products;
use crate::util::timing::TimingTree;
use crate::util::{log2_ceil, log2_strict, transpose, transpose_poly_values};
pub struct CircuitBuilder<F: Extendable<D>, const D: usize> {
pub struct CircuitBuilder<F: PrimeField + Extendable<D>, const D: usize> {
pub(crate) config: CircuitConfig,
/// The types of gates used in this circuit.
@ -67,7 +68,7 @@ pub struct CircuitBuilder<F: Extendable<D>, const D: usize> {
pub(crate) free_arithmetic: HashMap<(F, F), (usize, usize)>,
}
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn new(config: CircuitConfig) -> Self {
CircuitBuilder {
config,

View File

@ -3,7 +3,7 @@ use std::ops::{Range, RangeFrom};
use anyhow::Result;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::fri::commitment::PolynomialBatchCommitment;
use crate::fri::FriConfig;
use crate::gates::gate::{GateInstance, PrefixedGate};
@ -91,13 +91,13 @@ impl CircuitConfig {
}
/// Circuit data required by the prover or the verifier.
pub struct CircuitData<F: Extendable<D>, const D: usize> {
pub struct CircuitData<F: PrimeField + Extendable<D>, const D: usize> {
pub(crate) prover_only: ProverOnlyCircuitData<F, D>,
pub(crate) verifier_only: VerifierOnlyCircuitData<F>,
pub(crate) common: CommonCircuitData<F, D>,
}
impl<F: Extendable<D>, const D: usize> CircuitData<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitData<F, D> {
pub fn prove(&self, inputs: PartialWitness<F>) -> Result<ProofWithPublicInputs<F, D>> {
prove(&self.prover_only, &self.common, inputs)
}
@ -114,12 +114,12 @@ impl<F: Extendable<D>, const D: usize> CircuitData<F, D> {
/// structure as succinct as we can. Thus we include various precomputed data which isn't strictly
/// required, like LDEs of preprocessed polynomials. If more succinctness was desired, we could
/// construct a more minimal prover structure and convert back and forth.
pub struct ProverCircuitData<F: Extendable<D>, const D: usize> {
pub struct ProverCircuitData<F: PrimeField + Extendable<D>, const D: usize> {
pub(crate) prover_only: ProverOnlyCircuitData<F, D>,
pub(crate) common: CommonCircuitData<F, D>,
}
impl<F: Extendable<D>, const D: usize> ProverCircuitData<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> ProverCircuitData<F, D> {
pub fn prove(&self, inputs: PartialWitness<F>) -> Result<ProofWithPublicInputs<F, D>> {
prove(&self.prover_only, &self.common, inputs)
}
@ -127,19 +127,19 @@ impl<F: Extendable<D>, const D: usize> ProverCircuitData<F, D> {
/// Circuit data required by the prover.
#[derive(Debug)]
pub struct VerifierCircuitData<F: Extendable<D>, const D: usize> {
pub struct VerifierCircuitData<F: PrimeField + Extendable<D>, const D: usize> {
pub(crate) verifier_only: VerifierOnlyCircuitData<F>,
pub(crate) common: CommonCircuitData<F, D>,
}
impl<F: Extendable<D>, const D: usize> VerifierCircuitData<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> VerifierCircuitData<F, D> {
pub fn verify(&self, proof_with_pis: ProofWithPublicInputs<F, D>) -> Result<()> {
verify(proof_with_pis, &self.verifier_only, &self.common)
}
}
/// Circuit data required by the prover, but not the verifier.
pub(crate) struct ProverOnlyCircuitData<F: Extendable<D>, const D: usize> {
pub(crate) struct ProverOnlyCircuitData<F: PrimeField + Extendable<D>, const D: usize> {
pub generators: Vec<Box<dyn WitnessGenerator<F>>>,
/// Commitments to the constants polynomials and sigma polynomials.
pub constants_sigmas_commitment: PolynomialBatchCommitment<F>,
@ -166,7 +166,7 @@ pub(crate) struct VerifierOnlyCircuitData<F: Field> {
/// Circuit data required by both the prover and the verifier.
#[derive(Debug)]
pub struct CommonCircuitData<F: Extendable<D>, const D: usize> {
pub struct CommonCircuitData<F: PrimeField + Extendable<D>, const D: usize> {
pub(crate) config: CircuitConfig,
pub(crate) degree_bits: usize,
@ -195,7 +195,7 @@ pub struct CommonCircuitData<F: Extendable<D>, const D: usize> {
pub(crate) circuit_digest: HashOut<F>,
}
impl<F: Extendable<D>, const D: usize> CommonCircuitData<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CommonCircuitData<F, D> {
pub fn degree(&self) -> usize {
1 << self.degree_bits
}

View File

@ -1,6 +1,6 @@
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::fri::commitment::SALT_SIZE;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -58,7 +58,7 @@ impl PlonkPolynomials {
/// Evaluate the polynomial which vanishes on any multiplicative subgroup of a given order `n`.
pub(crate) fn eval_zero_poly<F: Field>(n: usize, x: F) -> F {
// Z(x) = x^n - 1
x.exp(n as u64) - F::ONE
x.exp_u64(n as u64) - F::ONE
}
/// Precomputations of the evaluation of `Z_H(X) = X^n - 1` on a coset `gK` with `H <= K`.
@ -125,7 +125,7 @@ pub(crate) fn eval_l_1<F: Field>(n: usize, x: F) -> F {
/// the order-`n` subgroup.
///
/// Assumes `x != 1`; if `x` could be 1 then this is unsound.
pub(crate) fn eval_l_1_recursively<F: Extendable<D>, const D: usize>(
pub(crate) fn eval_l_1_recursively<F: PrimeField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
n: usize,
x: ExtensionTarget<D>,
@ -163,7 +163,7 @@ pub(crate) fn reduce_with_powers<F: Field>(terms: &[F], alpha: F) -> F {
sum
}
pub(crate) fn reduce_with_powers_ext_recursive<F: Extendable<D>, const D: usize>(
pub(crate) fn reduce_with_powers_ext_recursive<F: PrimeField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
terms: &[ExtensionTarget<D>],
alpha: Target,

View File

@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::fri::commitment::PolynomialBatchCommitment;
use crate::fri::proof::{FriProof, FriProofTarget};
use crate::hash::hash_types::MerkleCapTarget;
@ -57,7 +58,7 @@ pub struct OpeningSet<F: Extendable<D>, const D: usize> {
pub quotient_polys: Vec<F::Extension>,
}
impl<F: Extendable<D>, const D: usize> OpeningSet<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> OpeningSet<F, D> {
pub fn new(
z: F::Extension,
g: F::Extension,

View File

@ -3,6 +3,7 @@ use log::Level;
use rayon::prelude::*;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::fri::commitment::PolynomialBatchCommitment;
use crate::hash::hash_types::HashOut;
use crate::hash::hashing::hash_n_to_hash;
@ -21,7 +22,7 @@ use crate::util::partial_products::partial_products;
use crate::util::timing::TimingTree;
use crate::util::{log2_ceil, transpose};
pub(crate) fn prove<F: Extendable<D>, const D: usize>(
pub(crate) fn prove<F: PrimeField + Extendable<D>, const D: usize>(
prover_data: &ProverOnlyCircuitData<F, D>,
common_data: &CommonCircuitData<F, D>,
inputs: PartialWitness<F>,
@ -216,7 +217,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
}
/// Compute the partial products used in the `Z` polynomials.
fn all_wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
fn all_wires_permutation_partial_products<F: PrimeField + Extendable<D>, const D: usize>(
witness: &MatrixWitness<F>,
betas: &[F],
gammas: &[F],
@ -239,7 +240,7 @@ fn all_wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
/// Compute the partial products used in the `Z` polynomial.
/// Returns the polynomials interpolating `partial_products(f / g)`
/// where `f, g` are the products in the definition of `Z`: `Z(g^i) = f / g`.
fn wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
fn wires_permutation_partial_products<F: PrimeField + Extendable<D>, const D: usize>(
witness: &MatrixWitness<F>,
beta: F,
gamma: F,
@ -293,7 +294,7 @@ fn wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
.collect()
}
fn compute_zs<F: Extendable<D>, const D: usize>(
fn compute_zs<F: PrimeField + Extendable<D>, const D: usize>(
partial_products: &[Vec<PolynomialValues<F>>],
common_data: &CommonCircuitData<F, D>,
) -> Vec<PolynomialValues<F>> {
@ -303,7 +304,7 @@ fn compute_zs<F: Extendable<D>, const D: usize>(
}
/// Compute the `Z` polynomial by reusing the computations done in `wires_permutation_partial_products`.
fn compute_z<F: Extendable<D>, const D: usize>(
fn compute_z<F: PrimeField + Extendable<D>, const D: usize>(
partial_products: &[PolynomialValues<F>],
common_data: &CommonCircuitData<F, D>,
) -> PolynomialValues<F> {
@ -316,7 +317,7 @@ fn compute_z<F: Extendable<D>, const D: usize>(
plonk_z_points.into()
}
fn compute_quotient_polys<'a, F: Extendable<D>, const D: usize>(
fn compute_quotient_polys<'a, F: PrimeField + Extendable<D>, const D: usize>(
common_data: &CommonCircuitData<F, D>,
prover_data: &'a ProverOnlyCircuitData<F, D>,
public_inputs_hash: &HashOut<F>,

View File

@ -1,4 +1,5 @@
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::hash::hash_types::HashOutTarget;
use crate::iop::challenger::RecursiveChallenger;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -9,7 +10,7 @@ use crate::plonk::vars::EvaluationTargets;
use crate::util::reducing::ReducingFactorTarget;
use crate::with_context;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
impl<F: PrimeField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Recursively verifies an inner proof.
pub fn add_recursive_verifier(
&mut self,
@ -139,7 +140,7 @@ mod tests {
use crate::util::log2_strict;
// Construct a `FriQueryRoundTarget` with the same dimensions as the ones in `proof`.
fn get_fri_query_round<F: Extendable<D>, const D: usize>(
fn get_fri_query_round<F: PrimeField + Extendable<D>, const D: usize>(
proof: &Proof<F, D>,
builder: &mut CircuitBuilder<F, D>,
) -> FriQueryRoundTarget<D> {
@ -172,7 +173,7 @@ mod tests {
}
// Construct a `ProofTarget` with the same dimensions as `proof`.
fn proof_to_proof_target<F: Extendable<D>, const D: usize>(
fn proof_to_proof_target<F: PrimeField + Extendable<D>, const D: usize>(
proof_with_pis: &ProofWithPublicInputs<F, D>,
builder: &mut CircuitBuilder<F, D>,
) -> ProofWithPublicInputsTarget<D> {

View File

@ -1,6 +1,6 @@
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::gate::PrefixedGate;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -15,7 +15,7 @@ use crate::with_context;
/// Evaluate the vanishing polynomial at `x`. In this context, the vanishing polynomial is a random
/// linear combination of gate constraints, plus some other terms relating to the permutation
/// argument. All such terms should vanish on `H`.
pub(crate) fn eval_vanishing_poly<F: Extendable<D>, const D: usize>(
pub(crate) fn eval_vanishing_poly<F: PrimeField + Extendable<D>, const D: usize>(
common_data: &CommonCircuitData<F, D>,
x: F::Extension,
vars: EvaluationVars<F, D>,
@ -102,7 +102,7 @@ pub(crate) fn eval_vanishing_poly<F: Extendable<D>, const D: usize>(
}
/// Like `eval_vanishing_poly`, but specialized for base field points.
pub(crate) fn eval_vanishing_poly_base<F: Extendable<D>, const D: usize>(
pub(crate) fn eval_vanishing_poly_base<F: PrimeField + Extendable<D>, const D: usize>(
common_data: &CommonCircuitData<F, D>,
index: usize,
x: F,
@ -200,7 +200,7 @@ pub(crate) fn eval_vanishing_poly_base<F: Extendable<D>, const D: usize>(
/// `num_gate_constraints` is the largest number of constraints imposed by any gate. It is not
/// strictly necessary, but it helps performance by ensuring that we allocate a vector with exactly
/// the capacity that we need.
pub fn evaluate_gate_constraints<F: Extendable<D>, const D: usize>(
pub fn evaluate_gate_constraints<F: PrimeField + Extendable<D>, const D: usize>(
gates: &[PrefixedGate<F, D>],
num_gate_constraints: usize,
vars: EvaluationVars<F, D>,
@ -219,7 +219,7 @@ pub fn evaluate_gate_constraints<F: Extendable<D>, const D: usize>(
constraints
}
pub fn evaluate_gate_constraints_base<F: Extendable<D>, const D: usize>(
pub fn evaluate_gate_constraints_base<F: PrimeField + Extendable<D>, const D: usize>(
gates: &[PrefixedGate<F, D>],
num_gate_constraints: usize,
vars: EvaluationVarsBase<F>,
@ -238,7 +238,7 @@ pub fn evaluate_gate_constraints_base<F: Extendable<D>, const D: usize>(
constraints
}
pub fn evaluate_gate_constraints_recursively<F: Extendable<D>, const D: usize>(
pub fn evaluate_gate_constraints_recursively<F: PrimeField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
gates: &[PrefixedGate<F, D>],
num_gate_constraints: usize,
@ -270,7 +270,7 @@ pub fn evaluate_gate_constraints_recursively<F: Extendable<D>, const D: usize>(
///
/// Assumes `x != 1`; if `x` could be 1 then this is unsound. This is fine if `x` is a random
/// variable drawn from a sufficiently large domain.
pub(crate) fn eval_vanishing_poly_recursively<F: Extendable<D>, const D: usize>(
pub(crate) fn eval_vanishing_poly_recursively<F: PrimeField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
common_data: &CommonCircuitData<F, D>,
x: ExtensionTarget<D>,

View File

@ -1,7 +1,7 @@
use anyhow::{ensure, Result};
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::fri::verifier::verify_fri_proof;
use crate::hash::hashing::hash_n_to_hash;
use crate::iop::challenger::Challenger;
@ -11,7 +11,7 @@ use crate::plonk::proof::ProofWithPublicInputs;
use crate::plonk::vanishing_poly::eval_vanishing_poly;
use crate::plonk::vars::EvaluationVars;
pub(crate) fn verify<F: Extendable<D>, const D: usize>(
pub(crate) fn verify<F: PrimeField + Extendable<D>, const D: usize>(
proof_with_pis: ProofWithPublicInputs<F, D>,
verifier_data: &VerifierOnlyCircuitData<F>,
common_data: &CommonCircuitData<F, D>,

View File

@ -90,8 +90,8 @@ impl<F: Field> PolynomialCoeffs<F> {
// Equals to the evaluation of `a` on `{g.w^i}`.
let mut a_eval = fft(&a);
// Compute the denominators `1/(g^n.w^(n*i) - 1)` using batch inversion.
let denominator_g = g.exp(n as u64);
let root_n = root.exp(n as u64);
let denominator_g = g.exp_u64(n as u64);
let root_n = root.exp_u64(n as u64);
let mut root_pow = F::ONE;
let denominators = (0..a_eval.len())
.map(|i| {

View File

@ -585,7 +585,7 @@ mod tests {
PolynomialCoeffs::new(xn_min_one_vec)
};
let a = g.exp(rng.gen_range(0..(n as u64)));
let a = g.exp_u64(rng.gen_range(0..(n as u64)));
let denom = PolynomialCoeffs::new(vec![-a, F::ONE]);
let now = Instant::now();
xn_minus_one.div_rem(&denom);

View File

@ -3,6 +3,7 @@ use std::ops::Sub;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::PrimeField;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::util::ceil_div_usize;
@ -60,7 +61,7 @@ pub fn check_partial_products<T: Product + Copy + Sub<Output = T>>(
res
}
pub fn check_partial_products_recursively<F: Extendable<D>, const D: usize>(
pub fn check_partial_products_recursively<F: PrimeField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
v: &[ExtensionTarget<D>],
partials: &[ExtensionTarget<D>],

View File

@ -2,7 +2,7 @@ use std::borrow::Borrow;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
use crate::gates::reducing::ReducingGate;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -67,13 +67,13 @@ impl<F: Field> ReducingFactor<F> {
}
pub fn shift(&mut self, x: F) -> F {
let tmp = self.base.exp(self.count) * x;
let tmp = self.base.exp_u64(self.count) * x;
self.count = 0;
tmp
}
pub fn shift_poly(&mut self, p: &mut PolynomialCoeffs<F>) {
*p *= self.base.exp(self.count);
*p *= self.base.exp_u64(self.count);
self.count = 0;
}
@ -100,7 +100,7 @@ impl<const D: usize> ReducingFactorTarget<D> {
builder: &mut CircuitBuilder<F, D>,
) -> ExtensionTarget<D>
where
F: Extendable<D>,
F: PrimeField + Extendable<D>,
{
let max_coeffs_len = ReducingGate::<D>::max_coeffs_len(
builder.config.num_wires,
@ -149,7 +149,7 @@ impl<const D: usize> ReducingFactorTarget<D> {
builder: &mut CircuitBuilder<F, D>,
) -> ExtensionTarget<D>
where
F: Extendable<D>,
F: PrimeField + Extendable<D>,
{
let l = terms.len();
self.count += l as u64;
@ -170,7 +170,7 @@ impl<const D: usize> ReducingFactorTarget<D> {
builder: &mut CircuitBuilder<F, D>,
) -> ExtensionTarget<D>
where
F: Extendable<D>,
F: PrimeField + Extendable<D>,
{
let exp = builder.exp_u64_extension(self.base, self.count);
self.count = 0;