Choose between high- and low-degree interpolation gate depending on the arity

This commit is contained in:
wborgeaud 2021-11-22 16:10:14 +01:00
parent 8522026c36
commit 6aaea002ed
7 changed files with 280 additions and 188 deletions

View File

@ -3,8 +3,10 @@ use crate::field::extension_field::Extendable;
use crate::field::field_types::{Field, RichField};
use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget};
use crate::fri::FriConfig;
use crate::gadgets::interpolation::InterpolationGate;
use crate::gates::gate::Gate;
use crate::gates::interpolation::InterpolationGate;
use crate::gates::interpolation::HighDegreeInterpolationGate;
use crate::gates::low_degree_interpolation::LowDegreeInterpolationGate;
use crate::gates::random_access::RandomAccessGate;
use crate::hash::hash_types::MerkleCapTarget;
use crate::iop::challenger::RecursiveChallenger;
@ -27,6 +29,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
arity_bits: usize,
evals: &[ExtensionTarget<D>],
beta: ExtensionTarget<D>,
common_data: &CommonCircuitData<F, D>,
) -> ExtensionTarget<D> {
let arity = 1 << arity_bits;
debug_assert_eq!(evals.len(), arity);
@ -43,7 +46,21 @@ impl<F: RichField + 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.
self.interpolate_coset(arity_bits, coset_start, &evals, beta)
if 1 << arity_bits > common_data.quotient_degree_factor {
self.interpolate_coset::<LowDegreeInterpolationGate<F, D>>(
arity_bits,
coset_start,
&evals,
beta,
)
} else {
self.interpolate_coset::<HighDegreeInterpolationGate<F, D>>(
arity_bits,
coset_start,
&evals,
beta,
)
}
}
/// Make sure we have enough wires and routed wires to do the FRI checks efficiently. This check
@ -54,7 +71,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
&self.config,
max_fri_arity_bits.max(self.config.cap_height),
);
let interpolation_gate = InterpolationGate::<F, D>::new(max_fri_arity_bits);
let interpolation_gate = HighDegreeInterpolationGate::<F, D>::new(max_fri_arity_bits);
let min_wires = random_access
.num_wires()
@ -379,6 +396,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
arity_bits,
evals,
betas[i],
&common_data
)
);

View File

@ -1,23 +1,90 @@
use std::ops::Range;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::RichField;
use crate::gates::interpolation::InterpolationGate;
use crate::gates::gate::Gate;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
pub(crate) trait InterpolationGate<F: RichField + Extendable<D>, const D: usize>:
Gate<F, D> + Copy
{
fn new(subgroup_bits: usize) -> Self;
fn num_points(&self) -> usize;
/// Wire index of the coset shift.
fn wire_shift(&self) -> usize {
0
}
fn start_values(&self) -> usize {
1
}
/// Wire indices of the `i`th interpolant value.
fn wires_value(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_values() + i * D;
start..start + D
}
fn start_evaluation_point(&self) -> usize {
self.start_values() + self.num_points() * D
}
/// Wire indices of the point to evaluate the interpolant at.
fn wires_evaluation_point(&self) -> Range<usize> {
let start = self.start_evaluation_point();
start..start + D
}
fn start_evaluation_value(&self) -> usize {
self.start_evaluation_point() + D
}
/// Wire indices of the interpolated value.
fn wires_evaluation_value(&self) -> Range<usize> {
let start = self.start_evaluation_value();
start..start + D
}
fn start_coeffs(&self) -> usize {
self.start_evaluation_value() + D
}
/// The number of routed wires required in the typical usage of this gate, where the points to
/// interpolate, the evaluation point, and the corresponding value are all routed.
fn num_routed_wires(&self) -> usize {
self.start_coeffs()
}
/// Wire indices of the interpolant's `i`th coefficient.
fn wires_coeff(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_coeffs() + i * D;
start..start + D
}
fn end_coeffs(&self) -> usize {
self.start_coeffs() + D * self.num_points()
}
}
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Interpolates a polynomial, whose points are a coset of the multiplicative subgroup with the
/// given size, and whose values are given. Returns the evaluation of the interpolant at
/// `evaluation_point`.
pub fn interpolate_coset(
pub(crate) fn interpolate_coset<G: InterpolationGate<F, D>>(
&mut self,
subgroup_bits: usize,
coset_shift: Target,
values: &[ExtensionTarget<D>],
evaluation_point: ExtensionTarget<D>,
) -> ExtensionTarget<D> {
let gate = InterpolationGate::new(subgroup_bits);
let gate_index = self.add_gate(gate.clone(), vec![]);
let gate = G::new(subgroup_bits);
let gate_index = self.add_gate(gate, vec![]);
self.connect(coset_shift, Target::wire(gate_index, gate.wire_shift()));
for (i, &v) in values.iter().enumerate() {
self.connect_extension(
@ -38,11 +105,14 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
mod tests {
use anyhow::Result;
use crate::field::extension_field::quadratic::QuadraticExtension;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::extension_field::FieldExtension;
use crate::field::field_types::Field;
use crate::field::goldilocks_field::GoldilocksField;
use crate::field::interpolation::interpolant;
use crate::gates::interpolation::HighDegreeInterpolationGate;
use crate::gates::low_degree_interpolation::LowDegreeInterpolationGate;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
@ -51,10 +121,11 @@ mod tests {
#[test]
fn test_interpolate() -> Result<()> {
type F = GoldilocksField;
type FF = QuarticExtension<GoldilocksField>;
const D: usize = 2;
type FF = QuadraticExtension<GoldilocksField>;
let config = CircuitConfig::standard_recursion_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, 4>::new(config);
let mut builder = CircuitBuilder::<F, D>::new(config);
let subgroup_bits = 2;
let len = 1 << subgroup_bits;
@ -66,7 +137,7 @@ mod tests {
let homogeneous_points = points
.iter()
.zip(values.iter())
.map(|(&a, &b)| (<FF as FieldExtension<4>>::from_basefield(a), b))
.map(|(&a, &b)| (<FF as FieldExtension<D>>::from_basefield(a), b))
.collect::<Vec<_>>();
let true_interpolant = interpolant(&homogeneous_points);
@ -83,9 +154,21 @@ mod tests {
let zt = builder.constant_extension(z);
let eval = builder.interpolate_coset(subgroup_bits, coset_shift_target, &value_targets, zt);
let eval_hd = builder.interpolate_coset::<HighDegreeInterpolationGate<F, D>>(
subgroup_bits,
coset_shift_target,
&value_targets,
zt,
);
let eval_ld = builder.interpolate_coset::<LowDegreeInterpolationGate<F, D>>(
subgroup_bits,
coset_shift_target,
&value_targets,
zt,
);
let true_eval_target = builder.constant_extension(true_eval);
builder.connect_extension(eval, true_eval_target);
builder.connect_extension(eval_hd, true_eval_target);
builder.connect_extension(eval_ld, true_eval_target);
let data = builder.build();
let proof = data.prove(pw)?;

View File

@ -225,11 +225,12 @@ mod tests {
use super::*;
use crate::field::goldilocks_field::GoldilocksField;
use crate::gadgets::interpolation::InterpolationGate;
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
use crate::gates::base_sum::BaseSumGate;
use crate::gates::constant::ConstantGate;
use crate::gates::gmimc::GMiMCGate;
use crate::gates::interpolation::InterpolationGate;
use crate::gates::interpolation::HighDegreeInterpolationGate;
use crate::gates::noop::NoopGate;
#[test]
@ -244,7 +245,7 @@ mod tests {
GateRef::new(ArithmeticExtensionGate { num_ops: 4 }),
GateRef::new(BaseSumGate::<4>::new(4)),
GateRef::new(GMiMCGate::<F, D, 12>::new()),
GateRef::new(InterpolationGate::new(2)),
GateRef::new(HighDegreeInterpolationGate::new(2)),
];
let (tree, _, _) = Tree::from_gates(gates.clone());

View File

@ -6,6 +6,7 @@ use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::RichField;
use crate::field::interpolation::interpolant;
use crate::gadgets::interpolation::InterpolationGate;
use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
@ -19,77 +20,13 @@ use crate::polynomial::polynomial::PolynomialCoeffs;
/// Interpolates a polynomial, whose points are a (base field) coset of the multiplicative subgroup
/// with the given size, and whose values are extension field elements, given by input wires.
/// Outputs the evaluation of the interpolant at a given (extension field) evaluation point.
#[derive(Clone, Debug)]
pub(crate) struct InterpolationGate<F: RichField + Extendable<D>, const D: usize> {
#[derive(Copy, Clone, Debug)]
pub(crate) struct HighDegreeInterpolationGate<F: RichField + Extendable<D>, const D: usize> {
pub subgroup_bits: usize,
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D>, const D: usize> InterpolationGate<F, D> {
pub fn new(subgroup_bits: usize) -> Self {
Self {
subgroup_bits,
_phantom: PhantomData,
}
}
fn num_points(&self) -> usize {
1 << self.subgroup_bits
}
/// Wire index of the coset shift.
pub fn wire_shift(&self) -> usize {
0
}
fn start_values(&self) -> usize {
1
}
/// Wire indices of the `i`th interpolant value.
pub fn wires_value(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_values() + i * D;
start..start + D
}
fn start_evaluation_point(&self) -> usize {
self.start_values() + self.num_points() * D
}
/// Wire indices of the point to evaluate the interpolant at.
pub fn wires_evaluation_point(&self) -> Range<usize> {
let start = self.start_evaluation_point();
start..start + D
}
fn start_evaluation_value(&self) -> usize {
self.start_evaluation_point() + D
}
/// Wire indices of the interpolated value.
pub fn wires_evaluation_value(&self) -> Range<usize> {
let start = self.start_evaluation_value();
start..start + D
}
fn start_coeffs(&self) -> usize {
self.start_evaluation_value() + D
}
/// The number of routed wires required in the typical usage of this gate, where the points to
/// interpolate, the evaluation point, and the corresponding value are all routed.
pub(crate) fn num_routed_wires(&self) -> usize {
self.start_coeffs()
}
/// Wire indices of the interpolant's `i`th coefficient.
pub fn wires_coeff(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_coeffs() + i * D;
start..start + D
}
impl<F: RichField + Extendable<D>, const D: usize> HighDegreeInterpolationGate<F, D> {
/// End of wire indices, exclusive.
fn end(&self) -> usize {
self.start_coeffs() + self.num_points() * D
@ -128,7 +65,77 @@ impl<F: RichField + Extendable<D>, const D: usize> InterpolationGate<F, D> {
}
}
impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for InterpolationGate<F, D> {
impl<F: RichField + Extendable<D>, const D: usize> InterpolationGate<F, D>
for HighDegreeInterpolationGate<F, D>
{
fn new(subgroup_bits: usize) -> Self {
Self {
subgroup_bits,
_phantom: PhantomData,
}
}
fn num_points(&self) -> usize {
1 << self.subgroup_bits
}
/// Wire index of the coset shift.
fn wire_shift(&self) -> usize {
0
}
fn start_values(&self) -> usize {
1
}
/// Wire indices of the `i`th interpolant value.
fn wires_value(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_values() + i * D;
start..start + D
}
fn start_evaluation_point(&self) -> usize {
self.start_values() + self.num_points() * D
}
/// Wire indices of the point to evaluate the interpolant at.
fn wires_evaluation_point(&self) -> Range<usize> {
let start = self.start_evaluation_point();
start..start + D
}
fn start_evaluation_value(&self) -> usize {
self.start_evaluation_point() + D
}
/// Wire indices of the interpolated value.
fn wires_evaluation_value(&self) -> Range<usize> {
let start = self.start_evaluation_value();
start..start + D
}
fn start_coeffs(&self) -> usize {
self.start_evaluation_value() + D
}
/// The number of routed wires required in the typical usage of this gate, where the points to
/// interpolate, the evaluation point, and the corresponding value are all routed.
fn num_routed_wires(&self) -> usize {
self.start_coeffs()
}
/// Wire indices of the interpolant's `i`th coefficient.
fn wires_coeff(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_coeffs() + i * D;
start..start + D
}
}
impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D>
for HighDegreeInterpolationGate<F, D>
{
fn id(&self) -> String {
format!("{:?}<D={}>", self, D)
}
@ -251,7 +258,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for InterpolationG
#[derive(Debug)]
struct InterpolationGenerator<F: RichField + Extendable<D>, const D: usize> {
gate_index: usize,
gate: InterpolationGate<F, D>,
gate: HighDegreeInterpolationGate<F, D>,
_phantom: PhantomData<F>,
}
@ -324,16 +331,17 @@ mod tests {
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::field::goldilocks_field::GoldilocksField;
use crate::gadgets::interpolation::InterpolationGate;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::gates::interpolation::InterpolationGate;
use crate::gates::interpolation::HighDegreeInterpolationGate;
use crate::hash::hash_types::HashOut;
use crate::plonk::vars::EvaluationVars;
use crate::polynomial::polynomial::PolynomialCoeffs;
#[test]
fn wire_indices() {
let gate = InterpolationGate::<GoldilocksField, 4> {
let gate = HighDegreeInterpolationGate::<GoldilocksField, 4> {
subgroup_bits: 1,
_phantom: PhantomData,
};
@ -352,12 +360,12 @@ mod tests {
#[test]
fn low_degree() {
test_low_degree::<GoldilocksField, _, 4>(InterpolationGate::new(2));
test_low_degree::<GoldilocksField, _, 4>(HighDegreeInterpolationGate::new(2));
}
#[test]
fn eval_fns() -> Result<()> {
test_eval_fns::<GoldilocksField, _, 4>(InterpolationGate::new(2))
test_eval_fns::<GoldilocksField, _, 4>(HighDegreeInterpolationGate::new(2))
}
#[test]
@ -368,7 +376,7 @@ mod tests {
/// Returns the local wires for an interpolation gate for given coeffs, points and eval point.
fn get_wires(
gate: &InterpolationGate<F, D>,
gate: &HighDegreeInterpolationGate<F, D>,
shift: F,
coeffs: PolynomialCoeffs<FF>,
eval_point: FF,
@ -390,7 +398,7 @@ mod tests {
let shift = F::rand();
let coeffs = PolynomialCoeffs::new(vec![FF::rand(), FF::rand()]);
let eval_point = FF::rand();
let gate = InterpolationGate::<F, D>::new(1);
let gate = HighDegreeInterpolationGate::<F, D>::new(1);
let vars = EvaluationVars {
local_constants: &[],
local_wires: &get_wires(&gate, shift, coeffs, eval_point),

View File

@ -1,11 +1,12 @@
use std::marker::PhantomData;
use std::ops::Range;
use crate::field::extension_field::algebra::{ExtensionAlgebra, PolynomialCoeffsAlgebra};
use crate::field::extension_field::algebra::PolynomialCoeffsAlgebra;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::{Field, RichField};
use crate::field::interpolation::interpolant;
use crate::gadgets::interpolation::InterpolationGate;
use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
@ -19,81 +20,13 @@ use crate::polynomial::polynomial::PolynomialCoeffs;
/// Interpolates a polynomial, whose points are a (base field) coset of the multiplicative subgroup
/// with the given size, and whose values are extension field elements, given by input wires.
/// Outputs the evaluation of the interpolant at a given (extension field) evaluation point.
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub(crate) struct LowDegreeInterpolationGate<F: RichField + Extendable<D>, const D: usize> {
pub subgroup_bits: usize,
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D>, const D: usize> LowDegreeInterpolationGate<F, D> {
pub fn new(subgroup_bits: usize) -> Self {
Self {
subgroup_bits,
_phantom: PhantomData,
}
}
fn num_points(&self) -> usize {
1 << self.subgroup_bits
}
/// Wire index of the coset shift.
pub fn wire_shift(&self) -> usize {
0
}
fn start_values(&self) -> usize {
1
}
/// Wire indices of the `i`th interpolant value.
pub fn wires_value(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_values() + i * D;
start..start + D
}
fn start_evaluation_point(&self) -> usize {
self.start_values() + self.num_points() * D
}
/// Wire indices of the point to evaluate the interpolant at.
pub fn wires_evaluation_point(&self) -> Range<usize> {
let start = self.start_evaluation_point();
start..start + D
}
fn start_evaluation_value(&self) -> usize {
self.start_evaluation_point() + D
}
/// Wire indices of the interpolated value.
pub fn wires_evaluation_value(&self) -> Range<usize> {
let start = self.start_evaluation_value();
start..start + D
}
fn start_coeffs(&self) -> usize {
self.start_evaluation_value() + D
}
/// The number of routed wires required in the typical usage of this gate, where the points to
/// interpolate, the evaluation point, and the corresponding value are all routed.
pub(crate) fn num_routed_wires(&self) -> usize {
self.start_coeffs()
}
/// Wire indices of the interpolant's `i`th coefficient.
pub fn wires_coeff(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_coeffs() + i * D;
start..start + D
}
fn end_coeffs(&self) -> usize {
self.start_coeffs() + D * self.num_points()
}
pub fn powers_init(&self, i: usize) -> usize {
debug_assert!(0 < i && i < self.num_points());
if i == 1 {
@ -123,29 +56,77 @@ impl<F: RichField + Extendable<D>, const D: usize> LowDegreeInterpolationGate<F,
// Speed matters here, so we avoid `cyclic_subgroup_coset_known_order` which allocates.
g.powers().take(size).map(move |x| x * shift)
}
}
/// The domain of the points we're interpolating.
fn coset_ext(&self, shift: F::Extension) -> impl Iterator<Item = F::Extension> {
let g = F::primitive_root_of_unity(self.subgroup_bits);
let size = 1 << self.subgroup_bits;
g.powers().take(size).map(move |x| shift.scalar_mul(x))
impl<F: RichField + Extendable<D>, const D: usize> InterpolationGate<F, D>
for LowDegreeInterpolationGate<F, D>
{
fn new(subgroup_bits: usize) -> Self {
Self {
subgroup_bits,
_phantom: PhantomData,
}
}
/// The domain of the points we're interpolating.
fn coset_ext_recursive(
&self,
builder: &mut CircuitBuilder<F, D>,
shift: ExtensionTarget<D>,
) -> Vec<ExtensionTarget<D>> {
let g = F::primitive_root_of_unity(self.subgroup_bits);
let size = 1 << self.subgroup_bits;
g.powers()
.take(size)
.map(move |x| {
let subgroup_element = builder.constant(x.into());
builder.scalar_mul_ext(subgroup_element, shift)
})
.collect()
fn num_points(&self) -> usize {
1 << self.subgroup_bits
}
/// Wire index of the coset shift.
fn wire_shift(&self) -> usize {
0
}
fn start_values(&self) -> usize {
1
}
/// Wire indices of the `i`th interpolant value.
fn wires_value(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_values() + i * D;
start..start + D
}
fn start_evaluation_point(&self) -> usize {
self.start_values() + self.num_points() * D
}
/// Wire indices of the point to evaluate the interpolant at.
fn wires_evaluation_point(&self) -> Range<usize> {
let start = self.start_evaluation_point();
start..start + D
}
fn start_evaluation_value(&self) -> usize {
self.start_evaluation_point() + D
}
/// Wire indices of the interpolated value.
fn wires_evaluation_value(&self) -> Range<usize> {
let start = self.start_evaluation_value();
start..start + D
}
fn start_coeffs(&self) -> usize {
self.start_evaluation_value() + D
}
/// The number of routed wires required in the typical usage of this gate, where the points to
/// interpolate, the evaluation point, and the corresponding value are all routed.
fn num_routed_wires(&self) -> usize {
self.start_coeffs()
}
/// Wire indices of the interpolant's `i`th coefficient.
fn wires_coeff(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points());
let start = self.start_coeffs() + i * D;
start..start + D
}
fn end_coeffs(&self) -> usize {
self.start_coeffs() + D * self.num_points()
}
}
@ -186,7 +167,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LowDegreeInter
constraints.extend(&(value - computed_value).to_basefield_array());
}
let mut evaluation_point_powers = (1..self.num_points())
let evaluation_point_powers = (1..self.num_points())
.map(|i| vars.get_local_ext_algebra(self.powers_eval(i)))
.collect::<Vec<_>>();
let evaluation_point = evaluation_point_powers[0];
@ -408,11 +389,13 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
let wire_shift = get_local_wire(self.gate.wire_shift());
for i in 2..self.gate.num_points() {
out_buffer.set_wire(
local_wire(self.gate.powers_init(i)),
wire_shift.exp_u64(i as u64),
);
for (i, power) in wire_shift
.powers()
.take(self.gate.num_points())
.enumerate()
.skip(2)
{
out_buffer.set_wire(local_wire(self.gate.powers_init(i)), power);
}
// Compute the interpolant.
@ -452,6 +435,7 @@ mod tests {
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::field::goldilocks_field::GoldilocksField;
use crate::gadgets::interpolation::InterpolationGate;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::gates::low_degree_interpolation::LowDegreeInterpolationGate;

View File

@ -687,7 +687,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
marked_targets: self.marked_targets,
representative_map: forest.parents,
fft_root_table: Some(fft_root_table),
instances: self.gate_instances,
};
// The HashSet of gates will have a non-deterministic order. When converting to a Vec, we

View File

@ -9,7 +9,7 @@ use crate::field::field_types::{Field, RichField};
use crate::fri::commitment::PolynomialBatchCommitment;
use crate::fri::reduction_strategies::FriReductionStrategy;
use crate::fri::{FriConfig, FriParams};
use crate::gates::gate::{GateInstance, PrefixedGate};
use crate::gates::gate::PrefixedGate;
use crate::hash::hash_types::{HashOut, MerkleCapTarget};
use crate::hash::merkle_tree::MerkleCap;
use crate::iop::generator::WitnessGenerator;
@ -177,7 +177,6 @@ pub(crate) struct ProverOnlyCircuitData<F: RichField + Extendable<D>, const D: u
pub representative_map: Vec<usize>,
/// Pre-computed roots for faster FFT.
pub fft_root_table: Option<FftRootTable<F>>,
pub instances: Vec<GateInstance<F, D>>,
}
/// Circuit data required by the verifier, but not the prover.