mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 06:13: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!("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,24 +17,29 @@ fn main() {
|
||||
const W: usize = 13;
|
||||
const HASHES_PER_POLY: usize = 1 << (13 + LDE_BITS);
|
||||
|
||||
let threads = (0..THREADS).map(|_i| {
|
||||
thread::spawn(move || {
|
||||
let mut x = [F::ZERO; W];
|
||||
for i in 0..W {
|
||||
x[i] = F::from_canonical_u64((i as u64) * 123456 + 789);
|
||||
}
|
||||
let threads = (0..THREADS)
|
||||
.map(|_i| {
|
||||
thread::spawn(move || {
|
||||
let mut x = [F::ZERO; W];
|
||||
for i in 0..W {
|
||||
x[i] = F::from_canonical_u64((i as u64) * 123456 + 789);
|
||||
}
|
||||
|
||||
let hashes_per_thread = HASHES_PER_POLY * PROVER_POLYS / THREADS;
|
||||
let start = Instant::now();
|
||||
for _ in 0..hashes_per_thread {
|
||||
x = gmimc_permute_array::<_, W, GMIMC_ROUNDS>(x, GMIMC_CONSTANTS);
|
||||
}
|
||||
let duration = start.elapsed();
|
||||
println!("took {:?}", duration);
|
||||
println!("avg {:?}us", duration.as_secs_f64() * 1e6 / (hashes_per_thread as f64));
|
||||
println!("result {:?}", x);
|
||||
let hashes_per_thread = HASHES_PER_POLY * PROVER_POLYS / THREADS;
|
||||
let start = Instant::now();
|
||||
for _ in 0..hashes_per_thread {
|
||||
x = gmimc_permute_array::<_, W, GMIMC_ROUNDS>(x, GMIMC_CONSTANTS);
|
||||
}
|
||||
let duration = start.elapsed();
|
||||
println!("took {:?}", duration);
|
||||
println!(
|
||||
"avg {:?}us",
|
||||
duration.as_secs_f64() * 1e6 / (hashes_per_thread as f64)
|
||||
);
|
||||
println!("result {:?}", x);
|
||||
})
|
||||
})
|
||||
}).collect::<Vec<_>>();
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for t in threads {
|
||||
t.join().expect("oops");
|
||||
|
||||
@ -3,14 +3,17 @@ use std::time::Instant;
|
||||
|
||||
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::gates::constant::ConstantGate;
|
||||
use crate::gates::gate::{GateInstance, GateRef};
|
||||
use crate::gates::noop::NoopGate;
|
||||
use crate::generator::{CopyGenerator, WitnessGenerator};
|
||||
use crate::hash::merkle_root_bit_rev_order;
|
||||
use crate::field::cosets::get_unique_coset_shifts;
|
||||
use crate::polynomial::polynomial::PolynomialValues;
|
||||
use crate::target::Target;
|
||||
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...
|
||||
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
|
||||
}
|
||||
|
||||
fn check_gate_compatibility(&self, gate: &GateRef<F>) {
|
||||
assert!(gate.0.num_wires() <= self.config.num_wires,
|
||||
"{:?} requires {} wires, but our GateConfig has only {}",
|
||||
gate.0.id(), gate.0.num_wires(), self.config.num_wires);
|
||||
assert!(
|
||||
gate.0.num_wires() <= self.config.num_wires,
|
||||
"{:?} requires {} wires, but our GateConfig has only {}",
|
||||
gate.0.id(),
|
||||
gate.0.num_wires(),
|
||||
self.config.num_wires
|
||||
);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// Both elements must be routable, otherwise this method will panic.
|
||||
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!(y.is_routable(self.config), "Tried to route a wire that isn't routable");
|
||||
assert!(
|
||||
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.
|
||||
}
|
||||
|
||||
@ -140,7 +156,10 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
/// Returns a routable target with the given constant value.
|
||||
pub fn constant(&mut self, c: F) -> Target {
|
||||
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> {
|
||||
@ -156,11 +175,15 @@ impl<F: Field> CircuitBuilder<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())
|
||||
.max()
|
||||
.unwrap();
|
||||
let constants_per_gate = self.gate_instances.iter()
|
||||
let constants_per_gate = self
|
||||
.gate_instances
|
||||
.iter()
|
||||
.map(|gate_inst| {
|
||||
let mut padded_constants = gate_inst.constants.clone();
|
||||
for _ in padded_constants.len()..num_constants {
|
||||
@ -177,13 +200,17 @@ impl<F: Field> CircuitBuilder<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.
|
||||
pub fn build(mut self) -> CircuitData<F> {
|
||||
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();
|
||||
let degree = self.gate_instances.len();
|
||||
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 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 {};
|
||||
|
||||
// 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<_>>();
|
||||
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())
|
||||
.max()
|
||||
.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.
|
||||
pub fn build_prover(self) -> ProverCircuitData<F> {
|
||||
// TODO: Can skip parts of this.
|
||||
let CircuitData { prover_only, common, .. } = self.build();
|
||||
ProverCircuitData { prover_only, common }
|
||||
let CircuitData {
|
||||
prover_only,
|
||||
common,
|
||||
..
|
||||
} = self.build();
|
||||
ProverCircuitData {
|
||||
prover_only,
|
||||
common,
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a "verifier circuit", with data needed to verify proofs but not generate them.
|
||||
pub fn build_verifier(self) -> VerifierCircuitData<F> {
|
||||
// TODO: Can skip parts of this.
|
||||
let CircuitData { verifier_only, common, .. } = self.build();
|
||||
VerifierCircuitData { verifier_only, common }
|
||||
let CircuitData {
|
||||
verifier_only,
|
||||
common,
|
||||
..
|
||||
} = self.build();
|
||||
VerifierCircuitData {
|
||||
verifier_only,
|
||||
common,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +128,8 @@ impl<F: Field> CommonCircuitData<F> {
|
||||
}
|
||||
|
||||
pub fn constraint_degree(&self) -> usize {
|
||||
self.gates.iter()
|
||||
self.gates
|
||||
.iter()
|
||||
.map(|g| g.0.degree())
|
||||
.max()
|
||||
.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
|
||||
/// `2^subgroup_bits`.
|
||||
pub(crate) fn get_unique_coset_shifts<F: Field>(
|
||||
subgroup_size: usize,
|
||||
num_shifts: usize,
|
||||
) -> Vec<F> {
|
||||
pub(crate) fn get_unique_coset_shifts<F: Field>(subgroup_size: usize, num_shifts: usize) -> Vec<F> {
|
||||
// From Lagrange's theorem.
|
||||
let num_cosets = (F::ORDER - 1) / (subgroup_size as u64);
|
||||
assert!(num_shifts as u64 <= num_cosets,
|
||||
"The subgroup does not have enough distinct cosets");
|
||||
assert!(
|
||||
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.
|
||||
// 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.
|
||||
F::MULTIPLICATIVE_GROUP_GENERATOR.powers()
|
||||
F::MULTIPLICATIVE_GROUP_GENERATOR
|
||||
.powers()
|
||||
.take(num_shifts)
|
||||
.collect()
|
||||
}
|
||||
@ -45,7 +45,8 @@ mod tests {
|
||||
let coset = F::cyclic_subgroup_coset_known_order(generator, shift, subgroup_size);
|
||||
assert!(
|
||||
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::{Debug, Display, Formatter};
|
||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
|
||||
use num::Integer;
|
||||
@ -123,11 +123,7 @@ impl Field for CrandallField {
|
||||
}
|
||||
}
|
||||
|
||||
let inverse = Self(if u == 1 {
|
||||
b
|
||||
} else {
|
||||
c
|
||||
});
|
||||
let inverse = Self(if u == 1 { b } else { c });
|
||||
|
||||
// Should change to debug_assert_eq; using assert_eq as an extra precaution for now until
|
||||
// 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 PolynomialValues { values } = poly;
|
||||
let PolynomialValues { values: mut result } = fft_with_precomputation_power_of_2(
|
||||
PolynomialCoeffs { coeffs: values },
|
||||
precomputation);
|
||||
let PolynomialValues { values: mut result } =
|
||||
fft_with_precomputation_power_of_2(PolynomialCoeffs { coeffs: values }, precomputation);
|
||||
|
||||
// We reverse all values except the first, and divide each by n.
|
||||
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)]
|
||||
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::fft::{fft, ifft};
|
||||
use crate::field::field::Field;
|
||||
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||
use crate::util::{log2_ceil, log2_strict};
|
||||
|
||||
#[test]
|
||||
fn fft_and_ifft() {
|
||||
@ -195,7 +194,9 @@ mod tests {
|
||||
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_pow = log2_strict(degree);
|
||||
|
||||
|
||||
@ -1,28 +1,30 @@
|
||||
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 rand::rngs::OsRng;
|
||||
use rand::Rng;
|
||||
use std::fmt::{Debug, Display};
|
||||
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.
|
||||
pub trait Field: 'static
|
||||
+ Copy
|
||||
+ Eq
|
||||
+ Hash
|
||||
+ Neg<Output=Self>
|
||||
+ Add<Self, Output=Self>
|
||||
+ AddAssign<Self>
|
||||
+ Sub<Self, Output=Self>
|
||||
+ SubAssign<Self>
|
||||
+ Mul<Self, Output=Self>
|
||||
+ MulAssign<Self>
|
||||
+ Div<Self, Output=Self>
|
||||
+ DivAssign<Self>
|
||||
+ Debug
|
||||
+ Display
|
||||
+ Send
|
||||
+ Sync {
|
||||
pub trait Field:
|
||||
'static
|
||||
+ Copy
|
||||
+ Eq
|
||||
+ Hash
|
||||
+ Neg<Output = Self>
|
||||
+ Add<Self, Output = Self>
|
||||
+ AddAssign<Self>
|
||||
+ Sub<Self, Output = Self>
|
||||
+ SubAssign<Self>
|
||||
+ Mul<Self, Output = Self>
|
||||
+ MulAssign<Self>
|
||||
+ Div<Self, Output = Self>
|
||||
+ DivAssign<Self>
|
||||
+ Debug
|
||||
+ Display
|
||||
+ Send
|
||||
+ Sync
|
||||
{
|
||||
const ZERO: Self;
|
||||
const ONE: Self;
|
||||
const TWO: Self;
|
||||
@ -92,7 +94,9 @@ pub trait Field: 'static
|
||||
assert!(n_power <= Self::TWO_ADICITY);
|
||||
let base = Self::POWER_OF_TWO_GENERATOR;
|
||||
// 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.
|
||||
@ -109,9 +113,7 @@ pub trait Field: 'static
|
||||
/// 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> {
|
||||
let subgroup = Self::cyclic_subgroup_known_order(generator, order);
|
||||
subgroup.into_iter()
|
||||
.map(|x| x * shift)
|
||||
.collect()
|
||||
subgroup.into_iter().map(|x| x * shift).collect()
|
||||
}
|
||||
|
||||
fn to_canonical_u64(&self) -> u64;
|
||||
@ -144,7 +146,10 @@ pub trait Field: 'static
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@ -55,7 +55,6 @@ pub fn test_inputs(modulus: u64, word_bits: usize) -> Vec<u64> {
|
||||
// .collect()
|
||||
}
|
||||
|
||||
|
||||
/// Apply the unary functions `op` and `expected_op`
|
||||
/// coordinate-wise to the inputs from `test_inputs(modulus,
|
||||
/// 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,
|
||||
{
|
||||
let inputs = test_inputs(modulus, word_bits);
|
||||
let expected: Vec<_> = inputs.iter()
|
||||
.map(|&x| expected_op(x))
|
||||
.collect();
|
||||
let expected: Vec<_> = inputs.iter().map(|&x| expected_op(x)).collect();
|
||||
let output: Vec<_> = inputs
|
||||
.iter()
|
||||
.map(|&x| op(F::from_canonical_u64(x)).to_canonical_u64())
|
||||
.collect();
|
||||
// Compare expected outputs with actual outputs
|
||||
for i in 0..inputs.len() {
|
||||
assert_eq!(output[i], expected[i],
|
||||
"Expected {}, got {} for input {}",
|
||||
expected[i], output[i], inputs[i]);
|
||||
assert_eq!(
|
||||
output[i], expected[i],
|
||||
"Expected {}, got {} for input {}",
|
||||
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
|
||||
// cycle().skip(i) rotates left by i, we need to rotate by
|
||||
// n_input_elts - i.
|
||||
let shifted_inputs: Vec<_> = inputs.iter()
|
||||
let shifted_inputs: Vec<_> = inputs
|
||||
.iter()
|
||||
.cycle()
|
||||
.skip(inputs.len() - i)
|
||||
.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()))
|
||||
.collect();
|
||||
|
||||
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()
|
||||
}).collect();
|
||||
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()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Compare expected outputs with actual outputs
|
||||
for i in 0..inputs.len() {
|
||||
assert_eq!(output[i], expected[i],
|
||||
"On inputs {} . {}, expected {} but got {}",
|
||||
inputs[i], shifted_inputs[i], expected[i], output[i]);
|
||||
assert_eq!(
|
||||
output[i], expected[i],
|
||||
"On inputs {} . {}, expected {} but got {}",
|
||||
inputs[i], shifted_inputs[i], expected[i], output[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -146,57 +152,77 @@ macro_rules! test_arithmetic {
|
||||
#[test]
|
||||
fn arithmetic_addition() {
|
||||
let modulus = <$field>::ORDER;
|
||||
crate::field::field_testing::run_binaryop_test_cases(modulus, WORD_BITS, <$field>::add, |x, y| {
|
||||
let (z, over) = x.overflowing_add(y);
|
||||
if over {
|
||||
z.overflowing_sub(modulus).0
|
||||
} else if z >= modulus {
|
||||
z - modulus
|
||||
} else {
|
||||
z
|
||||
}
|
||||
})
|
||||
crate::field::field_testing::run_binaryop_test_cases(
|
||||
modulus,
|
||||
WORD_BITS,
|
||||
<$field>::add,
|
||||
|x, y| {
|
||||
let (z, over) = x.overflowing_add(y);
|
||||
if over {
|
||||
z.overflowing_sub(modulus).0
|
||||
} else if z >= modulus {
|
||||
z - modulus
|
||||
} else {
|
||||
z
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithmetic_subtraction() {
|
||||
let modulus = <$field>::ORDER;
|
||||
crate::field::field_testing::run_binaryop_test_cases(modulus, WORD_BITS, <$field>::sub, |x, y| {
|
||||
if x >= y {
|
||||
x - y
|
||||
} else {
|
||||
&modulus - y + x
|
||||
}
|
||||
})
|
||||
crate::field::field_testing::run_binaryop_test_cases(
|
||||
modulus,
|
||||
WORD_BITS,
|
||||
<$field>::sub,
|
||||
|x, y| {
|
||||
if x >= y {
|
||||
x - y
|
||||
} else {
|
||||
&modulus - y + x
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithmetic_negation() {
|
||||
let modulus = <$field>::ORDER;
|
||||
crate::field::field_testing::run_unaryop_test_cases(modulus, WORD_BITS, <$field>::neg, |x| {
|
||||
if x == 0 {
|
||||
0
|
||||
} else {
|
||||
modulus - x
|
||||
}
|
||||
})
|
||||
crate::field::field_testing::run_unaryop_test_cases(
|
||||
modulus,
|
||||
WORD_BITS,
|
||||
<$field>::neg,
|
||||
|x| {
|
||||
if x == 0 {
|
||||
0
|
||||
} else {
|
||||
modulus - x
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithmetic_multiplication() {
|
||||
let modulus = <$field>::ORDER;
|
||||
crate::field::field_testing::run_binaryop_test_cases(modulus, WORD_BITS, <$field>::mul, |x, y| {
|
||||
((x as u128) * (y as u128) % (modulus as u128)) as u64
|
||||
})
|
||||
crate::field::field_testing::run_binaryop_test_cases(
|
||||
modulus,
|
||||
WORD_BITS,
|
||||
<$field>::mul,
|
||||
|x, y| ((x as u128) * (y as u128) % (modulus as u128)) as u64,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arithmetic_square() {
|
||||
let modulus = <$field>::ORDER;
|
||||
crate::field::field_testing::run_unaryop_test_cases(
|
||||
modulus, WORD_BITS,
|
||||
modulus,
|
||||
WORD_BITS,
|
||||
|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]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
pub mod crandall_field;
|
||||
pub mod field;
|
||||
pub mod fft;
|
||||
pub(crate) mod cosets;
|
||||
pub mod crandall_field;
|
||||
pub mod fft;
|
||||
pub mod field;
|
||||
|
||||
#[cfg(test)]
|
||||
mod field_testing;
|
||||
|
||||
212
src/fri.rs
212
src/fri.rs
@ -1,10 +1,13 @@
|
||||
use crate::field::fft::fft;
|
||||
use crate::field::field::Field;
|
||||
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::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||
use crate::proof::{Hash, FriProof};
|
||||
use crate::field::fft::fft;
|
||||
use crate::gadgets::merkle_proofs::MerkleTree;
|
||||
use crate::proof::{FriEvaluations, FriMerkleProofs, FriProof, FriQueryRound, Hash};
|
||||
use crate::util::log2_strict;
|
||||
use std::cmp::min;
|
||||
|
||||
/// Somewhat arbitrary. Smaller values will increase delta, but with diminishing returns,
|
||||
/// 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)`.
|
||||
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 {
|
||||
@ -50,20 +54,24 @@ fn fri_l(codeword_len: usize, rate_log: usize, conjecture: bool) -> f64 {
|
||||
}
|
||||
|
||||
// TODO: Different arity + PoW.
|
||||
/// Performs a FRI round.
|
||||
fn fri_round<F: Field>(
|
||||
/// Builds a FRI proof.
|
||||
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>,
|
||||
// Evaluation of the polynomial on the large domain.
|
||||
polynomial_values: &PolynomialValues<F>,
|
||||
challenger: &mut Challenger<F>,
|
||||
config: &FriConfig,
|
||||
) -> FriProof<F> {
|
||||
let n = polynomial_values.values.len();
|
||||
assert_eq!(
|
||||
polynomial_coeffs.coeffs.len(),
|
||||
n
|
||||
);
|
||||
let mut trees = vec![MerkleTree::new(polynomial_values.values.iter().map(|&v| vec![v]).collect())];
|
||||
let mut root = trees.last().unwrap().root;
|
||||
assert_eq!(polynomial_coeffs.coeffs.len(), n);
|
||||
|
||||
let mut trees = vec![MerkleTree::new(
|
||||
polynomial_values.values.iter().map(|&v| vec![v]).collect(),
|
||||
true,
|
||||
)];
|
||||
let mut root = trees[0].root;
|
||||
let mut coeffs = polynomial_coeffs.clone();
|
||||
let mut values;
|
||||
|
||||
@ -72,6 +80,7 @@ fn fri_round<F: Field>(
|
||||
// Commit phase
|
||||
for _ in 0..config.reduction_count {
|
||||
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
|
||||
.coeffs
|
||||
@ -79,30 +88,185 @@ fn fri_round<F: Field>(
|
||||
.map(|chunk| chunk[0] + beta * chunk[1])
|
||||
.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);
|
||||
trees.push(tree);
|
||||
}
|
||||
|
||||
// Query phase
|
||||
let mut merkle_proofs = Vec::new();
|
||||
let mut evals = Vec::new();
|
||||
for i in 0..config.reduction_count {
|
||||
let mut query_round_proofs = Vec::new();
|
||||
for _ in 0..config.num_query_rounds {
|
||||
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_index = (x.to_canonical_u64() as usize) % n;
|
||||
let n2 = n>>1;
|
||||
evals.extend(std::array::IntoIter::new([polynomial_values.values[x_index], polynomial_values.values[n2 + x_index]]));
|
||||
merkle_proofs.extend(std::array::IntoIter::new([trees[i].prove(x_index), trees[i].prove(n2 + x_index)]));
|
||||
let mut domain_size = n;
|
||||
let mut x_index = x.to_canonical_u64() as usize;
|
||||
for i in 0..config.reduction_count {
|
||||
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 {
|
||||
commit_phase_merkle_roots: trees.iter().map(|t| t.root).collect(),
|
||||
initial_merkle_proofs: vec![],
|
||||
intermediate_merkle_proofs: merkle_proofs,
|
||||
final_poly: coeffs
|
||||
query_round_proofs,
|
||||
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::field::field::Field;
|
||||
use crate::target::Target;
|
||||
use crate::gates::arithmetic::ArithmeticGate;
|
||||
use crate::target::Target;
|
||||
use crate::wire::Wire;
|
||||
|
||||
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 wire_multiplicand_0 = Wire { gate, input: ArithmeticGate::WIRE_MULTIPLICAND_0 };
|
||||
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 };
|
||||
let wire_multiplicand_0 = Wire {
|
||||
gate,
|
||||
input: ArithmeticGate::WIRE_MULTIPLICAND_0,
|
||||
};
|
||||
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(one, Target::Wire(wire_multiplicand_1));
|
||||
|
||||
@ -11,31 +11,44 @@ use crate::wire::Wire;
|
||||
impl<F: Field> CircuitBuilder<F> {
|
||||
pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] {
|
||||
let zero = self.zero();
|
||||
let gate = self.add_gate_no_constants(
|
||||
GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants());
|
||||
let gate =
|
||||
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.
|
||||
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);
|
||||
|
||||
// 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.
|
||||
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);
|
||||
|
||||
// Route input wires.
|
||||
for i in 0..12 {
|
||||
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);
|
||||
}
|
||||
|
||||
// Collect output wires.
|
||||
(0..12)
|
||||
.map(|i| Target::Wire(
|
||||
Wire { gate, input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i) }))
|
||||
.map(|i| {
|
||||
Target::Wire(Wire {
|
||||
gate,
|
||||
input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i),
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::field::field::Field;
|
||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||
use crate::target::Target;
|
||||
use crate::wire::Wire;
|
||||
use crate::witness::PartialWitness;
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
|
||||
impl<F: Field> CircuitBuilder<F> {
|
||||
/// 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
|
||||
/// is correct. The output should be treated as a "purported" decomposition which must be
|
||||
/// enforced elsewhere.
|
||||
pub(crate) fn split_le_virtual(
|
||||
&mut self,
|
||||
integer: Target,
|
||||
num_bits: usize,
|
||||
) -> Vec<Target> {
|
||||
pub(crate) fn split_le_virtual(&mut self, integer: Target, num_bits: usize) -> Vec<Target> {
|
||||
let bit_targets = self.add_virtual_advice_targets(num_bits);
|
||||
split_le_generator::<F>(integer, bit_targets.clone());
|
||||
bit_targets
|
||||
@ -37,9 +33,12 @@ pub fn split_le_generator_local_wires<F: Field>(
|
||||
integer_input_index: usize,
|
||||
bit_input_indices: &[usize],
|
||||
) -> Box<dyn WitnessGenerator<F>> {
|
||||
let integer = Target::Wire(
|
||||
Wire { gate, input: integer_input_index });
|
||||
let bits = bit_input_indices.iter()
|
||||
let integer = Target::Wire(Wire {
|
||||
gate,
|
||||
input: integer_input_index,
|
||||
});
|
||||
let bits = bit_input_indices
|
||||
.iter()
|
||||
.map(|&input| Target::Wire(Wire { gate, input }))
|
||||
.collect();
|
||||
Box::new(SplitGenerator { integer, bits })
|
||||
@ -66,8 +65,10 @@ impl<F: Field> SimpleGenerator<F> for SplitGenerator {
|
||||
integer_value >>= 1;
|
||||
}
|
||||
|
||||
debug_assert_eq!(integer_value, 0,
|
||||
"Integer too large to fit in given number of bits");
|
||||
debug_assert_eq!(
|
||||
integer_value, 0,
|
||||
"Integer too large to fit in given number of bits"
|
||||
);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::{Gate, GateRef};
|
||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||
use crate::target::Target;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::wire::Wire;
|
||||
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 addend = witness.get_wire(addend_target);
|
||||
|
||||
let output = self.const_0 * multiplicand_0 * multiplicand_1
|
||||
+ self.const_1 * addend;
|
||||
let output = self.const_0 * multiplicand_0 * multiplicand_1 + self.const_1 * addend;
|
||||
|
||||
PartialWitness::singleton_wire(output_target, output)
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::{Gate, GateRef};
|
||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||
use crate::target::Target;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::wire::Wire;
|
||||
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> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,10 +2,10 @@ use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::field::field::Field;
|
||||
use crate::generator::WitnessGenerator;
|
||||
use crate::target::Target;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
|
||||
/// A custom gate.
|
||||
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_INDEX_ACCUMULATOR_OLD);
|
||||
|
||||
dep_input_indices.into_iter()
|
||||
.map(|input| Target::Wire(Wire { gate: self.gate_index, input }))
|
||||
dep_input_indices
|
||||
.into_iter()
|
||||
.map(|input| {
|
||||
Target::Wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input,
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -177,10 +183,12 @@ impl<F: Field, const R: usize> SimpleGenerator<F> for GMiMCGenerator<F, R> {
|
||||
let mut result = PartialWitness::new();
|
||||
|
||||
let mut state = (0..W)
|
||||
.map(|i| witness.get_wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input: GMiMCGate::<F, R>::wire_input(i),
|
||||
}))
|
||||
.map(|i| {
|
||||
witness.get_wire(Wire {
|
||||
gate: self.gate_index,
|
||||
input: GMiMCGate::<F, R>::wire_input(i),
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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,
|
||||
input: GMiMCGate::<F, R>::WIRE_INDEX_ACCUMULATOR_NEW,
|
||||
},
|
||||
new_index_acc_value);
|
||||
new_index_acc_value,
|
||||
);
|
||||
|
||||
// Value that is implicitly added to each element.
|
||||
// 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,
|
||||
input: GMiMCGate::<F, R>::wire_cubing_input(r),
|
||||
},
|
||||
cubing_input);
|
||||
cubing_input,
|
||||
);
|
||||
let f = cubing_input.cube();
|
||||
addition_buffer += f;
|
||||
state[active] -= f;
|
||||
@ -232,7 +242,8 @@ impl<F: Field, const R: usize> SimpleGenerator<F> for GMiMCGenerator<F, R> {
|
||||
gate: self.gate_index,
|
||||
input: GMiMCGate::<F, R>::wire_output(i),
|
||||
},
|
||||
state[i]);
|
||||
state[i],
|
||||
);
|
||||
}
|
||||
|
||||
result
|
||||
@ -258,7 +269,7 @@ mod tests {
|
||||
type F = CrandallField;
|
||||
const R: usize = 101;
|
||||
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 config = CircuitConfig {
|
||||
@ -267,38 +278,51 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let permutation_inputs = (0..W)
|
||||
.map(F::from_canonical_usize)
|
||||
.collect::<Vec<_>>();
|
||||
let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::<Vec<_>>();
|
||||
|
||||
let mut witness = PartialWitness::new();
|
||||
witness.set_wire(
|
||||
Wire { gate: 0, input: Gate::WIRE_INDEX_ACCUMULATOR_OLD },
|
||||
F::from_canonical_usize(7));
|
||||
Wire {
|
||||
gate: 0,
|
||||
input: Gate::WIRE_INDEX_ACCUMULATOR_OLD,
|
||||
},
|
||||
F::from_canonical_usize(7),
|
||||
);
|
||||
witness.set_wire(
|
||||
Wire { gate: 0, input: Gate::WIRE_SWAP },
|
||||
F::ZERO);
|
||||
Wire {
|
||||
gate: 0,
|
||||
input: Gate::WIRE_SWAP,
|
||||
},
|
||||
F::ZERO,
|
||||
);
|
||||
for i in 0..W {
|
||||
witness.set_wire(
|
||||
Wire { gate: 0, input: Gate::wire_input(i) },
|
||||
permutation_inputs[i]);
|
||||
Wire {
|
||||
gate: 0,
|
||||
input: Gate::wire_input(i),
|
||||
},
|
||||
permutation_inputs[i],
|
||||
);
|
||||
}
|
||||
|
||||
let generators = gate.0.generators(0, &[], &[]);
|
||||
generate_partial_witness(&mut witness, &generators);
|
||||
|
||||
let expected_outputs: [F; W] = gmimc_permute_naive(
|
||||
permutation_inputs.try_into().unwrap(),
|
||||
constants);
|
||||
let expected_outputs: [F; W] =
|
||||
gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants);
|
||||
|
||||
for i in 0..W {
|
||||
let out = witness.get_wire(
|
||||
Wire { gate: 0, input: Gate::wire_output(i) });
|
||||
let out = witness.get_wire(Wire {
|
||||
gate: 0,
|
||||
input: Gate::wire_output(i),
|
||||
});
|
||||
assert_eq!(out, expected_outputs[i]);
|
||||
}
|
||||
|
||||
let acc_new = witness.get_wire(
|
||||
Wire { gate: 0, input: Gate::WIRE_INDEX_ACCUMULATOR_NEW });
|
||||
let acc_new = witness.get_wire(Wire {
|
||||
gate: 0,
|
||||
input: Gate::WIRE_INDEX_ACCUMULATOR_NEW,
|
||||
});
|
||||
assert_eq!(acc_new, F::from_canonical_usize(7 * 2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::{Gate, GateRef};
|
||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||
use crate::target::Target;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::witness::PartialWitness;
|
||||
|
||||
/// 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::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::{Gate, GateRef};
|
||||
use crate::generator::WitnessGenerator;
|
||||
use crate::target::Target;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
|
||||
/// A gate which takes a single constant parameter and outputs that value.
|
||||
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
|
||||
}
|
||||
|
||||
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.
|
||||
let state_0 = [a[0], a[1], a[2], a[3], b[0],
|
||||
b[1], b[2], b[3],
|
||||
F::ZERO, F::ZERO, F::ZERO, F::ZERO];
|
||||
let state_0 = [
|
||||
a[0],
|
||||
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());
|
||||
[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 crate::circuit_builder::CircuitBuilder;
|
||||
use crate::field::field::Field;
|
||||
use crate::gmimc::gmimc_permute_array;
|
||||
use crate::proof::{Hash, HashTarget};
|
||||
use crate::util::reverse_index_bits_in_place;
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::target::Target;
|
||||
use crate::util::reverse_index_bits_in_place;
|
||||
|
||||
pub(crate) const SPONGE_RATE: usize = 8;
|
||||
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;
|
||||
/// 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
|
||||
/// 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> {
|
||||
let elems_per_leaf = vecs[0].len();
|
||||
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())
|
||||
.collect();
|
||||
merkle_root_inner(subtree_roots)
|
||||
}
|
||||
|
||||
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))
|
||||
.collect::<Vec<_>>();
|
||||
while hashes.len() > 1 {
|
||||
hashes = hashes.chunks(2)
|
||||
hashes = hashes
|
||||
.chunks(2)
|
||||
.map(|pair| compress(pair[0], pair[1]))
|
||||
.collect();
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
pub mod circuit_builder;
|
||||
pub mod circuit_data;
|
||||
pub mod vars;
|
||||
pub mod field;
|
||||
pub mod fri;
|
||||
pub mod gadgets;
|
||||
@ -9,6 +8,7 @@ pub mod generator;
|
||||
pub mod gmimc;
|
||||
pub mod hash;
|
||||
pub mod merkle_proofs;
|
||||
mod merkle_tree;
|
||||
pub mod plonk_challenger;
|
||||
pub mod plonk_common;
|
||||
pub mod polynomial;
|
||||
@ -18,6 +18,7 @@ pub mod recursive_verifier;
|
||||
pub mod rescue;
|
||||
pub mod target;
|
||||
pub mod util;
|
||||
pub mod vars;
|
||||
pub mod verifier;
|
||||
pub mod wire;
|
||||
pub mod witness;
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gmimc::GMiMCGate;
|
||||
use crate::hash::{compress, hash_or_noop};
|
||||
use crate::hash::GMIMC_ROUNDS;
|
||||
use crate::hash::{compress, hash_or_noop};
|
||||
use crate::proof::{Hash, HashTarget};
|
||||
use crate::target::Target;
|
||||
use crate::util::reverse_index_bits;
|
||||
use crate::wire::Wire;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MerkleProof<F: Field> {
|
||||
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
|
||||
pub siblings: Vec<Hash<F>>,
|
||||
@ -23,18 +25,24 @@ pub(crate) fn verify_merkle_proof<F: Field>(
|
||||
leaf_data: Vec<F>,
|
||||
leaf_index: usize,
|
||||
merkle_root: Hash<F>,
|
||||
proof: MerkleProof<F>,
|
||||
) -> bool {
|
||||
proof: &MerkleProof<F>,
|
||||
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);
|
||||
for (i, sibling_digest) in proof.siblings.into_iter().enumerate() {
|
||||
let bit = (leaf_index >> i & 1) == 1;
|
||||
for (i, &sibling_digest) in proof.siblings.iter().enumerate() {
|
||||
let bit = (index >> i & 1) == 1;
|
||||
current_digest = if bit {
|
||||
compress(sibling_digest, current_digest)
|
||||
} else {
|
||||
compress(current_digest, sibling_digest)
|
||||
}
|
||||
}
|
||||
current_digest == merkle_root
|
||||
(current_digest == merkle_root).then(|| ())
|
||||
}
|
||||
|
||||
impl<F: Field> CircuitBuilder<F> {
|
||||
@ -55,24 +63,37 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
let mut acc_leaf_index = zero;
|
||||
|
||||
for (bit, sibling) in purported_index_bits.into_iter().zip(proof.siblings) {
|
||||
let gate = self.add_gate_no_constants(
|
||||
GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants());
|
||||
let gate = self
|
||||
.add_gate_no_constants(GMiMCGate::<F, GMIMC_ROUNDS>::with_automatic_constants());
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
let input_wires = (0..12)
|
||||
.map(|i| Target::Wire(
|
||||
Wire { gate, input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_input(i) }))
|
||||
.map(|i| {
|
||||
Target::Wire(Wire {
|
||||
gate,
|
||||
input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_input(i),
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for i in 0..4 {
|
||||
@ -81,10 +102,16 @@ impl<F: Field> CircuitBuilder<F> {
|
||||
self.route(zero, input_wires[8 + i]);
|
||||
}
|
||||
|
||||
state = HashTarget::from_vec((0..4)
|
||||
.map(|i| Target::Wire(
|
||||
Wire { gate, input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i) }))
|
||||
.collect())
|
||||
state = HashTarget::from_vec(
|
||||
(0..4)
|
||||
.map(|i| {
|
||||
Target::Wire(Wire {
|
||||
gate,
|
||||
input: GMiMCGate::<F, GMIMC_ROUNDS>::wire_output(i),
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
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::field::field::Field;
|
||||
use crate::hash::{permute, SPONGE_WIDTH, SPONGE_RATE};
|
||||
use crate::target::Target;
|
||||
use crate::hash::{permute, SPONGE_RATE, SPONGE_WIDTH};
|
||||
use crate::proof::{Hash, HashTarget};
|
||||
use crate::target::Target;
|
||||
|
||||
/// Observes prover messages, and generates challenges by hashing the transcript.
|
||||
#[derive(Clone)]
|
||||
@ -130,10 +130,7 @@ impl RecursiveChallenger {
|
||||
self.observe_elements(&hash.elements)
|
||||
}
|
||||
|
||||
pub(crate) fn get_challenge<F: Field>(
|
||||
&mut self,
|
||||
builder: &mut CircuitBuilder<F>,
|
||||
) -> Target {
|
||||
pub(crate) fn get_challenge<F: Field>(&mut self, builder: &mut CircuitBuilder<F>) -> Target {
|
||||
self.absorb_buffered_inputs(builder);
|
||||
|
||||
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.
|
||||
fn absorb_buffered_inputs<F: Field>(
|
||||
&mut self,
|
||||
builder: &mut CircuitBuilder<F>,
|
||||
) {
|
||||
fn absorb_buffered_inputs<F: Field>(&mut self, builder: &mut CircuitBuilder<F>) {
|
||||
for input_chunk in self.input_buffer.chunks(SPONGE_RATE) {
|
||||
// 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,
|
||||
@ -198,14 +192,14 @@ impl RecursiveChallenger {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::circuit_data::CircuitConfig;
|
||||
use crate::field::crandall_field::CrandallField;
|
||||
use crate::field::field::Field;
|
||||
use crate::generator::generate_partial_witness;
|
||||
use crate::plonk_challenger::{Challenger, RecursiveChallenger};
|
||||
use crate::target::Target;
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::witness::PartialWitness;
|
||||
use crate::field::field::Field;
|
||||
|
||||
/// Tests for consistency between `Challenger` and `RecursiveChallenger`.
|
||||
#[test]
|
||||
@ -237,8 +231,7 @@ mod tests {
|
||||
};
|
||||
let mut builder = CircuitBuilder::<F>::new(config);
|
||||
let mut recursive_challenger = RecursiveChallenger::new(&mut builder);
|
||||
let mut recursive_outputs_per_round: Vec<Vec<Target>> =
|
||||
Vec::new();
|
||||
let mut recursive_outputs_per_round: Vec<Vec<Target>> = Vec::new();
|
||||
for (r, inputs) in inputs_per_round.iter().enumerate() {
|
||||
recursive_challenger.observe_elements(&builder.constants(inputs));
|
||||
recursive_outputs_per_round.push(
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use crate::circuit_builder::CircuitBuilder;
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::GateRef;
|
||||
use crate::target::Target;
|
||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||
use crate::gates::gate::GateRef;
|
||||
|
||||
/// Evaluates all gate constraints.
|
||||
///
|
||||
@ -18,8 +18,10 @@ pub fn evaluate_gate_constraints<F: Field>(
|
||||
for gate in gates {
|
||||
let gate_constraints = gate.0.eval_filtered(vars);
|
||||
for (i, c) in gate_constraints.into_iter().enumerate() {
|
||||
debug_assert!(i < num_gate_constraints,
|
||||
"num_constraints() gave too low of a number");
|
||||
debug_assert!(
|
||||
i < num_gate_constraints,
|
||||
"num_constraints() gave too low of a number"
|
||||
);
|
||||
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.
|
||||
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))
|
||||
.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);
|
||||
// Divide every element of `a_eval` by the corresponding denominator.
|
||||
// Then, `a_eval` is the evaluation of `a/Z_H` on `{g.w^i}`.
|
||||
a_eval.values
|
||||
a_eval
|
||||
.values
|
||||
.iter_mut()
|
||||
.zip(denominators_inv.iter())
|
||||
.for_each(|(x, &d)| {
|
||||
|
||||
@ -26,13 +26,8 @@ impl<F: Field> PolynomialValues<F> {
|
||||
self.values.len()
|
||||
}
|
||||
|
||||
pub fn lde_multiple(
|
||||
polys: Vec<Self>,
|
||||
rate_bits: usize,
|
||||
) -> Vec<Self> {
|
||||
polys.into_iter()
|
||||
.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 fn lde(self, rate_bits: usize) -> Self {
|
||||
@ -82,13 +77,15 @@ impl<F: Field> PolynomialCoeffs<F> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn lde_multiple(
|
||||
polys: Vec<Self>,
|
||||
rate_bits: usize,
|
||||
) -> Vec<Self> {
|
||||
polys.into_iter()
|
||||
.map(|p| p.lde(rate_bits))
|
||||
.collect()
|
||||
pub fn eval(&self, x: F) -> F {
|
||||
self.coeffs
|
||||
.iter()
|
||||
.rev()
|
||||
.fold(F::ZERO, |acc, &c| acc * x + c)
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
41
src/proof.rs
41
src/proof.rs
@ -1,6 +1,7 @@
|
||||
use crate::field::field::Field;
|
||||
use crate::merkle_proofs::{MerkleProof, MerkleProofTarget};
|
||||
use crate::polynomial::polynomial::PolynomialCoeffs;
|
||||
use crate::target::Target;
|
||||
use crate::merkle_proofs::{MerkleProofTarget, MerkleProof};
|
||||
use std::convert::TryInto;
|
||||
|
||||
/// Represents a ~256 bit hash output.
|
||||
@ -12,7 +13,9 @@ pub struct Hash<F: Field> {
|
||||
impl<F: Field> Hash<F> {
|
||||
pub(crate) fn from_vec(elements: Vec<F>) -> Self {
|
||||
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 {
|
||||
@ -20,7 +23,9 @@ impl<F: Field> Hash<F> {
|
||||
while elements.len() < 4 {
|
||||
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 {
|
||||
pub(crate) fn from_vec(elements: Vec<Target>) -> Self {
|
||||
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 {
|
||||
@ -40,7 +47,9 @@ impl HashTarget {
|
||||
while elements.len() < 4 {
|
||||
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>,
|
||||
}
|
||||
|
||||
// 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> {
|
||||
/// A Merkle root for each reduced polynomial in the commit phase.
|
||||
pub commit_phase_merkle_roots: Vec<Hash<F>>,
|
||||
/// Merkle proofs for the original purported codewords, i.e. the subject of the LDT.
|
||||
pub initial_merkle_proofs: Vec<MerkleProof<F>>,
|
||||
/// Merkle proofs for the reduced polynomials that were sent in the commit phase.
|
||||
pub intermediate_merkle_proofs: Vec<MerkleProof<F>>,
|
||||
/// Query rounds proofs
|
||||
pub query_round_proofs: Vec<FriQueryRound<F>>,
|
||||
/// The final polynomial in coefficient form.
|
||||
pub final_poly: PolynomialCoeffs<F>,
|
||||
}
|
||||
|
||||
141
src/prover.rs
141
src/prover.rs
@ -4,17 +4,17 @@ use log::info;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
|
||||
use crate::vars::EvaluationVars;
|
||||
use crate::field::fft::{fft, ifft};
|
||||
use crate::field::field::Field;
|
||||
use crate::generator::generate_partial_witness;
|
||||
use crate::hash::merkle_root_bit_rev_order;
|
||||
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::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||
use crate::proof::Proof;
|
||||
use crate::util::{transpose, transpose_poly_values};
|
||||
use crate::vars::EvaluationVars;
|
||||
use crate::wire::Wire;
|
||||
use crate::witness::PartialWitness;
|
||||
|
||||
@ -29,8 +29,10 @@ pub(crate) fn prove<F: Field>(
|
||||
let mut witness = inputs;
|
||||
info!("Running {} generators", prover_data.generators.len());
|
||||
generate_partial_witness(&mut witness, &prover_data.generators);
|
||||
info!("{:.3}s to generate witness",
|
||||
start_witness.elapsed().as_secs_f32());
|
||||
info!(
|
||||
"{:.3}s to generate witness",
|
||||
start_witness.elapsed().as_secs_f32()
|
||||
);
|
||||
|
||||
let config = common_data.config;
|
||||
let num_wires = config.num_wires;
|
||||
@ -43,21 +45,27 @@ pub(crate) fn prove<F: Field>(
|
||||
.into_par_iter()
|
||||
.map(|i| compute_wire_lde(i, &witness, degree, config.rate_bits))
|
||||
.collect::<Vec<_>>();
|
||||
info!("{:.3}s to compute wire LDEs",
|
||||
start_wire_ldes.elapsed().as_secs_f32());
|
||||
info!(
|
||||
"{:.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
|
||||
// merkle_root_bit_rev_order do it implicitly.
|
||||
let start_wire_transpose = Instant::now();
|
||||
let wire_ldes_t = transpose_poly_values(wire_ldes);
|
||||
info!("{:.3}s to transpose wire LDEs",
|
||||
start_wire_transpose.elapsed().as_secs_f32());
|
||||
info!(
|
||||
"{:.3}s to transpose wire LDEs",
|
||||
start_wire_transpose.elapsed().as_secs_f32()
|
||||
);
|
||||
|
||||
// TODO: Could avoid cloning if it's significant?
|
||||
let start_wires_root = Instant::now();
|
||||
let wires_root = merkle_root_bit_rev_order(wire_ldes_t.clone());
|
||||
info!("{:.3}s to Merklize wire LDEs",
|
||||
start_wires_root.elapsed().as_secs_f32());
|
||||
info!(
|
||||
"{:.3}s to Merklize wire LDEs",
|
||||
start_wires_root.elapsed().as_secs_f32()
|
||||
);
|
||||
|
||||
let mut challenger = Challenger::new();
|
||||
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_ldes = PolynomialValues::lde_multiple(plonk_z_vecs, config.rate_bits);
|
||||
let plonk_z_ldes_t = transpose_poly_values(plonk_z_ldes);
|
||||
info!("{:.3}s to compute Z's and their LDEs",
|
||||
start_plonk_z.elapsed().as_secs_f32());
|
||||
info!(
|
||||
"{:.3}s to compute Z's and their LDEs",
|
||||
start_plonk_z.elapsed().as_secs_f32()
|
||||
);
|
||||
|
||||
let start_plonk_z_root = Instant::now();
|
||||
let plonk_zs_root = merkle_root_bit_rev_order(plonk_z_ldes_t.clone());
|
||||
info!("{:.3}s to Merklize Z's",
|
||||
start_plonk_z_root.elapsed().as_secs_f32());
|
||||
info!(
|
||||
"{:.3}s to Merklize Z's",
|
||||
start_plonk_z_root.elapsed().as_secs_f32()
|
||||
);
|
||||
|
||||
challenger.observe_hash(&plonk_zs_root);
|
||||
|
||||
@ -86,9 +98,18 @@ pub(crate) fn prove<F: Field>(
|
||||
|
||||
let start_vanishing_polys = Instant::now();
|
||||
let vanishing_polys = compute_vanishing_polys(
|
||||
common_data, prover_data, wire_ldes_t, plonk_z_ldes_t, beta, gamma, &alphas);
|
||||
info!("{:.3}s to compute vanishing polys",
|
||||
start_vanishing_polys.elapsed().as_secs_f32());
|
||||
common_data,
|
||||
prover_data,
|
||||
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.
|
||||
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);
|
||||
// Split t into degree-n chunks.
|
||||
let quotient_poly_coeff_chunks = quotient_poly_coeff.chunks(degree);
|
||||
let quotient_poly_coeff_ldes = PolynomialCoeffs::lde_multiple(
|
||||
quotient_poly_coeff_chunks, config.rate_bits);
|
||||
let quotient_poly_coeff_ldes =
|
||||
PolynomialCoeffs::lde_multiple(quotient_poly_coeff_chunks, config.rate_bits);
|
||||
let quotient_poly_chunk_ldes: Vec<PolynomialValues<F>> =
|
||||
quotient_poly_coeff_ldes.into_par_iter().map(fft).collect();
|
||||
all_quotient_poly_chunk_ldes.extend(quotient_poly_chunk_ldes);
|
||||
}
|
||||
let quotient_polys_root = merkle_root_bit_rev_order(
|
||||
transpose_poly_values(all_quotient_poly_chunk_ldes));
|
||||
info!("{:.3}s to compute quotient polys and their LDEs",
|
||||
quotient_polys_start.elapsed().as_secs_f32());
|
||||
let quotient_polys_root =
|
||||
merkle_root_bit_rev_order(transpose_poly_values(all_quotient_poly_chunk_ldes));
|
||||
info!(
|
||||
"{:.3}s to compute quotient polys and their LDEs",
|
||||
quotient_polys_start.elapsed().as_secs_f32()
|
||||
);
|
||||
|
||||
let openings = Vec::new(); // TODO
|
||||
|
||||
let fri_proofs = Vec::new(); // TODO
|
||||
|
||||
info!("{:.3}s for overall witness & proof generation",
|
||||
start_proof_gen.elapsed().as_secs_f32());
|
||||
info!(
|
||||
"{:.3}s for overall witness & proof generation",
|
||||
start_proof_gen.elapsed().as_secs_f32()
|
||||
);
|
||||
|
||||
Proof {
|
||||
wires_root,
|
||||
@ -150,28 +175,41 @@ fn compute_vanishing_polys<F: Field>(
|
||||
let num_checks = common_data.config.num_checks;
|
||||
|
||||
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 i_next = (i + 1) % lde_size;
|
||||
let local_wires = &wire_ldes_t[i];
|
||||
let next_wires = &wire_ldes_t[i_next];
|
||||
let local_constants = &prover_data.constant_ldes_t[i];
|
||||
let next_constants = &prover_data.constant_ldes_t[i_next];
|
||||
let local_plonk_zs = &plonk_z_lde_t[i];
|
||||
let next_plonk_zs = &plonk_z_lde_t[i_next];
|
||||
let s_sigmas = &prover_data.sigma_ldes_t[i];
|
||||
let values: Vec<Vec<F>> = points
|
||||
.into_par_iter()
|
||||
.enumerate()
|
||||
.map(|(i, x)| {
|
||||
let i_next = (i + 1) % lde_size;
|
||||
let local_wires = &wire_ldes_t[i];
|
||||
let next_wires = &wire_ldes_t[i_next];
|
||||
let local_constants = &prover_data.constant_ldes_t[i];
|
||||
let next_constants = &prover_data.constant_ldes_t[i_next];
|
||||
let local_plonk_zs = &plonk_z_lde_t[i];
|
||||
let next_plonk_zs = &plonk_z_lde_t[i_next];
|
||||
let s_sigmas = &prover_data.sigma_ldes_t[i];
|
||||
|
||||
debug_assert_eq!(local_wires.len(), common_data.config.num_wires);
|
||||
debug_assert_eq!(local_plonk_zs.len(), num_checks);
|
||||
debug_assert_eq!(local_wires.len(), common_data.config.num_wires);
|
||||
debug_assert_eq!(local_plonk_zs.len(), num_checks);
|
||||
|
||||
let vars = EvaluationVars {
|
||||
local_constants,
|
||||
next_constants,
|
||||
local_wires,
|
||||
next_wires,
|
||||
};
|
||||
compute_vanishing_poly_entry(
|
||||
common_data, x, vars, local_plonk_zs, next_plonk_zs, s_sigmas, beta, gamma, alphas)
|
||||
}).collect();
|
||||
let vars = EvaluationVars {
|
||||
local_constants,
|
||||
next_constants,
|
||||
local_wires,
|
||||
next_wires,
|
||||
};
|
||||
compute_vanishing_poly_entry(
|
||||
common_data,
|
||||
x,
|
||||
vars,
|
||||
local_plonk_zs,
|
||||
next_plonk_zs,
|
||||
s_sigmas,
|
||||
beta,
|
||||
gamma,
|
||||
alphas,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
transpose(&values)
|
||||
.into_iter()
|
||||
@ -193,8 +231,8 @@ fn compute_vanishing_poly_entry<F: Field>(
|
||||
gamma: F,
|
||||
alphas: &[F],
|
||||
) -> Vec<F> {
|
||||
let constraint_terms = evaluate_gate_constraints(
|
||||
&common_data.gates, common_data.num_gate_constraints, vars);
|
||||
let constraint_terms =
|
||||
evaluate_gate_constraints(&common_data.gates, common_data.num_gate_constraints, vars);
|
||||
|
||||
// The L_1(x) (Z(x) - 1) vanishing terms.
|
||||
let mut vanishing_z_1_terms = Vec::new();
|
||||
@ -223,7 +261,8 @@ fn compute_vanishing_poly_entry<F: Field>(
|
||||
vanishing_z_1_terms,
|
||||
vanishing_v_shift_terms,
|
||||
constraint_terms,
|
||||
].concat();
|
||||
]
|
||||
.concat();
|
||||
|
||||
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
|
||||
// arbitrary pick zero. Ideally we would verify that no constraints operate on these unset
|
||||
// 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();
|
||||
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 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, ],
|
||||
[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, ],
|
||||
[
|
||||
10760600708254618966,
|
||||
16769767337539665921,
|
||||
5534023221388089754,
|
||||
2049638230143736946,
|
||||
16140901062381928449,
|
||||
2635249153041947502,
|
||||
3074457345215605419,
|
||||
11068046442776179508,
|
||||
13835058053470224385,
|
||||
6148914690431210838,
|
||||
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] = [
|
||||
[12050887499329086906, 1748247961703512657, 315780861775001585, 2827656358919812970, 13335864861236723579, 3010729529365640897, 8463534053828271146, 2528500966106598845, 8969871077123422281, 1002624930202741107, 599979829006456404, 4386170815218774254, ],
|
||||
[5771413917591851532, 11946802620311685142, 4759792267858670262, 6879094914431255667, 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, ],
|
||||
[
|
||||
12050887499329086906,
|
||||
1748247961703512657,
|
||||
315780861775001585,
|
||||
2827656358919812970,
|
||||
13335864861236723579,
|
||||
3010729529365640897,
|
||||
8463534053828271146,
|
||||
2528500966106598845,
|
||||
8969871077123422281,
|
||||
1002624930202741107,
|
||||
599979829006456404,
|
||||
4386170815218774254,
|
||||
],
|
||||
[
|
||||
5771413917591851532,
|
||||
11946802620311685142,
|
||||
4759792267858670262,
|
||||
6879094914431255667,
|
||||
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] {
|
||||
|
||||
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>> {
|
||||
let poly_values = polys.into_iter()
|
||||
.map(|p| p.values)
|
||||
.collect::<Vec<_>>();
|
||||
let poly_values = polys.into_iter().map(|p| p.values).collect::<Vec<_>>();
|
||||
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;
|
||||
for i in 0..num_bits {
|
||||
let i_rev = num_bits - i - 1;
|
||||
@ -93,9 +91,11 @@ mod tests {
|
||||
fn test_reverse_index_bits() {
|
||||
assert_eq!(
|
||||
reverse_index_bits(vec![10, 20, 30, 40]),
|
||||
vec![10, 30, 20, 40]);
|
||||
vec![10, 30, 20, 40]
|
||||
);
|
||||
assert_eq!(
|
||||
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]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,12 +32,10 @@ impl<F: Field> PartialWitness<F> {
|
||||
|
||||
pub fn get_target(&self, target: Target) -> F {
|
||||
self.target_values[&target]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_targets(&self, targets: &[Target]) -> Vec<F> {
|
||||
targets.iter()
|
||||
.map(|&t| self.get_target(t))
|
||||
.collect()
|
||||
targets.iter().map(|&t| self.get_target(t)).collect()
|
||||
}
|
||||
|
||||
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) {
|
||||
let opt_old_value = self.target_values.insert(target, value);
|
||||
if let Some(old_value) = opt_old_value {
|
||||
assert_eq!(old_value, value,
|
||||
"Target was set twice with different values: {:?}", target);
|
||||
assert_eq!(
|
||||
old_value, value,
|
||||
"Target was set twice with different values: {:?}",
|
||||
target
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user