mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-11 10:13:09 +00:00
Merge pull request #181 from mir-protocol/push_to_8192
Final arithmetic optimization and recursive circuit with `<2^13` gates
This commit is contained in:
commit
20cf073e2a
@ -41,23 +41,14 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
let coset_start = self.mul(start, x);
|
||||
|
||||
// The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta.
|
||||
let g_powers = g
|
||||
let points = g
|
||||
.powers()
|
||||
.take(arity)
|
||||
.map(|y| self.constant(y))
|
||||
.map(|y| {
|
||||
let yc = self.constant(y);
|
||||
self.mul(coset_start, yc)
|
||||
})
|
||||
.zip(evals)
|
||||
.collect::<Vec<_>>();
|
||||
let mut coset = Vec::new();
|
||||
for i in 0..arity / 2 {
|
||||
let res = self.mul_two(
|
||||
coset_start,
|
||||
g_powers[2 * i],
|
||||
coset_start,
|
||||
g_powers[2 * i + 1],
|
||||
);
|
||||
coset.push(res.0);
|
||||
coset.push(res.1);
|
||||
}
|
||||
let points = coset.into_iter().zip(evals).collect::<Vec<_>>();
|
||||
|
||||
self.interpolate(&points, beta)
|
||||
}
|
||||
@ -100,7 +91,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// Size of the LDE domain.
|
||||
let n = proof.final_poly.len() << (total_arities + config.rate_bits);
|
||||
|
||||
challenger.observe_opening_set(&os);
|
||||
challenger.observe_opening_set(os);
|
||||
|
||||
// Scaling factor to combine polynomials.
|
||||
let alpha = challenger.get_extension_challenge(self);
|
||||
@ -265,14 +256,11 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
precomputed_reduced_evals.slope,
|
||||
precomputed_reduced_evals.zs,
|
||||
);
|
||||
let (zs_numerator, vanish_zeta_right) = self.sub_two_extension(
|
||||
zs_composition_eval,
|
||||
interpol_val,
|
||||
subgroup_x,
|
||||
precomputed_reduced_evals.zeta_right,
|
||||
);
|
||||
let (mut sum, zs_denominator) =
|
||||
alpha.shift_and_mul(sum, vanish_zeta, vanish_zeta_right, self);
|
||||
let zs_numerator = self.sub_extension(zs_composition_eval, interpol_val);
|
||||
let vanish_zeta_right =
|
||||
self.sub_extension(subgroup_x, precomputed_reduced_evals.zeta_right);
|
||||
sum = alpha.shift(sum, self);
|
||||
let zs_denominator = self.mul_extension(vanish_zeta, vanish_zeta_right);
|
||||
sum = self.div_add_extension(zs_numerator, zs_denominator, sum);
|
||||
|
||||
sum
|
||||
@ -296,8 +284,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// TODO: Do we need to range check `x_index` to a target smaller than `p`?
|
||||
let x_index = challenger.get_challenge(self);
|
||||
let mut x_index_bits = self.low_bits(x_index, n_log, 64);
|
||||
let cap_index = self
|
||||
.le_sum(x_index_bits[x_index_bits.len() - common_data.config.cap_height..].into_iter());
|
||||
let cap_index =
|
||||
self.le_sum(x_index_bits[x_index_bits.len() - common_data.config.cap_height..].iter());
|
||||
with_context!(
|
||||
self,
|
||||
"check FRI initial proof",
|
||||
@ -317,19 +305,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
let phi = self.exp_from_bits(phi, x_index_bits.iter().rev());
|
||||
let g_ext = self.convert_to_ext(g);
|
||||
let phi_ext = self.convert_to_ext(phi);
|
||||
let zero = self.zero_extension();
|
||||
// `subgroup_x = g*phi, vanish_zeta = g*phi - zeta`
|
||||
let tmp = self.double_arithmetic_extension(
|
||||
F::ONE,
|
||||
F::NEG_ONE,
|
||||
g_ext,
|
||||
phi_ext,
|
||||
zero,
|
||||
g_ext,
|
||||
phi_ext,
|
||||
zeta,
|
||||
);
|
||||
(tmp.0 .0[0], tmp.1)
|
||||
let subgroup_x = self.mul(g, phi);
|
||||
let vanish_zeta = self.mul_sub_extension(g_ext, phi_ext, zeta);
|
||||
(subgroup_x, vanish_zeta)
|
||||
});
|
||||
|
||||
// old_eval is the last derived evaluation; it will be checked for consistency with its
|
||||
@ -369,7 +348,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
"infer evaluation using interpolation",
|
||||
self.compute_evaluation(
|
||||
subgroup_x,
|
||||
&x_index_within_coset_bits,
|
||||
x_index_within_coset_bits,
|
||||
arity_bits,
|
||||
evals,
|
||||
betas[i],
|
||||
@ -409,7 +388,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
struct PrecomputedReducedEvalsTarget<const D: usize> {
|
||||
pub single: ExtensionTarget<D>,
|
||||
pub zs: ExtensionTarget<D>,
|
||||
pub zs_right: ExtensionTarget<D>,
|
||||
/// Slope of the line from `(zeta, zs)` to `(zeta_right, zs_right)`.
|
||||
pub slope: ExtensionTarget<D>,
|
||||
pub zeta_right: ExtensionTarget<D>,
|
||||
@ -440,12 +418,12 @@ impl<const D: usize> PrecomputedReducedEvalsTarget<D> {
|
||||
|
||||
let g = builder.constant_extension(F::Extension::primitive_root_of_unity(degree_log));
|
||||
let zeta_right = builder.mul_extension(g, zeta);
|
||||
let (numerator, denominator) = builder.sub_two_extension(zs_right, zs, zeta_right, zeta);
|
||||
let numerator = builder.sub_extension(zs_right, zs);
|
||||
let denominator = builder.sub_extension(zeta_right, zeta);
|
||||
|
||||
Self {
|
||||
single,
|
||||
zs,
|
||||
zs_right,
|
||||
slope: builder.div_extension(numerator, denominator),
|
||||
zeta_right,
|
||||
}
|
||||
|
||||
@ -86,16 +86,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.arithmetic(F::ONE, x, y, F::ZERO, x)
|
||||
}
|
||||
|
||||
/// Computes `x * y`.
|
||||
pub fn mul_two(&mut self, a0: Target, b0: Target, a1: Target, b1: Target) -> (Target, Target) {
|
||||
let a0_ext = self.convert_to_ext(a0);
|
||||
let b0_ext = self.convert_to_ext(b0);
|
||||
let a1_ext = self.convert_to_ext(a1);
|
||||
let b1_ext = self.convert_to_ext(b1);
|
||||
let res = self.mul_two_extension(a0_ext, b0_ext, a1_ext, b1_ext);
|
||||
(res.0 .0[0], res.1 .0[0])
|
||||
}
|
||||
|
||||
/// Multiply `n` `Target`s with `ceil(n/2) + 1` `ArithmeticExtensionGate`s.
|
||||
pub fn mul_many(&mut self, terms: &[Target]) -> Target {
|
||||
let terms_ext = terms
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
use std::convert::TryInto;
|
||||
|
||||
use itertools::Itertools;
|
||||
use num::Integer;
|
||||
|
||||
use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget};
|
||||
use crate::field::extension_field::{Extendable, OEF};
|
||||
use crate::field::field_types::Field;
|
||||
use crate::gates::arithmetic::ArithmeticExtensionGate;
|
||||
use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS};
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::PartialWitness;
|
||||
@ -14,51 +13,28 @@ use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::bits_u64;
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
pub fn double_arithmetic_extension(
|
||||
&mut self,
|
||||
const_0: F,
|
||||
const_1: F,
|
||||
first_multiplicand_0: ExtensionTarget<D>,
|
||||
first_multiplicand_1: ExtensionTarget<D>,
|
||||
first_addend: ExtensionTarget<D>,
|
||||
second_multiplicand_0: ExtensionTarget<D>,
|
||||
second_multiplicand_1: ExtensionTarget<D>,
|
||||
second_addend: ExtensionTarget<D>,
|
||||
) -> (ExtensionTarget<D>, ExtensionTarget<D>) {
|
||||
let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]);
|
||||
/// Finds the last available arithmetic gate with the given constants or add one if there aren't any.
|
||||
/// Returns `(g,i)` such that there is an arithmetic gate with the given constants at index
|
||||
/// `g` and the gate's `i`-th operation is available.
|
||||
fn find_arithmetic_gate(&mut self, const_0: F, const_1: F) -> (usize, usize) {
|
||||
let (gate, i) = self
|
||||
.free_arithmetic
|
||||
.get(&(const_0, const_1))
|
||||
.copied()
|
||||
.unwrap_or_else(|| {
|
||||
let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]);
|
||||
(gate, 0)
|
||||
});
|
||||
|
||||
let wire_first_multiplicand_0 = ExtensionTarget::from_range(
|
||||
gate,
|
||||
ArithmeticExtensionGate::<D>::wires_first_multiplicand_0(),
|
||||
);
|
||||
let wire_first_multiplicand_1 = ExtensionTarget::from_range(
|
||||
gate,
|
||||
ArithmeticExtensionGate::<D>::wires_first_multiplicand_1(),
|
||||
);
|
||||
let wire_first_addend =
|
||||
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_first_addend());
|
||||
let wire_second_multiplicand_0 = ExtensionTarget::from_range(
|
||||
gate,
|
||||
ArithmeticExtensionGate::<D>::wires_second_multiplicand_0(),
|
||||
);
|
||||
let wire_second_multiplicand_1 = ExtensionTarget::from_range(
|
||||
gate,
|
||||
ArithmeticExtensionGate::<D>::wires_second_multiplicand_1(),
|
||||
);
|
||||
let wire_second_addend =
|
||||
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_second_addend());
|
||||
let wire_first_output =
|
||||
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_first_output());
|
||||
let wire_second_output =
|
||||
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_second_output());
|
||||
// Update `free_arithmetic` with new values.
|
||||
if i < NUM_ARITHMETIC_OPS - 1 {
|
||||
self.free_arithmetic
|
||||
.insert((const_0, const_1), (gate, i + 1));
|
||||
} else {
|
||||
self.free_arithmetic.remove(&(const_0, const_1));
|
||||
}
|
||||
|
||||
self.route_extension(first_multiplicand_0, wire_first_multiplicand_0);
|
||||
self.route_extension(first_multiplicand_1, wire_first_multiplicand_1);
|
||||
self.route_extension(first_addend, wire_first_addend);
|
||||
self.route_extension(second_multiplicand_0, wire_second_multiplicand_0);
|
||||
self.route_extension(second_multiplicand_1, wire_second_multiplicand_1);
|
||||
self.route_extension(second_addend, wire_second_addend);
|
||||
(wire_first_output, wire_second_output)
|
||||
(gate, i)
|
||||
}
|
||||
|
||||
pub fn arithmetic_extension(
|
||||
@ -80,18 +56,23 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
return result;
|
||||
}
|
||||
|
||||
let zero = self.zero_extension();
|
||||
self.double_arithmetic_extension(
|
||||
const_0,
|
||||
const_1,
|
||||
multiplicand_0,
|
||||
multiplicand_1,
|
||||
addend,
|
||||
zero,
|
||||
zero,
|
||||
zero,
|
||||
)
|
||||
.0
|
||||
let (gate, i) = self.find_arithmetic_gate(const_0, const_1);
|
||||
let wires_multiplicand_0 = ExtensionTarget::from_range(
|
||||
gate,
|
||||
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(i),
|
||||
);
|
||||
let wires_multiplicand_1 = ExtensionTarget::from_range(
|
||||
gate,
|
||||
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(i),
|
||||
);
|
||||
let wires_addend =
|
||||
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_ith_addend(i));
|
||||
|
||||
self.route_extension(multiplicand_0, wires_multiplicand_0);
|
||||
self.route_extension(multiplicand_1, wires_multiplicand_1);
|
||||
self.route_extension(addend, wires_addend);
|
||||
|
||||
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_ith_output(i))
|
||||
}
|
||||
|
||||
/// Checks for special cases where the value of
|
||||
@ -172,21 +153,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
pairs: Vec<(ExtensionTarget<D>, ExtensionTarget<D>)>,
|
||||
) -> ExtensionTarget<D> {
|
||||
let mut acc = starting_acc;
|
||||
for chunk in pairs.chunks_exact(2) {
|
||||
let (a0, b0) = chunk[0];
|
||||
let (a1, b1) = chunk[1];
|
||||
let gate = self.num_gates();
|
||||
let first_out = ExtensionTarget::from_range(
|
||||
gate,
|
||||
ArithmeticExtensionGate::<D>::wires_first_output(),
|
||||
);
|
||||
acc = self
|
||||
.double_arithmetic_extension(constant, F::ONE, a0, b0, acc, a1, b1, first_out)
|
||||
.1;
|
||||
}
|
||||
if pairs.len().is_odd() {
|
||||
let n = pairs.len() - 1;
|
||||
acc = self.arithmetic_extension(constant, F::ONE, pairs[n].0, pairs[n].1, acc);
|
||||
for (a, b) in pairs {
|
||||
acc = self.arithmetic_extension(constant, F::ONE, a, b, acc);
|
||||
}
|
||||
acc
|
||||
}
|
||||
@ -200,38 +168,15 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.arithmetic_extension(F::ONE, F::ONE, one, a, b)
|
||||
}
|
||||
|
||||
/// Returns `(a0+b0, a1+b1)`.
|
||||
pub fn add_two_extension(
|
||||
&mut self,
|
||||
a0: ExtensionTarget<D>,
|
||||
b0: ExtensionTarget<D>,
|
||||
a1: ExtensionTarget<D>,
|
||||
b1: ExtensionTarget<D>,
|
||||
) -> (ExtensionTarget<D>, ExtensionTarget<D>) {
|
||||
let one = self.one_extension();
|
||||
self.double_arithmetic_extension(F::ONE, F::ONE, one, a0, b0, one, a1, b1)
|
||||
}
|
||||
|
||||
pub fn add_ext_algebra(
|
||||
&mut self,
|
||||
a: ExtensionAlgebraTarget<D>,
|
||||
mut a: ExtensionAlgebraTarget<D>,
|
||||
b: ExtensionAlgebraTarget<D>,
|
||||
) -> ExtensionAlgebraTarget<D> {
|
||||
// We run two additions in parallel. So `[a0,a1,a2,a3] + [b0,b1,b2,b3]` is computed with two
|
||||
// `add_two_extension`, first `[a0,a1]+[b0,b1]` then `[a2,a3]+[b2,b3]`.
|
||||
let mut res = Vec::with_capacity(D);
|
||||
// We need some extra logic if D is odd.
|
||||
let d_even = D & (D ^ 1); // = 2 * (D/2)
|
||||
for mut chunk in &(0..d_even).chunks(2) {
|
||||
let i = chunk.next().unwrap();
|
||||
let j = chunk.next().unwrap();
|
||||
let (o0, o1) = self.add_two_extension(a.0[i], b.0[i], a.0[j], b.0[j]);
|
||||
res.extend([o0, o1]);
|
||||
for i in 0..D {
|
||||
a.0[i] = self.add_extension(a.0[i], b.0[i]);
|
||||
}
|
||||
if D.is_odd() {
|
||||
res.push(self.add_extension(a.0[D - 1], b.0[D - 1]));
|
||||
}
|
||||
ExtensionAlgebraTarget(res.try_into().unwrap())
|
||||
a
|
||||
}
|
||||
|
||||
/// Add 3 `ExtensionTarget`s with 1 `ArithmeticExtensionGate`s.
|
||||
@ -274,35 +219,15 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.arithmetic_extension(F::ONE, F::NEG_ONE, one, a, b)
|
||||
}
|
||||
|
||||
pub fn sub_two_extension(
|
||||
&mut self,
|
||||
a0: ExtensionTarget<D>,
|
||||
b0: ExtensionTarget<D>,
|
||||
a1: ExtensionTarget<D>,
|
||||
b1: ExtensionTarget<D>,
|
||||
) -> (ExtensionTarget<D>, ExtensionTarget<D>) {
|
||||
let one = self.one_extension();
|
||||
self.double_arithmetic_extension(F::ONE, F::NEG_ONE, one, a0, b0, one, a1, b1)
|
||||
}
|
||||
|
||||
pub fn sub_ext_algebra(
|
||||
&mut self,
|
||||
a: ExtensionAlgebraTarget<D>,
|
||||
mut a: ExtensionAlgebraTarget<D>,
|
||||
b: ExtensionAlgebraTarget<D>,
|
||||
) -> ExtensionAlgebraTarget<D> {
|
||||
// See `add_ext_algebra`.
|
||||
let mut res = Vec::with_capacity(D);
|
||||
let d_even = D & (D ^ 1); // = 2 * (D/2)
|
||||
for mut chunk in &(0..d_even).chunks(2) {
|
||||
let i = chunk.next().unwrap();
|
||||
let j = chunk.next().unwrap();
|
||||
let (o0, o1) = self.sub_two_extension(a.0[i], b.0[i], a.0[j], b.0[j]);
|
||||
res.extend([o0, o1]);
|
||||
for i in 0..D {
|
||||
a.0[i] = self.sub_extension(a.0[i], b.0[i]);
|
||||
}
|
||||
if D.is_odd() {
|
||||
res.push(self.sub_extension(a.0[D - 1], b.0[D - 1]));
|
||||
}
|
||||
ExtensionAlgebraTarget(res.try_into().unwrap())
|
||||
a
|
||||
}
|
||||
|
||||
pub fn mul_extension_with_const(
|
||||
@ -312,17 +237,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
multiplicand_1: ExtensionTarget<D>,
|
||||
) -> ExtensionTarget<D> {
|
||||
let zero = self.zero_extension();
|
||||
self.double_arithmetic_extension(
|
||||
const_0,
|
||||
F::ZERO,
|
||||
multiplicand_0,
|
||||
multiplicand_1,
|
||||
zero,
|
||||
zero,
|
||||
zero,
|
||||
zero,
|
||||
)
|
||||
.0
|
||||
self.arithmetic_extension(const_0, F::ZERO, multiplicand_0, multiplicand_1, zero)
|
||||
}
|
||||
|
||||
pub fn mul_extension(
|
||||
@ -333,18 +248,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.mul_extension_with_const(F::ONE, multiplicand_0, multiplicand_1)
|
||||
}
|
||||
|
||||
/// Returns `(a0*b0, a1*b1)`.
|
||||
pub fn mul_two_extension(
|
||||
&mut self,
|
||||
a0: ExtensionTarget<D>,
|
||||
b0: ExtensionTarget<D>,
|
||||
a1: ExtensionTarget<D>,
|
||||
b1: ExtensionTarget<D>,
|
||||
) -> (ExtensionTarget<D>, ExtensionTarget<D>) {
|
||||
let zero = self.zero_extension();
|
||||
self.double_arithmetic_extension(F::ONE, F::ZERO, a0, b0, zero, a1, b1, zero)
|
||||
}
|
||||
|
||||
/// Computes `x^2`.
|
||||
pub fn square_extension(&mut self, x: ExtensionTarget<D>) -> ExtensionTarget<D> {
|
||||
self.mul_extension(x, x)
|
||||
@ -402,12 +305,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
b: ExtensionTarget<D>,
|
||||
c: ExtensionTarget<D>,
|
||||
) -> ExtensionTarget<D> {
|
||||
let zero = self.zero_extension();
|
||||
let gate = self.num_gates();
|
||||
let first_out =
|
||||
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_first_output());
|
||||
self.double_arithmetic_extension(F::ONE, F::ZERO, a, b, zero, c, first_out, zero)
|
||||
.1
|
||||
let tmp = self.mul_extension(a, b);
|
||||
self.mul_extension(tmp, c)
|
||||
}
|
||||
|
||||
/// Multiply `n` `ExtensionTarget`s with `n/2` `ArithmeticExtensionGate`s.
|
||||
@ -484,22 +383,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
b: ExtensionAlgebraTarget<D>,
|
||||
mut c: ExtensionAlgebraTarget<D>,
|
||||
) -> ExtensionAlgebraTarget<D> {
|
||||
for i in 0..D / 2 {
|
||||
let res = self.double_arithmetic_extension(
|
||||
F::ONE,
|
||||
F::ONE,
|
||||
a,
|
||||
b.0[2 * i],
|
||||
c.0[2 * i],
|
||||
a,
|
||||
b.0[2 * i + 1],
|
||||
c.0[2 * i + 1],
|
||||
);
|
||||
c.0[2 * i] = res.0;
|
||||
c.0[2 * i + 1] = res.1;
|
||||
}
|
||||
if D.is_odd() {
|
||||
c.0[D - 1] = self.arithmetic_extension(F::ONE, F::ONE, a, b.0[D - 1], c.0[D - 1]);
|
||||
for i in 0..D {
|
||||
c.0[i] = self.mul_add_extension(a, b.0[i], c.0[i]);
|
||||
}
|
||||
c
|
||||
}
|
||||
@ -571,7 +456,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
z: ExtensionTarget<D>,
|
||||
) -> ExtensionTarget<D> {
|
||||
let inv = self.add_virtual_extension_target();
|
||||
let zero = self.zero_extension();
|
||||
let one = self.one_extension();
|
||||
self.add_generator(QuotientGeneratorExtension {
|
||||
numerator: one,
|
||||
@ -580,11 +464,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
});
|
||||
|
||||
// Enforce that x times its purported inverse equals 1.
|
||||
let (y_inv, res) =
|
||||
self.double_arithmetic_extension(F::ONE, F::ONE, y, inv, zero, x, inv, z);
|
||||
let y_inv = self.mul_extension(y, inv);
|
||||
self.assert_equal_extension(y_inv, one);
|
||||
|
||||
res
|
||||
self.mul_add_extension(x, inv, z)
|
||||
}
|
||||
|
||||
/// Computes `1 / x`. Results in an unsatisfiable instance if `x = 0`.
|
||||
|
||||
@ -5,29 +5,6 @@ use crate::iop::target::Target;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Interpolate two points. No need for an `InterpolationGate` since the coefficients
|
||||
/// of the linear interpolation polynomial can be easily computed with arithmetic operations.
|
||||
pub fn interpolate2(
|
||||
&mut self,
|
||||
interpolation_points: [(ExtensionTarget<D>, ExtensionTarget<D>); 2],
|
||||
evaluation_point: ExtensionTarget<D>,
|
||||
) -> ExtensionTarget<D> {
|
||||
// a0 -> a1
|
||||
// b0 -> b1
|
||||
// x -> a1 + (x-a0)*(b1-a1)/(b0-a0)
|
||||
|
||||
let (x_m_a0, b1_m_a1) = self.sub_two_extension(
|
||||
evaluation_point,
|
||||
interpolation_points[0].0,
|
||||
interpolation_points[1].1,
|
||||
interpolation_points[0].1,
|
||||
);
|
||||
let b0_m_a0 = self.sub_extension(interpolation_points[1].0, interpolation_points[0].0);
|
||||
let quotient = self.div_extension(b1_m_a1, b0_m_a0);
|
||||
|
||||
self.mul_add_extension(x_m_a0, quotient, interpolation_points[0].1)
|
||||
}
|
||||
|
||||
/// Interpolate a list of point/evaluation pairs at a given point.
|
||||
/// Returns the evaluation of the interpolated polynomial at `evaluation_point`.
|
||||
pub fn interpolate(
|
||||
@ -108,39 +85,4 @@ mod tests {
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interpolate2() -> Result<()> {
|
||||
type F = CrandallField;
|
||||
type FF = QuarticCrandallField;
|
||||
let config = CircuitConfig::large_zk_config();
|
||||
let pw = PartialWitness::new(config.num_wires);
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
|
||||
let len = 2;
|
||||
let points = (0..len)
|
||||
.map(|_| (FF::rand(), FF::rand()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let true_interpolant = interpolant(&points);
|
||||
|
||||
let z = FF::rand();
|
||||
let true_eval = true_interpolant.eval(z);
|
||||
|
||||
let points_target = points
|
||||
.iter()
|
||||
.map(|&(p, v)| (builder.constant_extension(p), builder.constant_extension(v)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let zt = builder.constant_extension(z);
|
||||
|
||||
let eval = builder.interpolate2(points_target.try_into().unwrap(), zt);
|
||||
let true_eval_target = builder.constant_extension(true_eval);
|
||||
builder.assert_equal_extension(eval, true_eval_target);
|
||||
|
||||
let data = builder.build();
|
||||
let proof = data.prove(pw)?;
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::gates::arithmetic::ArithmeticExtensionGate;
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
|
||||
@ -25,12 +24,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
x: ExtensionTarget<D>,
|
||||
y: ExtensionTarget<D>,
|
||||
) -> ExtensionTarget<D> {
|
||||
let gate = self.num_gates();
|
||||
// Holds `by - y`.
|
||||
let first_out =
|
||||
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_first_output());
|
||||
self.double_arithmetic_extension(F::ONE, F::NEG_ONE, b, y, y, b, x, first_out)
|
||||
.1
|
||||
let tmp = self.mul_sub_extension(b, y, y);
|
||||
self.mul_sub_extension(b, x, tmp)
|
||||
}
|
||||
|
||||
/// See `select_ext`.
|
||||
|
||||
@ -10,34 +10,25 @@ use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
|
||||
/// Number of arithmetic operations performed by an arithmetic gate.
|
||||
pub const NUM_ARITHMETIC_OPS: usize = 4;
|
||||
|
||||
/// A gate which can a linear combination `c0*x*y+c1*z` twice with the same `x`.
|
||||
#[derive(Debug)]
|
||||
pub struct ArithmeticExtensionGate<const D: usize>;
|
||||
|
||||
impl<const D: usize> ArithmeticExtensionGate<D> {
|
||||
pub fn wires_first_multiplicand_0() -> Range<usize> {
|
||||
0..D
|
||||
pub fn wires_ith_multiplicand_0(i: usize) -> Range<usize> {
|
||||
4 * D * i..4 * D * i + D
|
||||
}
|
||||
pub fn wires_first_multiplicand_1() -> Range<usize> {
|
||||
D..2 * D
|
||||
pub fn wires_ith_multiplicand_1(i: usize) -> Range<usize> {
|
||||
4 * D * i + D..4 * D * i + 2 * D
|
||||
}
|
||||
pub fn wires_first_addend() -> Range<usize> {
|
||||
2 * D..3 * D
|
||||
pub fn wires_ith_addend(i: usize) -> Range<usize> {
|
||||
4 * D * i + 2 * D..4 * D * i + 3 * D
|
||||
}
|
||||
pub fn wires_second_multiplicand_0() -> Range<usize> {
|
||||
3 * D..4 * D
|
||||
}
|
||||
pub fn wires_second_multiplicand_1() -> Range<usize> {
|
||||
4 * D..5 * D
|
||||
}
|
||||
pub fn wires_second_addend() -> Range<usize> {
|
||||
5 * D..6 * D
|
||||
}
|
||||
pub fn wires_first_output() -> Range<usize> {
|
||||
6 * D..7 * D
|
||||
}
|
||||
pub fn wires_second_output() -> Range<usize> {
|
||||
7 * D..8 * D
|
||||
pub fn wires_ith_output(i: usize) -> Range<usize> {
|
||||
4 * D * i + 3 * D..4 * D * i + 4 * D
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,24 +41,18 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
|
||||
let first_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_0());
|
||||
let first_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_1());
|
||||
let first_addend = vars.get_local_ext_algebra(Self::wires_first_addend());
|
||||
let second_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_0());
|
||||
let second_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_1());
|
||||
let second_addend = vars.get_local_ext_algebra(Self::wires_second_addend());
|
||||
let first_output = vars.get_local_ext_algebra(Self::wires_first_output());
|
||||
let second_output = vars.get_local_ext_algebra(Self::wires_second_output());
|
||||
let mut constraints = Vec::new();
|
||||
for i in 0..NUM_ARITHMETIC_OPS {
|
||||
let multiplicand_0 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_0(i));
|
||||
let multiplicand_1 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_1(i));
|
||||
let addend = vars.get_local_ext_algebra(Self::wires_ith_addend(i));
|
||||
let output = vars.get_local_ext_algebra(Self::wires_ith_output(i));
|
||||
let computed_output =
|
||||
multiplicand_0 * multiplicand_1 * const_0.into() + addend * const_1.into();
|
||||
|
||||
let first_computed_output = first_multiplicand_0 * first_multiplicand_1 * const_0.into()
|
||||
+ first_addend * const_1.into();
|
||||
let second_computed_output = second_multiplicand_0 * second_multiplicand_1 * const_0.into()
|
||||
+ second_addend * const_1.into();
|
||||
constraints.extend((output - computed_output).to_basefield_array());
|
||||
}
|
||||
|
||||
let mut constraints = (first_output - first_computed_output)
|
||||
.to_basefield_array()
|
||||
.to_vec();
|
||||
constraints.extend((second_output - second_computed_output).to_basefield_array());
|
||||
constraints
|
||||
}
|
||||
|
||||
@ -75,24 +60,18 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
|
||||
let first_multiplicand_0 = vars.get_local_ext(Self::wires_first_multiplicand_0());
|
||||
let first_multiplicand_1 = vars.get_local_ext(Self::wires_first_multiplicand_1());
|
||||
let first_addend = vars.get_local_ext(Self::wires_first_addend());
|
||||
let second_multiplicand_0 = vars.get_local_ext(Self::wires_second_multiplicand_0());
|
||||
let second_multiplicand_1 = vars.get_local_ext(Self::wires_second_multiplicand_1());
|
||||
let second_addend = vars.get_local_ext(Self::wires_second_addend());
|
||||
let first_output = vars.get_local_ext(Self::wires_first_output());
|
||||
let second_output = vars.get_local_ext(Self::wires_second_output());
|
||||
let mut constraints = Vec::new();
|
||||
for i in 0..NUM_ARITHMETIC_OPS {
|
||||
let multiplicand_0 = vars.get_local_ext(Self::wires_ith_multiplicand_0(i));
|
||||
let multiplicand_1 = vars.get_local_ext(Self::wires_ith_multiplicand_1(i));
|
||||
let addend = vars.get_local_ext(Self::wires_ith_addend(i));
|
||||
let output = vars.get_local_ext(Self::wires_ith_output(i));
|
||||
let computed_output =
|
||||
multiplicand_0 * multiplicand_1 * const_0.into() + addend * const_1.into();
|
||||
|
||||
let first_computed_output = first_multiplicand_0 * first_multiplicand_1 * const_0.into()
|
||||
+ first_addend * const_1.into();
|
||||
let second_computed_output = second_multiplicand_0 * second_multiplicand_1 * const_0.into()
|
||||
+ second_addend * const_1.into();
|
||||
constraints.extend((output - computed_output).to_basefield_array());
|
||||
}
|
||||
|
||||
let mut constraints = (first_output - first_computed_output)
|
||||
.to_basefield_array()
|
||||
.to_vec();
|
||||
constraints.extend((second_output - second_computed_output).to_basefield_array());
|
||||
constraints
|
||||
}
|
||||
|
||||
@ -104,34 +83,23 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
|
||||
let const_0 = vars.local_constants[0];
|
||||
let const_1 = vars.local_constants[1];
|
||||
|
||||
let first_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_0());
|
||||
let first_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_1());
|
||||
let first_addend = vars.get_local_ext_algebra(Self::wires_first_addend());
|
||||
let second_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_0());
|
||||
let second_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_1());
|
||||
let second_addend = vars.get_local_ext_algebra(Self::wires_second_addend());
|
||||
let first_output = vars.get_local_ext_algebra(Self::wires_first_output());
|
||||
let second_output = vars.get_local_ext_algebra(Self::wires_second_output());
|
||||
let mut constraints = Vec::new();
|
||||
for i in 0..NUM_ARITHMETIC_OPS {
|
||||
let multiplicand_0 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_0(i));
|
||||
let multiplicand_1 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_1(i));
|
||||
let addend = vars.get_local_ext_algebra(Self::wires_ith_addend(i));
|
||||
let output = vars.get_local_ext_algebra(Self::wires_ith_output(i));
|
||||
let computed_output = {
|
||||
let mul = builder.mul_ext_algebra(multiplicand_0, multiplicand_1);
|
||||
let scaled_mul = builder.scalar_mul_ext_algebra(const_0, mul);
|
||||
let scaled_addend = builder.scalar_mul_ext_algebra(const_1, addend);
|
||||
builder.add_ext_algebra(scaled_mul, scaled_addend)
|
||||
};
|
||||
|
||||
let first_computed_output =
|
||||
builder.mul_ext_algebra(first_multiplicand_0, first_multiplicand_1);
|
||||
let first_computed_output = builder.scalar_mul_ext_algebra(const_0, first_computed_output);
|
||||
let first_scaled_addend = builder.scalar_mul_ext_algebra(const_1, first_addend);
|
||||
let first_computed_output =
|
||||
builder.add_ext_algebra(first_computed_output, first_scaled_addend);
|
||||
let diff = builder.sub_ext_algebra(output, computed_output);
|
||||
constraints.extend(diff.to_ext_target_array());
|
||||
}
|
||||
|
||||
let second_computed_output =
|
||||
builder.mul_ext_algebra(second_multiplicand_0, second_multiplicand_1);
|
||||
let second_computed_output =
|
||||
builder.scalar_mul_ext_algebra(const_0, second_computed_output);
|
||||
let second_scaled_addend = builder.scalar_mul_ext_algebra(const_1, second_addend);
|
||||
let second_computed_output =
|
||||
builder.add_ext_algebra(second_computed_output, second_scaled_addend);
|
||||
|
||||
let diff_0 = builder.sub_ext_algebra(first_output, first_computed_output);
|
||||
let diff_1 = builder.sub_ext_algebra(second_output, second_computed_output);
|
||||
let mut constraints = diff_0.to_ext_target_array().to_vec();
|
||||
constraints.extend(diff_1.to_ext_target_array());
|
||||
constraints
|
||||
}
|
||||
|
||||
@ -140,21 +108,21 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
|
||||
gate_index: usize,
|
||||
local_constants: &[F],
|
||||
) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
let gen0 = ArithmeticExtensionGenerator0 {
|
||||
gate_index,
|
||||
const_0: local_constants[0],
|
||||
const_1: local_constants[1],
|
||||
};
|
||||
let gen1 = ArithmeticExtensionGenerator1 {
|
||||
gate_index,
|
||||
const_0: local_constants[0],
|
||||
const_1: local_constants[1],
|
||||
};
|
||||
vec![Box::new(gen0), Box::new(gen1)]
|
||||
(0..NUM_ARITHMETIC_OPS)
|
||||
.map(|i| {
|
||||
let g: Box<dyn WitnessGenerator<F>> = Box::new(ArithmeticExtensionGenerator {
|
||||
gate_index,
|
||||
const_0: local_constants[0],
|
||||
const_1: local_constants[1],
|
||||
i,
|
||||
});
|
||||
g
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn num_wires(&self) -> usize {
|
||||
8 * D
|
||||
NUM_ARITHMETIC_OPS * 4 * D
|
||||
}
|
||||
|
||||
fn num_constants(&self) -> usize {
|
||||
@ -166,27 +134,25 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
|
||||
}
|
||||
|
||||
fn num_constraints(&self) -> usize {
|
||||
2 * D
|
||||
NUM_ARITHMETIC_OPS * D
|
||||
}
|
||||
}
|
||||
|
||||
struct ArithmeticExtensionGenerator0<F: Extendable<D>, const D: usize> {
|
||||
#[derive(Clone)]
|
||||
struct ArithmeticExtensionGenerator<F: Extendable<D>, const D: usize> {
|
||||
gate_index: usize,
|
||||
const_0: F,
|
||||
const_1: F,
|
||||
i: usize,
|
||||
}
|
||||
|
||||
struct ArithmeticExtensionGenerator1<F: Extendable<D>, const D: usize> {
|
||||
gate_index: usize,
|
||||
const_0: F,
|
||||
const_1: F,
|
||||
}
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensionGenerator0<F, D> {
|
||||
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensionGenerator<F, D> {
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
ArithmeticExtensionGate::<D>::wires_first_multiplicand_0()
|
||||
.chain(ArithmeticExtensionGate::<D>::wires_first_multiplicand_1())
|
||||
.chain(ArithmeticExtensionGate::<D>::wires_first_addend())
|
||||
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(self.i)
|
||||
.chain(ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(
|
||||
self.i,
|
||||
))
|
||||
.chain(ArithmeticExtensionGate::<D>::wires_ith_addend(self.i))
|
||||
.map(|i| Target::wire(self.gate_index, i))
|
||||
.collect()
|
||||
}
|
||||
@ -197,48 +163,17 @@ impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensio
|
||||
witness.get_extension_target(t)
|
||||
};
|
||||
|
||||
let multiplicand_0 =
|
||||
extract_extension(ArithmeticExtensionGate::<D>::wires_first_multiplicand_0());
|
||||
let multiplicand_1 =
|
||||
extract_extension(ArithmeticExtensionGate::<D>::wires_first_multiplicand_1());
|
||||
let addend = extract_extension(ArithmeticExtensionGate::<D>::wires_first_addend());
|
||||
|
||||
let output_target = ExtensionTarget::from_range(
|
||||
self.gate_index,
|
||||
ArithmeticExtensionGate::<D>::wires_first_output(),
|
||||
let multiplicand_0 = extract_extension(
|
||||
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(self.i),
|
||||
);
|
||||
|
||||
let computed_output =
|
||||
multiplicand_0 * multiplicand_1 * self.const_0.into() + addend * self.const_1.into();
|
||||
|
||||
out_buffer.set_extension_target(output_target, computed_output)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensionGenerator1<F, D> {
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
ArithmeticExtensionGate::<D>::wires_second_multiplicand_0()
|
||||
.chain(ArithmeticExtensionGate::<D>::wires_second_multiplicand_1())
|
||||
.chain(ArithmeticExtensionGate::<D>::wires_second_addend())
|
||||
.map(|i| Target::wire(self.gate_index, i))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
|
||||
let extract_extension = |range: Range<usize>| -> F::Extension {
|
||||
let t = ExtensionTarget::from_range(self.gate_index, range);
|
||||
witness.get_extension_target(t)
|
||||
};
|
||||
|
||||
let multiplicand_0 =
|
||||
extract_extension(ArithmeticExtensionGate::<D>::wires_second_multiplicand_0());
|
||||
let multiplicand_1 =
|
||||
extract_extension(ArithmeticExtensionGate::<D>::wires_second_multiplicand_1());
|
||||
let addend = extract_extension(ArithmeticExtensionGate::<D>::wires_second_addend());
|
||||
let multiplicand_1 = extract_extension(
|
||||
ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(self.i),
|
||||
);
|
||||
let addend = extract_extension(ArithmeticExtensionGate::<D>::wires_ith_addend(self.i));
|
||||
|
||||
let output_target = ExtensionTarget::from_range(
|
||||
self.gate_index,
|
||||
ArithmeticExtensionGate::<D>::wires_second_output(),
|
||||
ArithmeticExtensionGate::<D>::wires_ith_output(self.i),
|
||||
);
|
||||
|
||||
let computed_output =
|
||||
|
||||
@ -139,7 +139,7 @@ impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> for GMiMCGate<
|
||||
|
||||
for r in 0..R {
|
||||
let active = r % W;
|
||||
let cubing_input = state[active] + addition_buffer + self.constants[r].into();
|
||||
let cubing_input = state[active] + addition_buffer + self.constants[r];
|
||||
let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)];
|
||||
constraints.push(cubing_input - cubing_input_wire);
|
||||
let f = cubing_input_wire.cube();
|
||||
@ -160,8 +160,6 @@ impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> for GMiMCGate<
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
vars: EvaluationTargets<D>,
|
||||
) -> Vec<ExtensionTarget<D>> {
|
||||
let one = builder.one_extension();
|
||||
let neg_one = builder.neg_one_extension();
|
||||
let mut constraints = Vec::with_capacity(self.num_constraints());
|
||||
|
||||
let swap = vars.local_wires[Self::WIRE_SWAP];
|
||||
@ -197,18 +195,8 @@ impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> for GMiMCGate<
|
||||
let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)];
|
||||
constraints.push(builder.sub_extension(cubing_input, cubing_input_wire));
|
||||
let f = builder.cube_extension(cubing_input_wire);
|
||||
// addition_buffer += f
|
||||
// state[active] -= f
|
||||
(addition_buffer, state[active]) = builder.double_arithmetic_extension(
|
||||
F::ONE,
|
||||
F::ONE,
|
||||
one,
|
||||
addition_buffer,
|
||||
f,
|
||||
neg_one,
|
||||
f,
|
||||
state[active],
|
||||
);
|
||||
addition_buffer = builder.add_extension(addition_buffer, f);
|
||||
state[active] = builder.sub_extension(state[active], f);
|
||||
}
|
||||
|
||||
for i in 0..W {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use std::convert::identity;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
@ -75,11 +74,6 @@ pub(crate) fn generate_partial_witness<F: Field>(
|
||||
|
||||
pending_generator_indices = next_pending_generator_indices;
|
||||
}
|
||||
|
||||
assert!(
|
||||
generator_is_expired.into_iter().all(identity),
|
||||
"Some generators weren't run."
|
||||
);
|
||||
}
|
||||
|
||||
/// A generator participates in the generation of the witness.
|
||||
|
||||
@ -60,6 +60,10 @@ pub struct CircuitBuilder<F: Extendable<D>, const D: usize> {
|
||||
|
||||
constants_to_targets: HashMap<F, Target>,
|
||||
targets_to_constants: HashMap<Target, F>,
|
||||
|
||||
/// A map `(c0, c1) -> (g, i)` from constants `(c0,c1)` to an available arithmetic gate using
|
||||
/// these constants with gate index `g` and already using `i` arithmetic operations.
|
||||
pub(crate) free_arithmetic: HashMap<(F, F), (usize, usize)>,
|
||||
}
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
@ -76,6 +80,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
generators: Vec::new(),
|
||||
constants_to_targets: HashMap::new(),
|
||||
targets_to_constants: HashMap::new(),
|
||||
free_arithmetic: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ impl CircuitConfig {
|
||||
pub(crate) fn large_config() -> Self {
|
||||
Self {
|
||||
num_wires: 126,
|
||||
num_routed_wires: 33,
|
||||
num_routed_wires: 64,
|
||||
security_bits: 128,
|
||||
rate_bits: 3,
|
||||
num_challenges: 3,
|
||||
@ -78,6 +78,7 @@ impl CircuitConfig {
|
||||
pub(crate) fn large_zk_config() -> Self {
|
||||
CircuitConfig {
|
||||
zero_knowledge: true,
|
||||
cap_height: 1,
|
||||
fri_config: FriConfig {
|
||||
proof_of_work_bits: 1,
|
||||
reduction_arity_bits: vec![1, 1, 1, 1],
|
||||
|
||||
@ -37,7 +37,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.constants(&inner_common_data.circuit_digest.elements),
|
||||
);
|
||||
challenger.observe_hash(&digest);
|
||||
challenger.observe_hash(&public_inputs_hash);
|
||||
challenger.observe_hash(public_inputs_hash);
|
||||
|
||||
challenger.observe_cap(&proof.wires_cap);
|
||||
let betas = challenger.get_n_challenges(self, num_challenges);
|
||||
@ -420,25 +420,25 @@ mod tests {
|
||||
const D: usize = 4;
|
||||
let config = CircuitConfig {
|
||||
num_wires: 126,
|
||||
num_routed_wires: 37,
|
||||
num_routed_wires: 64,
|
||||
security_bits: 128,
|
||||
rate_bits: 3,
|
||||
num_challenges: 3,
|
||||
zero_knowledge: false,
|
||||
cap_height: 3,
|
||||
fri_config: FriConfig {
|
||||
proof_of_work_bits: 1,
|
||||
reduction_arity_bits: vec![2, 2, 2, 2, 2, 2],
|
||||
num_query_rounds: 40,
|
||||
proof_of_work_bits: 20,
|
||||
reduction_arity_bits: vec![3, 3, 3],
|
||||
num_query_rounds: 27,
|
||||
},
|
||||
};
|
||||
let (proof_with_pis, vd, cd) = {
|
||||
let (proof_with_pis, vd, cd) = {
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
|
||||
let _two = builder.two();
|
||||
let _two = builder.hash_n_to_hash(vec![_two], true).elements[0];
|
||||
let mut _two = builder.hash_n_to_hash(vec![_two], true).elements[0];
|
||||
for _ in 0..10000 {
|
||||
let _two = builder.mul(_two, _two);
|
||||
_two = builder.mul(_two, _two);
|
||||
}
|
||||
let data = builder.build();
|
||||
(
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use num::Integer;
|
||||
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field_types::Field;
|
||||
@ -306,17 +304,8 @@ pub(crate) fn eval_vanishing_poly_recursively<F: Extendable<D>, const D: usize>(
|
||||
|
||||
// Holds `k[i] * x`.
|
||||
let mut s_ids = Vec::new();
|
||||
for j in 0..common_data.config.num_routed_wires / 2 {
|
||||
let k_0 = builder.constant(common_data.k_is[2 * j]);
|
||||
let k_0_ext = builder.convert_to_ext(k_0);
|
||||
let k_1 = builder.constant(common_data.k_is[2 * j + 1]);
|
||||
let k_1_ext = builder.convert_to_ext(k_1);
|
||||
let tmp = builder.mul_two_extension(k_0_ext, x, k_1_ext, x);
|
||||
s_ids.push(tmp.0);
|
||||
s_ids.push(tmp.1);
|
||||
}
|
||||
if common_data.config.num_routed_wires.is_odd() {
|
||||
let k = builder.constant(common_data.k_is[common_data.k_is.len() - 1]);
|
||||
for j in 0..common_data.config.num_routed_wires {
|
||||
let k = builder.constant(common_data.k_is[j]);
|
||||
let k_ext = builder.convert_to_ext(k);
|
||||
s_ids.push(builder.mul_extension(k_ext, x));
|
||||
}
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use num::Integer;
|
||||
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::{Extendable, Frobenius};
|
||||
use crate::field::field_types::Field;
|
||||
use crate::gates::arithmetic::ArithmeticExtensionGate;
|
||||
use crate::gates::reducing::ReducingGate;
|
||||
use crate::iop::target::Target;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
@ -164,40 +161,15 @@ impl<const D: usize> ReducingFactorTarget<D> {
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
let zero = builder.zero_extension();
|
||||
let l = terms.len();
|
||||
self.count += l as u64;
|
||||
|
||||
let mut terms_vec = terms.to_vec();
|
||||
// If needed, we pad the original vector so that it has even length.
|
||||
if terms_vec.len().is_odd() {
|
||||
terms_vec.push(zero);
|
||||
}
|
||||
let mut acc = terms_vec.pop().unwrap();
|
||||
terms_vec.reverse();
|
||||
|
||||
let mut acc = zero;
|
||||
for pair in terms_vec.chunks(2) {
|
||||
// We will route the output of the first arithmetic operation to the multiplicand of the
|
||||
// second, i.e. we compute the following:
|
||||
// out_0 = alpha acc + pair[0]
|
||||
// acc' = out_1 = alpha out_0 + pair[1]
|
||||
let gate = builder.num_gates();
|
||||
let out_0 = ExtensionTarget::from_range(
|
||||
gate,
|
||||
ArithmeticExtensionGate::<D>::wires_first_output(),
|
||||
);
|
||||
acc = builder
|
||||
.double_arithmetic_extension(
|
||||
F::ONE,
|
||||
F::ONE,
|
||||
self.base,
|
||||
acc,
|
||||
pair[0],
|
||||
self.base,
|
||||
out_0,
|
||||
pair[1],
|
||||
)
|
||||
.1;
|
||||
for x in terms_vec {
|
||||
acc = builder.mul_add_extension(self.base, acc, x);
|
||||
}
|
||||
acc
|
||||
}
|
||||
@ -215,23 +187,6 @@ impl<const D: usize> ReducingFactorTarget<D> {
|
||||
builder.mul_extension(exp, x)
|
||||
}
|
||||
|
||||
/// Returns `(self.shift(x), a*b)`.
|
||||
/// Used to take advantage of the second arithmetic operation in the `ArithmeticExtensionGate`.
|
||||
pub fn shift_and_mul<F>(
|
||||
&mut self,
|
||||
x: ExtensionTarget<D>,
|
||||
a: ExtensionTarget<D>,
|
||||
b: ExtensionTarget<D>,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> (ExtensionTarget<D>, ExtensionTarget<D>)
|
||||
where
|
||||
F: Extendable<D>,
|
||||
{
|
||||
let exp = builder.exp_u64_extension(self.base, self.count);
|
||||
self.count = 0;
|
||||
builder.mul_two_extension(exp, x, a, b)
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.count = 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user