mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-08 00:33:06 +00:00
Merge pull request #44 from mir-protocol/fri-extension-field
FRI with extension fields
This commit is contained in:
commit
7d302aac34
@ -3,6 +3,7 @@ use env_logger::Env;
|
||||
use plonky2::circuit_builder::CircuitBuilder;
|
||||
use plonky2::circuit_data::CircuitConfig;
|
||||
use plonky2::field::crandall_field::CrandallField;
|
||||
use plonky2::field::extension_field::Extendable;
|
||||
use plonky2::field::field::Field;
|
||||
use plonky2::fri::FriConfig;
|
||||
use plonky2::gates::constant::ConstantGate;
|
||||
@ -18,7 +19,7 @@ fn main() {
|
||||
// change this to info or warn later.
|
||||
env_logger::Builder::from_env(Env::default().default_filter_or("debug")).init();
|
||||
|
||||
bench_prove::<CrandallField>();
|
||||
bench_prove::<CrandallField, 2>();
|
||||
|
||||
// bench_field_mul::<CrandallField>();
|
||||
|
||||
@ -27,7 +28,7 @@ fn main() {
|
||||
// bench_gmimc::<CrandallField>();
|
||||
}
|
||||
|
||||
fn bench_prove<F: Field>() {
|
||||
fn bench_prove<F: Field + Extendable<D>, const D: usize>() {
|
||||
let gmimc_gate = GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants();
|
||||
|
||||
let config = CircuitConfig {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field::Field;
|
||||
use crate::fri::FriConfig;
|
||||
use crate::gates::gate::GateRef;
|
||||
@ -56,7 +57,10 @@ pub struct CircuitData<F: Field> {
|
||||
}
|
||||
|
||||
impl<F: Field> CircuitData<F> {
|
||||
pub fn prove(&self, inputs: PartialWitness<F>) -> Proof<F> {
|
||||
pub fn prove<const D: usize>(&self, inputs: PartialWitness<F>) -> Proof<F, D>
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
prove(&self.prover_only, &self.common, inputs)
|
||||
}
|
||||
|
||||
@ -78,7 +82,10 @@ pub struct ProverCircuitData<F: Field> {
|
||||
}
|
||||
|
||||
impl<F: Field> ProverCircuitData<F> {
|
||||
pub fn prove(&self, inputs: PartialWitness<F>) -> Proof<F> {
|
||||
pub fn prove<const D: usize>(&self, inputs: PartialWitness<F>) -> Proof<F, D>
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
prove(&self.prover_only, &self.common, inputs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,9 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi
|
||||
|
||||
use num::Integer;
|
||||
|
||||
use crate::field::extension_field::quadratic::QuadraticCrandallField;
|
||||
use crate::field::extension_field::quartic::QuarticCrandallField;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field::Field;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter::{Product, Sum};
|
||||
@ -412,6 +415,14 @@ impl DivAssign for CrandallField {
|
||||
}
|
||||
}
|
||||
|
||||
impl Extendable<2> for CrandallField {
|
||||
type Extension = QuadraticCrandallField;
|
||||
}
|
||||
|
||||
impl Extendable<4> for CrandallField {
|
||||
type Extension = QuarticCrandallField;
|
||||
}
|
||||
|
||||
/// Reduces to a 64-bit value. The result might not be in canonical form; it could be in between the
|
||||
/// field order and `2^64`.
|
||||
#[inline]
|
||||
|
||||
@ -1,2 +1,97 @@
|
||||
pub mod binary;
|
||||
use crate::field::extension_field::quadratic::QuadraticFieldExtension;
|
||||
use crate::field::extension_field::quartic::QuarticFieldExtension;
|
||||
use crate::field::field::Field;
|
||||
|
||||
pub mod quadratic;
|
||||
pub mod quartic;
|
||||
|
||||
pub trait Extendable<const D: usize>: Sized {
|
||||
type Extension: Field + FieldExtension<D, BaseField = Self> + From<Self>;
|
||||
}
|
||||
|
||||
impl<F: Field> Extendable<1> for F {
|
||||
type Extension = Self;
|
||||
}
|
||||
|
||||
pub trait FieldExtension<const D: usize>: Field {
|
||||
type BaseField: Field;
|
||||
|
||||
fn to_basefield_array(&self) -> [Self::BaseField; D];
|
||||
|
||||
fn from_basefield_array(arr: [Self::BaseField; D]) -> Self;
|
||||
|
||||
fn from_basefield(x: Self::BaseField) -> Self;
|
||||
}
|
||||
|
||||
impl<F: Field> FieldExtension<1> for F {
|
||||
type BaseField = F;
|
||||
|
||||
fn to_basefield_array(&self) -> [Self::BaseField; 1] {
|
||||
[*self]
|
||||
}
|
||||
|
||||
fn from_basefield_array(arr: [Self::BaseField; 1]) -> Self {
|
||||
arr[0]
|
||||
}
|
||||
|
||||
fn from_basefield(x: Self::BaseField) -> Self {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
impl<FE: QuadraticFieldExtension> FieldExtension<2> for FE {
|
||||
type BaseField = FE::BaseField;
|
||||
|
||||
fn to_basefield_array(&self) -> [Self::BaseField; 2] {
|
||||
self.to_canonical_representation()
|
||||
}
|
||||
|
||||
fn from_basefield_array(arr: [Self::BaseField; 2]) -> Self {
|
||||
Self::from_canonical_representation(arr)
|
||||
}
|
||||
|
||||
fn from_basefield(x: Self::BaseField) -> Self {
|
||||
x.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<FE: QuarticFieldExtension> FieldExtension<4> for FE {
|
||||
type BaseField = FE::BaseField;
|
||||
|
||||
fn to_basefield_array(&self) -> [Self::BaseField; 4] {
|
||||
self.to_canonical_representation()
|
||||
}
|
||||
|
||||
fn from_basefield_array(arr: [Self::BaseField; 4]) -> Self {
|
||||
Self::from_canonical_representation(arr)
|
||||
}
|
||||
|
||||
fn from_basefield(x: Self::BaseField) -> Self {
|
||||
x.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Flatten the slice by sending every extension field element to its D-sized canonical representation.
|
||||
pub fn flatten<F: Field, const D: usize>(l: &[F::Extension]) -> Vec<F>
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
l.iter()
|
||||
.flat_map(|x| x.to_basefield_array().to_vec())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Batch every D-sized chunks into extension field elements.
|
||||
pub fn unflatten<F: Field, const D: usize>(l: &[F]) -> Vec<F::Extension>
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
debug_assert_eq!(l.len() % D, 0);
|
||||
l.chunks_exact(D)
|
||||
.map(|c| {
|
||||
let mut arr = [F::ZERO; D];
|
||||
arr.copy_from_slice(c);
|
||||
F::Extension::from_basefield_array(arr)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -6,7 +6,9 @@ use std::hash::{Hash, Hasher};
|
||||
use std::iter::{Product, Sum};
|
||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
|
||||
pub trait BinaryFieldExtension: Field {
|
||||
pub trait QuadraticFieldExtension:
|
||||
Field + From<<Self as QuadraticFieldExtension>::BaseField>
|
||||
{
|
||||
type BaseField: Field;
|
||||
|
||||
// Element W of BaseField, such that `X^2 - W` is irreducible over BaseField.
|
||||
@ -30,14 +32,12 @@ pub trait BinaryFieldExtension: Field {
|
||||
|
||||
Self::from_canonical_representation([a0, a1 * z])
|
||||
}
|
||||
|
||||
fn scalar_mul(&self, c: Self::BaseField) -> Self;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct BinaryCrandallField([CrandallField; 2]);
|
||||
pub struct QuadraticCrandallField([CrandallField; 2]);
|
||||
|
||||
impl BinaryFieldExtension for BinaryCrandallField {
|
||||
impl QuadraticFieldExtension for QuadraticCrandallField {
|
||||
type BaseField = CrandallField;
|
||||
// Verifiable in Sage with
|
||||
// ``R.<x> = GF(p)[]; assert (x^2 -3).is_irreducible()`.
|
||||
@ -50,22 +50,23 @@ impl BinaryFieldExtension for BinaryCrandallField {
|
||||
fn from_canonical_representation(v: [Self::BaseField; 2]) -> Self {
|
||||
Self(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn scalar_mul(&self, c: Self::BaseField) -> Self {
|
||||
let [a0, a1] = self.to_canonical_representation();
|
||||
Self([a0 * c, a1 * c])
|
||||
impl From<<Self as QuadraticFieldExtension>::BaseField> for QuadraticCrandallField {
|
||||
fn from(x: <Self as QuadraticFieldExtension>::BaseField) -> Self {
|
||||
Self([x, <Self as QuadraticFieldExtension>::BaseField::ZERO])
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for BinaryCrandallField {
|
||||
impl PartialEq for QuadraticCrandallField {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.to_canonical_representation() == other.to_canonical_representation()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for BinaryCrandallField {}
|
||||
impl Eq for QuadraticCrandallField {}
|
||||
|
||||
impl Hash for BinaryCrandallField {
|
||||
impl Hash for QuadraticCrandallField {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
for l in &self.to_canonical_representation() {
|
||||
Hash::hash(l, state);
|
||||
@ -73,7 +74,7 @@ impl Hash for BinaryCrandallField {
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for BinaryCrandallField {
|
||||
impl Field for QuadraticCrandallField {
|
||||
const ZERO: Self = Self([CrandallField::ZERO; 2]);
|
||||
const ONE: Self = Self([CrandallField::ONE, CrandallField::ZERO]);
|
||||
const TWO: Self = Self([CrandallField::TWO, CrandallField::ZERO]);
|
||||
@ -82,9 +83,15 @@ impl Field for BinaryCrandallField {
|
||||
// Does not fit in 64-bits.
|
||||
const ORDER: u64 = 0;
|
||||
const TWO_ADICITY: usize = 29;
|
||||
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([CrandallField(3), CrandallField::ONE]);
|
||||
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([
|
||||
CrandallField(6483724566312148654),
|
||||
CrandallField(12194665049945415126),
|
||||
]);
|
||||
// Chosen so that when raised to the power `1<<(Self::TWO_ADICITY-Self::BaseField::TWO_ADICITY)`,
|
||||
// we get `Self::BaseField::POWER_OF_TWO_GENERATOR`. This makes `primitive_root_of_unity` coherent
|
||||
// with the base field which implies that the FFT commutes with field inclusion.
|
||||
const POWER_OF_TWO_GENERATOR: Self =
|
||||
Self([CrandallField::ZERO, CrandallField(7889429148549342301)]);
|
||||
Self([CrandallField::ZERO, CrandallField(14420468973723774561)]);
|
||||
|
||||
// Algorithm 11.3.4 in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
|
||||
fn try_inverse(&self) -> Option<Self> {
|
||||
@ -96,7 +103,7 @@ impl Field for BinaryCrandallField {
|
||||
let a_pow_r = a_pow_r_minus_1 * *self;
|
||||
debug_assert!(a_pow_r.is_in_basefield());
|
||||
|
||||
Some(a_pow_r_minus_1.scalar_mul(a_pow_r.0[0].inverse()))
|
||||
Some(a_pow_r_minus_1 * a_pow_r.0[0].inverse().into())
|
||||
}
|
||||
|
||||
fn to_canonical_u64(&self) -> u64 {
|
||||
@ -105,32 +112,32 @@ impl Field for BinaryCrandallField {
|
||||
|
||||
fn from_canonical_u64(n: u64) -> Self {
|
||||
Self([
|
||||
<Self as BinaryFieldExtension>::BaseField::from_canonical_u64(n),
|
||||
<Self as BinaryFieldExtension>::BaseField::ZERO,
|
||||
<Self as QuadraticFieldExtension>::BaseField::from_canonical_u64(n),
|
||||
<Self as QuadraticFieldExtension>::BaseField::ZERO,
|
||||
])
|
||||
}
|
||||
|
||||
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
|
||||
Self([
|
||||
<Self as BinaryFieldExtension>::BaseField::rand_from_rng(rng),
|
||||
<Self as BinaryFieldExtension>::BaseField::rand_from_rng(rng),
|
||||
<Self as QuadraticFieldExtension>::BaseField::rand_from_rng(rng),
|
||||
<Self as QuadraticFieldExtension>::BaseField::rand_from_rng(rng),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BinaryCrandallField {
|
||||
impl Display for QuadraticCrandallField {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} + {}*a", self.0[0], self.0[1])
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for BinaryCrandallField {
|
||||
impl Debug for QuadraticCrandallField {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for BinaryCrandallField {
|
||||
impl Neg for QuadraticCrandallField {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
@ -139,7 +146,7 @@ impl Neg for BinaryCrandallField {
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for BinaryCrandallField {
|
||||
impl Add for QuadraticCrandallField {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
@ -148,19 +155,19 @@ impl Add for BinaryCrandallField {
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for BinaryCrandallField {
|
||||
impl AddAssign for QuadraticCrandallField {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
*self = *self + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sum for BinaryCrandallField {
|
||||
impl Sum for QuadraticCrandallField {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::ZERO, |acc, x| acc + x)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for BinaryCrandallField {
|
||||
impl Sub for QuadraticCrandallField {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
@ -169,14 +176,14 @@ impl Sub for BinaryCrandallField {
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for BinaryCrandallField {
|
||||
impl SubAssign for QuadraticCrandallField {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for BinaryCrandallField {
|
||||
impl Mul for QuadraticCrandallField {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
@ -191,20 +198,20 @@ impl Mul for BinaryCrandallField {
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for BinaryCrandallField {
|
||||
impl MulAssign for QuadraticCrandallField {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, rhs: Self) {
|
||||
*self = *self * rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Product for BinaryCrandallField {
|
||||
impl Product for QuadraticCrandallField {
|
||||
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::ONE, |acc, x| acc * x)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div for BinaryCrandallField {
|
||||
impl Div for QuadraticCrandallField {
|
||||
type Output = Self;
|
||||
|
||||
#[allow(clippy::suspicious_arithmetic_impl)]
|
||||
@ -213,7 +220,7 @@ impl Div for BinaryCrandallField {
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign for BinaryCrandallField {
|
||||
impl DivAssign for QuadraticCrandallField {
|
||||
fn div_assign(&mut self, rhs: Self) {
|
||||
*self = *self / rhs;
|
||||
}
|
||||
@ -221,7 +228,9 @@ impl DivAssign for BinaryCrandallField {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::field::extension_field::binary::{BinaryCrandallField, BinaryFieldExtension};
|
||||
use crate::field::extension_field::quadratic::{
|
||||
QuadraticCrandallField, QuadraticFieldExtension,
|
||||
};
|
||||
use crate::field::field::Field;
|
||||
|
||||
fn exp_naive<F: Field>(x: F, power: u64) -> F {
|
||||
@ -239,7 +248,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_add_neg_sub_mul() {
|
||||
type F = BinaryCrandallField;
|
||||
type F = QuadraticCrandallField;
|
||||
let x = F::rand();
|
||||
let y = F::rand();
|
||||
let z = F::rand();
|
||||
@ -247,7 +256,7 @@ mod tests {
|
||||
assert_eq!(-x, F::ZERO - x);
|
||||
assert_eq!(
|
||||
x + x,
|
||||
x.scalar_mul(<F as BinaryFieldExtension>::BaseField::TWO)
|
||||
x * <F as QuadraticFieldExtension>::BaseField::TWO.into()
|
||||
);
|
||||
assert_eq!(x * (-x), -x.square());
|
||||
assert_eq!(x + y, y + x);
|
||||
@ -260,7 +269,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_inv_div() {
|
||||
type F = BinaryCrandallField;
|
||||
type F = QuadraticCrandallField;
|
||||
let x = F::rand();
|
||||
let y = F::rand();
|
||||
let z = F::rand();
|
||||
@ -274,10 +283,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_frobenius() {
|
||||
type F = BinaryCrandallField;
|
||||
type F = QuadraticCrandallField;
|
||||
let x = F::rand();
|
||||
assert_eq!(
|
||||
exp_naive(x, <F as BinaryFieldExtension>::BaseField::ORDER),
|
||||
exp_naive(x, <F as QuadraticFieldExtension>::BaseField::ORDER),
|
||||
x.frobenius()
|
||||
);
|
||||
}
|
||||
@ -285,11 +294,29 @@ mod tests {
|
||||
#[test]
|
||||
fn test_field_order() {
|
||||
// F::ORDER = 340282366831806780677557380898690695169 = 18446744071293632512 *18446744071293632514 + 1
|
||||
type F = BinaryCrandallField;
|
||||
type F = QuadraticCrandallField;
|
||||
let x = F::rand();
|
||||
assert_eq!(
|
||||
exp_naive(exp_naive(x, 18446744071293632512), 18446744071293632514),
|
||||
F::ONE
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_power_of_two_gen() {
|
||||
type F = QuadraticCrandallField;
|
||||
// F::ORDER = 2^29 * 2762315674048163 * 229454332791453 + 1
|
||||
assert_eq!(
|
||||
F::MULTIPLICATIVE_GROUP_GENERATOR
|
||||
.exp_usize(2762315674048163)
|
||||
.exp_usize(229454332791453),
|
||||
F::POWER_OF_TWO_GENERATOR
|
||||
);
|
||||
assert_eq!(
|
||||
F::POWER_OF_TWO_GENERATOR.exp_usize(
|
||||
1 << (F::TWO_ADICITY - <F as QuadraticFieldExtension>::BaseField::TWO_ADICITY)
|
||||
),
|
||||
<F as QuadraticFieldExtension>::BaseField::POWER_OF_TWO_GENERATOR.into()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ use std::hash::{Hash, Hasher};
|
||||
use std::iter::{Product, Sum};
|
||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
|
||||
pub trait QuarticFieldExtension: Field {
|
||||
pub trait QuarticFieldExtension: Field + From<<Self as QuarticFieldExtension>::BaseField> {
|
||||
type BaseField: Field;
|
||||
|
||||
// Element W of BaseField, such that `X^4 - W` is irreducible over BaseField.
|
||||
@ -38,8 +38,6 @@ pub trait QuarticFieldExtension: Field {
|
||||
|
||||
Self::from_canonical_representation([b0, b1, b2, b3])
|
||||
}
|
||||
|
||||
fn scalar_mul(&self, c: Self::BaseField) -> Self;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -58,10 +56,16 @@ impl QuarticFieldExtension for QuarticCrandallField {
|
||||
fn from_canonical_representation(v: [Self::BaseField; 4]) -> Self {
|
||||
Self(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn scalar_mul(&self, c: Self::BaseField) -> Self {
|
||||
let [a0, a1, a2, a3] = self.to_canonical_representation();
|
||||
Self([a0 * c, a1 * c, a2 * c, a3 * c])
|
||||
impl From<<Self as QuarticFieldExtension>::BaseField> for QuarticCrandallField {
|
||||
fn from(x: <Self as QuarticFieldExtension>::BaseField) -> Self {
|
||||
Self([
|
||||
x,
|
||||
<Self as QuarticFieldExtension>::BaseField::ZERO,
|
||||
<Self as QuarticFieldExtension>::BaseField::ZERO,
|
||||
<Self as QuarticFieldExtension>::BaseField::ZERO,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,16 +110,19 @@ impl Field for QuarticCrandallField {
|
||||
const ORDER: u64 = 0;
|
||||
const TWO_ADICITY: usize = 30;
|
||||
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([
|
||||
CrandallField(3),
|
||||
CrandallField::ONE,
|
||||
CrandallField::ZERO,
|
||||
CrandallField::ZERO,
|
||||
CrandallField(12476589904174392631),
|
||||
CrandallField(896937834427772243),
|
||||
CrandallField(7795248119019507390),
|
||||
CrandallField(9005769437373554825),
|
||||
]);
|
||||
// Chosen so that when raised to the power `1<<(Self::TWO_ADICITY-Self::BaseField::TWO_ADICITY)`,
|
||||
// we get `Self::BaseField::POWER_OF_TWO_GENERATOR`. This makes `primitive_root_of_unity` coherent
|
||||
// with the base field which implies that the FFT commutes with field inclusion.
|
||||
const POWER_OF_TWO_GENERATOR: Self = Self([
|
||||
CrandallField::ZERO,
|
||||
CrandallField::ZERO,
|
||||
CrandallField::ZERO,
|
||||
CrandallField(14096607364803438105),
|
||||
CrandallField(15170983443234254033),
|
||||
]);
|
||||
|
||||
// Algorithm 11.3.4 in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
|
||||
@ -131,7 +138,7 @@ impl Field for QuarticCrandallField {
|
||||
let a_pow_r = a_pow_r_minus_1 * *self;
|
||||
debug_assert!(a_pow_r.is_in_basefield());
|
||||
|
||||
Some(a_pow_r_minus_1.scalar_mul(a_pow_r.0[0].inverse()))
|
||||
Some(a_pow_r_minus_1 * a_pow_r.0[0].inverse().into())
|
||||
}
|
||||
|
||||
fn to_canonical_u64(&self) -> u64 {
|
||||
@ -302,7 +309,7 @@ mod tests {
|
||||
assert_eq!(-x, F::ZERO - x);
|
||||
assert_eq!(
|
||||
x + x,
|
||||
x.scalar_mul(<F as QuarticFieldExtension>::BaseField::TWO)
|
||||
x * <F as QuarticFieldExtension>::BaseField::TWO.into()
|
||||
);
|
||||
assert_eq!(x * (-x), -x.square());
|
||||
assert_eq!(x + y, y + x);
|
||||
@ -350,4 +357,26 @@ mod tests {
|
||||
F::ONE
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_power_of_two_gen() {
|
||||
type F = QuarticCrandallField;
|
||||
// F::ORDER = 2^30 * 1090552343587053358839971118999869 * 98885475095492590491252558464653635 + 1
|
||||
assert_eq!(
|
||||
exp_naive(
|
||||
exp_naive(
|
||||
F::MULTIPLICATIVE_GROUP_GENERATOR,
|
||||
1090552343587053358839971118999869
|
||||
),
|
||||
98885475095492590491252558464653635
|
||||
),
|
||||
F::POWER_OF_TWO_GENERATOR
|
||||
);
|
||||
assert_eq!(
|
||||
F::POWER_OF_TWO_GENERATOR.exp_usize(
|
||||
1 << (F::TWO_ADICITY - <F as QuarticFieldExtension>::BaseField::TWO_ADICITY)
|
||||
),
|
||||
<F as QuarticFieldExtension>::BaseField::POWER_OF_TWO_GENERATOR.into()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ use std::iter::{Product, Sum};
|
||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
|
||||
use num::Integer;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::Rng;
|
||||
|
||||
use crate::util::bits_u64;
|
||||
|
||||
@ -52,26 +52,27 @@ fn fri_l(codeword_len: usize, rate_log: usize, conjecture: bool) -> f64 {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::field::crandall_field::CrandallField;
|
||||
use crate::field::extension_field::quadratic::QuadraticCrandallField;
|
||||
use crate::field::extension_field::quartic::QuarticCrandallField;
|
||||
use crate::field::extension_field::{flatten, Extendable, FieldExtension};
|
||||
use crate::field::fft::ifft;
|
||||
use crate::field::field::Field;
|
||||
use crate::fri::prover::fri_proof;
|
||||
use crate::fri::verifier::verify_fri_proof;
|
||||
use crate::merkle_tree::MerkleTree;
|
||||
use crate::plonk_challenger::Challenger;
|
||||
use crate::polynomial::polynomial::PolynomialCoeffs;
|
||||
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||
use crate::util::reverse_index_bits_in_place;
|
||||
use anyhow::Result;
|
||||
use rand::rngs::ThreadRng;
|
||||
use rand::Rng;
|
||||
|
||||
fn test_fri(
|
||||
fn check_fri<F: Field + Extendable<D>, const D: usize>(
|
||||
degree_log: usize,
|
||||
rate_bits: usize,
|
||||
reduction_arity_bits: Vec<usize>,
|
||||
num_query_rounds: usize,
|
||||
) -> Result<()> {
|
||||
type F = CrandallField;
|
||||
|
||||
let n = 1 << degree_log;
|
||||
let coeffs = PolynomialCoeffs::new(F::rand_vec(n)).lde(rate_bits);
|
||||
let coset_lde = coeffs.clone().coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR);
|
||||
@ -91,15 +92,28 @@ mod tests {
|
||||
reverse_index_bits_in_place(&mut leaves);
|
||||
MerkleTree::new(leaves, false)
|
||||
};
|
||||
let coset_lde = PolynomialValues::new(
|
||||
coset_lde
|
||||
.values
|
||||
.into_iter()
|
||||
.map(F::Extension::from)
|
||||
.collect(),
|
||||
);
|
||||
let root = tree.root;
|
||||
let mut challenger = Challenger::new();
|
||||
let proof = fri_proof(&[&tree], &coeffs, &coset_lde, &mut challenger, &config);
|
||||
let proof = fri_proof::<F, D>(
|
||||
&[&tree],
|
||||
&coeffs.to_extension::<D>(),
|
||||
&coset_lde,
|
||||
&mut challenger,
|
||||
&config,
|
||||
);
|
||||
|
||||
let mut challenger = Challenger::new();
|
||||
verify_fri_proof(
|
||||
degree_log,
|
||||
&[],
|
||||
F::ONE,
|
||||
F::Extension::ONE,
|
||||
&[root],
|
||||
&proof,
|
||||
&mut challenger,
|
||||
@ -120,14 +134,13 @@ mod tests {
|
||||
arities
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fri_multi_params() -> Result<()> {
|
||||
fn check_fri_multi_params<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
|
||||
let mut rng = rand::thread_rng();
|
||||
for degree_log in 1..6 {
|
||||
for rate_bits in 0..3 {
|
||||
for num_query_round in 0..4 {
|
||||
for _ in 0..3 {
|
||||
test_fri(
|
||||
check_fri::<F, D>(
|
||||
degree_log,
|
||||
rate_bits,
|
||||
gen_arities(degree_log, &mut rng),
|
||||
@ -139,4 +152,31 @@ mod tests {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
mod base {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_fri_multi_params() -> Result<()> {
|
||||
check_fri_multi_params::<CrandallField, 1>()
|
||||
}
|
||||
}
|
||||
|
||||
mod quadratic {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_fri_multi_params() -> Result<()> {
|
||||
check_fri_multi_params::<CrandallField, 2>()
|
||||
}
|
||||
}
|
||||
|
||||
mod quartic {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_fri_multi_params() -> Result<()> {
|
||||
check_fri_multi_params::<CrandallField, 4>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::field::extension_field::{flatten, unflatten, Extendable};
|
||||
use crate::field::field::Field;
|
||||
use crate::fri::FriConfig;
|
||||
use crate::hash::hash_n_to_1;
|
||||
@ -9,15 +10,15 @@ use crate::proof::{FriInitialTreeProof, FriProof, FriQueryRound, FriQueryStep, H
|
||||
use crate::util::reverse_index_bits_in_place;
|
||||
|
||||
/// Builds a FRI proof.
|
||||
pub fn fri_proof<F: Field>(
|
||||
pub fn fri_proof<F: Field + 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>,
|
||||
lde_polynomial_coeffs: &PolynomialCoeffs<F::Extension>,
|
||||
// Evaluation of the polynomial on the large domain.
|
||||
lde_polynomial_values: &PolynomialValues<F>,
|
||||
lde_polynomial_values: &PolynomialValues<F::Extension>,
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> FriProof<F> {
|
||||
) -> FriProof<F, D> {
|
||||
let n = lde_polynomial_values.values.len();
|
||||
assert_eq!(lde_polynomial_coeffs.coeffs.len(), n);
|
||||
|
||||
@ -45,12 +46,12 @@ pub fn fri_proof<F: Field>(
|
||||
}
|
||||
}
|
||||
|
||||
fn fri_committed_trees<F: Field>(
|
||||
polynomial_coeffs: &PolynomialCoeffs<F>,
|
||||
polynomial_values: &PolynomialValues<F>,
|
||||
fn fri_committed_trees<F: Field + Extendable<D>, const D: usize>(
|
||||
polynomial_coeffs: &PolynomialCoeffs<F::Extension>,
|
||||
polynomial_values: &PolynomialValues<F::Extension>,
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> (Vec<MerkleTree<F>>, PolynomialCoeffs<F>) {
|
||||
) -> (Vec<MerkleTree<F>>, PolynomialCoeffs<F::Extension>) {
|
||||
let mut values = polynomial_values.clone();
|
||||
let mut coeffs = polynomial_coeffs.clone();
|
||||
|
||||
@ -66,7 +67,7 @@ fn fri_committed_trees<F: Field>(
|
||||
values
|
||||
.values
|
||||
.chunks(arity)
|
||||
.map(|chunk| chunk.to_vec())
|
||||
.map(|chunk: &[F::Extension]| flatten(chunk))
|
||||
.collect(),
|
||||
false,
|
||||
);
|
||||
@ -74,7 +75,7 @@ fn fri_committed_trees<F: Field>(
|
||||
challenger.observe_hash(&tree.root);
|
||||
trees.push(tree);
|
||||
|
||||
let beta = challenger.get_challenge();
|
||||
let beta = challenger.get_extension_challenge();
|
||||
// P(x) = sum_{i<r} x^i * P_i(x^r) becomes sum_{i<r} beta^i * P_i(x).
|
||||
coeffs = PolynomialCoeffs::new(
|
||||
coeffs
|
||||
@ -85,10 +86,10 @@ fn fri_committed_trees<F: Field>(
|
||||
);
|
||||
shift = shift.exp_u32(arity as u32);
|
||||
// TODO: Is it faster to interpolate?
|
||||
values = coeffs.clone().coset_fft(shift);
|
||||
values = coeffs.clone().coset_fft(shift.into())
|
||||
}
|
||||
|
||||
challenger.observe_elements(&coeffs.coeffs);
|
||||
challenger.observe_extension_elements(&coeffs.coeffs);
|
||||
(trees, coeffs)
|
||||
}
|
||||
|
||||
@ -112,25 +113,25 @@ fn fri_proof_of_work<F: Field>(current_hash: Hash<F>, config: &FriConfig) -> F {
|
||||
.expect("Proof of work failed.")
|
||||
}
|
||||
|
||||
fn fri_prover_query_rounds<F: Field>(
|
||||
fn fri_prover_query_rounds<F: Field + Extendable<D>, const D: usize>(
|
||||
initial_merkle_trees: &[&MerkleTree<F>],
|
||||
trees: &[MerkleTree<F>],
|
||||
challenger: &mut Challenger<F>,
|
||||
n: usize,
|
||||
config: &FriConfig,
|
||||
) -> Vec<FriQueryRound<F>> {
|
||||
) -> Vec<FriQueryRound<F, D>> {
|
||||
(0..config.num_query_rounds)
|
||||
.map(|_| fri_prover_query_round(initial_merkle_trees, trees, challenger, n, config))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn fri_prover_query_round<F: Field>(
|
||||
fn fri_prover_query_round<F: Field + Extendable<D>, const D: usize>(
|
||||
initial_merkle_trees: &[&MerkleTree<F>],
|
||||
trees: &[MerkleTree<F>],
|
||||
challenger: &mut Challenger<F>,
|
||||
n: usize,
|
||||
config: &FriConfig,
|
||||
) -> FriQueryRound<F> {
|
||||
) -> FriQueryRound<F, D> {
|
||||
let mut query_steps = Vec::new();
|
||||
let x = challenger.get_challenge();
|
||||
let mut x_index = x.to_canonical_u64() as usize % n;
|
||||
@ -141,7 +142,7 @@ fn fri_prover_query_round<F: Field>(
|
||||
for (i, tree) in trees.iter().enumerate() {
|
||||
let arity_bits = config.reduction_arity_bits[i];
|
||||
let arity = 1 << arity_bits;
|
||||
let mut evals = tree.get(x_index >> arity_bits).to_vec();
|
||||
let mut evals = unflatten(tree.get(x_index >> arity_bits));
|
||||
evals.remove(x_index & (arity - 1));
|
||||
let merkle_proof = tree.prove(x_index >> arity_bits);
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::field::extension_field::{flatten, Extendable, FieldExtension};
|
||||
use crate::field::field::Field;
|
||||
use crate::field::lagrange::{barycentric_weights, interpolant, interpolate};
|
||||
use crate::fri::FriConfig;
|
||||
@ -12,13 +13,13 @@ use anyhow::{ensure, Result};
|
||||
|
||||
/// 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<F: Field>(
|
||||
fn compute_evaluation<F: Field + Extendable<D>, const D: usize>(
|
||||
x: F,
|
||||
old_x_index: usize,
|
||||
arity_bits: usize,
|
||||
last_evals: &[F],
|
||||
beta: F,
|
||||
) -> F {
|
||||
last_evals: &[F::Extension],
|
||||
beta: F::Extension,
|
||||
) -> F::Extension {
|
||||
debug_assert_eq!(last_evals.len(), 1 << arity_bits);
|
||||
|
||||
let g = F::primitive_root_of_unity(arity_bits);
|
||||
@ -32,14 +33,14 @@ fn compute_evaluation<F: Field>(
|
||||
let points = g
|
||||
.powers()
|
||||
.zip(evals)
|
||||
.map(|(y, e)| (x * y, e))
|
||||
.map(|(y, e)| ((x * y).into(), e))
|
||||
.collect::<Vec<_>>();
|
||||
let barycentric_weights = barycentric_weights(&points);
|
||||
interpolate(&points, beta, &barycentric_weights)
|
||||
}
|
||||
|
||||
fn fri_verify_proof_of_work<F: Field>(
|
||||
proof: &FriProof<F>,
|
||||
fn fri_verify_proof_of_work<F: Field + Extendable<D>, const D: usize>(
|
||||
proof: &FriProof<F, D>,
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> Result<()> {
|
||||
@ -62,14 +63,14 @@ fn fri_verify_proof_of_work<F: Field>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn verify_fri_proof<F: Field>(
|
||||
pub fn verify_fri_proof<F: Field + Extendable<D>, const D: usize>(
|
||||
purported_degree_log: usize,
|
||||
// Point-evaluation pairs for polynomial commitments.
|
||||
points: &[(F, F)],
|
||||
points: &[(F::Extension, F::Extension)],
|
||||
// Scaling factor to combine polynomials.
|
||||
alpha: F,
|
||||
alpha: F::Extension,
|
||||
initial_merkle_roots: &[Hash<F>],
|
||||
proof: &FriProof<F>,
|
||||
proof: &FriProof<F, D>,
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> Result<()> {
|
||||
@ -89,10 +90,10 @@ pub fn verify_fri_proof<F: Field>(
|
||||
.iter()
|
||||
.map(|root| {
|
||||
challenger.observe_hash(root);
|
||||
challenger.get_challenge()
|
||||
challenger.get_extension_challenge()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
challenger.observe_elements(&proof.final_poly.coeffs);
|
||||
challenger.observe_extension_elements(&proof.final_poly.coeffs);
|
||||
|
||||
// Check PoW.
|
||||
fri_verify_proof_of_work(proof, challenger, config)?;
|
||||
@ -138,39 +139,42 @@ fn fri_verify_initial_proof<F: Field>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fri_combine_initial<F: Field>(
|
||||
fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
|
||||
proof: &FriInitialTreeProof<F>,
|
||||
alpha: F,
|
||||
interpolant: &PolynomialCoeffs<F>,
|
||||
points: &[(F, F)],
|
||||
alpha: F::Extension,
|
||||
interpolant: &PolynomialCoeffs<F::Extension>,
|
||||
points: &[(F::Extension, F::Extension)],
|
||||
subgroup_x: F,
|
||||
config: &FriConfig,
|
||||
) -> F {
|
||||
) -> F::Extension {
|
||||
let e = proof
|
||||
.evals_proofs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, (v, _))| &v[..v.len() - if config.blinding[i] { SALT_SIZE } else { 0 }])
|
||||
.rev()
|
||||
.fold(F::ZERO, |acc, &e| alpha * acc + e);
|
||||
let numerator = e - interpolant.eval(subgroup_x);
|
||||
let denominator = points.iter().map(|&(x, _)| subgroup_x - x).product();
|
||||
.fold(F::Extension::ZERO, |acc, &e| alpha * acc + e.into());
|
||||
let numerator = e - interpolant.eval(subgroup_x.into());
|
||||
let denominator = points
|
||||
.iter()
|
||||
.map(|&(x, _)| F::Extension::from_basefield(subgroup_x) - x)
|
||||
.product();
|
||||
numerator / denominator
|
||||
}
|
||||
|
||||
fn fri_verifier_query_round<F: Field>(
|
||||
interpolant: &PolynomialCoeffs<F>,
|
||||
points: &[(F, F)],
|
||||
alpha: F,
|
||||
fn fri_verifier_query_round<F: Field + Extendable<D>, const D: usize>(
|
||||
interpolant: &PolynomialCoeffs<F::Extension>,
|
||||
points: &[(F::Extension, F::Extension)],
|
||||
alpha: F::Extension,
|
||||
initial_merkle_roots: &[Hash<F>],
|
||||
proof: &FriProof<F>,
|
||||
proof: &FriProof<F, D>,
|
||||
challenger: &mut Challenger<F>,
|
||||
n: usize,
|
||||
betas: &[F],
|
||||
round_proof: &FriQueryRound<F>,
|
||||
betas: &[F::Extension],
|
||||
round_proof: &FriQueryRound<F, D>,
|
||||
config: &FriConfig,
|
||||
) -> Result<()> {
|
||||
let mut evaluations: Vec<Vec<F>> = Vec::new();
|
||||
let mut evaluations: Vec<Vec<F::Extension>> = Vec::new();
|
||||
let x = challenger.get_challenge();
|
||||
let mut domain_size = n;
|
||||
let mut x_index = x.to_canonical_u64() as usize % n;
|
||||
@ -212,7 +216,7 @@ fn fri_verifier_query_round<F: Field>(
|
||||
evals.insert(x_index & (arity - 1), e_x);
|
||||
evaluations.push(evals);
|
||||
verify_merkle_proof(
|
||||
evaluations[i].clone(),
|
||||
flatten(&evaluations[i]),
|
||||
x_index >> arity_bits,
|
||||
proof.commit_phase_merkle_roots[i],
|
||||
&round_proof.steps[i].merkle_proof,
|
||||
@ -246,7 +250,7 @@ fn fri_verifier_query_round<F: Field>(
|
||||
// Final check of FRI. After all the reductions, we check that the final polynomial is equal
|
||||
// to the one sent by the prover.
|
||||
ensure!(
|
||||
proof.final_poly.eval(subgroup_x) == purported_eval,
|
||||
proof.final_poly.eval(subgroup_x.into()) == purported_eval,
|
||||
"Final polynomial evaluation is invalid."
|
||||
);
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||
use crate::field::field::Field;
|
||||
use crate::hash::{permute, SPONGE_RATE, SPONGE_WIDTH};
|
||||
use crate::proof::{Hash, HashTarget};
|
||||
@ -36,12 +37,30 @@ impl<F: Field> Challenger<F> {
|
||||
self.input_buffer.push(element);
|
||||
}
|
||||
|
||||
pub fn observe_extension_element<const D: usize>(&mut self, element: &F::Extension)
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
for &e in &element.to_basefield_array() {
|
||||
self.observe_element(e);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn observe_elements(&mut self, elements: &[F]) {
|
||||
for &element in elements {
|
||||
self.observe_element(element);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn observe_extension_elements<const D: usize>(&mut self, elements: &[F::Extension])
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
for element in elements {
|
||||
self.observe_extension_element(element);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn observe_hash(&mut self, hash: &Hash<F>) {
|
||||
self.observe_elements(&hash.elements)
|
||||
}
|
||||
@ -87,6 +106,22 @@ impl<F: Field> Challenger<F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_extension_challenge<const D: usize>(&mut self) -> F::Extension
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
let mut arr = [F::ZERO; D];
|
||||
arr.copy_from_slice(&self.get_n_challenges(D));
|
||||
F::Extension::from_basefield_array(arr)
|
||||
}
|
||||
|
||||
pub fn get_n_extension_challenges<const D: usize>(&mut self, n: usize) -> Vec<F::Extension>
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
(0..n).map(|_| self.get_extension_challenge()).collect()
|
||||
}
|
||||
|
||||
/// Absorb any buffered inputs. After calling this, the input buffer will be empty.
|
||||
fn absorb_buffered_inputs(&mut self) {
|
||||
if self.input_buffer.is_empty() {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
use anyhow::Result;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::extension_field::FieldExtension;
|
||||
use crate::field::field::Field;
|
||||
use crate::field::lagrange::interpolant;
|
||||
use crate::fri::{prover::fri_proof, verifier::verify_fri_proof, FriConfig};
|
||||
@ -74,19 +76,22 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
&leaf[0..leaf.len() - if self.blinding { SALT_SIZE } else { 0 }]
|
||||
}
|
||||
|
||||
pub fn open(
|
||||
pub fn open<const D: usize>(
|
||||
&self,
|
||||
points: &[F],
|
||||
points: &[F::Extension],
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> (OpeningProof<F>, Vec<Vec<F>>) {
|
||||
) -> (OpeningProof<F, D>, Vec<Vec<F::Extension>>)
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
assert_eq!(self.rate_bits, config.rate_bits);
|
||||
assert_eq!(config.blinding.len(), 1);
|
||||
assert_eq!(self.blinding, config.blinding[0]);
|
||||
for p in points {
|
||||
assert_ne!(
|
||||
p.exp_usize(self.degree),
|
||||
F::ONE,
|
||||
F::Extension::ONE,
|
||||
"Opening point is in the subgroup."
|
||||
);
|
||||
}
|
||||
@ -96,15 +101,17 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
.map(|&x| {
|
||||
self.polynomials
|
||||
.iter()
|
||||
.map(|p| p.eval(x))
|
||||
.map(|p| p.to_extension().eval(x))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
for evals in &evaluations {
|
||||
challenger.observe_elements(evals);
|
||||
for e in evals {
|
||||
challenger.observe_extension_element(e);
|
||||
}
|
||||
}
|
||||
|
||||
let alpha = challenger.get_challenge();
|
||||
let alpha = challenger.get_extension_challenge();
|
||||
|
||||
// Scale polynomials by `alpha`.
|
||||
let composition_poly = self
|
||||
@ -112,7 +119,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
.iter()
|
||||
.rev()
|
||||
.fold(PolynomialCoeffs::zero(self.degree), |acc, p| {
|
||||
&(&acc * alpha) + &p
|
||||
&(&acc * alpha) + &p.to_extension()
|
||||
});
|
||||
// Scale evaluations by `alpha`.
|
||||
let composition_evals = evaluations
|
||||
@ -125,7 +132,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(self.rate_bits);
|
||||
let lde_quotient_values = lde_quotient
|
||||
.clone()
|
||||
.coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR);
|
||||
.coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR.into());
|
||||
|
||||
let fri_proof = fri_proof(
|
||||
&[&self.merkle_tree],
|
||||
@ -144,12 +151,15 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn batch_open(
|
||||
pub fn batch_open<const D: usize>(
|
||||
commitments: &[&Self],
|
||||
points: &[F],
|
||||
points: &[F::Extension],
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> (OpeningProof<F>, Vec<Vec<Vec<F>>>) {
|
||||
) -> (OpeningProof<F, D>, Vec<Vec<Vec<F::Extension>>>)
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
let degree = commitments[0].degree;
|
||||
assert_eq!(config.blinding.len(), commitments.len());
|
||||
for (i, commitment) in commitments.iter().enumerate() {
|
||||
@ -166,7 +176,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
for p in points {
|
||||
assert_ne!(
|
||||
p.exp_usize(degree),
|
||||
F::ONE,
|
||||
F::Extension::ONE,
|
||||
"Opening point is in the subgroup."
|
||||
);
|
||||
}
|
||||
@ -176,26 +186,30 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
.map(|&x| {
|
||||
commitments
|
||||
.iter()
|
||||
.map(move |c| c.polynomials.iter().map(|p| p.eval(x)).collect::<Vec<_>>())
|
||||
.map(move |c| {
|
||||
c.polynomials
|
||||
.iter()
|
||||
.map(|p| p.to_extension().eval(x))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
for evals_per_point in &evaluations {
|
||||
for evals in evals_per_point {
|
||||
challenger.observe_elements(evals);
|
||||
challenger.observe_extension_elements(evals);
|
||||
}
|
||||
}
|
||||
|
||||
let alpha = challenger.get_challenge();
|
||||
let alpha = challenger.get_extension_challenge();
|
||||
|
||||
// Scale polynomials by `alpha`.
|
||||
let composition_poly = commitments
|
||||
.iter()
|
||||
.flat_map(|c| &c.polynomials)
|
||||
.rev()
|
||||
.map(|p| p.clone().into())
|
||||
.fold(PolynomialCoeffs::zero(degree), |acc, p| {
|
||||
&(&acc * alpha) + &p
|
||||
&(&acc * alpha) + &p.to_extension()
|
||||
});
|
||||
// Scale evaluations by `alpha`.
|
||||
let composition_evals = &evaluations
|
||||
@ -204,16 +218,16 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
v.iter()
|
||||
.flatten()
|
||||
.rev()
|
||||
.fold(F::ZERO, |acc, &e| acc * alpha + e)
|
||||
.fold(F::Extension::ZERO, |acc, &e| acc * alpha + e)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let quotient = Self::compute_quotient(points, &composition_evals, &composition_poly);
|
||||
|
||||
let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(config.rate_bits);
|
||||
let lde_quotient_values = lde_quotient
|
||||
.clone()
|
||||
.coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR);
|
||||
let lde_quotient_values = lde_quotient.clone().coset_fft(F::Extension::from_basefield(
|
||||
F::MULTIPLICATIVE_GROUP_GENERATOR,
|
||||
));
|
||||
|
||||
let fri_proof = fri_proof(
|
||||
&commitments
|
||||
@ -235,12 +249,15 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn batch_open_plonk(
|
||||
pub fn batch_open_plonk<const D: usize>(
|
||||
commitments: &[&Self; 5],
|
||||
points: &[F],
|
||||
points: &[F::Extension],
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> (OpeningProof<F>, Vec<OpeningSet<F>>) {
|
||||
) -> (OpeningProof<F, D>, Vec<OpeningSet<F::Extension>>)
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
let (op, mut evaluations) = Self::batch_open(commitments, points, challenger, config);
|
||||
let opening_sets = evaluations
|
||||
.par_iter_mut()
|
||||
@ -260,11 +277,14 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
|
||||
/// Given `points=(x_i)`, `evals=(y_i)` and `poly=P` with `P(x_i)=y_i`, computes the polynomial
|
||||
/// `Q=(P-I)/Z` where `I` interpolates `(x_i, y_i)` and `Z` is the vanishing polynomial on `(x_i)`.
|
||||
fn compute_quotient(
|
||||
points: &[F],
|
||||
evals: &[F],
|
||||
poly: &PolynomialCoeffs<F>,
|
||||
) -> PolynomialCoeffs<F> {
|
||||
fn compute_quotient<const D: usize>(
|
||||
points: &[F::Extension],
|
||||
evals: &[F::Extension],
|
||||
poly: &PolynomialCoeffs<F::Extension>,
|
||||
) -> PolynomialCoeffs<F::Extension>
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
let pairs = points
|
||||
.iter()
|
||||
.zip(evals)
|
||||
@ -274,7 +294,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
|
||||
let interpolant = interpolant(&pairs);
|
||||
let denominator = points.iter().fold(PolynomialCoeffs::one(), |acc, &x| {
|
||||
&acc * &PolynomialCoeffs::new(vec![-x, F::ONE])
|
||||
&acc * &PolynomialCoeffs::new(vec![-x, F::Extension::ONE])
|
||||
});
|
||||
let numerator = poly - &interpolant;
|
||||
let (mut quotient, rem) = numerator.div_rem(&denominator);
|
||||
@ -284,28 +304,28 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OpeningProof<F: Field> {
|
||||
fri_proof: FriProof<F>,
|
||||
pub struct OpeningProof<F: Field + Extendable<D>, const D: usize> {
|
||||
fri_proof: FriProof<F, D>,
|
||||
// TODO: Get the degree from `CommonCircuitData` instead.
|
||||
quotient_degree: usize,
|
||||
}
|
||||
|
||||
impl<F: Field> OpeningProof<F> {
|
||||
impl<F: Field + Extendable<D>, const D: usize> OpeningProof<F, D> {
|
||||
pub fn verify(
|
||||
&self,
|
||||
points: &[F],
|
||||
evaluations: &[Vec<Vec<F>>],
|
||||
points: &[F::Extension],
|
||||
evaluations: &[Vec<Vec<F::Extension>>],
|
||||
merkle_roots: &[Hash<F>],
|
||||
challenger: &mut Challenger<F>,
|
||||
fri_config: &FriConfig,
|
||||
) -> Result<()> {
|
||||
for evals_per_point in evaluations {
|
||||
for evals in evals_per_point {
|
||||
challenger.observe_elements(evals);
|
||||
challenger.observe_extension_elements(evals);
|
||||
}
|
||||
}
|
||||
|
||||
let alpha = challenger.get_challenge();
|
||||
let alpha = challenger.get_extension_challenge();
|
||||
|
||||
let scaled_evals = evaluations
|
||||
.par_iter()
|
||||
@ -313,7 +333,7 @@ impl<F: Field> OpeningProof<F> {
|
||||
v.iter()
|
||||
.flatten()
|
||||
.rev()
|
||||
.fold(F::ZERO, |acc, &e| acc * alpha + e)
|
||||
.fold(F::Extension::ZERO, |acc, &e| acc * alpha + e)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@ -343,28 +363,25 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
fn gen_random_test_case<F: Field>(
|
||||
fn gen_random_test_case<F: Field + Extendable<D>, const D: usize>(
|
||||
k: usize,
|
||||
degree_log: usize,
|
||||
num_points: usize,
|
||||
) -> (Vec<PolynomialCoeffs<F>>, Vec<F>) {
|
||||
) -> (Vec<PolynomialCoeffs<F>>, Vec<F::Extension>) {
|
||||
let degree = 1 << degree_log;
|
||||
|
||||
let polys = (0..k)
|
||||
.map(|_| PolynomialCoeffs::new(F::rand_vec(degree)))
|
||||
.collect();
|
||||
let mut points = F::rand_vec(num_points);
|
||||
let mut points = F::Extension::rand_vec(num_points);
|
||||
while points.iter().any(|&x| x.exp_usize(degree).is_one()) {
|
||||
points = F::rand_vec(num_points);
|
||||
points = F::Extension::rand_vec(num_points);
|
||||
}
|
||||
|
||||
(polys, points)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_polynomial_commitment() -> Result<()> {
|
||||
type F = CrandallField;
|
||||
|
||||
fn check_polynomial_commitment<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
|
||||
let k = 10;
|
||||
let degree_log = 11;
|
||||
let num_points = 3;
|
||||
@ -375,10 +392,10 @@ mod tests {
|
||||
num_query_rounds: 3,
|
||||
blinding: vec![false],
|
||||
};
|
||||
let (polys, points) = gen_random_test_case::<F>(k, degree_log, num_points);
|
||||
let (polys, points) = gen_random_test_case::<F, D>(k, degree_log, num_points);
|
||||
|
||||
let lpc = ListPolynomialCommitment::new(polys, fri_config.rate_bits, false);
|
||||
let (proof, evaluations) = lpc.open(&points, &mut Challenger::new(), &fri_config);
|
||||
let (proof, evaluations) = lpc.open::<D>(&points, &mut Challenger::new(), &fri_config);
|
||||
proof.verify(
|
||||
&points,
|
||||
&evaluations.into_iter().map(|e| vec![e]).collect::<Vec<_>>(),
|
||||
@ -388,10 +405,8 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_polynomial_commitment_blinding() -> Result<()> {
|
||||
type F = CrandallField;
|
||||
|
||||
fn check_polynomial_commitment_blinding<F: Field + Extendable<D>, const D: usize>() -> Result<()>
|
||||
{
|
||||
let k = 10;
|
||||
let degree_log = 11;
|
||||
let num_points = 3;
|
||||
@ -402,10 +417,10 @@ mod tests {
|
||||
num_query_rounds: 3,
|
||||
blinding: vec![true],
|
||||
};
|
||||
let (polys, points) = gen_random_test_case::<F>(k, degree_log, num_points);
|
||||
let (polys, points) = gen_random_test_case::<F, D>(k, degree_log, num_points);
|
||||
|
||||
let lpc = ListPolynomialCommitment::new(polys, fri_config.rate_bits, true);
|
||||
let (proof, evaluations) = lpc.open(&points, &mut Challenger::new(), &fri_config);
|
||||
let (proof, evaluations) = lpc.open::<D>(&points, &mut Challenger::new(), &fri_config);
|
||||
proof.verify(
|
||||
&points,
|
||||
&evaluations.into_iter().map(|e| vec![e]).collect::<Vec<_>>(),
|
||||
@ -415,10 +430,7 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_batch_polynomial_commitment() -> Result<()> {
|
||||
type F = CrandallField;
|
||||
|
||||
fn check_batch_polynomial_commitment<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
|
||||
let k0 = 10;
|
||||
let k1 = 3;
|
||||
let k2 = 7;
|
||||
@ -431,15 +443,15 @@ mod tests {
|
||||
num_query_rounds: 3,
|
||||
blinding: vec![false, false, false],
|
||||
};
|
||||
let (polys0, _) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys1, _) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys2, points) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys0, _) = gen_random_test_case::<F, D>(k0, degree_log, num_points);
|
||||
let (polys1, _) = gen_random_test_case::<F, D>(k1, degree_log, num_points);
|
||||
let (polys2, points) = gen_random_test_case::<F, D>(k2, degree_log, num_points);
|
||||
|
||||
let lpc0 = ListPolynomialCommitment::new(polys0, fri_config.rate_bits, false);
|
||||
let lpc1 = ListPolynomialCommitment::new(polys1, fri_config.rate_bits, false);
|
||||
let lpc2 = ListPolynomialCommitment::new(polys2, fri_config.rate_bits, false);
|
||||
|
||||
let (proof, evaluations) = ListPolynomialCommitment::batch_open(
|
||||
let (proof, evaluations) = ListPolynomialCommitment::batch_open::<D>(
|
||||
&[&lpc0, &lpc1, &lpc2],
|
||||
&points,
|
||||
&mut Challenger::new(),
|
||||
@ -458,10 +470,8 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_batch_polynomial_commitment_blinding() -> Result<()> {
|
||||
type F = CrandallField;
|
||||
|
||||
fn check_batch_polynomial_commitment_blinding<F: Field + Extendable<D>, const D: usize>(
|
||||
) -> Result<()> {
|
||||
let k0 = 10;
|
||||
let k1 = 3;
|
||||
let k2 = 7;
|
||||
@ -474,15 +484,15 @@ mod tests {
|
||||
num_query_rounds: 3,
|
||||
blinding: vec![true, false, true],
|
||||
};
|
||||
let (polys0, _) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys1, _) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys2, points) = gen_random_test_case::<F>(k0, degree_log, num_points);
|
||||
let (polys0, _) = gen_random_test_case::<F, D>(k0, degree_log, num_points);
|
||||
let (polys1, _) = gen_random_test_case::<F, D>(k1, degree_log, num_points);
|
||||
let (polys2, points) = gen_random_test_case::<F, D>(k2, degree_log, num_points);
|
||||
|
||||
let lpc0 = ListPolynomialCommitment::new(polys0, fri_config.rate_bits, true);
|
||||
let lpc1 = ListPolynomialCommitment::new(polys1, fri_config.rate_bits, false);
|
||||
let lpc2 = ListPolynomialCommitment::new(polys2, fri_config.rate_bits, true);
|
||||
|
||||
let (proof, evaluations) = ListPolynomialCommitment::batch_open(
|
||||
let (proof, evaluations) = ListPolynomialCommitment::batch_open::<D>(
|
||||
&[&lpc0, &lpc1, &lpc2],
|
||||
&points,
|
||||
&mut Challenger::new(),
|
||||
@ -500,4 +510,43 @@ mod tests {
|
||||
&fri_config,
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! tests_commitments {
|
||||
($F:ty, $D:expr) => {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_polynomial_commitment() -> Result<()> {
|
||||
check_polynomial_commitment::<$F, $D>()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_polynomial_commitment_blinding() -> Result<()> {
|
||||
check_polynomial_commitment_blinding::<$F, $D>()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_batch_polynomial_commitment() -> Result<()> {
|
||||
check_batch_polynomial_commitment::<$F, $D>()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_batch_polynomial_commitment_blinding() -> Result<()> {
|
||||
check_batch_polynomial_commitment_blinding::<$F, $D>()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
mod base {
|
||||
tests_commitments!(crate::field::crandall_field::CrandallField, 1);
|
||||
}
|
||||
|
||||
mod quadratic {
|
||||
tests_commitments!(crate::field::crandall_field::CrandallField, 2);
|
||||
}
|
||||
|
||||
mod quartic {
|
||||
use super::*;
|
||||
tests_commitments!(crate::field::crandall_field::CrandallField, 4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
use std::cmp::max;
|
||||
use std::ops::{Add, Mul, Sub};
|
||||
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::fft::{fft, ifft};
|
||||
use crate::field::field::Field;
|
||||
use crate::util::{log2_ceil, log2_strict};
|
||||
use crate::util::log2_strict;
|
||||
|
||||
/// A polynomial in point-value form.
|
||||
///
|
||||
@ -167,6 +168,13 @@ impl<F: Field> PolynomialCoeffs<F> {
|
||||
.into();
|
||||
modified_poly.fft()
|
||||
}
|
||||
|
||||
pub fn to_extension<const D: usize>(&self) -> PolynomialCoeffs<F::Extension>
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
PolynomialCoeffs::new(self.coeffs.iter().map(|&c| c.into()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> PartialEq for PolynomialCoeffs<F> {
|
||||
@ -229,6 +237,7 @@ impl<F: Field> Mul<F> for &PolynomialCoeffs<F> {
|
||||
impl<F: Field> Mul for &PolynomialCoeffs<F> {
|
||||
type Output = PolynomialCoeffs<F>;
|
||||
|
||||
#[allow(clippy::suspicious_arithmetic_impl)]
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
let new_len = (self.len() + rhs.len()).next_power_of_two();
|
||||
let a = self.padded(new_len);
|
||||
|
||||
21
src/proof.rs
21
src/proof.rs
@ -1,3 +1,4 @@
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field::Field;
|
||||
use crate::merkle_proofs::{MerkleProof, MerkleProofTarget};
|
||||
use crate::polynomial::commitment::{ListPolynomialCommitment, OpeningProof};
|
||||
@ -54,7 +55,7 @@ impl HashTarget {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Proof<F: Field> {
|
||||
pub struct Proof<F: Field + Extendable<D>, const D: usize> {
|
||||
/// Merkle root of LDEs of wire values.
|
||||
pub wires_root: Hash<F>,
|
||||
/// Merkle root of LDEs of Z, in the context of Plonk's permutation argument.
|
||||
@ -63,10 +64,10 @@ pub struct Proof<F: Field> {
|
||||
pub quotient_polys_root: Hash<F>,
|
||||
|
||||
/// Purported values of each polynomial at each challenge point.
|
||||
pub openings: Vec<OpeningSet<F>>,
|
||||
pub openings: Vec<OpeningSet<F::Extension>>,
|
||||
|
||||
/// A FRI argument for each FRI query.
|
||||
pub opening_proof: OpeningProof<F>,
|
||||
pub opening_proof: OpeningProof<F, D>,
|
||||
}
|
||||
|
||||
pub struct ProofTarget {
|
||||
@ -86,8 +87,8 @@ pub struct ProofTarget {
|
||||
|
||||
/// Evaluations and Merkle proof produced by the prover in a FRI query step.
|
||||
// TODO: Implement FriQueryStepTarget
|
||||
pub struct FriQueryStep<F: Field> {
|
||||
pub evals: Vec<F>,
|
||||
pub struct FriQueryStep<F: Field + Extendable<D>, const D: usize> {
|
||||
pub evals: Vec<F::Extension>,
|
||||
pub merkle_proof: MerkleProof<F>,
|
||||
}
|
||||
|
||||
@ -100,18 +101,18 @@ pub struct FriInitialTreeProof<F: Field> {
|
||||
|
||||
/// Proof for a FRI query round.
|
||||
// TODO: Implement FriQueryRoundTarget
|
||||
pub struct FriQueryRound<F: Field> {
|
||||
pub struct FriQueryRound<F: Field + Extendable<D>, const D: usize> {
|
||||
pub initial_trees_proof: FriInitialTreeProof<F>,
|
||||
pub steps: Vec<FriQueryStep<F>>,
|
||||
pub steps: Vec<FriQueryStep<F, D>>,
|
||||
}
|
||||
|
||||
pub struct FriProof<F: Field> {
|
||||
pub struct FriProof<F: Field + Extendable<D>, const D: usize> {
|
||||
/// A Merkle root for each reduced polynomial in the commit phase.
|
||||
pub commit_phase_merkle_roots: Vec<Hash<F>>,
|
||||
/// Query rounds proofs
|
||||
pub query_round_proofs: Vec<FriQueryRound<F>>,
|
||||
pub query_round_proofs: Vec<FriQueryRound<F, D>>,
|
||||
/// The final polynomial in coefficient form.
|
||||
pub final_poly: PolynomialCoeffs<F>,
|
||||
pub final_poly: PolynomialCoeffs<F::Extension>,
|
||||
/// Witness showing that the prover did PoW.
|
||||
pub pow_witness: F,
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ use log::info;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::fft::ifft;
|
||||
use crate::field::field::Field;
|
||||
use crate::generator::generate_partial_witness;
|
||||
@ -21,11 +22,11 @@ use crate::witness::PartialWitness;
|
||||
/// Corresponds to constants - sigmas - wires - zs - quotient — polynomial commitments.
|
||||
pub const PLONK_BLINDING: [bool; 5] = [false, false, true, true, true];
|
||||
|
||||
pub(crate) fn prove<F: Field>(
|
||||
pub(crate) fn prove<F: Field + Extendable<D>, const D: usize>(
|
||||
prover_data: &ProverOnlyCircuitData<F>,
|
||||
common_data: &CommonCircuitData<F>,
|
||||
inputs: PartialWitness<F>,
|
||||
) -> Proof<F> {
|
||||
) -> Proof<F, D> {
|
||||
let fri_config = &common_data.config.fri_config;
|
||||
|
||||
let start_proof_gen = Instant::now();
|
||||
@ -109,7 +110,7 @@ pub(crate) fn prove<F: Field>(
|
||||
|
||||
challenger.observe_hash("ient_polys_commitment.merkle_tree.root);
|
||||
|
||||
let zetas = challenger.get_n_challenges(config.num_challenges);
|
||||
let zetas = challenger.get_n_extension_challenges(config.num_challenges);
|
||||
|
||||
let (opening_proof, openings) = timed!(
|
||||
ListPolynomialCommitment::batch_open_plonk(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user