mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-08 16:53:07 +00:00
Progress on FRI
This commit is contained in:
parent
7ff4150679
commit
6b407e45ef
@ -17,5 +17,8 @@ fn main() {
|
|||||||
|
|
||||||
println!("result {:?}", x);
|
println!("result {:?}", x);
|
||||||
println!("took {:?}", duration);
|
println!("took {:?}", duration);
|
||||||
println!("avg {:?}ns", duration.as_secs_f64() * 1e9 / (num_muls as f64));
|
println!(
|
||||||
|
"avg {:?}ns",
|
||||||
|
duration.as_secs_f64() * 1e9 / (num_muls as f64)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,8 @@ fn main() {
|
|||||||
const W: usize = 13;
|
const W: usize = 13;
|
||||||
const HASHES_PER_POLY: usize = 1 << (13 + LDE_BITS);
|
const HASHES_PER_POLY: usize = 1 << (13 + LDE_BITS);
|
||||||
|
|
||||||
let threads = (0..THREADS).map(|_i| {
|
let threads = (0..THREADS)
|
||||||
|
.map(|_i| {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let mut x = [F::ZERO; W];
|
let mut x = [F::ZERO; W];
|
||||||
for i in 0..W {
|
for i in 0..W {
|
||||||
@ -31,10 +32,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
let duration = start.elapsed();
|
let duration = start.elapsed();
|
||||||
println!("took {:?}", duration);
|
println!("took {:?}", duration);
|
||||||
println!("avg {:?}us", duration.as_secs_f64() * 1e6 / (hashes_per_thread as f64));
|
println!(
|
||||||
|
"avg {:?}us",
|
||||||
|
duration.as_secs_f64() * 1e6 / (hashes_per_thread as f64)
|
||||||
|
);
|
||||||
println!("result {:?}", x);
|
println!("result {:?}", x);
|
||||||
})
|
})
|
||||||
}).collect::<Vec<_>>();
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for t in threads {
|
for t in threads {
|
||||||
t.join().expect("oops");
|
t.join().expect("oops");
|
||||||
|
|||||||
@ -3,14 +3,17 @@ use std::time::Instant;
|
|||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, VerifierCircuitData, VerifierOnlyCircuitData};
|
use crate::circuit_data::{
|
||||||
|
CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData,
|
||||||
|
VerifierCircuitData, VerifierOnlyCircuitData,
|
||||||
|
};
|
||||||
|
use crate::field::cosets::get_unique_coset_shifts;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gates::constant::ConstantGate;
|
use crate::gates::constant::ConstantGate;
|
||||||
use crate::gates::gate::{GateInstance, GateRef};
|
use crate::gates::gate::{GateInstance, GateRef};
|
||||||
use crate::gates::noop::NoopGate;
|
use crate::gates::noop::NoopGate;
|
||||||
use crate::generator::{CopyGenerator, WitnessGenerator};
|
use crate::generator::{CopyGenerator, WitnessGenerator};
|
||||||
use crate::hash::merkle_root_bit_rev_order;
|
use crate::hash::merkle_root_bit_rev_order;
|
||||||
use crate::field::cosets::get_unique_coset_shifts;
|
|
||||||
use crate::polynomial::polynomial::PolynomialValues;
|
use crate::polynomial::polynomial::PolynomialValues;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::util::{log2_strict, transpose, transpose_poly_values};
|
use crate::util::{log2_strict, transpose, transpose_poly_values};
|
||||||
@ -79,14 +82,21 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
// TODO: Not passing next constants for now. Not sure if it's really useful...
|
// TODO: Not passing next constants for now. Not sure if it's really useful...
|
||||||
self.add_generators(gate_type.0.generators(index, &constants, &[]));
|
self.add_generators(gate_type.0.generators(index, &constants, &[]));
|
||||||
|
|
||||||
self.gate_instances.push(GateInstance { gate_type, constants });
|
self.gate_instances.push(GateInstance {
|
||||||
|
gate_type,
|
||||||
|
constants,
|
||||||
|
});
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_gate_compatibility(&self, gate: &GateRef<F>) {
|
fn check_gate_compatibility(&self, gate: &GateRef<F>) {
|
||||||
assert!(gate.0.num_wires() <= self.config.num_wires,
|
assert!(
|
||||||
|
gate.0.num_wires() <= self.config.num_wires,
|
||||||
"{:?} requires {} wires, but our GateConfig has only {}",
|
"{:?} requires {} wires, but our GateConfig has only {}",
|
||||||
gate.0.id(), gate.0.num_wires(), self.config.num_wires);
|
gate.0.id(),
|
||||||
|
gate.0.num_wires(),
|
||||||
|
self.config.num_wires
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shorthand for `generate_copy` and `assert_equal`.
|
/// Shorthand for `generate_copy` and `assert_equal`.
|
||||||
@ -104,8 +114,14 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
/// Uses Plonk's permutation argument to require that two elements be equal.
|
/// Uses Plonk's permutation argument to require that two elements be equal.
|
||||||
/// Both elements must be routable, otherwise this method will panic.
|
/// Both elements must be routable, otherwise this method will panic.
|
||||||
pub fn assert_equal(&mut self, x: Target, y: Target) {
|
pub fn assert_equal(&mut self, x: Target, y: Target) {
|
||||||
assert!(x.is_routable(self.config), "Tried to route a wire that isn't routable");
|
assert!(
|
||||||
assert!(y.is_routable(self.config), "Tried to route a wire that isn't routable");
|
x.is_routable(self.config),
|
||||||
|
"Tried to route a wire that isn't routable"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
y.is_routable(self.config),
|
||||||
|
"Tried to route a wire that isn't routable"
|
||||||
|
);
|
||||||
// TODO: Add to copy_constraints.
|
// TODO: Add to copy_constraints.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +156,10 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
/// Returns a routable target with the given constant value.
|
/// Returns a routable target with the given constant value.
|
||||||
pub fn constant(&mut self, c: F) -> Target {
|
pub fn constant(&mut self, c: F) -> Target {
|
||||||
let gate = self.add_gate(ConstantGate::get(), vec![c]);
|
let gate = self.add_gate(ConstantGate::get(), vec![c]);
|
||||||
Target::Wire(Wire { gate, input: ConstantGate::WIRE_OUTPUT })
|
Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: ConstantGate::WIRE_OUTPUT,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constants(&mut self, constants: &[F]) -> Vec<Target> {
|
pub fn constants(&mut self, constants: &[F]) -> Vec<Target> {
|
||||||
@ -156,11 +175,15 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn constant_polys(&self) -> Vec<PolynomialValues<F>> {
|
fn constant_polys(&self) -> Vec<PolynomialValues<F>> {
|
||||||
let num_constants = self.gate_instances.iter()
|
let num_constants = self
|
||||||
|
.gate_instances
|
||||||
|
.iter()
|
||||||
.map(|gate_inst| gate_inst.constants.len())
|
.map(|gate_inst| gate_inst.constants.len())
|
||||||
.max()
|
.max()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let constants_per_gate = self.gate_instances.iter()
|
let constants_per_gate = self
|
||||||
|
.gate_instances
|
||||||
|
.iter()
|
||||||
.map(|gate_inst| {
|
.map(|gate_inst| {
|
||||||
let mut padded_constants = gate_inst.constants.clone();
|
let mut padded_constants = gate_inst.constants.clone();
|
||||||
for _ in padded_constants.len()..num_constants {
|
for _ in padded_constants.len()..num_constants {
|
||||||
@ -177,13 +200,17 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sigma_vecs(&self) -> Vec<PolynomialValues<F>> {
|
fn sigma_vecs(&self) -> Vec<PolynomialValues<F>> {
|
||||||
vec![PolynomialValues::zero(self.gate_instances.len()); self.config.num_routed_wires] // TODO
|
vec![PolynomialValues::zero(self.gate_instances.len()); self.config.num_routed_wires]
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a "full circuit", with both prover and verifier data.
|
/// Builds a "full circuit", with both prover and verifier data.
|
||||||
pub fn build(mut self) -> CircuitData<F> {
|
pub fn build(mut self) -> CircuitData<F> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
info!("degree before blinding & padding: {}", self.gate_instances.len());
|
info!(
|
||||||
|
"degree before blinding & padding: {}",
|
||||||
|
self.gate_instances.len()
|
||||||
|
);
|
||||||
self.blind_and_pad();
|
self.blind_and_pad();
|
||||||
let degree = self.gate_instances.len();
|
let degree = self.gate_instances.len();
|
||||||
info!("degree after blinding & padding: {}", degree);
|
info!("degree after blinding & padding: {}", degree);
|
||||||
@ -199,7 +226,11 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
let sigmas_root = merkle_root_bit_rev_order(sigma_ldes_t.clone());
|
let sigmas_root = merkle_root_bit_rev_order(sigma_ldes_t.clone());
|
||||||
|
|
||||||
let generators = self.generators;
|
let generators = self.generators;
|
||||||
let prover_only = ProverOnlyCircuitData { generators, constant_ldes_t, sigma_ldes_t };
|
let prover_only = ProverOnlyCircuitData {
|
||||||
|
generators,
|
||||||
|
constant_ldes_t,
|
||||||
|
sigma_ldes_t,
|
||||||
|
};
|
||||||
let verifier_only = VerifierOnlyCircuitData {};
|
let verifier_only = VerifierOnlyCircuitData {};
|
||||||
|
|
||||||
// The HashSet of gates will have a non-deterministic order. When converting to a Vec, we
|
// The HashSet of gates will have a non-deterministic order. When converting to a Vec, we
|
||||||
@ -207,7 +238,8 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
let mut gates = self.gates.iter().cloned().collect::<Vec<_>>();
|
let mut gates = self.gates.iter().cloned().collect::<Vec<_>>();
|
||||||
gates.sort_unstable_by_key(|gate| gate.0.id());
|
gates.sort_unstable_by_key(|gate| gate.0.id());
|
||||||
|
|
||||||
let num_gate_constraints = gates.iter()
|
let num_gate_constraints = gates
|
||||||
|
.iter()
|
||||||
.map(|gate| gate.0.num_constraints())
|
.map(|gate| gate.0.num_constraints())
|
||||||
.max()
|
.max()
|
||||||
.expect("No gates?");
|
.expect("No gates?");
|
||||||
@ -236,14 +268,28 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
/// Builds a "prover circuit", with data needed to generate proofs but not verify them.
|
/// Builds a "prover circuit", with data needed to generate proofs but not verify them.
|
||||||
pub fn build_prover(self) -> ProverCircuitData<F> {
|
pub fn build_prover(self) -> ProverCircuitData<F> {
|
||||||
// TODO: Can skip parts of this.
|
// TODO: Can skip parts of this.
|
||||||
let CircuitData { prover_only, common, .. } = self.build();
|
let CircuitData {
|
||||||
ProverCircuitData { prover_only, common }
|
prover_only,
|
||||||
|
common,
|
||||||
|
..
|
||||||
|
} = self.build();
|
||||||
|
ProverCircuitData {
|
||||||
|
prover_only,
|
||||||
|
common,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a "verifier circuit", with data needed to verify proofs but not generate them.
|
/// Builds a "verifier circuit", with data needed to verify proofs but not generate them.
|
||||||
pub fn build_verifier(self) -> VerifierCircuitData<F> {
|
pub fn build_verifier(self) -> VerifierCircuitData<F> {
|
||||||
// TODO: Can skip parts of this.
|
// TODO: Can skip parts of this.
|
||||||
let CircuitData { verifier_only, common, .. } = self.build();
|
let CircuitData {
|
||||||
VerifierCircuitData { verifier_only, common }
|
verifier_only,
|
||||||
|
common,
|
||||||
|
..
|
||||||
|
} = self.build();
|
||||||
|
VerifierCircuitData {
|
||||||
|
verifier_only,
|
||||||
|
common,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,7 +128,8 @@ impl<F: Field> CommonCircuitData<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn constraint_degree(&self) -> usize {
|
pub fn constraint_degree(&self) -> usize {
|
||||||
self.gates.iter()
|
self.gates
|
||||||
|
.iter()
|
||||||
.map(|g| g.0.degree())
|
.map(|g| g.0.degree())
|
||||||
.max()
|
.max()
|
||||||
.expect("No gates?")
|
.expect("No gates?")
|
||||||
|
|||||||
@ -2,19 +2,19 @@ use crate::field::field::Field;
|
|||||||
|
|
||||||
/// Finds a set of shifts that result in unique cosets for the multiplicative subgroup of size
|
/// Finds a set of shifts that result in unique cosets for the multiplicative subgroup of size
|
||||||
/// `2^subgroup_bits`.
|
/// `2^subgroup_bits`.
|
||||||
pub(crate) fn get_unique_coset_shifts<F: Field>(
|
pub(crate) fn get_unique_coset_shifts<F: Field>(subgroup_size: usize, num_shifts: usize) -> Vec<F> {
|
||||||
subgroup_size: usize,
|
|
||||||
num_shifts: usize,
|
|
||||||
) -> Vec<F> {
|
|
||||||
// From Lagrange's theorem.
|
// From Lagrange's theorem.
|
||||||
let num_cosets = (F::ORDER - 1) / (subgroup_size as u64);
|
let num_cosets = (F::ORDER - 1) / (subgroup_size as u64);
|
||||||
assert!(num_shifts as u64 <= num_cosets,
|
assert!(
|
||||||
"The subgroup does not have enough distinct cosets");
|
num_shifts as u64 <= num_cosets,
|
||||||
|
"The subgroup does not have enough distinct cosets"
|
||||||
|
);
|
||||||
|
|
||||||
// Let g be a generator of the entire multiplicative group. Let n be the order of the subgroup.
|
// Let g be a generator of the entire multiplicative group. Let n be the order of the subgroup.
|
||||||
// The subgroup can be written as <g^(|F*| / n)>. We can use g^0, ..., g^(num_shifts - 1) as our
|
// The subgroup can be written as <g^(|F*| / n)>. We can use g^0, ..., g^(num_shifts - 1) as our
|
||||||
// shifts, since g^i <g^(|F*| / n)> are distinct cosets provided i < |F*| / n, which we checked.
|
// shifts, since g^i <g^(|F*| / n)> are distinct cosets provided i < |F*| / n, which we checked.
|
||||||
F::MULTIPLICATIVE_GROUP_GENERATOR.powers()
|
F::MULTIPLICATIVE_GROUP_GENERATOR
|
||||||
|
.powers()
|
||||||
.take(num_shifts)
|
.take(num_shifts)
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@ -45,7 +45,8 @@ mod tests {
|
|||||||
let coset = F::cyclic_subgroup_coset_known_order(generator, shift, subgroup_size);
|
let coset = F::cyclic_subgroup_coset_known_order(generator, shift, subgroup_size);
|
||||||
assert!(
|
assert!(
|
||||||
coset.into_iter().all(|x| union.insert(x)),
|
coset.into_iter().all(|x| union.insert(x)),
|
||||||
"Duplicate element!");
|
"Duplicate element!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use std::fmt::{Debug, Display, Formatter};
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
|
||||||
use num::Integer;
|
use num::Integer;
|
||||||
@ -123,11 +123,7 @@ impl Field for CrandallField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let inverse = Self(if u == 1 {
|
let inverse = Self(if u == 1 { b } else { c });
|
||||||
b
|
|
||||||
} else {
|
|
||||||
c
|
|
||||||
});
|
|
||||||
|
|
||||||
// Should change to debug_assert_eq; using assert_eq as an extra precaution for now until
|
// Should change to debug_assert_eq; using assert_eq as an extra precaution for now until
|
||||||
// we're more confident the impl is correct.
|
// we're more confident the impl is correct.
|
||||||
|
|||||||
@ -62,9 +62,8 @@ pub(crate) fn ifft_with_precomputation_power_of_2<F: Field>(
|
|||||||
let n_inv = F::from_canonical_usize(n).try_inverse().unwrap();
|
let n_inv = F::from_canonical_usize(n).try_inverse().unwrap();
|
||||||
|
|
||||||
let PolynomialValues { values } = poly;
|
let PolynomialValues { values } = poly;
|
||||||
let PolynomialValues { values: mut result } = fft_with_precomputation_power_of_2(
|
let PolynomialValues { values: mut result } =
|
||||||
PolynomialCoeffs { coeffs: values },
|
fft_with_precomputation_power_of_2(PolynomialCoeffs { coeffs: values }, precomputation);
|
||||||
precomputation);
|
|
||||||
|
|
||||||
// We reverse all values except the first, and divide each by n.
|
// We reverse all values except the first, and divide each by n.
|
||||||
result[0] = result[0] * n_inv;
|
result[0] = result[0] * n_inv;
|
||||||
@ -155,11 +154,11 @@ pub(crate) fn coset_ifft<F: Field>(poly: PolynomialValues<F>, shift: F) -> Polyn
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::util::{log2_ceil, log2_strict};
|
|
||||||
use crate::field::fft::{ifft, fft};
|
|
||||||
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
|
||||||
use crate::field::field::Field;
|
|
||||||
use crate::field::crandall_field::CrandallField;
|
use crate::field::crandall_field::CrandallField;
|
||||||
|
use crate::field::fft::{fft, ifft};
|
||||||
|
use crate::field::field::Field;
|
||||||
|
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||||
|
use crate::util::{log2_ceil, log2_strict};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fft_and_ifft() {
|
fn fft_and_ifft() {
|
||||||
@ -195,7 +194,9 @@ mod tests {
|
|||||||
evaluate_naive_power_of_2(&coefficients_padded)
|
evaluate_naive_power_of_2(&coefficients_padded)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate_naive_power_of_2<F: Field>(coefficients: &PolynomialCoeffs<F>) -> PolynomialValues<F> {
|
fn evaluate_naive_power_of_2<F: Field>(
|
||||||
|
coefficients: &PolynomialCoeffs<F>,
|
||||||
|
) -> PolynomialValues<F> {
|
||||||
let degree = coefficients.len();
|
let degree = coefficients.len();
|
||||||
let degree_pow = log2_strict(degree);
|
let degree_pow = log2_strict(degree);
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
use std::fmt::{Debug, Display};
|
|
||||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
|
||||||
use rand::Rng;
|
|
||||||
use rand::rngs::OsRng;
|
|
||||||
use crate::util::bits_u64;
|
use crate::util::bits_u64;
|
||||||
|
use rand::rngs::OsRng;
|
||||||
|
use rand::Rng;
|
||||||
|
use std::fmt::{Debug, Display};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
|
||||||
/// A finite field with prime order less than 2^64.
|
/// A finite field with prime order less than 2^64.
|
||||||
pub trait Field: 'static
|
pub trait Field:
|
||||||
|
'static
|
||||||
+ Copy
|
+ Copy
|
||||||
+ Eq
|
+ Eq
|
||||||
+ Hash
|
+ Hash
|
||||||
@ -22,7 +23,8 @@ pub trait Field: 'static
|
|||||||
+ Debug
|
+ Debug
|
||||||
+ Display
|
+ Display
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync {
|
+ Sync
|
||||||
|
{
|
||||||
const ZERO: Self;
|
const ZERO: Self;
|
||||||
const ONE: Self;
|
const ONE: Self;
|
||||||
const TWO: Self;
|
const TWO: Self;
|
||||||
@ -92,7 +94,9 @@ pub trait Field: 'static
|
|||||||
assert!(n_power <= Self::TWO_ADICITY);
|
assert!(n_power <= Self::TWO_ADICITY);
|
||||||
let base = Self::POWER_OF_TWO_GENERATOR;
|
let base = Self::POWER_OF_TWO_GENERATOR;
|
||||||
// TODO: Just repeated squaring should be a bit faster, to avoid conditionals.
|
// TODO: Just repeated squaring should be a bit faster, to avoid conditionals.
|
||||||
base.exp(Self::from_canonical_u64(1u64 << (Self::TWO_ADICITY - n_power)))
|
base.exp(Self::from_canonical_u64(
|
||||||
|
1u64 << (Self::TWO_ADICITY - n_power),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes a multiplicative subgroup whose order is known in advance.
|
/// Computes a multiplicative subgroup whose order is known in advance.
|
||||||
@ -109,9 +113,7 @@ pub trait Field: 'static
|
|||||||
/// Computes a coset of a multiplicative subgroup whose order is known in advance.
|
/// Computes a coset of a multiplicative subgroup whose order is known in advance.
|
||||||
fn cyclic_subgroup_coset_known_order(generator: Self, shift: Self, order: usize) -> Vec<Self> {
|
fn cyclic_subgroup_coset_known_order(generator: Self, shift: Self, order: usize) -> Vec<Self> {
|
||||||
let subgroup = Self::cyclic_subgroup_known_order(generator, order);
|
let subgroup = Self::cyclic_subgroup_known_order(generator, order);
|
||||||
subgroup.into_iter()
|
subgroup.into_iter().map(|x| x * shift).collect()
|
||||||
.map(|x| x * shift)
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_canonical_u64(&self) -> u64;
|
fn to_canonical_u64(&self) -> u64;
|
||||||
@ -144,7 +146,10 @@ pub trait Field: 'static
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn powers(&self) -> Powers<Self> {
|
fn powers(&self) -> Powers<Self> {
|
||||||
Powers { base: *self, current: Self::ONE }
|
Powers {
|
||||||
|
base: *self,
|
||||||
|
current: Self::ONE,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
|
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
|
||||||
|
|||||||
@ -55,7 +55,6 @@ pub fn test_inputs(modulus: u64, word_bits: usize) -> Vec<u64> {
|
|||||||
// .collect()
|
// .collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Apply the unary functions `op` and `expected_op`
|
/// Apply the unary functions `op` and `expected_op`
|
||||||
/// coordinate-wise to the inputs from `test_inputs(modulus,
|
/// coordinate-wise to the inputs from `test_inputs(modulus,
|
||||||
/// word_bits)` and panic if the two resulting vectors differ.
|
/// word_bits)` and panic if the two resulting vectors differ.
|
||||||
@ -70,18 +69,18 @@ pub fn run_unaryop_test_cases<F, UnaryOp, ExpectedOp>(
|
|||||||
ExpectedOp: Fn(u64) -> u64,
|
ExpectedOp: Fn(u64) -> u64,
|
||||||
{
|
{
|
||||||
let inputs = test_inputs(modulus, word_bits);
|
let inputs = test_inputs(modulus, word_bits);
|
||||||
let expected: Vec<_> = inputs.iter()
|
let expected: Vec<_> = inputs.iter().map(|&x| expected_op(x)).collect();
|
||||||
.map(|&x| expected_op(x))
|
|
||||||
.collect();
|
|
||||||
let output: Vec<_> = inputs
|
let output: Vec<_> = inputs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&x| op(F::from_canonical_u64(x)).to_canonical_u64())
|
.map(|&x| op(F::from_canonical_u64(x)).to_canonical_u64())
|
||||||
.collect();
|
.collect();
|
||||||
// Compare expected outputs with actual outputs
|
// Compare expected outputs with actual outputs
|
||||||
for i in 0..inputs.len() {
|
for i in 0..inputs.len() {
|
||||||
assert_eq!(output[i], expected[i],
|
assert_eq!(
|
||||||
|
output[i], expected[i],
|
||||||
"Expected {}, got {} for input {}",
|
"Expected {}, got {} for input {}",
|
||||||
expected[i], output[i], inputs[i]);
|
expected[i], output[i], inputs[i]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +105,8 @@ pub fn run_binaryop_test_cases<F, BinaryOp, ExpectedOp>(
|
|||||||
// Iterator over inputs rotated right by i places. Since
|
// Iterator over inputs rotated right by i places. Since
|
||||||
// cycle().skip(i) rotates left by i, we need to rotate by
|
// cycle().skip(i) rotates left by i, we need to rotate by
|
||||||
// n_input_elts - i.
|
// n_input_elts - i.
|
||||||
let shifted_inputs: Vec<_> = inputs.iter()
|
let shifted_inputs: Vec<_> = inputs
|
||||||
|
.iter()
|
||||||
.cycle()
|
.cycle()
|
||||||
.skip(inputs.len() - i)
|
.skip(inputs.len() - i)
|
||||||
.take(inputs.len())
|
.take(inputs.len())
|
||||||
@ -119,15 +119,21 @@ pub fn run_binaryop_test_cases<F, BinaryOp, ExpectedOp>(
|
|||||||
.map(|(x, y)| expected_op(x.clone(), y.clone()))
|
.map(|(x, y)| expected_op(x.clone(), y.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let output: Vec<_> = inputs.iter().zip(shifted_inputs.clone()).map(|(&x, &y)| {
|
let output: Vec<_> = inputs
|
||||||
|
.iter()
|
||||||
|
.zip(shifted_inputs.clone())
|
||||||
|
.map(|(&x, &y)| {
|
||||||
op(F::from_canonical_u64(x), F::from_canonical_u64(y)).to_canonical_u64()
|
op(F::from_canonical_u64(x), F::from_canonical_u64(y)).to_canonical_u64()
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Compare expected outputs with actual outputs
|
// Compare expected outputs with actual outputs
|
||||||
for i in 0..inputs.len() {
|
for i in 0..inputs.len() {
|
||||||
assert_eq!(output[i], expected[i],
|
assert_eq!(
|
||||||
|
output[i], expected[i],
|
||||||
"On inputs {} . {}, expected {} but got {}",
|
"On inputs {} . {}, expected {} but got {}",
|
||||||
inputs[i], shifted_inputs[i], expected[i], output[i]);
|
inputs[i], shifted_inputs[i], expected[i], output[i]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,7 +152,11 @@ macro_rules! test_arithmetic {
|
|||||||
#[test]
|
#[test]
|
||||||
fn arithmetic_addition() {
|
fn arithmetic_addition() {
|
||||||
let modulus = <$field>::ORDER;
|
let modulus = <$field>::ORDER;
|
||||||
crate::field::field_testing::run_binaryop_test_cases(modulus, WORD_BITS, <$field>::add, |x, y| {
|
crate::field::field_testing::run_binaryop_test_cases(
|
||||||
|
modulus,
|
||||||
|
WORD_BITS,
|
||||||
|
<$field>::add,
|
||||||
|
|x, y| {
|
||||||
let (z, over) = x.overflowing_add(y);
|
let (z, over) = x.overflowing_add(y);
|
||||||
if over {
|
if over {
|
||||||
z.overflowing_sub(modulus).0
|
z.overflowing_sub(modulus).0
|
||||||
@ -155,48 +165,64 @@ macro_rules! test_arithmetic {
|
|||||||
} else {
|
} else {
|
||||||
z
|
z
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn arithmetic_subtraction() {
|
fn arithmetic_subtraction() {
|
||||||
let modulus = <$field>::ORDER;
|
let modulus = <$field>::ORDER;
|
||||||
crate::field::field_testing::run_binaryop_test_cases(modulus, WORD_BITS, <$field>::sub, |x, y| {
|
crate::field::field_testing::run_binaryop_test_cases(
|
||||||
|
modulus,
|
||||||
|
WORD_BITS,
|
||||||
|
<$field>::sub,
|
||||||
|
|x, y| {
|
||||||
if x >= y {
|
if x >= y {
|
||||||
x - y
|
x - y
|
||||||
} else {
|
} else {
|
||||||
&modulus - y + x
|
&modulus - y + x
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn arithmetic_negation() {
|
fn arithmetic_negation() {
|
||||||
let modulus = <$field>::ORDER;
|
let modulus = <$field>::ORDER;
|
||||||
crate::field::field_testing::run_unaryop_test_cases(modulus, WORD_BITS, <$field>::neg, |x| {
|
crate::field::field_testing::run_unaryop_test_cases(
|
||||||
|
modulus,
|
||||||
|
WORD_BITS,
|
||||||
|
<$field>::neg,
|
||||||
|
|x| {
|
||||||
if x == 0 {
|
if x == 0 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
modulus - x
|
modulus - x
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn arithmetic_multiplication() {
|
fn arithmetic_multiplication() {
|
||||||
let modulus = <$field>::ORDER;
|
let modulus = <$field>::ORDER;
|
||||||
crate::field::field_testing::run_binaryop_test_cases(modulus, WORD_BITS, <$field>::mul, |x, y| {
|
crate::field::field_testing::run_binaryop_test_cases(
|
||||||
((x as u128) * (y as u128) % (modulus as u128)) as u64
|
modulus,
|
||||||
})
|
WORD_BITS,
|
||||||
|
<$field>::mul,
|
||||||
|
|x, y| ((x as u128) * (y as u128) % (modulus as u128)) as u64,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn arithmetic_square() {
|
fn arithmetic_square() {
|
||||||
let modulus = <$field>::ORDER;
|
let modulus = <$field>::ORDER;
|
||||||
crate::field::field_testing::run_unaryop_test_cases(
|
crate::field::field_testing::run_unaryop_test_cases(
|
||||||
modulus, WORD_BITS,
|
modulus,
|
||||||
|
WORD_BITS,
|
||||||
|x: $field| x.square(),
|
|x: $field| x.square(),
|
||||||
|x| ((x as u128) * (x as u128) % (modulus as u128)) as u64)
|
|x| ((x as u128) * (x as u128) % (modulus as u128)) as u64,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
pub mod crandall_field;
|
|
||||||
pub mod field;
|
|
||||||
pub mod fft;
|
|
||||||
pub(crate) mod cosets;
|
pub(crate) mod cosets;
|
||||||
|
pub mod crandall_field;
|
||||||
|
pub mod fft;
|
||||||
|
pub mod field;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod field_testing;
|
mod field_testing;
|
||||||
|
|||||||
210
src/fri.rs
210
src/fri.rs
@ -1,10 +1,13 @@
|
|||||||
|
use crate::field::fft::fft;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::hash::{compress, hash_n_to_hash};
|
use crate::hash::{compress, hash_n_to_hash};
|
||||||
|
use crate::merkle_proofs::verify_merkle_proof;
|
||||||
|
use crate::merkle_tree::MerkleTree;
|
||||||
use crate::plonk_challenger::Challenger;
|
use crate::plonk_challenger::Challenger;
|
||||||
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||||
use crate::proof::{Hash, FriProof};
|
use crate::proof::{FriEvaluations, FriMerkleProofs, FriProof, FriQueryRound, Hash};
|
||||||
use crate::field::fft::fft;
|
use crate::util::log2_strict;
|
||||||
use crate::gadgets::merkle_proofs::MerkleTree;
|
use std::cmp::min;
|
||||||
|
|
||||||
/// Somewhat arbitrary. Smaller values will increase delta, but with diminishing returns,
|
/// Somewhat arbitrary. Smaller values will increase delta, but with diminishing returns,
|
||||||
/// while increasing L, potentially requiring more challenge points.
|
/// while increasing L, potentially requiring more challenge points.
|
||||||
@ -23,7 +26,8 @@ struct FriConfig {
|
|||||||
/// then the final domain will have size `2^(n-reduction_count)`.
|
/// then the final domain will have size `2^(n-reduction_count)`.
|
||||||
reduction_count: usize,
|
reduction_count: usize,
|
||||||
|
|
||||||
rate_bits: usize,
|
/// Number of query rounds to perform.
|
||||||
|
num_query_rounds: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fri_delta(rate_log: usize, conjecture: bool) -> f64 {
|
fn fri_delta(rate_log: usize, conjecture: bool) -> f64 {
|
||||||
@ -50,20 +54,24 @@ fn fri_l(codeword_len: usize, rate_log: usize, conjecture: bool) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Different arity + PoW.
|
// TODO: Different arity + PoW.
|
||||||
/// Performs a FRI round.
|
/// Builds a FRI proof.
|
||||||
fn fri_round<F: Field>(
|
fn fri_proof<F: Field>(
|
||||||
|
// Coefficients of the polynomial on which the LDT is performed.
|
||||||
|
// Only the first `1/rate_bits` coefficients are non-zero.
|
||||||
polynomial_coeffs: &PolynomialCoeffs<F>,
|
polynomial_coeffs: &PolynomialCoeffs<F>,
|
||||||
|
// Evaluation of the polynomial on the large domain.
|
||||||
polynomial_values: &PolynomialValues<F>,
|
polynomial_values: &PolynomialValues<F>,
|
||||||
challenger: &mut Challenger<F>,
|
challenger: &mut Challenger<F>,
|
||||||
config: &FriConfig,
|
config: &FriConfig,
|
||||||
) -> FriProof<F> {
|
) -> FriProof<F> {
|
||||||
let n = polynomial_values.values.len();
|
let n = polynomial_values.values.len();
|
||||||
assert_eq!(
|
assert_eq!(polynomial_coeffs.coeffs.len(), n);
|
||||||
polynomial_coeffs.coeffs.len(),
|
|
||||||
n
|
let mut trees = vec![MerkleTree::new(
|
||||||
);
|
polynomial_values.values.iter().map(|&v| vec![v]).collect(),
|
||||||
let mut trees = vec![MerkleTree::new(polynomial_values.values.iter().map(|&v| vec![v]).collect())];
|
true,
|
||||||
let mut root = trees.last().unwrap().root;
|
)];
|
||||||
|
let mut root = trees[0].root;
|
||||||
let mut coeffs = polynomial_coeffs.clone();
|
let mut coeffs = polynomial_coeffs.clone();
|
||||||
let mut values;
|
let mut values;
|
||||||
|
|
||||||
@ -72,6 +80,7 @@ fn fri_round<F: Field>(
|
|||||||
// Commit phase
|
// Commit phase
|
||||||
for _ in 0..config.reduction_count {
|
for _ in 0..config.reduction_count {
|
||||||
let beta = challenger.get_challenge();
|
let beta = challenger.get_challenge();
|
||||||
|
// P(x) = P_0(x^2) + xP_1(x^2) becomes P_0(x) + beta*P_1(x)
|
||||||
coeffs = PolynomialCoeffs::new(
|
coeffs = PolynomialCoeffs::new(
|
||||||
coeffs
|
coeffs
|
||||||
.coeffs
|
.coeffs
|
||||||
@ -79,30 +88,185 @@ fn fri_round<F: Field>(
|
|||||||
.map(|chunk| chunk[0] + beta * chunk[1])
|
.map(|chunk| chunk[0] + beta * chunk[1])
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
values = fft(coeffs.clone().lde(config.rate_bits));
|
values = fft(coeffs.clone());
|
||||||
|
|
||||||
let tree = MerkleTree::new(values.values.iter().map(|&v| vec![v]).collect());
|
let tree = MerkleTree::new(values.values.iter().map(|&v| vec![v]).collect(), true);
|
||||||
challenger.observe_hash(&tree.root);
|
challenger.observe_hash(&tree.root);
|
||||||
trees.push(tree);
|
trees.push(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query phase
|
// Query phase
|
||||||
let mut merkle_proofs = Vec::new();
|
let mut query_round_proofs = Vec::new();
|
||||||
let mut evals = Vec::new();
|
for _ in 0..config.num_query_rounds {
|
||||||
for i in 0..config.reduction_count {
|
let mut merkle_proofs = FriMerkleProofs { proofs: Vec::new() };
|
||||||
|
let mut evals = FriEvaluations {
|
||||||
|
first_layer: (F::ZERO, F::ZERO),
|
||||||
|
rest: Vec::new(),
|
||||||
|
};
|
||||||
|
// TODO: Challenger doesn't change between query rounds, so x is always the same.
|
||||||
|
// Once PoW is added, this should be fixed.
|
||||||
let x = challenger.get_challenge();
|
let x = challenger.get_challenge();
|
||||||
let x_index = (x.to_canonical_u64() as usize) % n;
|
let mut domain_size = n;
|
||||||
let n2 = n>>1;
|
let mut x_index = x.to_canonical_u64() as usize;
|
||||||
evals.extend(std::array::IntoIter::new([polynomial_values.values[x_index], polynomial_values.values[n2 + x_index]]));
|
for i in 0..config.reduction_count {
|
||||||
merkle_proofs.extend(std::array::IntoIter::new([trees[i].prove(x_index), trees[i].prove(n2 + x_index)]));
|
let domain_size2 = domain_size >> 1;
|
||||||
|
x_index %= domain_size;
|
||||||
|
let minus_x_index = (domain_size2 + x_index) % domain_size;
|
||||||
|
if i == 0 {
|
||||||
|
// For the first layer, we need to send the evaluation at `x` and `-x`.
|
||||||
|
evals.first_layer = (trees[i].get(x_index)[0], trees[i].get(minus_x_index)[0]);
|
||||||
|
} else {
|
||||||
|
// For the other layers, we only need to send the `-x`, the one at `x` can be inferred
|
||||||
|
// by the verifier. See the `compute_evaluation` function.
|
||||||
|
evals.rest.push(trees[i].get(minus_x_index)[0]);
|
||||||
|
}
|
||||||
|
merkle_proofs
|
||||||
|
.proofs
|
||||||
|
.push((trees[i].prove(x_index), trees[i].prove(minus_x_index)));
|
||||||
|
|
||||||
|
domain_size = domain_size2;
|
||||||
|
}
|
||||||
|
query_round_proofs.push(FriQueryRound {
|
||||||
|
merkle_proofs,
|
||||||
|
evals,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FriProof {
|
FriProof {
|
||||||
commit_phase_merkle_roots: trees.iter().map(|t| t.root).collect(),
|
commit_phase_merkle_roots: trees.iter().map(|t| t.root).collect(),
|
||||||
initial_merkle_proofs: vec![],
|
initial_merkle_proofs: vec![],
|
||||||
intermediate_merkle_proofs: merkle_proofs,
|
query_round_proofs,
|
||||||
final_poly: coeffs
|
final_poly: coeffs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes P'(x^2) from P_even(x) and P_odd(x), where P' is the FRI reduced polynomial,
|
||||||
|
/// P_even is the even coefficients polynomial and P_off is the odd coefficients polynomial.
|
||||||
|
fn compute_evaluation<F: Field>(x: F, last_e_x: F, last_e_x_minus: F, beta: F) -> F {
|
||||||
|
// P(x) = P_0(x^2) + xP_1(x^2)
|
||||||
|
// P'(x^2) = P_0(x^2) + beta*P_1(x^2)
|
||||||
|
// P'(x^2) = ((P(x)+P(-x))/2) + beta*((P(x)-P(-x))/(2x)
|
||||||
|
(last_e_x + last_e_x_minus) / F::TWO + beta * (last_e_x - last_e_x_minus) / (F::TWO * x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn verify_fri_proof<F: Field>(
|
||||||
|
proof: &FriProof<F>,
|
||||||
|
challenger: &mut Challenger<F>,
|
||||||
|
config: &FriConfig,
|
||||||
|
) -> Option<()> {
|
||||||
|
// Size of the LDE domain.
|
||||||
|
let n = proof.final_poly.len() << config.reduction_count;
|
||||||
|
|
||||||
|
// Recover the random betas used in the FRI reductions.
|
||||||
|
let betas = proof.commit_phase_merkle_roots[..proof.commit_phase_merkle_roots.len() - 1]
|
||||||
|
.iter()
|
||||||
|
.map(|root| {
|
||||||
|
challenger.observe_hash(root);
|
||||||
|
challenger.get_challenge()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
challenger.observe_hash(proof.commit_phase_merkle_roots.last().unwrap());
|
||||||
|
|
||||||
|
// Check that parameters are coherent.
|
||||||
|
assert_eq!(config.num_query_rounds, proof.query_round_proofs.len());
|
||||||
|
assert!(config.reduction_count > 0);
|
||||||
|
|
||||||
|
for round in 0..config.num_query_rounds {
|
||||||
|
let round_proof = &proof.query_round_proofs[round];
|
||||||
|
let mut e_xs = Vec::new();
|
||||||
|
let x = challenger.get_challenge();
|
||||||
|
let mut domain_size = n;
|
||||||
|
let mut x_index = x.to_canonical_u64() as usize;
|
||||||
|
// `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
|
||||||
|
let mut subgroup_x = F::primitive_root_of_unity(log2_strict(n)).exp_usize(x_index % n);
|
||||||
|
for i in 0..config.reduction_count {
|
||||||
|
x_index %= domain_size;
|
||||||
|
let domain_size2 = domain_size >> 1;
|
||||||
|
let minus_x_index = (domain_size2 + x_index) % domain_size;
|
||||||
|
let (e_x, e_x_minus, merkle_proof, merkle_proof_minus) = if i == 0 {
|
||||||
|
let (e_x, e_x_minus) = round_proof.evals.first_layer;
|
||||||
|
let (merkle_proof, merkle_proof_minus) = &round_proof.merkle_proofs.proofs[i];
|
||||||
|
e_xs.push((e_x, e_x_minus));
|
||||||
|
(e_x, e_x_minus, merkle_proof, merkle_proof_minus)
|
||||||
|
} else {
|
||||||
|
let (last_e_x, last_e_x_minus) = e_xs[i - 1];
|
||||||
|
let e_x = compute_evaluation(subgroup_x, last_e_x, last_e_x_minus, betas[i - 1]);
|
||||||
|
let e_x_minus = round_proof.evals.rest[i - 1];
|
||||||
|
let (merkle_proof, merkle_proof_minus) = &round_proof.merkle_proofs.proofs[i];
|
||||||
|
e_xs.push((e_x, e_x_minus));
|
||||||
|
(e_x, e_x_minus, merkle_proof, merkle_proof_minus)
|
||||||
|
};
|
||||||
|
(verify_merkle_proof(
|
||||||
|
vec![e_x],
|
||||||
|
x_index,
|
||||||
|
proof.commit_phase_merkle_roots[i],
|
||||||
|
merkle_proof,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.is_some()
|
||||||
|
&& verify_merkle_proof(
|
||||||
|
vec![e_x_minus],
|
||||||
|
minus_x_index,
|
||||||
|
proof.commit_phase_merkle_roots[i],
|
||||||
|
merkle_proof_minus,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.is_some())
|
||||||
|
.then(|| ())?;
|
||||||
|
if i > 0 {
|
||||||
|
subgroup_x = subgroup_x.square();
|
||||||
|
}
|
||||||
|
domain_size = domain_size2;
|
||||||
|
}
|
||||||
|
let (last_e_x, last_e_x_minus) = e_xs[config.reduction_count - 1];
|
||||||
|
let purported_eval = compute_evaluation(
|
||||||
|
subgroup_x,
|
||||||
|
last_e_x,
|
||||||
|
last_e_x_minus,
|
||||||
|
betas[config.reduction_count - 1],
|
||||||
|
);
|
||||||
|
// Final check of FRI. After all the reduction, we check that the final polynomial is equal
|
||||||
|
// to the one sent by the prover.
|
||||||
|
(proof.final_poly.eval(subgroup_x.square()) == purported_eval).then(|| ())?;
|
||||||
|
}
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::field::crandall_field::CrandallField;
|
||||||
|
use crate::field::fft::ifft;
|
||||||
|
|
||||||
|
fn test_fri(degree: usize, rate_bits: usize, reduction_count: usize, num_query_rounds: usize) {
|
||||||
|
type F = CrandallField;
|
||||||
|
|
||||||
|
let n = degree;
|
||||||
|
let evals = PolynomialValues::new((0..n).map(|_| F::rand()).collect());
|
||||||
|
let lde = evals.clone().lde(rate_bits);
|
||||||
|
let config = FriConfig {
|
||||||
|
reduction_count,
|
||||||
|
num_query_rounds,
|
||||||
|
proof_of_work_bits: 0,
|
||||||
|
reduction_arity_bits: Vec::new(),
|
||||||
|
};
|
||||||
|
let mut challenger = Challenger::new();
|
||||||
|
let proof = fri_proof(&ifft(lde.clone()), &lde, &mut challenger, &config);
|
||||||
|
|
||||||
|
let mut challenger = Challenger::new();
|
||||||
|
assert!(verify_fri_proof(&proof, &mut challenger, &config).is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fri_multi_params() {
|
||||||
|
for degree_log in 1..6 {
|
||||||
|
for rate_bits in 0..4 {
|
||||||
|
for reduction_count in 1..=(degree_log + rate_bits) {
|
||||||
|
for num_query_round in 0..4 {
|
||||||
|
test_fri(1 << degree_log, rate_bits, reduction_count, num_query_round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::target::Target;
|
|
||||||
use crate::gates::arithmetic::ArithmeticGate;
|
use crate::gates::arithmetic::ArithmeticGate;
|
||||||
|
use crate::target::Target;
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
|
|
||||||
impl<F: Field> CircuitBuilder<F> {
|
impl<F: Field> CircuitBuilder<F> {
|
||||||
@ -22,10 +22,22 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
|
|
||||||
let gate = self.add_gate(ArithmeticGate::new(), vec![F::ONE, F::ONE]);
|
let gate = self.add_gate(ArithmeticGate::new(), vec![F::ONE, F::ONE]);
|
||||||
|
|
||||||
let wire_multiplicand_0 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_0 };
|
let wire_multiplicand_0 = Wire {
|
||||||
let wire_multiplicand_1 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_1 };
|
gate,
|
||||||
let wire_addend = Wire { gate, input: ArithmeticGate::WIRE_ADDEND };
|
input: ArithmeticGate::WIRE_MULTIPLICAND_0,
|
||||||
let wire_output = Wire { gate, input: ArithmeticGate::WIRE_OUTPUT };
|
};
|
||||||
|
let wire_multiplicand_1 = Wire {
|
||||||
|
gate,
|
||||||
|
input: ArithmeticGate::WIRE_MULTIPLICAND_1,
|
||||||
|
};
|
||||||
|
let wire_addend = Wire {
|
||||||
|
gate,
|
||||||
|
input: ArithmeticGate::WIRE_ADDEND,
|
||||||
|
};
|
||||||
|
let wire_output = Wire {
|
||||||
|
gate,
|
||||||
|
input: ArithmeticGate::WIRE_OUTPUT,
|
||||||
|
};
|
||||||
|
|
||||||
self.route(x, Target::Wire(wire_multiplicand_0));
|
self.route(x, Target::Wire(wire_multiplicand_0));
|
||||||
self.route(one, Target::Wire(wire_multiplicand_1));
|
self.route(one, Target::Wire(wire_multiplicand_1));
|
||||||
|
|||||||
@ -11,31 +11,44 @@ use crate::wire::Wire;
|
|||||||
impl<F: Field> CircuitBuilder<F> {
|
impl<F: Field> CircuitBuilder<F> {
|
||||||
pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] {
|
pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] {
|
||||||
let zero = self.zero();
|
let zero = self.zero();
|
||||||
let gate = self.add_gate_no_constants(
|
let gate =
|
||||||
GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants());
|
self.add_gate_no_constants(GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants());
|
||||||
|
|
||||||
// We don't want to swap any inputs, so set that wire to 0.
|
// We don't want to swap any inputs, so set that wire to 0.
|
||||||
let swap_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_SWAP;
|
let swap_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_SWAP;
|
||||||
let swap_wire = Target::Wire(Wire { gate, input: swap_wire });
|
let swap_wire = Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: swap_wire,
|
||||||
|
});
|
||||||
self.route(zero, swap_wire);
|
self.route(zero, swap_wire);
|
||||||
|
|
||||||
// The old accumulator wire doesn't matter, since we won't read the new accumulator wire.
|
// The old accumulator wire doesn't matter, since we won't read the new accumulator wire.
|
||||||
// We do have to set it to something though, so we'll arbitrary pick 0.
|
// We do have to set it to something though, so we'll arbitrary pick 0.
|
||||||
let old_acc_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_INDEX_ACCUMULATOR_OLD;
|
let old_acc_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_INDEX_ACCUMULATOR_OLD;
|
||||||
let old_acc_wire = Target::Wire(Wire { gate, input: old_acc_wire });
|
let old_acc_wire = Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: old_acc_wire,
|
||||||
|
});
|
||||||
self.route(zero, old_acc_wire);
|
self.route(zero, old_acc_wire);
|
||||||
|
|
||||||
// Route input wires.
|
// Route input wires.
|
||||||
for i in 0..12 {
|
for i in 0..12 {
|
||||||
let in_wire = GMiMCGate::<F, GMIMC_ROUNDS>::wire_input(i);
|
let in_wire = GMiMCGate::<F, GMIMC_ROUNDS>::wire_input(i);
|
||||||
let in_wire = Target::Wire(Wire { gate, input: in_wire });
|
let in_wire = Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: in_wire,
|
||||||
|
});
|
||||||
self.route(inputs[i], in_wire);
|
self.route(inputs[i], in_wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect output wires.
|
// Collect output wires.
|
||||||
(0..12)
|
(0..12)
|
||||||
.map(|i| Target::Wire(
|
.map(|i| {
|
||||||
Wire { gate, input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i) }))
|
Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i),
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
use crate::witness::PartialWitness;
|
use crate::witness::PartialWitness;
|
||||||
use crate::circuit_builder::CircuitBuilder;
|
|
||||||
|
|
||||||
impl<F: Field> CircuitBuilder<F> {
|
impl<F: Field> CircuitBuilder<F> {
|
||||||
/// Split the given integer into a list of virtual advice targets, where each one represents a
|
/// Split the given integer into a list of virtual advice targets, where each one represents a
|
||||||
@ -12,11 +12,7 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
/// Note that this only handles witness generation; it does not enforce that the decomposition
|
/// Note that this only handles witness generation; it does not enforce that the decomposition
|
||||||
/// is correct. The output should be treated as a "purported" decomposition which must be
|
/// is correct. The output should be treated as a "purported" decomposition which must be
|
||||||
/// enforced elsewhere.
|
/// enforced elsewhere.
|
||||||
pub(crate) fn split_le_virtual(
|
pub(crate) fn split_le_virtual(&mut self, integer: Target, num_bits: usize) -> Vec<Target> {
|
||||||
&mut self,
|
|
||||||
integer: Target,
|
|
||||||
num_bits: usize,
|
|
||||||
) -> Vec<Target> {
|
|
||||||
let bit_targets = self.add_virtual_advice_targets(num_bits);
|
let bit_targets = self.add_virtual_advice_targets(num_bits);
|
||||||
split_le_generator::<F>(integer, bit_targets.clone());
|
split_le_generator::<F>(integer, bit_targets.clone());
|
||||||
bit_targets
|
bit_targets
|
||||||
@ -37,9 +33,12 @@ pub fn split_le_generator_local_wires<F: Field>(
|
|||||||
integer_input_index: usize,
|
integer_input_index: usize,
|
||||||
bit_input_indices: &[usize],
|
bit_input_indices: &[usize],
|
||||||
) -> Box<dyn WitnessGenerator<F>> {
|
) -> Box<dyn WitnessGenerator<F>> {
|
||||||
let integer = Target::Wire(
|
let integer = Target::Wire(Wire {
|
||||||
Wire { gate, input: integer_input_index });
|
gate,
|
||||||
let bits = bit_input_indices.iter()
|
input: integer_input_index,
|
||||||
|
});
|
||||||
|
let bits = bit_input_indices
|
||||||
|
.iter()
|
||||||
.map(|&input| Target::Wire(Wire { gate, input }))
|
.map(|&input| Target::Wire(Wire { gate, input }))
|
||||||
.collect();
|
.collect();
|
||||||
Box::new(SplitGenerator { integer, bits })
|
Box::new(SplitGenerator { integer, bits })
|
||||||
@ -66,8 +65,10 @@ impl<F: Field> SimpleGenerator<F> for SplitGenerator {
|
|||||||
integer_value >>= 1;
|
integer_value >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert_eq!(integer_value, 0,
|
debug_assert_eq!(
|
||||||
"Integer too large to fit in given number of bits");
|
integer_value, 0,
|
||||||
|
"Integer too large to fit in given number of bits"
|
||||||
|
);
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gates::gate::{Gate, GateRef};
|
use crate::gates::gate::{Gate, GateRef};
|
||||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
|
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
use crate::witness::PartialWitness;
|
use crate::witness::PartialWitness;
|
||||||
|
|
||||||
@ -137,8 +137,7 @@ impl<F: Field> SimpleGenerator<F> for ArithmeticGenerator<F> {
|
|||||||
let multiplicand_1 = witness.get_wire(multiplicand_1_target);
|
let multiplicand_1 = witness.get_wire(multiplicand_1_target);
|
||||||
let addend = witness.get_wire(addend_target);
|
let addend = witness.get_wire(addend_target);
|
||||||
|
|
||||||
let output = self.const_0 * multiplicand_0 * multiplicand_1
|
let output = self.const_0 * multiplicand_0 * multiplicand_1 + self.const_1 * addend;
|
||||||
+ self.const_1 * addend;
|
|
||||||
|
|
||||||
PartialWitness::singleton_wire(output_target, output)
|
PartialWitness::singleton_wire(output_target, output)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gates::gate::{Gate, GateRef};
|
use crate::gates::gate::{Gate, GateRef};
|
||||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
|
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
use crate::witness::PartialWitness;
|
use crate::witness::PartialWitness;
|
||||||
|
|
||||||
@ -83,7 +83,10 @@ impl<F: Field> SimpleGenerator<F> for ConstantGenerator<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_once(&self, _witness: &PartialWitness<F>) -> PartialWitness<F> {
|
fn run_once(&self, _witness: &PartialWitness<F>) -> PartialWitness<F> {
|
||||||
let wire = Wire { gate: self.gate_index, input: ConstantGate::WIRE_OUTPUT };
|
let wire = Wire {
|
||||||
|
gate: self.gate_index,
|
||||||
|
input: ConstantGate::WIRE_OUTPUT,
|
||||||
|
};
|
||||||
PartialWitness::singleton_target(Target::Wire(wire), self.constant)
|
PartialWitness::singleton_target(Target::Wire(wire), self.constant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,10 @@ use std::hash::{Hash, Hasher};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::generator::WitnessGenerator;
|
use crate::generator::WitnessGenerator;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
|
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||||
|
|
||||||
/// A custom gate.
|
/// A custom gate.
|
||||||
pub trait Gate<F: Field>: 'static + Send + Sync {
|
pub trait Gate<F: Field>: 'static + Send + Sync {
|
||||||
|
|||||||
@ -168,8 +168,14 @@ impl<F: Field, const R: usize> SimpleGenerator<F> for GMiMCGenerator<F, R> {
|
|||||||
dep_input_indices.push(GMiMCGate::<F, R>::WIRE_SWAP);
|
dep_input_indices.push(GMiMCGate::<F, R>::WIRE_SWAP);
|
||||||
dep_input_indices.push(GMiMCGate::<F, R>::WIRE_INDEX_ACCUMULATOR_OLD);
|
dep_input_indices.push(GMiMCGate::<F, R>::WIRE_INDEX_ACCUMULATOR_OLD);
|
||||||
|
|
||||||
dep_input_indices.into_iter()
|
dep_input_indices
|
||||||
.map(|input| Target::Wire(Wire { gate: self.gate_index, input }))
|
.into_iter()
|
||||||
|
.map(|input| {
|
||||||
|
Target::Wire(Wire {
|
||||||
|
gate: self.gate_index,
|
||||||
|
input,
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,10 +183,12 @@ impl<F: Field, const R: usize> SimpleGenerator<F> for GMiMCGenerator<F, R> {
|
|||||||
let mut result = PartialWitness::new();
|
let mut result = PartialWitness::new();
|
||||||
|
|
||||||
let mut state = (0..W)
|
let mut state = (0..W)
|
||||||
.map(|i| witness.get_wire(Wire {
|
.map(|i| {
|
||||||
|
witness.get_wire(Wire {
|
||||||
gate: self.gate_index,
|
gate: self.gate_index,
|
||||||
input: GMiMCGate::<F, R>::wire_input(i),
|
input: GMiMCGate::<F, R>::wire_input(i),
|
||||||
}))
|
})
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let swap_value = witness.get_wire(Wire {
|
let swap_value = witness.get_wire(Wire {
|
||||||
@ -205,7 +213,8 @@ impl<F: Field, const R: usize> SimpleGenerator<F> for GMiMCGenerator<F, R> {
|
|||||||
gate: self.gate_index,
|
gate: self.gate_index,
|
||||||
input: GMiMCGate::<F, R>::WIRE_INDEX_ACCUMULATOR_NEW,
|
input: GMiMCGate::<F, R>::WIRE_INDEX_ACCUMULATOR_NEW,
|
||||||
},
|
},
|
||||||
new_index_acc_value);
|
new_index_acc_value,
|
||||||
|
);
|
||||||
|
|
||||||
// Value that is implicitly added to each element.
|
// Value that is implicitly added to each element.
|
||||||
// See https://affine.group/2020/02/starkware-challenge
|
// See https://affine.group/2020/02/starkware-challenge
|
||||||
@ -219,7 +228,8 @@ impl<F: Field, const R: usize> SimpleGenerator<F> for GMiMCGenerator<F, R> {
|
|||||||
gate: self.gate_index,
|
gate: self.gate_index,
|
||||||
input: GMiMCGate::<F, R>::wire_cubing_input(r),
|
input: GMiMCGate::<F, R>::wire_cubing_input(r),
|
||||||
},
|
},
|
||||||
cubing_input);
|
cubing_input,
|
||||||
|
);
|
||||||
let f = cubing_input.cube();
|
let f = cubing_input.cube();
|
||||||
addition_buffer += f;
|
addition_buffer += f;
|
||||||
state[active] -= f;
|
state[active] -= f;
|
||||||
@ -232,7 +242,8 @@ impl<F: Field, const R: usize> SimpleGenerator<F> for GMiMCGenerator<F, R> {
|
|||||||
gate: self.gate_index,
|
gate: self.gate_index,
|
||||||
input: GMiMCGate::<F, R>::wire_output(i),
|
input: GMiMCGate::<F, R>::wire_output(i),
|
||||||
},
|
},
|
||||||
state[i]);
|
state[i],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
@ -258,7 +269,7 @@ mod tests {
|
|||||||
type F = CrandallField;
|
type F = CrandallField;
|
||||||
const R: usize = 101;
|
const R: usize = 101;
|
||||||
let constants = Arc::new([F::TWO; R]);
|
let constants = Arc::new([F::TWO; R]);
|
||||||
type Gate = GMiMCGate::<F, R>;
|
type Gate = GMiMCGate<F, R>;
|
||||||
let gate = Gate::with_constants(constants.clone());
|
let gate = Gate::with_constants(constants.clone());
|
||||||
|
|
||||||
let config = CircuitConfig {
|
let config = CircuitConfig {
|
||||||
@ -267,38 +278,51 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let permutation_inputs = (0..W)
|
let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::<Vec<_>>();
|
||||||
.map(F::from_canonical_usize)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let mut witness = PartialWitness::new();
|
let mut witness = PartialWitness::new();
|
||||||
witness.set_wire(
|
witness.set_wire(
|
||||||
Wire { gate: 0, input: Gate::WIRE_INDEX_ACCUMULATOR_OLD },
|
Wire {
|
||||||
F::from_canonical_usize(7));
|
gate: 0,
|
||||||
|
input: Gate::WIRE_INDEX_ACCUMULATOR_OLD,
|
||||||
|
},
|
||||||
|
F::from_canonical_usize(7),
|
||||||
|
);
|
||||||
witness.set_wire(
|
witness.set_wire(
|
||||||
Wire { gate: 0, input: Gate::WIRE_SWAP },
|
Wire {
|
||||||
F::ZERO);
|
gate: 0,
|
||||||
|
input: Gate::WIRE_SWAP,
|
||||||
|
},
|
||||||
|
F::ZERO,
|
||||||
|
);
|
||||||
for i in 0..W {
|
for i in 0..W {
|
||||||
witness.set_wire(
|
witness.set_wire(
|
||||||
Wire { gate: 0, input: Gate::wire_input(i) },
|
Wire {
|
||||||
permutation_inputs[i]);
|
gate: 0,
|
||||||
|
input: Gate::wire_input(i),
|
||||||
|
},
|
||||||
|
permutation_inputs[i],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let generators = gate.0.generators(0, &[], &[]);
|
let generators = gate.0.generators(0, &[], &[]);
|
||||||
generate_partial_witness(&mut witness, &generators);
|
generate_partial_witness(&mut witness, &generators);
|
||||||
|
|
||||||
let expected_outputs: [F; W] = gmimc_permute_naive(
|
let expected_outputs: [F; W] =
|
||||||
permutation_inputs.try_into().unwrap(),
|
gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants);
|
||||||
constants);
|
|
||||||
|
|
||||||
for i in 0..W {
|
for i in 0..W {
|
||||||
let out = witness.get_wire(
|
let out = witness.get_wire(Wire {
|
||||||
Wire { gate: 0, input: Gate::wire_output(i) });
|
gate: 0,
|
||||||
|
input: Gate::wire_output(i),
|
||||||
|
});
|
||||||
assert_eq!(out, expected_outputs[i]);
|
assert_eq!(out, expected_outputs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let acc_new = witness.get_wire(
|
let acc_new = witness.get_wire(Wire {
|
||||||
Wire { gate: 0, input: Gate::WIRE_INDEX_ACCUMULATOR_NEW });
|
gate: 0,
|
||||||
|
input: Gate::WIRE_INDEX_ACCUMULATOR_NEW,
|
||||||
|
});
|
||||||
assert_eq!(acc_new, F::from_canonical_usize(7 * 2));
|
assert_eq!(acc_new, F::from_canonical_usize(7 * 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gates::gate::{Gate, GateRef};
|
use crate::gates::gate::{Gate, GateRef};
|
||||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
|
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||||
use crate::witness::PartialWitness;
|
use crate::witness::PartialWitness;
|
||||||
|
|
||||||
/// Performs some arithmetic involved in the evaluation of GMiMC's constraint polynomials for one
|
/// Performs some arithmetic involved in the evaluation of GMiMC's constraint polynomials for one
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gates::gate::{Gate, GateRef};
|
use crate::gates::gate::{Gate, GateRef};
|
||||||
use crate::generator::WitnessGenerator;
|
use crate::generator::WitnessGenerator;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
|
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||||
|
|
||||||
/// A gate which takes a single constant parameter and outputs that value.
|
/// A gate which takes a single constant parameter and outputs that value.
|
||||||
pub struct NoopGate;
|
pub struct NoopGate;
|
||||||
|
|||||||
23
src/gmimc.rs
23
src/gmimc.rs
@ -15,11 +15,26 @@ pub(crate) fn gmimc_automatic_constants<F: Field, const R: usize>() -> [F; R] {
|
|||||||
constants
|
constants
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gmimc_compress<F: Field, const R: usize>(a: [F; 4], b: [F; 4], constants: Arc<[F; R]>) -> [F; 4] {
|
pub fn gmimc_compress<F: Field, const R: usize>(
|
||||||
|
a: [F; 4],
|
||||||
|
b: [F; 4],
|
||||||
|
constants: Arc<[F; R]>,
|
||||||
|
) -> [F; 4] {
|
||||||
// Sponge with r=8, c=4.
|
// Sponge with r=8, c=4.
|
||||||
let state_0 = [a[0], a[1], a[2], a[3], b[0],
|
let state_0 = [
|
||||||
b[1], b[2], b[3],
|
a[0],
|
||||||
F::ZERO, F::ZERO, F::ZERO, F::ZERO];
|
a[1],
|
||||||
|
a[2],
|
||||||
|
a[3],
|
||||||
|
b[0],
|
||||||
|
b[1],
|
||||||
|
b[2],
|
||||||
|
b[3],
|
||||||
|
F::ZERO,
|
||||||
|
F::ZERO,
|
||||||
|
F::ZERO,
|
||||||
|
F::ZERO,
|
||||||
|
];
|
||||||
let state_1 = gmimc_permute::<F, 12, R>(state_0, constants.clone());
|
let state_1 = gmimc_permute::<F, 12, R>(state_0, constants.clone());
|
||||||
[state_1[0], state_1[1], state_1[2], state_1[3]]
|
[state_1[0], state_1[1], state_1[2], state_1[3]]
|
||||||
}
|
}
|
||||||
|
|||||||
117
src/hash.rs
117
src/hash.rs
@ -4,12 +4,12 @@ use std::convert::TryInto;
|
|||||||
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gmimc::gmimc_permute_array;
|
use crate::gmimc::gmimc_permute_array;
|
||||||
use crate::proof::{Hash, HashTarget};
|
use crate::proof::{Hash, HashTarget};
|
||||||
use crate::util::reverse_index_bits_in_place;
|
|
||||||
use crate::circuit_builder::CircuitBuilder;
|
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
|
use crate::util::reverse_index_bits_in_place;
|
||||||
|
|
||||||
pub(crate) const SPONGE_RATE: usize = 8;
|
pub(crate) const SPONGE_RATE: usize = 8;
|
||||||
pub(crate) const SPONGE_CAPACITY: usize = 4;
|
pub(crate) const SPONGE_CAPACITY: usize = 4;
|
||||||
@ -17,7 +17,109 @@ pub(crate) const SPONGE_WIDTH: usize = SPONGE_RATE + SPONGE_CAPACITY;
|
|||||||
|
|
||||||
pub const GMIMC_ROUNDS: usize = 101;
|
pub const GMIMC_ROUNDS: usize = 101;
|
||||||
/// This is the result of `gmimc_automatic_constants`; i.e. it's from ChaCha20 seeded with 0.
|
/// This is the result of `gmimc_automatic_constants`; i.e. it's from ChaCha20 seeded with 0.
|
||||||
pub const GMIMC_CONSTANTS: [u64; GMIMC_ROUNDS] = [13080132715619999810, 8594738768332784433, 12896916466795114362, 1109962092924985887, 16216730424513838303, 10137062674532189451, 15292064468290167604, 17255573296743700660, 14827154243383347999, 2846171648262623971, 16246264665335217464, 14214208089399786945, 9667108688411000080, 6470857421371427314, 14103331941574951088, 11854816474757864855, 3498097497657653643, 7947235693333396721, 11110078702363612411, 16384314114341783099, 15404405914224921002, 14077880832148466479, 9555554663682579629, 13859595359622389547, 16859897326779206643, 17685474422023725021, 17858764736437889563, 9410011023624402450, 12495243630852222748, 12416945299436348089, 5776666812952701944, 6314421663507268983, 7402742472177291738, 982536713292517255, 17321168867539521172, 2934354895304883596, 10567510599683852824, 8135543734546633309, 116353493093565855, 8029688164312877009, 9003846638141970076, 7052445133185619935, 9645665433271393194, 5446430061585660707, 16770910636054378912, 17708360573237778662, 4661556288797079635, 11977051900536351292, 4378616569536950472, 3334807503157233344, 8019184736760206441, 2395043909056213726, 6558421058999795722, 11735894061922784518, 8143540539718733269, 5991753490174091591, 12235918792748480378, 2880312033996085535, 18224748117164817283, 18070411014966027790, 8156487614951798795, 10615269511128318233, 12489426406026437595, 5055279340584943685, 7231927320516917417, 2602078848371820415, 12445944370602567717, 3978905924297801117, 16711272946032085229, 10439032362290464320, 15110119873264383151, 821141790739535246, 11073536381779174375, 4866839313593360589, 13118391690850240703, 14527674975242150843, 7612751960041028847, 6808090908507673494, 6899703780195472329, 3664666286710282218, 783179505504239941, 8990689242729919931, 9646603556395461579, 7351246026916028004, 16970959815450893036, 15735726859844361172, 10347018222946250943, 12195545879691602738, 7423314197870213963, 14908016118492485461, 5840340123122280205, 17740311464247702688, 815306422036794512, 17456357369997417977, 6982651077270605698, 11970987325834369417, 8167785009370061651, 9483259820363401119, 954550221761525285, 10339565172077536587, 8651171085167737860];
|
pub const GMIMC_CONSTANTS: [u64; GMIMC_ROUNDS] = [
|
||||||
|
13080132715619999810,
|
||||||
|
8594738768332784433,
|
||||||
|
12896916466795114362,
|
||||||
|
1109962092924985887,
|
||||||
|
16216730424513838303,
|
||||||
|
10137062674532189451,
|
||||||
|
15292064468290167604,
|
||||||
|
17255573296743700660,
|
||||||
|
14827154243383347999,
|
||||||
|
2846171648262623971,
|
||||||
|
16246264665335217464,
|
||||||
|
14214208089399786945,
|
||||||
|
9667108688411000080,
|
||||||
|
6470857421371427314,
|
||||||
|
14103331941574951088,
|
||||||
|
11854816474757864855,
|
||||||
|
3498097497657653643,
|
||||||
|
7947235693333396721,
|
||||||
|
11110078702363612411,
|
||||||
|
16384314114341783099,
|
||||||
|
15404405914224921002,
|
||||||
|
14077880832148466479,
|
||||||
|
9555554663682579629,
|
||||||
|
13859595359622389547,
|
||||||
|
16859897326779206643,
|
||||||
|
17685474422023725021,
|
||||||
|
17858764736437889563,
|
||||||
|
9410011023624402450,
|
||||||
|
12495243630852222748,
|
||||||
|
12416945299436348089,
|
||||||
|
5776666812952701944,
|
||||||
|
6314421663507268983,
|
||||||
|
7402742472177291738,
|
||||||
|
982536713292517255,
|
||||||
|
17321168867539521172,
|
||||||
|
2934354895304883596,
|
||||||
|
10567510599683852824,
|
||||||
|
8135543734546633309,
|
||||||
|
116353493093565855,
|
||||||
|
8029688164312877009,
|
||||||
|
9003846638141970076,
|
||||||
|
7052445133185619935,
|
||||||
|
9645665433271393194,
|
||||||
|
5446430061585660707,
|
||||||
|
16770910636054378912,
|
||||||
|
17708360573237778662,
|
||||||
|
4661556288797079635,
|
||||||
|
11977051900536351292,
|
||||||
|
4378616569536950472,
|
||||||
|
3334807503157233344,
|
||||||
|
8019184736760206441,
|
||||||
|
2395043909056213726,
|
||||||
|
6558421058999795722,
|
||||||
|
11735894061922784518,
|
||||||
|
8143540539718733269,
|
||||||
|
5991753490174091591,
|
||||||
|
12235918792748480378,
|
||||||
|
2880312033996085535,
|
||||||
|
18224748117164817283,
|
||||||
|
18070411014966027790,
|
||||||
|
8156487614951798795,
|
||||||
|
10615269511128318233,
|
||||||
|
12489426406026437595,
|
||||||
|
5055279340584943685,
|
||||||
|
7231927320516917417,
|
||||||
|
2602078848371820415,
|
||||||
|
12445944370602567717,
|
||||||
|
3978905924297801117,
|
||||||
|
16711272946032085229,
|
||||||
|
10439032362290464320,
|
||||||
|
15110119873264383151,
|
||||||
|
821141790739535246,
|
||||||
|
11073536381779174375,
|
||||||
|
4866839313593360589,
|
||||||
|
13118391690850240703,
|
||||||
|
14527674975242150843,
|
||||||
|
7612751960041028847,
|
||||||
|
6808090908507673494,
|
||||||
|
6899703780195472329,
|
||||||
|
3664666286710282218,
|
||||||
|
783179505504239941,
|
||||||
|
8990689242729919931,
|
||||||
|
9646603556395461579,
|
||||||
|
7351246026916028004,
|
||||||
|
16970959815450893036,
|
||||||
|
15735726859844361172,
|
||||||
|
10347018222946250943,
|
||||||
|
12195545879691602738,
|
||||||
|
7423314197870213963,
|
||||||
|
14908016118492485461,
|
||||||
|
5840340123122280205,
|
||||||
|
17740311464247702688,
|
||||||
|
815306422036794512,
|
||||||
|
17456357369997417977,
|
||||||
|
6982651077270605698,
|
||||||
|
11970987325834369417,
|
||||||
|
8167785009370061651,
|
||||||
|
9483259820363401119,
|
||||||
|
954550221761525285,
|
||||||
|
10339565172077536587,
|
||||||
|
8651171085167737860,
|
||||||
|
];
|
||||||
|
|
||||||
/// Controls the granularity of parallelization when building Merkle trees. I.e., we will try to
|
/// Controls the granularity of parallelization when building Merkle trees. I.e., we will try to
|
||||||
/// split up the task into units of work, such that each unit involves hashing roughly this many
|
/// split up the task into units of work, such that each unit involves hashing roughly this many
|
||||||
@ -160,18 +262,21 @@ pub(crate) fn merkle_root_bit_rev_order<F: Field>(mut vecs: Vec<Vec<F>>) -> Hash
|
|||||||
pub(crate) fn merkle_root<F: Field>(vecs: Vec<Vec<F>>) -> Hash<F> {
|
pub(crate) fn merkle_root<F: Field>(vecs: Vec<Vec<F>>) -> Hash<F> {
|
||||||
let elems_per_leaf = vecs[0].len();
|
let elems_per_leaf = vecs[0].len();
|
||||||
let leaves_per_chunk = (ELEMS_PER_CHUNK / elems_per_leaf).next_power_of_two();
|
let leaves_per_chunk = (ELEMS_PER_CHUNK / elems_per_leaf).next_power_of_two();
|
||||||
let subtree_roots: Vec<Vec<F>> = vecs.par_chunks(leaves_per_chunk)
|
let subtree_roots: Vec<Vec<F>> = vecs
|
||||||
|
.par_chunks(leaves_per_chunk)
|
||||||
.map(|chunk| merkle_root_inner(chunk.to_vec()).elements.to_vec())
|
.map(|chunk| merkle_root_inner(chunk.to_vec()).elements.to_vec())
|
||||||
.collect();
|
.collect();
|
||||||
merkle_root_inner(subtree_roots)
|
merkle_root_inner(subtree_roots)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn merkle_root_inner<F: Field>(vecs: Vec<Vec<F>>) -> Hash<F> {
|
pub(crate) fn merkle_root_inner<F: Field>(vecs: Vec<Vec<F>>) -> Hash<F> {
|
||||||
let mut hashes = vecs.into_iter()
|
let mut hashes = vecs
|
||||||
|
.into_iter()
|
||||||
.map(|leaf_set| hash_or_noop(leaf_set))
|
.map(|leaf_set| hash_or_noop(leaf_set))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
while hashes.len() > 1 {
|
while hashes.len() > 1 {
|
||||||
hashes = hashes.chunks(2)
|
hashes = hashes
|
||||||
|
.chunks(2)
|
||||||
.map(|pair| compress(pair[0], pair[1]))
|
.map(|pair| compress(pair[0], pair[1]))
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
pub mod circuit_builder;
|
pub mod circuit_builder;
|
||||||
pub mod circuit_data;
|
pub mod circuit_data;
|
||||||
pub mod vars;
|
|
||||||
pub mod field;
|
pub mod field;
|
||||||
pub mod fri;
|
pub mod fri;
|
||||||
pub mod gadgets;
|
pub mod gadgets;
|
||||||
@ -9,6 +8,7 @@ pub mod generator;
|
|||||||
pub mod gmimc;
|
pub mod gmimc;
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
pub mod merkle_proofs;
|
pub mod merkle_proofs;
|
||||||
|
mod merkle_tree;
|
||||||
pub mod plonk_challenger;
|
pub mod plonk_challenger;
|
||||||
pub mod plonk_common;
|
pub mod plonk_common;
|
||||||
pub mod polynomial;
|
pub mod polynomial;
|
||||||
@ -18,6 +18,7 @@ pub mod recursive_verifier;
|
|||||||
pub mod rescue;
|
pub mod rescue;
|
||||||
pub mod target;
|
pub mod target;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
pub mod vars;
|
||||||
pub mod verifier;
|
pub mod verifier;
|
||||||
pub mod wire;
|
pub mod wire;
|
||||||
pub mod witness;
|
pub mod witness;
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::gates::gmimc::GMiMCGate;
|
use crate::gates::gmimc::GMiMCGate;
|
||||||
use crate::hash::{compress, hash_or_noop};
|
|
||||||
use crate::hash::GMIMC_ROUNDS;
|
use crate::hash::GMIMC_ROUNDS;
|
||||||
|
use crate::hash::{compress, hash_or_noop};
|
||||||
use crate::proof::{Hash, HashTarget};
|
use crate::proof::{Hash, HashTarget};
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
|
use crate::util::reverse_index_bits;
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct MerkleProof<F: Field> {
|
pub struct MerkleProof<F: Field> {
|
||||||
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
|
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
|
||||||
pub siblings: Vec<Hash<F>>,
|
pub siblings: Vec<Hash<F>>,
|
||||||
@ -23,18 +25,24 @@ pub(crate) fn verify_merkle_proof<F: Field>(
|
|||||||
leaf_data: Vec<F>,
|
leaf_data: Vec<F>,
|
||||||
leaf_index: usize,
|
leaf_index: usize,
|
||||||
merkle_root: Hash<F>,
|
merkle_root: Hash<F>,
|
||||||
proof: MerkleProof<F>,
|
proof: &MerkleProof<F>,
|
||||||
) -> bool {
|
reverse_bits: bool,
|
||||||
|
) -> Option<()> {
|
||||||
|
let index = if reverse_bits {
|
||||||
|
crate::util::reverse_bits(leaf_index, proof.siblings.len())
|
||||||
|
} else {
|
||||||
|
leaf_index
|
||||||
|
};
|
||||||
let mut current_digest = hash_or_noop(leaf_data);
|
let mut current_digest = hash_or_noop(leaf_data);
|
||||||
for (i, sibling_digest) in proof.siblings.into_iter().enumerate() {
|
for (i, &sibling_digest) in proof.siblings.iter().enumerate() {
|
||||||
let bit = (leaf_index >> i & 1) == 1;
|
let bit = (index >> i & 1) == 1;
|
||||||
current_digest = if bit {
|
current_digest = if bit {
|
||||||
compress(sibling_digest, current_digest)
|
compress(sibling_digest, current_digest)
|
||||||
} else {
|
} else {
|
||||||
compress(current_digest, sibling_digest)
|
compress(current_digest, sibling_digest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_digest == merkle_root
|
(current_digest == merkle_root).then(|| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> CircuitBuilder<F> {
|
impl<F: Field> CircuitBuilder<F> {
|
||||||
@ -55,24 +63,37 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
let mut acc_leaf_index = zero;
|
let mut acc_leaf_index = zero;
|
||||||
|
|
||||||
for (bit, sibling) in purported_index_bits.into_iter().zip(proof.siblings) {
|
for (bit, sibling) in purported_index_bits.into_iter().zip(proof.siblings) {
|
||||||
let gate = self.add_gate_no_constants(
|
let gate = self
|
||||||
GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants());
|
.add_gate_no_constants(GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants());
|
||||||
|
|
||||||
let swap_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_SWAP;
|
let swap_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_SWAP;
|
||||||
let swap_wire = Target::Wire(Wire { gate, input: swap_wire });
|
let swap_wire = Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: swap_wire,
|
||||||
|
});
|
||||||
self.generate_copy(bit, swap_wire);
|
self.generate_copy(bit, swap_wire);
|
||||||
|
|
||||||
let old_acc_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_INDEX_ACCUMULATOR_OLD;
|
let old_acc_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_INDEX_ACCUMULATOR_OLD;
|
||||||
let old_acc_wire = Target::Wire(Wire { gate, input: old_acc_wire });
|
let old_acc_wire = Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: old_acc_wire,
|
||||||
|
});
|
||||||
self.route(acc_leaf_index, old_acc_wire);
|
self.route(acc_leaf_index, old_acc_wire);
|
||||||
|
|
||||||
let new_acc_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_INDEX_ACCUMULATOR_NEW;
|
let new_acc_wire = GMiMCGate::<F, GMIMC_ROUNDS>::WIRE_INDEX_ACCUMULATOR_NEW;
|
||||||
let new_acc_wire = Target::Wire(Wire { gate, input: new_acc_wire });
|
let new_acc_wire = Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: new_acc_wire,
|
||||||
|
});
|
||||||
acc_leaf_index = new_acc_wire;
|
acc_leaf_index = new_acc_wire;
|
||||||
|
|
||||||
let input_wires = (0..12)
|
let input_wires = (0..12)
|
||||||
.map(|i| Target::Wire(
|
.map(|i| {
|
||||||
Wire { gate, input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_input(i) }))
|
Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_input(i),
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
@ -81,10 +102,16 @@ impl<F: Field> CircuitBuilder<F> {
|
|||||||
self.route(zero, input_wires[8 + i]);
|
self.route(zero, input_wires[8 + i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
state = HashTarget::from_vec((0..4)
|
state = HashTarget::from_vec(
|
||||||
.map(|i| Target::Wire(
|
(0..4)
|
||||||
Wire { gate, input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i) }))
|
.map(|i| {
|
||||||
.collect())
|
Target::Wire(Wire {
|
||||||
|
gate,
|
||||||
|
input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assert_equal(acc_leaf_index, leaf_index);
|
self.assert_equal(acc_leaf_index, leaf_index);
|
||||||
|
|||||||
118
src/merkle_tree.rs
Normal file
118
src/merkle_tree.rs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
use crate::field::field::Field;
|
||||||
|
use crate::hash::{compress, hash_n_to_hash, hash_or_noop};
|
||||||
|
use crate::merkle_proofs::MerkleProof;
|
||||||
|
use crate::proof::Hash;
|
||||||
|
use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct MerkleTree<F: Field> {
|
||||||
|
/// The data in the leaves of the Merkle tree.
|
||||||
|
pub leaves: Vec<Vec<F>>,
|
||||||
|
|
||||||
|
/// The layers of hashes in the tree. The first layer is the one at the bottom.
|
||||||
|
pub layers: Vec<Vec<Hash<F>>>,
|
||||||
|
|
||||||
|
/// The Merkle root.
|
||||||
|
pub root: Hash<F>,
|
||||||
|
|
||||||
|
/// If true, the indices are in bit-reversed form, so that the leaf at index `i`
|
||||||
|
/// contains the leaf originally at index `reverse_bits(i)`.
|
||||||
|
pub reverse_bits: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: Field> MerkleTree<F> {
|
||||||
|
pub fn new(mut leaves: Vec<Vec<F>>, reverse_bits: bool) -> Self {
|
||||||
|
if reverse_bits {
|
||||||
|
reverse_index_bits_in_place(&mut leaves);
|
||||||
|
}
|
||||||
|
let mut layers = vec![leaves
|
||||||
|
.iter()
|
||||||
|
.map(|l| hash_or_noop(l.clone()))
|
||||||
|
.collect::<Vec<_>>()];
|
||||||
|
while let Some(l) = layers.last() {
|
||||||
|
if l.len() == 1 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
layers.push(
|
||||||
|
l.chunks(2)
|
||||||
|
.map(|chunk| compress(chunk[0], chunk[1]))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let root = layers.pop().unwrap()[0];
|
||||||
|
Self {
|
||||||
|
leaves,
|
||||||
|
layers,
|
||||||
|
root,
|
||||||
|
reverse_bits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, i: usize) -> &[F] {
|
||||||
|
let n = log2_strict(self.leaves.len());
|
||||||
|
&self.leaves[if self.reverse_bits {
|
||||||
|
reverse_bits(i, n)
|
||||||
|
} else {
|
||||||
|
i
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a Merkle proof from a leaf index.
|
||||||
|
pub fn prove(&self, leaf_index: usize) -> MerkleProof<F> {
|
||||||
|
let index = if self.reverse_bits {
|
||||||
|
reverse_bits(leaf_index, log2_strict(self.leaves.len()))
|
||||||
|
} else {
|
||||||
|
leaf_index
|
||||||
|
};
|
||||||
|
MerkleProof {
|
||||||
|
siblings: self
|
||||||
|
.layers
|
||||||
|
.iter()
|
||||||
|
.scan(index, |acc, layer| {
|
||||||
|
let index = *acc ^ 1;
|
||||||
|
*acc >>= 1;
|
||||||
|
Some(layer[index])
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::field::crandall_field::CrandallField;
|
||||||
|
use crate::merkle_proofs::verify_merkle_proof;
|
||||||
|
use crate::polynomial::division::divide_by_z_h;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_merkle_trees() {
|
||||||
|
type F = CrandallField;
|
||||||
|
|
||||||
|
let n = 1 << 10;
|
||||||
|
let leaves: Vec<Vec<F>> = (0..n)
|
||||||
|
.map(|_| (0..10).map(|_| F::rand()).collect())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let tree = MerkleTree::new(leaves.clone(), false);
|
||||||
|
for i in 0..n {
|
||||||
|
let proof = tree.prove(i);
|
||||||
|
assert!(
|
||||||
|
verify_merkle_proof(tree.leaves[i].clone(), i, tree.root, &proof, false).is_some()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tree_reversed_bits = MerkleTree::new(leaves.clone(), true);
|
||||||
|
for i in 0..n {
|
||||||
|
let proof = tree_reversed_bits.prove(i);
|
||||||
|
assert!(verify_merkle_proof(
|
||||||
|
leaves[i].clone(),
|
||||||
|
i,
|
||||||
|
tree_reversed_bits.root,
|
||||||
|
&proof,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.is_some());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,8 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::hash::{permute, SPONGE_WIDTH, SPONGE_RATE};
|
use crate::hash::{permute, SPONGE_RATE, SPONGE_WIDTH};
|
||||||
use crate::target::Target;
|
|
||||||
use crate::proof::{Hash, HashTarget};
|
use crate::proof::{Hash, HashTarget};
|
||||||
|
use crate::target::Target;
|
||||||
|
|
||||||
/// Observes prover messages, and generates challenges by hashing the transcript.
|
/// Observes prover messages, and generates challenges by hashing the transcript.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -130,10 +130,7 @@ impl RecursiveChallenger {
|
|||||||
self.observe_elements(&hash.elements)
|
self.observe_elements(&hash.elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_challenge<F: Field>(
|
pub(crate) fn get_challenge<F: Field>(&mut self, builder: &mut CircuitBuilder<F>) -> Target {
|
||||||
&mut self,
|
|
||||||
builder: &mut CircuitBuilder<F>,
|
|
||||||
) -> Target {
|
|
||||||
self.absorb_buffered_inputs(builder);
|
self.absorb_buffered_inputs(builder);
|
||||||
|
|
||||||
if self.output_buffer.is_empty() {
|
if self.output_buffer.is_empty() {
|
||||||
@ -174,10 +171,7 @@ impl RecursiveChallenger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Absorb any buffered inputs. After calling this, the input buffer will be empty.
|
/// Absorb any buffered inputs. After calling this, the input buffer will be empty.
|
||||||
fn absorb_buffered_inputs<F: Field>(
|
fn absorb_buffered_inputs<F: Field>(&mut self, builder: &mut CircuitBuilder<F>) {
|
||||||
&mut self,
|
|
||||||
builder: &mut CircuitBuilder<F>,
|
|
||||||
) {
|
|
||||||
for input_chunk in self.input_buffer.chunks(SPONGE_RATE) {
|
for input_chunk in self.input_buffer.chunks(SPONGE_RATE) {
|
||||||
// Overwrite the first r elements with the inputs. This differs from a standard sponge,
|
// Overwrite the first r elements with the inputs. This differs from a standard sponge,
|
||||||
// where we would xor or add in the inputs. This is a well-known variant, though,
|
// where we would xor or add in the inputs. This is a well-known variant, though,
|
||||||
@ -198,14 +192,14 @@ impl RecursiveChallenger {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::circuit_data::CircuitConfig;
|
use crate::circuit_data::CircuitConfig;
|
||||||
use crate::field::crandall_field::CrandallField;
|
use crate::field::crandall_field::CrandallField;
|
||||||
|
use crate::field::field::Field;
|
||||||
use crate::generator::generate_partial_witness;
|
use crate::generator::generate_partial_witness;
|
||||||
use crate::plonk_challenger::{Challenger, RecursiveChallenger};
|
use crate::plonk_challenger::{Challenger, RecursiveChallenger};
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::circuit_builder::CircuitBuilder;
|
|
||||||
use crate::witness::PartialWitness;
|
use crate::witness::PartialWitness;
|
||||||
use crate::field::field::Field;
|
|
||||||
|
|
||||||
/// Tests for consistency between `Challenger` and `RecursiveChallenger`.
|
/// Tests for consistency between `Challenger` and `RecursiveChallenger`.
|
||||||
#[test]
|
#[test]
|
||||||
@ -237,8 +231,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let mut builder = CircuitBuilder::<F>::new(config);
|
let mut builder = CircuitBuilder::<F>::new(config);
|
||||||
let mut recursive_challenger = RecursiveChallenger::new(&mut builder);
|
let mut recursive_challenger = RecursiveChallenger::new(&mut builder);
|
||||||
let mut recursive_outputs_per_round: Vec<Vec<Target>> =
|
let mut recursive_outputs_per_round: Vec<Vec<Target>> = Vec::new();
|
||||||
Vec::new();
|
|
||||||
for (r, inputs) in inputs_per_round.iter().enumerate() {
|
for (r, inputs) in inputs_per_round.iter().enumerate() {
|
||||||
recursive_challenger.observe_elements(&builder.constants(inputs));
|
recursive_challenger.observe_elements(&builder.constants(inputs));
|
||||||
recursive_outputs_per_round.push(
|
recursive_outputs_per_round.push(
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
|
use crate::gates::gate::GateRef;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||||
use crate::gates::gate::GateRef;
|
|
||||||
|
|
||||||
/// Evaluates all gate constraints.
|
/// Evaluates all gate constraints.
|
||||||
///
|
///
|
||||||
@ -18,8 +18,10 @@ pub fn evaluate_gate_constraints<F: Field>(
|
|||||||
for gate in gates {
|
for gate in gates {
|
||||||
let gate_constraints = gate.0.eval_filtered(vars);
|
let gate_constraints = gate.0.eval_filtered(vars);
|
||||||
for (i, c) in gate_constraints.into_iter().enumerate() {
|
for (i, c) in gate_constraints.into_iter().enumerate() {
|
||||||
debug_assert!(i < num_gate_constraints,
|
debug_assert!(
|
||||||
"num_constraints() gave too low of a number");
|
i < num_gate_constraints,
|
||||||
|
"num_constraints() gave too low of a number"
|
||||||
|
);
|
||||||
constraints[i] += c;
|
constraints[i] += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +66,8 @@ pub(crate) fn eval_l_1<F: Field>(n: usize, x: F) -> F {
|
|||||||
|
|
||||||
/// For each alpha in alphas, compute a reduction of the given terms using powers of alpha.
|
/// For each alpha in alphas, compute a reduction of the given terms using powers of alpha.
|
||||||
pub(crate) fn reduce_with_powers_multi<F: Field>(terms: &[F], alphas: &[F]) -> Vec<F> {
|
pub(crate) fn reduce_with_powers_multi<F: Field>(terms: &[F], alphas: &[F]) -> Vec<F> {
|
||||||
alphas.iter()
|
alphas
|
||||||
|
.iter()
|
||||||
.map(|&alpha| reduce_with_powers(terms, alpha))
|
.map(|&alpha| reduce_with_powers(terms, alpha))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,8 @@ pub(crate) fn divide_by_z_h<F: Field>(mut a: PolynomialCoeffs<F>, n: usize) -> P
|
|||||||
let denominators_inv = F::batch_multiplicative_inverse(&denominators);
|
let denominators_inv = F::batch_multiplicative_inverse(&denominators);
|
||||||
// Divide every element of `a_eval` by the corresponding denominator.
|
// Divide every element of `a_eval` by the corresponding denominator.
|
||||||
// Then, `a_eval` is the evaluation of `a/Z_H` on `{g.w^i}`.
|
// Then, `a_eval` is the evaluation of `a/Z_H` on `{g.w^i}`.
|
||||||
a_eval.values
|
a_eval
|
||||||
|
.values
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.zip(denominators_inv.iter())
|
.zip(denominators_inv.iter())
|
||||||
.for_each(|(x, &d)| {
|
.for_each(|(x, &d)| {
|
||||||
|
|||||||
@ -26,13 +26,8 @@ impl<F: Field> PolynomialValues<F> {
|
|||||||
self.values.len()
|
self.values.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lde_multiple(
|
pub fn lde_multiple(polys: Vec<Self>, rate_bits: usize) -> Vec<Self> {
|
||||||
polys: Vec<Self>,
|
polys.into_iter().map(|p| p.lde(rate_bits)).collect()
|
||||||
rate_bits: usize,
|
|
||||||
) -> Vec<Self> {
|
|
||||||
polys.into_iter()
|
|
||||||
.map(|p| p.lde(rate_bits))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lde(self, rate_bits: usize) -> Self {
|
pub fn lde(self, rate_bits: usize) -> Self {
|
||||||
@ -82,13 +77,15 @@ impl<F: Field> PolynomialCoeffs<F> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lde_multiple(
|
pub fn eval(&self, x: F) -> F {
|
||||||
polys: Vec<Self>,
|
self.coeffs
|
||||||
rate_bits: usize,
|
.iter()
|
||||||
) -> Vec<Self> {
|
.rev()
|
||||||
polys.into_iter()
|
.fold(F::ZERO, |acc, &c| acc * x + c)
|
||||||
.map(|p| p.lde(rate_bits))
|
}
|
||||||
.collect()
|
|
||||||
|
pub fn lde_multiple(polys: Vec<Self>, rate_bits: usize) -> Vec<Self> {
|
||||||
|
polys.into_iter().map(|p| p.lde(rate_bits)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lde(mut self, rate_bits: usize) -> Self {
|
pub(crate) fn lde(mut self, rate_bits: usize) -> Self {
|
||||||
|
|||||||
41
src/proof.rs
41
src/proof.rs
@ -1,6 +1,7 @@
|
|||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
|
use crate::merkle_proofs::{MerkleProof, MerkleProofTarget};
|
||||||
|
use crate::polynomial::polynomial::PolynomialCoeffs;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::merkle_proofs::{MerkleProofTarget, MerkleProof};
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
/// Represents a ~256 bit hash output.
|
/// Represents a ~256 bit hash output.
|
||||||
@ -12,7 +13,9 @@ pub struct Hash<F: Field> {
|
|||||||
impl<F: Field> Hash<F> {
|
impl<F: Field> Hash<F> {
|
||||||
pub(crate) fn from_vec(elements: Vec<F>) -> Self {
|
pub(crate) fn from_vec(elements: Vec<F>) -> Self {
|
||||||
debug_assert!(elements.len() == 4);
|
debug_assert!(elements.len() == 4);
|
||||||
Self { elements: elements.try_into().unwrap() }
|
Self {
|
||||||
|
elements: elements.try_into().unwrap(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_partial(mut elements: Vec<F>) -> Self {
|
pub(crate) fn from_partial(mut elements: Vec<F>) -> Self {
|
||||||
@ -20,7 +23,9 @@ impl<F: Field> Hash<F> {
|
|||||||
while elements.len() < 4 {
|
while elements.len() < 4 {
|
||||||
elements.push(F::ZERO);
|
elements.push(F::ZERO);
|
||||||
}
|
}
|
||||||
Self { elements: [elements[0], elements[1], elements[2], elements[3]] }
|
Self {
|
||||||
|
elements: [elements[0], elements[1], elements[2], elements[3]],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +37,9 @@ pub struct HashTarget {
|
|||||||
impl HashTarget {
|
impl HashTarget {
|
||||||
pub(crate) fn from_vec(elements: Vec<Target>) -> Self {
|
pub(crate) fn from_vec(elements: Vec<Target>) -> Self {
|
||||||
debug_assert!(elements.len() == 4);
|
debug_assert!(elements.len() == 4);
|
||||||
Self { elements: elements.try_into().unwrap() }
|
Self {
|
||||||
|
elements: elements.try_into().unwrap(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_partial(mut elements: Vec<Target>, zero: Target) -> Self {
|
pub(crate) fn from_partial(mut elements: Vec<Target>, zero: Target) -> Self {
|
||||||
@ -40,7 +47,9 @@ impl HashTarget {
|
|||||||
while elements.len() < 4 {
|
while elements.len() < 4 {
|
||||||
elements.push(zero);
|
elements.push(zero);
|
||||||
}
|
}
|
||||||
Self { elements: [elements[0], elements[1], elements[2], elements[3]] }
|
Self {
|
||||||
|
elements: [elements[0], elements[1], elements[2], elements[3]],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,13 +83,31 @@ pub struct ProofTarget {
|
|||||||
pub fri_proofs: Vec<FriProofTarget>,
|
pub fri_proofs: Vec<FriProofTarget>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement FriEvaluationsTarget
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FriEvaluations<F: Field> {
|
||||||
|
pub first_layer: (F, F),
|
||||||
|
pub rest: Vec<F>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement FriEvaluationsTarget
|
||||||
|
pub struct FriMerkleProofs<F: Field> {
|
||||||
|
pub proofs: Vec<(MerkleProof<F>, MerkleProof<F>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement FriQueryRoundTarget
|
||||||
|
pub struct FriQueryRound<F: Field> {
|
||||||
|
pub evals: FriEvaluations<F>,
|
||||||
|
pub merkle_proofs: FriMerkleProofs<F>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FriProof<F: Field> {
|
pub struct FriProof<F: Field> {
|
||||||
/// A Merkle root for each reduced polynomial in the commit phase.
|
/// A Merkle root for each reduced polynomial in the commit phase.
|
||||||
pub commit_phase_merkle_roots: Vec<Hash<F>>,
|
pub commit_phase_merkle_roots: Vec<Hash<F>>,
|
||||||
/// Merkle proofs for the original purported codewords, i.e. the subject of the LDT.
|
/// Merkle proofs for the original purported codewords, i.e. the subject of the LDT.
|
||||||
pub initial_merkle_proofs: Vec<MerkleProof<F>>,
|
pub initial_merkle_proofs: Vec<MerkleProof<F>>,
|
||||||
/// Merkle proofs for the reduced polynomials that were sent in the commit phase.
|
/// Query rounds proofs
|
||||||
pub intermediate_merkle_proofs: Vec<MerkleProof<F>>,
|
pub query_round_proofs: Vec<FriQueryRound<F>>,
|
||||||
/// The final polynomial in coefficient form.
|
/// The final polynomial in coefficient form.
|
||||||
pub final_poly: PolynomialCoeffs<F>,
|
pub final_poly: PolynomialCoeffs<F>,
|
||||||
}
|
}
|
||||||
|
|||||||
107
src/prover.rs
107
src/prover.rs
@ -4,17 +4,17 @@ use log::info;
|
|||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use crate::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
|
use crate::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
|
||||||
use crate::vars::EvaluationVars;
|
|
||||||
use crate::field::fft::{fft, ifft};
|
use crate::field::fft::{fft, ifft};
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::generator::generate_partial_witness;
|
use crate::generator::generate_partial_witness;
|
||||||
use crate::hash::merkle_root_bit_rev_order;
|
use crate::hash::merkle_root_bit_rev_order;
|
||||||
use crate::plonk_challenger::Challenger;
|
use crate::plonk_challenger::Challenger;
|
||||||
use crate::plonk_common::{eval_l_1, reduce_with_powers_multi, evaluate_gate_constraints};
|
use crate::plonk_common::{eval_l_1, evaluate_gate_constraints, reduce_with_powers_multi};
|
||||||
use crate::polynomial::division::divide_by_z_h;
|
use crate::polynomial::division::divide_by_z_h;
|
||||||
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||||
use crate::proof::Proof;
|
use crate::proof::Proof;
|
||||||
use crate::util::{transpose, transpose_poly_values};
|
use crate::util::{transpose, transpose_poly_values};
|
||||||
|
use crate::vars::EvaluationVars;
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
use crate::witness::PartialWitness;
|
use crate::witness::PartialWitness;
|
||||||
|
|
||||||
@ -29,8 +29,10 @@ pub(crate) fn prove<F: Field>(
|
|||||||
let mut witness = inputs;
|
let mut witness = inputs;
|
||||||
info!("Running {} generators", prover_data.generators.len());
|
info!("Running {} generators", prover_data.generators.len());
|
||||||
generate_partial_witness(&mut witness, &prover_data.generators);
|
generate_partial_witness(&mut witness, &prover_data.generators);
|
||||||
info!("{:.3}s to generate witness",
|
info!(
|
||||||
start_witness.elapsed().as_secs_f32());
|
"{:.3}s to generate witness",
|
||||||
|
start_witness.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
let config = common_data.config;
|
let config = common_data.config;
|
||||||
let num_wires = config.num_wires;
|
let num_wires = config.num_wires;
|
||||||
@ -43,21 +45,27 @@ pub(crate) fn prove<F: Field>(
|
|||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|i| compute_wire_lde(i, &witness, degree, config.rate_bits))
|
.map(|i| compute_wire_lde(i, &witness, degree, config.rate_bits))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
info!("{:.3}s to compute wire LDEs",
|
info!(
|
||||||
start_wire_ldes.elapsed().as_secs_f32());
|
"{:.3}s to compute wire LDEs",
|
||||||
|
start_wire_ldes.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: Could try parallelizing the transpose, or not doing it explicitly, instead having
|
// TODO: Could try parallelizing the transpose, or not doing it explicitly, instead having
|
||||||
// merkle_root_bit_rev_order do it implicitly.
|
// merkle_root_bit_rev_order do it implicitly.
|
||||||
let start_wire_transpose = Instant::now();
|
let start_wire_transpose = Instant::now();
|
||||||
let wire_ldes_t = transpose_poly_values(wire_ldes);
|
let wire_ldes_t = transpose_poly_values(wire_ldes);
|
||||||
info!("{:.3}s to transpose wire LDEs",
|
info!(
|
||||||
start_wire_transpose.elapsed().as_secs_f32());
|
"{:.3}s to transpose wire LDEs",
|
||||||
|
start_wire_transpose.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: Could avoid cloning if it's significant?
|
// TODO: Could avoid cloning if it's significant?
|
||||||
let start_wires_root = Instant::now();
|
let start_wires_root = Instant::now();
|
||||||
let wires_root = merkle_root_bit_rev_order(wire_ldes_t.clone());
|
let wires_root = merkle_root_bit_rev_order(wire_ldes_t.clone());
|
||||||
info!("{:.3}s to Merklize wire LDEs",
|
info!(
|
||||||
start_wires_root.elapsed().as_secs_f32());
|
"{:.3}s to Merklize wire LDEs",
|
||||||
|
start_wires_root.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
let mut challenger = Challenger::new();
|
let mut challenger = Challenger::new();
|
||||||
challenger.observe_hash(&wires_root);
|
challenger.observe_hash(&wires_root);
|
||||||
@ -68,13 +76,17 @@ pub(crate) fn prove<F: Field>(
|
|||||||
let plonk_z_vecs = compute_zs(&common_data);
|
let plonk_z_vecs = compute_zs(&common_data);
|
||||||
let plonk_z_ldes = PolynomialValues::lde_multiple(plonk_z_vecs, config.rate_bits);
|
let plonk_z_ldes = PolynomialValues::lde_multiple(plonk_z_vecs, config.rate_bits);
|
||||||
let plonk_z_ldes_t = transpose_poly_values(plonk_z_ldes);
|
let plonk_z_ldes_t = transpose_poly_values(plonk_z_ldes);
|
||||||
info!("{:.3}s to compute Z's and their LDEs",
|
info!(
|
||||||
start_plonk_z.elapsed().as_secs_f32());
|
"{:.3}s to compute Z's and their LDEs",
|
||||||
|
start_plonk_z.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
let start_plonk_z_root = Instant::now();
|
let start_plonk_z_root = Instant::now();
|
||||||
let plonk_zs_root = merkle_root_bit_rev_order(plonk_z_ldes_t.clone());
|
let plonk_zs_root = merkle_root_bit_rev_order(plonk_z_ldes_t.clone());
|
||||||
info!("{:.3}s to Merklize Z's",
|
info!(
|
||||||
start_plonk_z_root.elapsed().as_secs_f32());
|
"{:.3}s to Merklize Z's",
|
||||||
|
start_plonk_z_root.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
challenger.observe_hash(&plonk_zs_root);
|
challenger.observe_hash(&plonk_zs_root);
|
||||||
|
|
||||||
@ -86,9 +98,18 @@ pub(crate) fn prove<F: Field>(
|
|||||||
|
|
||||||
let start_vanishing_polys = Instant::now();
|
let start_vanishing_polys = Instant::now();
|
||||||
let vanishing_polys = compute_vanishing_polys(
|
let vanishing_polys = compute_vanishing_polys(
|
||||||
common_data, prover_data, wire_ldes_t, plonk_z_ldes_t, beta, gamma, &alphas);
|
common_data,
|
||||||
info!("{:.3}s to compute vanishing polys",
|
prover_data,
|
||||||
start_vanishing_polys.elapsed().as_secs_f32());
|
wire_ldes_t,
|
||||||
|
plonk_z_ldes_t,
|
||||||
|
beta,
|
||||||
|
gamma,
|
||||||
|
&alphas,
|
||||||
|
);
|
||||||
|
info!(
|
||||||
|
"{:.3}s to compute vanishing polys",
|
||||||
|
start_vanishing_polys.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
// Compute the quotient polynomials, aka `t` in the Plonk paper.
|
// Compute the quotient polynomials, aka `t` in the Plonk paper.
|
||||||
let quotient_polys_start = Instant::now();
|
let quotient_polys_start = Instant::now();
|
||||||
@ -98,23 +119,27 @@ pub(crate) fn prove<F: Field>(
|
|||||||
let quotient_poly_coeff = divide_by_z_h(vanishing_poly_coeff, degree);
|
let quotient_poly_coeff = divide_by_z_h(vanishing_poly_coeff, degree);
|
||||||
// Split t into degree-n chunks.
|
// Split t into degree-n chunks.
|
||||||
let quotient_poly_coeff_chunks = quotient_poly_coeff.chunks(degree);
|
let quotient_poly_coeff_chunks = quotient_poly_coeff.chunks(degree);
|
||||||
let quotient_poly_coeff_ldes = PolynomialCoeffs::lde_multiple(
|
let quotient_poly_coeff_ldes =
|
||||||
quotient_poly_coeff_chunks, config.rate_bits);
|
PolynomialCoeffs::lde_multiple(quotient_poly_coeff_chunks, config.rate_bits);
|
||||||
let quotient_poly_chunk_ldes: Vec<PolynomialValues<F>> =
|
let quotient_poly_chunk_ldes: Vec<PolynomialValues<F>> =
|
||||||
quotient_poly_coeff_ldes.into_par_iter().map(fft).collect();
|
quotient_poly_coeff_ldes.into_par_iter().map(fft).collect();
|
||||||
all_quotient_poly_chunk_ldes.extend(quotient_poly_chunk_ldes);
|
all_quotient_poly_chunk_ldes.extend(quotient_poly_chunk_ldes);
|
||||||
}
|
}
|
||||||
let quotient_polys_root = merkle_root_bit_rev_order(
|
let quotient_polys_root =
|
||||||
transpose_poly_values(all_quotient_poly_chunk_ldes));
|
merkle_root_bit_rev_order(transpose_poly_values(all_quotient_poly_chunk_ldes));
|
||||||
info!("{:.3}s to compute quotient polys and their LDEs",
|
info!(
|
||||||
quotient_polys_start.elapsed().as_secs_f32());
|
"{:.3}s to compute quotient polys and their LDEs",
|
||||||
|
quotient_polys_start.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
let openings = Vec::new(); // TODO
|
let openings = Vec::new(); // TODO
|
||||||
|
|
||||||
let fri_proofs = Vec::new(); // TODO
|
let fri_proofs = Vec::new(); // TODO
|
||||||
|
|
||||||
info!("{:.3}s for overall witness & proof generation",
|
info!(
|
||||||
start_proof_gen.elapsed().as_secs_f32());
|
"{:.3}s for overall witness & proof generation",
|
||||||
|
start_proof_gen.elapsed().as_secs_f32()
|
||||||
|
);
|
||||||
|
|
||||||
Proof {
|
Proof {
|
||||||
wires_root,
|
wires_root,
|
||||||
@ -150,7 +175,10 @@ fn compute_vanishing_polys<F: Field>(
|
|||||||
let num_checks = common_data.config.num_checks;
|
let num_checks = common_data.config.num_checks;
|
||||||
|
|
||||||
let points = F::cyclic_subgroup_known_order(lde_gen, lde_size);
|
let points = F::cyclic_subgroup_known_order(lde_gen, lde_size);
|
||||||
let values: Vec<Vec<F>> = points.into_par_iter().enumerate().map(|(i, x)| {
|
let values: Vec<Vec<F>> = points
|
||||||
|
.into_par_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, x)| {
|
||||||
let i_next = (i + 1) % lde_size;
|
let i_next = (i + 1) % lde_size;
|
||||||
let local_wires = &wire_ldes_t[i];
|
let local_wires = &wire_ldes_t[i];
|
||||||
let next_wires = &wire_ldes_t[i_next];
|
let next_wires = &wire_ldes_t[i_next];
|
||||||
@ -170,8 +198,18 @@ fn compute_vanishing_polys<F: Field>(
|
|||||||
next_wires,
|
next_wires,
|
||||||
};
|
};
|
||||||
compute_vanishing_poly_entry(
|
compute_vanishing_poly_entry(
|
||||||
common_data, x, vars, local_plonk_zs, next_plonk_zs, s_sigmas, beta, gamma, alphas)
|
common_data,
|
||||||
}).collect();
|
x,
|
||||||
|
vars,
|
||||||
|
local_plonk_zs,
|
||||||
|
next_plonk_zs,
|
||||||
|
s_sigmas,
|
||||||
|
beta,
|
||||||
|
gamma,
|
||||||
|
alphas,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
transpose(&values)
|
transpose(&values)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -193,8 +231,8 @@ fn compute_vanishing_poly_entry<F: Field>(
|
|||||||
gamma: F,
|
gamma: F,
|
||||||
alphas: &[F],
|
alphas: &[F],
|
||||||
) -> Vec<F> {
|
) -> Vec<F> {
|
||||||
let constraint_terms = evaluate_gate_constraints(
|
let constraint_terms =
|
||||||
&common_data.gates, common_data.num_gate_constraints, vars);
|
evaluate_gate_constraints(&common_data.gates, common_data.num_gate_constraints, vars);
|
||||||
|
|
||||||
// The L_1(x) (Z(x) - 1) vanishing terms.
|
// The L_1(x) (Z(x) - 1) vanishing terms.
|
||||||
let mut vanishing_z_1_terms = Vec::new();
|
let mut vanishing_z_1_terms = Vec::new();
|
||||||
@ -223,7 +261,8 @@ fn compute_vanishing_poly_entry<F: Field>(
|
|||||||
vanishing_z_1_terms,
|
vanishing_z_1_terms,
|
||||||
vanishing_v_shift_terms,
|
vanishing_v_shift_terms,
|
||||||
constraint_terms,
|
constraint_terms,
|
||||||
].concat();
|
]
|
||||||
|
.concat();
|
||||||
|
|
||||||
reduce_with_powers_multi(&vanishing_terms, alphas)
|
reduce_with_powers_multi(&vanishing_terms, alphas)
|
||||||
}
|
}
|
||||||
@ -239,7 +278,11 @@ fn compute_wire_lde<F: Field>(
|
|||||||
// wires, so some wire values will not be set. We can set these to any value; here we
|
// wires, so some wire values will not be set. We can set these to any value; here we
|
||||||
// arbitrary pick zero. Ideally we would verify that no constraints operate on these unset
|
// arbitrary pick zero. Ideally we would verify that no constraints operate on these unset
|
||||||
// wires, but that isn't trivial.
|
// wires, but that isn't trivial.
|
||||||
.map(|gate| witness.try_get_wire(Wire { gate, input }).unwrap_or(F::ZERO))
|
.map(|gate| {
|
||||||
|
witness
|
||||||
|
.try_get_wire(Wire { gate, input })
|
||||||
|
.unwrap_or(F::ZERO)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
PolynomialValues::new(wire_values).lde(rate_bits)
|
PolynomialValues::new(wire_values).lde(rate_bits)
|
||||||
}
|
}
|
||||||
|
|||||||
480
src/rescue.rs
480
src/rescue.rs
@ -7,41 +7,457 @@ const ROUNDS: usize = 10;
|
|||||||
const W: usize = 12;
|
const W: usize = 12;
|
||||||
|
|
||||||
const MDS: [[u64; W]; W] = [
|
const MDS: [[u64; W]; W] = [
|
||||||
[10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, 16140901062381928449, 2635249153041947502, 3074457345215605419, 11068046442776179508, 13835058053470224385, 6148914690431210838, 9223372035646816257, 1, ],
|
[
|
||||||
[5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, 16140901062381928449, 2635249153041947502, 3074457345215605419, 11068046442776179508, 13835058053470224385, 6148914690431210838, 9223372035646816257, ],
|
10760600708254618966,
|
||||||
[1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, 16140901062381928449, 2635249153041947502, 3074457345215605419, 11068046442776179508, 13835058053470224385, 6148914690431210838, ],
|
16769767337539665921,
|
||||||
[15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, 16140901062381928449, 2635249153041947502, 3074457345215605419, 11068046442776179508, 13835058053470224385, ],
|
5534023221388089754,
|
||||||
[17293822566837780481, 15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, 16140901062381928449, 2635249153041947502, 3074457345215605419, 11068046442776179508, ],
|
2049638230143736946,
|
||||||
[3255307777287111620, 17293822566837780481, 15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, 16140901062381928449, 2635249153041947502, 3074457345215605419, ],
|
16140901062381928449,
|
||||||
[1024819115071868473, 3255307777287111620, 17293822566837780481, 15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, 16140901062381928449, 2635249153041947502, ],
|
2635249153041947502,
|
||||||
[9708812669101911849, 1024819115071868473, 3255307777287111620, 17293822566837780481, 15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, 16140901062381928449, ],
|
3074457345215605419,
|
||||||
[2767011610694044877, 9708812669101911849, 1024819115071868473, 3255307777287111620, 17293822566837780481, 15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, 2049638230143736946, ],
|
11068046442776179508,
|
||||||
[878416384347315834, 2767011610694044877, 9708812669101911849, 1024819115071868473, 3255307777287111620, 17293822566837780481, 15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, 5534023221388089754, ],
|
13835058053470224385,
|
||||||
[17608255704416649217, 878416384347315834, 2767011610694044877, 9708812669101911849, 1024819115071868473, 3255307777287111620, 17293822566837780481, 15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, 16769767337539665921, ],
|
6148914690431210838,
|
||||||
[15238614667590392076, 17608255704416649217, 878416384347315834, 2767011610694044877, 9708812669101911849, 1024819115071868473, 3255307777287111620, 17293822566837780481, 15987178195121148178, 1317624576520973751, 5675921252705733081, 10760600708254618966, ],
|
9223372035646816257,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
2049638230143736946,
|
||||||
|
16140901062381928449,
|
||||||
|
2635249153041947502,
|
||||||
|
3074457345215605419,
|
||||||
|
11068046442776179508,
|
||||||
|
13835058053470224385,
|
||||||
|
6148914690431210838,
|
||||||
|
9223372035646816257,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
2049638230143736946,
|
||||||
|
16140901062381928449,
|
||||||
|
2635249153041947502,
|
||||||
|
3074457345215605419,
|
||||||
|
11068046442776179508,
|
||||||
|
13835058053470224385,
|
||||||
|
6148914690431210838,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
2049638230143736946,
|
||||||
|
16140901062381928449,
|
||||||
|
2635249153041947502,
|
||||||
|
3074457345215605419,
|
||||||
|
11068046442776179508,
|
||||||
|
13835058053470224385,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
17293822566837780481,
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
2049638230143736946,
|
||||||
|
16140901062381928449,
|
||||||
|
2635249153041947502,
|
||||||
|
3074457345215605419,
|
||||||
|
11068046442776179508,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
3255307777287111620,
|
||||||
|
17293822566837780481,
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
2049638230143736946,
|
||||||
|
16140901062381928449,
|
||||||
|
2635249153041947502,
|
||||||
|
3074457345215605419,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1024819115071868473,
|
||||||
|
3255307777287111620,
|
||||||
|
17293822566837780481,
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
2049638230143736946,
|
||||||
|
16140901062381928449,
|
||||||
|
2635249153041947502,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
9708812669101911849,
|
||||||
|
1024819115071868473,
|
||||||
|
3255307777287111620,
|
||||||
|
17293822566837780481,
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
2049638230143736946,
|
||||||
|
16140901062381928449,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2767011610694044877,
|
||||||
|
9708812669101911849,
|
||||||
|
1024819115071868473,
|
||||||
|
3255307777287111620,
|
||||||
|
17293822566837780481,
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
2049638230143736946,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
878416384347315834,
|
||||||
|
2767011610694044877,
|
||||||
|
9708812669101911849,
|
||||||
|
1024819115071868473,
|
||||||
|
3255307777287111620,
|
||||||
|
17293822566837780481,
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
5534023221388089754,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
17608255704416649217,
|
||||||
|
878416384347315834,
|
||||||
|
2767011610694044877,
|
||||||
|
9708812669101911849,
|
||||||
|
1024819115071868473,
|
||||||
|
3255307777287111620,
|
||||||
|
17293822566837780481,
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
16769767337539665921,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
15238614667590392076,
|
||||||
|
17608255704416649217,
|
||||||
|
878416384347315834,
|
||||||
|
2767011610694044877,
|
||||||
|
9708812669101911849,
|
||||||
|
1024819115071868473,
|
||||||
|
3255307777287111620,
|
||||||
|
17293822566837780481,
|
||||||
|
15987178195121148178,
|
||||||
|
1317624576520973751,
|
||||||
|
5675921252705733081,
|
||||||
|
10760600708254618966,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
const RESCUE_CONSTANTS: [[u64; W]; 20] = [
|
const RESCUE_CONSTANTS: [[u64; W]; 20] = [
|
||||||
[12050887499329086906, 1748247961703512657, 315780861775001585, 2827656358919812970, 13335864861236723579, 3010729529365640897, 8463534053828271146, 2528500966106598845, 8969871077123422281, 1002624930202741107, 599979829006456404, 4386170815218774254, ],
|
[
|
||||||
[5771413917591851532, 11946802620311685142, 4759792267858670262, 6879094914431255667, 3985911073214909073, 1542850118294175816, 5393560436452023029, 8331250756632997735, 3395511836281190608, 17601255793194446503, 12848459944475727152, 11995465655754698601, ],
|
12050887499329086906,
|
||||||
[14063960046551560130, 14790209580166185143, 5509023472758717841, 1274395897760495573, 16719545989415697758, 17865948122414223407, 3919263713959798649, 5633741078654387163, 15665612362287352054, 3418834727998553015, 5324019631954832682, 17962066557010997431, ],
|
1748247961703512657,
|
||||||
[3282193104189649752, 18423507935939999211, 9035104445528866459, 30842260240043277, 3896337933354935129, 6615548113269323045, 6625827707190475694, 6677757329269550670, 11419013193186889337, 17111888851716383760, 12075517898615128691, 8139844272075088233, ],
|
315780861775001585,
|
||||||
[8872892112814161072, 17529364346566228604, 7526576514327158912, 850359069964902700, 9679332912197531902, 10591229741059812071, 12759208863825924546, 14552519355635838750, 16066249893409806278, 11283035366525176262, 1047378652379935387, 17032498397644511356, ],
|
2827656358919812970,
|
||||||
[2938626421478254042, 10375267398354586672, 13728514869380643947, 16707318479225743731, 9785828188762698567, 8610686976269299752, 5478372191917042178, 12716344455538470365, 9968276048553747246, 14746805727771473956, 4822070620124107028, 9901161649549513416, ],
|
13335864861236723579,
|
||||||
[13458162407040644078, 4045792126424269312, 9709263167782315020, 2163173014916005515, 17079206331095671215, 2556388076102629669, 6582772486087242347, 1239959540200663058, 18268236910639895687, 12499012548657350745, 17213068585339946119, 7641451088868756688, ],
|
3010729529365640897,
|
||||||
[14674555473338434116, 14624532976317185113, 13625541984298615970, 7612892294159054770, 12294028208969561574, 6067206081581804358, 5778082506883496792, 7389487446513884800, 12929525660730020877, 18244350162788654296, 15285920877034454694, 3640669683987215349, ],
|
8463534053828271146,
|
||||||
[6737585134029996281, 1826890539455248546, 289376081355380231, 10782622161517803787, 12978425540147835172, 9828233103297278473, 16384075371934678711, 3187492301890791304, 12985433735185968457, 9470935291631377473, 16328323199113140151, 16218490552434224203, ],
|
2528500966106598845,
|
||||||
[6188809977565251499, 18437718710937437067, 4530469469895539008, 9596355277372723349, 13602518824447658705, 8759976068576854281, 10504320064094929535, 3980760429843656150, 14609448298151012462, 5839843841558860609, 10283805260656050418, 7239168159249274821, ],
|
8969871077123422281,
|
||||||
[3604243611640027441, 5237321927316578323, 5071861664926666316, 13025405632646149705, 3285281651566464074, 12121596060272825779, 1900602777802961569, 8122527981264852045, 6731303887159752901, 9197659817406857040, 844741616904786364, 14249777686667858094, ],
|
1002624930202741107,
|
||||||
[8602844218963499297, 10133401373828451640, 11618292280328565166, 8828272598402499582, 4252246265076774689, 9760449011955070998, 10233981507028897480, 10427510555228840014, 1007817664531124790, 4465396600980659145, 7727267420665314215, 7904022788946844554, ],
|
599979829006456404,
|
||||||
[11418297156527169222, 15865399053509010196, 1727198235391450850, 16557095577717348672, 1524052121709169653, 14531367160053894310, 4071756280138432327, 10333204220115446291, 16584144375833061215, 12237566480526488368, 11090440024401607208, 18281335018830792766, ],
|
4386170815218774254,
|
||||||
[16152169547074248135, 18338155611216027761, 15842640128213925612, 14687926435880145351, 13259626900273707210, 6187877366876303234, 10312881470701795438, 1924945292721719446, 2278209355262975917, 3250749056007953206, 11589006946114672195, 241829012299953928, ],
|
],
|
||||||
[11244459446597052449, 7319043416418482137, 8148526814449636806, 9054933038587901070, 550333919248348827, 5513167392062632770, 12644459803778263764, 9903621375535446226, 16390581784506871871, 14586524717888286021, 6975796306584548762, 5200407948555191573, ],
|
[
|
||||||
[2855794043288846965, 1259443213892506318, 6145351706926586935, 3853784494234324998, 5871277378086513850, 9414363368707862566, 11946957446931890832, 308083693687568600, 12712587722369770461, 6792392698104204991, 16465224002344550280, 10282380383506806095, ],
|
5771413917591851532,
|
||||||
[12608209810104211593, 11808578423511814760, 16177950852717156460, 9394439296563712221, 12586575762376685187, 17703393198607870393, 9811861465513647715, 14126450959506560131, 12713673607080398908, 18301828072718562389, 11180556590297273821, 4451415492203885059, ],
|
11946802620311685142,
|
||||||
[10465807219916311101, 1213997644391575261, 17672155373280862521, 1491206970207330736, 10977478805896263804, 13260961975618373124, 16060889403827043708, 3223573072465920682, 17624203443801796697, 10247205738678800822, 11100653267668698651, 14328592975764892571, ],
|
4759792267858670262,
|
||||||
[6984072551318461094, 3416562710010527326, 12847783919251969270, 12223185134739244472, 12073170519625198198, 6221124633828606855, 17596623990006806590, 1153871693574764968, 2548851681903410721, 9823373270182377847, 16708030507924899244, 9619306826188519218, ],
|
6879094914431255667,
|
||||||
[5842685042453818473, 12400879353954910914, 647112787845575111, 4893664959929687347, 3759391664155971284, 15871181179823725763, 3629377713951158273, 3439101502554162312, 8325686353010019444, 10630488935940555500, 3478529754946055748, 12681233130980545828, ],
|
3985911073214909073,
|
||||||
|
1542850118294175816,
|
||||||
|
5393560436452023029,
|
||||||
|
8331250756632997735,
|
||||||
|
3395511836281190608,
|
||||||
|
17601255793194446503,
|
||||||
|
12848459944475727152,
|
||||||
|
11995465655754698601,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
14063960046551560130,
|
||||||
|
14790209580166185143,
|
||||||
|
5509023472758717841,
|
||||||
|
1274395897760495573,
|
||||||
|
16719545989415697758,
|
||||||
|
17865948122414223407,
|
||||||
|
3919263713959798649,
|
||||||
|
5633741078654387163,
|
||||||
|
15665612362287352054,
|
||||||
|
3418834727998553015,
|
||||||
|
5324019631954832682,
|
||||||
|
17962066557010997431,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
3282193104189649752,
|
||||||
|
18423507935939999211,
|
||||||
|
9035104445528866459,
|
||||||
|
30842260240043277,
|
||||||
|
3896337933354935129,
|
||||||
|
6615548113269323045,
|
||||||
|
6625827707190475694,
|
||||||
|
6677757329269550670,
|
||||||
|
11419013193186889337,
|
||||||
|
17111888851716383760,
|
||||||
|
12075517898615128691,
|
||||||
|
8139844272075088233,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8872892112814161072,
|
||||||
|
17529364346566228604,
|
||||||
|
7526576514327158912,
|
||||||
|
850359069964902700,
|
||||||
|
9679332912197531902,
|
||||||
|
10591229741059812071,
|
||||||
|
12759208863825924546,
|
||||||
|
14552519355635838750,
|
||||||
|
16066249893409806278,
|
||||||
|
11283035366525176262,
|
||||||
|
1047378652379935387,
|
||||||
|
17032498397644511356,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2938626421478254042,
|
||||||
|
10375267398354586672,
|
||||||
|
13728514869380643947,
|
||||||
|
16707318479225743731,
|
||||||
|
9785828188762698567,
|
||||||
|
8610686976269299752,
|
||||||
|
5478372191917042178,
|
||||||
|
12716344455538470365,
|
||||||
|
9968276048553747246,
|
||||||
|
14746805727771473956,
|
||||||
|
4822070620124107028,
|
||||||
|
9901161649549513416,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
13458162407040644078,
|
||||||
|
4045792126424269312,
|
||||||
|
9709263167782315020,
|
||||||
|
2163173014916005515,
|
||||||
|
17079206331095671215,
|
||||||
|
2556388076102629669,
|
||||||
|
6582772486087242347,
|
||||||
|
1239959540200663058,
|
||||||
|
18268236910639895687,
|
||||||
|
12499012548657350745,
|
||||||
|
17213068585339946119,
|
||||||
|
7641451088868756688,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
14674555473338434116,
|
||||||
|
14624532976317185113,
|
||||||
|
13625541984298615970,
|
||||||
|
7612892294159054770,
|
||||||
|
12294028208969561574,
|
||||||
|
6067206081581804358,
|
||||||
|
5778082506883496792,
|
||||||
|
7389487446513884800,
|
||||||
|
12929525660730020877,
|
||||||
|
18244350162788654296,
|
||||||
|
15285920877034454694,
|
||||||
|
3640669683987215349,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
6737585134029996281,
|
||||||
|
1826890539455248546,
|
||||||
|
289376081355380231,
|
||||||
|
10782622161517803787,
|
||||||
|
12978425540147835172,
|
||||||
|
9828233103297278473,
|
||||||
|
16384075371934678711,
|
||||||
|
3187492301890791304,
|
||||||
|
12985433735185968457,
|
||||||
|
9470935291631377473,
|
||||||
|
16328323199113140151,
|
||||||
|
16218490552434224203,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
6188809977565251499,
|
||||||
|
18437718710937437067,
|
||||||
|
4530469469895539008,
|
||||||
|
9596355277372723349,
|
||||||
|
13602518824447658705,
|
||||||
|
8759976068576854281,
|
||||||
|
10504320064094929535,
|
||||||
|
3980760429843656150,
|
||||||
|
14609448298151012462,
|
||||||
|
5839843841558860609,
|
||||||
|
10283805260656050418,
|
||||||
|
7239168159249274821,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
3604243611640027441,
|
||||||
|
5237321927316578323,
|
||||||
|
5071861664926666316,
|
||||||
|
13025405632646149705,
|
||||||
|
3285281651566464074,
|
||||||
|
12121596060272825779,
|
||||||
|
1900602777802961569,
|
||||||
|
8122527981264852045,
|
||||||
|
6731303887159752901,
|
||||||
|
9197659817406857040,
|
||||||
|
844741616904786364,
|
||||||
|
14249777686667858094,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8602844218963499297,
|
||||||
|
10133401373828451640,
|
||||||
|
11618292280328565166,
|
||||||
|
8828272598402499582,
|
||||||
|
4252246265076774689,
|
||||||
|
9760449011955070998,
|
||||||
|
10233981507028897480,
|
||||||
|
10427510555228840014,
|
||||||
|
1007817664531124790,
|
||||||
|
4465396600980659145,
|
||||||
|
7727267420665314215,
|
||||||
|
7904022788946844554,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
11418297156527169222,
|
||||||
|
15865399053509010196,
|
||||||
|
1727198235391450850,
|
||||||
|
16557095577717348672,
|
||||||
|
1524052121709169653,
|
||||||
|
14531367160053894310,
|
||||||
|
4071756280138432327,
|
||||||
|
10333204220115446291,
|
||||||
|
16584144375833061215,
|
||||||
|
12237566480526488368,
|
||||||
|
11090440024401607208,
|
||||||
|
18281335018830792766,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
16152169547074248135,
|
||||||
|
18338155611216027761,
|
||||||
|
15842640128213925612,
|
||||||
|
14687926435880145351,
|
||||||
|
13259626900273707210,
|
||||||
|
6187877366876303234,
|
||||||
|
10312881470701795438,
|
||||||
|
1924945292721719446,
|
||||||
|
2278209355262975917,
|
||||||
|
3250749056007953206,
|
||||||
|
11589006946114672195,
|
||||||
|
241829012299953928,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
11244459446597052449,
|
||||||
|
7319043416418482137,
|
||||||
|
8148526814449636806,
|
||||||
|
9054933038587901070,
|
||||||
|
550333919248348827,
|
||||||
|
5513167392062632770,
|
||||||
|
12644459803778263764,
|
||||||
|
9903621375535446226,
|
||||||
|
16390581784506871871,
|
||||||
|
14586524717888286021,
|
||||||
|
6975796306584548762,
|
||||||
|
5200407948555191573,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2855794043288846965,
|
||||||
|
1259443213892506318,
|
||||||
|
6145351706926586935,
|
||||||
|
3853784494234324998,
|
||||||
|
5871277378086513850,
|
||||||
|
9414363368707862566,
|
||||||
|
11946957446931890832,
|
||||||
|
308083693687568600,
|
||||||
|
12712587722369770461,
|
||||||
|
6792392698104204991,
|
||||||
|
16465224002344550280,
|
||||||
|
10282380383506806095,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
12608209810104211593,
|
||||||
|
11808578423511814760,
|
||||||
|
16177950852717156460,
|
||||||
|
9394439296563712221,
|
||||||
|
12586575762376685187,
|
||||||
|
17703393198607870393,
|
||||||
|
9811861465513647715,
|
||||||
|
14126450959506560131,
|
||||||
|
12713673607080398908,
|
||||||
|
18301828072718562389,
|
||||||
|
11180556590297273821,
|
||||||
|
4451415492203885059,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
10465807219916311101,
|
||||||
|
1213997644391575261,
|
||||||
|
17672155373280862521,
|
||||||
|
1491206970207330736,
|
||||||
|
10977478805896263804,
|
||||||
|
13260961975618373124,
|
||||||
|
16060889403827043708,
|
||||||
|
3223573072465920682,
|
||||||
|
17624203443801796697,
|
||||||
|
10247205738678800822,
|
||||||
|
11100653267668698651,
|
||||||
|
14328592975764892571,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
6984072551318461094,
|
||||||
|
3416562710010527326,
|
||||||
|
12847783919251969270,
|
||||||
|
12223185134739244472,
|
||||||
|
12073170519625198198,
|
||||||
|
6221124633828606855,
|
||||||
|
17596623990006806590,
|
||||||
|
1153871693574764968,
|
||||||
|
2548851681903410721,
|
||||||
|
9823373270182377847,
|
||||||
|
16708030507924899244,
|
||||||
|
9619306826188519218,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
5842685042453818473,
|
||||||
|
12400879353954910914,
|
||||||
|
647112787845575111,
|
||||||
|
4893664959929687347,
|
||||||
|
3759391664155971284,
|
||||||
|
15871181179823725763,
|
||||||
|
3629377713951158273,
|
||||||
|
3439101502554162312,
|
||||||
|
8325686353010019444,
|
||||||
|
10630488935940555500,
|
||||||
|
3478529754946055748,
|
||||||
|
12681233130980545828,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
fn rescue<F: Field>(mut xs: [F; W]) -> [F; W] {
|
fn rescue<F: Field>(mut xs: [F; W]) -> [F; W] {
|
||||||
|
|||||||
12
src/util.rs
12
src/util.rs
@ -25,9 +25,7 @@ pub(crate) fn log2_strict(n: usize) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn transpose_poly_values<F: Field>(polys: Vec<PolynomialValues<F>>) -> Vec<Vec<F>> {
|
pub(crate) fn transpose_poly_values<F: Field>(polys: Vec<PolynomialValues<F>>) -> Vec<Vec<F>> {
|
||||||
let poly_values = polys.into_iter()
|
let poly_values = polys.into_iter().map(|p| p.values).collect::<Vec<_>>();
|
||||||
.map(|p| p.values)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
transpose(&poly_values)
|
transpose(&poly_values)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +65,7 @@ pub(crate) fn reverse_index_bits_in_place<T>(arr: &mut Vec<T>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reverse_bits(n: usize, num_bits: usize) -> usize {
|
pub(crate) fn reverse_bits(n: usize, num_bits: usize) -> usize {
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
for i in 0..num_bits {
|
for i in 0..num_bits {
|
||||||
let i_rev = num_bits - i - 1;
|
let i_rev = num_bits - i - 1;
|
||||||
@ -93,9 +91,11 @@ mod tests {
|
|||||||
fn test_reverse_index_bits() {
|
fn test_reverse_index_bits() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
reverse_index_bits(vec![10, 20, 30, 40]),
|
reverse_index_bits(vec![10, 20, 30, 40]),
|
||||||
vec![10, 30, 20, 40]);
|
vec![10, 30, 20, 40]
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
reverse_index_bits(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]),
|
reverse_index_bits(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]),
|
||||||
vec![0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]);
|
vec![0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,9 +35,7 @@ impl<F: Field> PartialWitness<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_targets(&self, targets: &[Target]) -> Vec<F> {
|
pub fn get_targets(&self, targets: &[Target]) -> Vec<F> {
|
||||||
targets.iter()
|
targets.iter().map(|&t| self.get_target(t)).collect()
|
||||||
.map(|&t| self.get_target(t))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_get_target(&self, target: Target) -> Option<F> {
|
pub fn try_get_target(&self, target: Target) -> Option<F> {
|
||||||
@ -63,8 +61,11 @@ impl<F: Field> PartialWitness<F> {
|
|||||||
pub fn set_target(&mut self, target: Target, value: F) {
|
pub fn set_target(&mut self, target: Target, value: F) {
|
||||||
let opt_old_value = self.target_values.insert(target, value);
|
let opt_old_value = self.target_values.insert(target, value);
|
||||||
if let Some(old_value) = opt_old_value {
|
if let Some(old_value) = opt_old_value {
|
||||||
assert_eq!(old_value, value,
|
assert_eq!(
|
||||||
"Target was set twice with different values: {:?}", target);
|
old_value, value,
|
||||||
|
"Target was set twice with different values: {:?}",
|
||||||
|
target
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user