This commit is contained in:
wborgeaud 2022-03-25 06:36:04 +01:00
parent 1d77116ef3
commit d6b99df876
17 changed files with 119 additions and 489 deletions

View File

@ -613,7 +613,6 @@ mod tests {
type FF = <C as GenericConfig<D>>::FE;
let config = CircuitConfig::standard_recursion_zk_config();
let config = CircuitConfig::standard_recursion_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, D>::new(config);

View File

@ -262,7 +262,6 @@ mod tests {
use crate::iop::witness::Witness;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::constest::check_constraints;
use crate::{
iop::witness::PartialWitness,
plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig, verifier::verify},
@ -353,7 +352,6 @@ mod tests {
pw.set_biguint_target(&y, &y_value);
pw.set_biguint_target(&expected_z, &expected_z_value);
// check_constraints::<F, C, D>(builder, pw)
let data = builder.build::<C>();
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)

View File

@ -130,48 +130,48 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32AddManyGate
constraints
}
// fn eval_unfiltered_base_one(
// &self,
// vars: EvaluationVarsBase<F>,
// mut yield_constr: StridedConstraintConsumer<F>,
// ) {
// for i in 0..self.num_ops {
// let addends: Vec<F> = (0..self.num_addends)
// .map(|j| vars.local_wires[self.wire_ith_op_jth_addend(i, j)])
// .collect();
// let carry = vars.local_wires[self.wire_ith_carry(i)];
//
// let computed_output = addends.iter().fold(F::ZERO, |x, &y| x + y) + carry;
//
// let output_result = vars.local_wires[self.wire_ith_output_result(i)];
// let output_carry = vars.local_wires[self.wire_ith_output_carry(i)];
//
// let base = F::from_canonical_u64(1 << 32u64);
// let combined_output = output_carry * base + output_result;
//
// yield_constr.one(combined_output - computed_output);
//
// let mut combined_result_limbs = F::ZERO;
// let mut combined_carry_limbs = F::ZERO;
// let base = F::from_canonical_u64(1u64 << Self::limb_bits());
// for j in (0..Self::num_limbs()).rev() {
// let this_limb = vars.local_wires[self.wire_ith_output_jth_limb(i, j)];
// let max_limb = 1 << Self::limb_bits();
// let product = (0..max_limb)
// .map(|x| this_limb - F::from_canonical_usize(x))
// .product();
// yield_constr.one(product);
//
// if j < Self::num_result_limbs() {
// combined_result_limbs = base * combined_result_limbs + this_limb;
// } else {
// combined_carry_limbs = base * combined_carry_limbs + this_limb;
// }
// }
// yield_constr.one(combined_result_limbs - output_result);
// yield_constr.one(combined_carry_limbs - output_carry);
// }
// }
fn eval_unfiltered_base_one(
&self,
vars: EvaluationVarsBase<F>,
mut yield_constr: StridedConstraintConsumer<F>,
) {
for i in 0..self.num_ops {
let addends: Vec<F> = (0..self.num_addends)
.map(|j| vars.local_wires[self.wire_ith_op_jth_addend(i, j)])
.collect();
let carry = vars.local_wires[self.wire_ith_carry(i)];
let computed_output = addends.iter().fold(F::ZERO, |x, &y| x + y) + carry;
let output_result = vars.local_wires[self.wire_ith_output_result(i)];
let output_carry = vars.local_wires[self.wire_ith_output_carry(i)];
let base = F::from_canonical_u64(1 << 32u64);
let combined_output = output_carry * base + output_result;
yield_constr.one(combined_output - computed_output);
let mut combined_result_limbs = F::ZERO;
let mut combined_carry_limbs = F::ZERO;
let base = F::from_canonical_u64(1u64 << Self::limb_bits());
for j in (0..Self::num_limbs()).rev() {
let this_limb = vars.local_wires[self.wire_ith_output_jth_limb(i, j)];
let max_limb = 1 << Self::limb_bits();
let product = (0..max_limb)
.map(|x| this_limb - F::from_canonical_usize(x))
.product();
yield_constr.one(product);
if j < Self::num_result_limbs() {
combined_result_limbs = base * combined_result_limbs + this_limb;
} else {
combined_carry_limbs = base * combined_carry_limbs + this_limb;
}
}
yield_constr.one(combined_result_limbs - output_result);
yield_constr.one(combined_carry_limbs - output_carry);
}
}
fn eval_unfiltered_recursively(
&self,

View File

@ -125,17 +125,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for U32ArithmeticG
constraints
}
// fn eval_unfiltered_base_one(
// &self,
// _vars: EvaluationVarsBase<F>,
// _yield_constr: StridedConstraintConsumer<F>,
// ) {
// panic!("use eval_unfiltered_base_packed instead");
// }
//
// fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch<F>) -> Vec<F> {
// self.eval_unfiltered_base_batch_packed(vars_base)
// }
fn eval_unfiltered_base_one(
&self,
_vars: EvaluationVarsBase<F>,
_yield_constr: StridedConstraintConsumer<F>,
) {
panic!("use eval_unfiltered_base_packed instead");
}
fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch<F>) -> Vec<F> {
self.eval_unfiltered_base_batch_packed(vars_base)
}
fn eval_unfiltered_recursively(
&self,

View File

@ -48,17 +48,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
.collect()
}
// fn eval_unfiltered_base_one(
// &self,
// _vars: EvaluationVarsBase<F>,
// _yield_constr: StridedConstraintConsumer<F>,
// ) {
// panic!("use eval_unfiltered_base_packed instead");
// }
fn eval_unfiltered_base_one(
&self,
_vars: EvaluationVarsBase<F>,
_yield_constr: StridedConstraintConsumer<F>,
) {
panic!("use eval_unfiltered_base_packed instead");
}
// fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch<F>) -> Vec<F> {
// self.eval_unfiltered_base_batch_packed(vars_base)
// }
fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch<F>) -> Vec<F> {
self.eval_unfiltered_base_batch_packed(vars_base)
}
fn eval_unfiltered_recursively(
&self,
@ -113,17 +113,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ConstantGate {
}
}
// impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for ConstantGate {
// fn eval_unfiltered_base_packed<P: PackedField<Scalar = F>>(
// &self,
// vars: EvaluationVarsBasePacked<P>,
// mut yield_constr: StridedConstraintConsumer<P>,
// ) {
// yield_constr.many((0..self.num_consts).map(|i| {
// vars.get_constant(self.const_input(i)) - vars.local_wires[self.wire_output(i)]
// }));
// }
// }
impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for ConstantGate {
fn eval_unfiltered_base_packed<P: PackedField<Scalar = F>>(
&self,
vars: EvaluationVarsBasePacked<P>,
mut yield_constr: StridedConstraintConsumer<P>,
) {
yield_constr.many((0..self.num_consts).map(|i| {
vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)]
}));
}
}
#[derive(Debug)]
struct ConstantGenerator<F: Field> {

View File

@ -7,7 +7,6 @@ use plonky2_field::batch_util::batch_multiply_inplace;
use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::field_types::Field;
use crate::gates::gate_tree::Tree;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
@ -93,13 +92,6 @@ pub trait Gate<F: RichField + Extendable<D>, const D: usize>: 'static + Send + S
combination_range,
vars.local_constants[selector_index],
);
// println!(
// "{} {:?} {} {}",
// self.id(),
// combination_range,
// gate_index,
// self.degree()
// );
vars.remove_prefix(num_selectors);
self.eval_unfiltered(vars)
.into_iter()
@ -237,18 +229,9 @@ pub struct PrefixedGate<F: RichField + Extendable<D>, const D: usize> {
pub prefix: Vec<bool>,
}
impl<F: RichField + Extendable<D>, const D: usize> PrefixedGate<F, D> {
pub fn from_tree(tree: Tree<GateRef<F, D>>) -> Vec<Self> {
tree.traversal()
.into_iter()
.map(|(gate, prefix)| PrefixedGate { gate, prefix })
.collect()
}
}
/// A gate's filter is computed as `prod b_i*c_i + (1-b_i)*(1-c_i)`, with `(b_i)` the prefix and
/// `(c_i)` the local constants, which is one if the prefix of `constants` matches `prefix`.
fn compute_filter<'a, K: Field>(
fn compute_filter<K: Field>(
gate_index: usize,
combination_range: (usize, usize),
constant: K,

View File

@ -1,294 +0,0 @@
use log::debug;
use plonky2_field::extension_field::Extendable;
use crate::gates::gate::GateRef;
use crate::hash::hash_types::RichField;
/// A binary tree where leaves hold some type `T` and other nodes are empty.
#[derive(Debug, Clone)]
pub enum Tree<T> {
Leaf(T),
Bifurcation(Option<Box<Tree<T>>>, Option<Box<Tree<T>>>),
}
impl<T> Default for Tree<T> {
fn default() -> Self {
Self::Bifurcation(None, None)
}
}
impl<T: Clone> Tree<T> {
/// Traverse a tree using a depth-first traversal and collect data and position for each leaf.
/// A leaf's position is represented by its left/right path, where `false` means left and `true` means right.
pub fn traversal(&self) -> Vec<(T, Vec<bool>)> {
let mut res = Vec::new();
let prefix = [];
self.traverse(&prefix, &mut res);
res
}
/// Utility function to traverse the tree.
fn traverse(&self, prefix: &[bool], current: &mut Vec<(T, Vec<bool>)>) {
match &self {
// If node is a leaf, collect the data and position.
Tree::Leaf(t) => {
current.push((t.clone(), prefix.to_vec()));
}
// Otherwise, traverse the left subtree and then the right subtree.
Tree::Bifurcation(left, right) => {
if let Some(l) = left {
let mut left_prefix = prefix.to_vec();
left_prefix.push(false);
l.traverse(&left_prefix, current);
}
if let Some(r) = right {
let mut right_prefix = prefix.to_vec();
right_prefix.push(true);
r.traverse(&right_prefix, current);
}
}
}
}
}
impl<F: RichField + Extendable<D>, const D: usize> Tree<GateRef<F, D>> {
/// The binary gate tree influences the degree `D` of the constraint polynomial and the number `C`
/// of constant wires in the circuit. We want to construct a tree minimizing both values. To do so
/// we iterate over possible values of `(D, C)` and try to construct a tree with these values.
/// For this construction, we use the greedy algorithm in `Self::find_tree`.
/// This latter function greedily adds gates at the depth where
/// `filtered_deg(gate)=D, constant_wires(gate)=C` to ensure no space is wasted.
/// We return the first tree found in this manner, along with it's maximum filtered degree
/// and the number of constant wires needed when using this tree.
pub fn from_gates(mut gates: Vec<GateRef<F, D>>) -> (Self, usize, usize) {
let timer = std::time::Instant::now();
gates.sort_unstable_by_key(|g| (-(g.0.degree() as isize), -(g.0.num_constants() as isize)));
for max_degree_bits in 1..10 {
// The quotient polynomials are padded to the next power of 2 in `compute_quotient_polys`.
// So we can restrict our search space by setting `max_degree` to 1 + a power of 2.
let max_degree = (1 << max_degree_bits) + 1;
for max_constants in 1..100 {
if let Some(mut best_tree) = Self::find_tree(&gates, max_degree, max_constants) {
let mut best_num_constants = best_tree.num_constants();
let mut best_degree = max_degree;
// Iterate backwards from `max_degree` to try to find a tree with a lower degree
// but the same number of constants.
'optdegree: for degree in (0..max_degree).rev() {
if let Some(tree) = Self::find_tree(&gates, degree, max_constants) {
let num_constants = tree.num_constants();
if num_constants > best_num_constants {
break 'optdegree;
} else {
best_degree = degree;
best_num_constants = num_constants;
best_tree = tree;
}
}
}
debug!(
"Found tree with max degree {} and {} constants wires in {:.4}s.",
best_degree,
best_num_constants,
timer.elapsed().as_secs_f32()
);
return (best_tree, best_degree, best_num_constants);
}
}
}
panic!("Can't find a tree.")
}
/// Greedily add gates wherever possible. Returns `None` if this fails.
fn find_tree(gates: &[GateRef<F, D>], max_degree: usize, max_constants: usize) -> Option<Self> {
let mut tree = Tree::default();
for g in gates {
tree.try_add_gate(g, max_degree, max_constants)?;
}
tree.shorten();
Some(tree)
}
/// Try to add a gate in the tree. Returns `None` if this fails.
fn try_add_gate(
&mut self,
g: &GateRef<F, D>,
max_degree: usize,
max_constants: usize,
) -> Option<()> {
// We want `gate.degree + depth <= max_degree` and `gate.num_constants + depth <= max_wires`.
let depth = max_degree
.checked_sub(g.0.degree())?
.min(max_constants.checked_sub(g.0.num_constants())?);
self.try_add_gate_at_depth(g, depth)
}
/// Try to add a gate in the tree at a specified depth. Returns `None` if this fails.
fn try_add_gate_at_depth(&mut self, g: &GateRef<F, D>, depth: usize) -> Option<()> {
// If depth is 0, we have to insert the gate here.
if depth == 0 {
return if let Tree::Bifurcation(None, None) = self {
// Insert the gate as a new leaf.
*self = Tree::Leaf(g.clone());
Some(())
} else {
// A leaf is already here.
None
};
}
// A leaf is already here so we cannot go deeper.
if let Tree::Leaf(_) = self {
return None;
}
if let Tree::Bifurcation(left, right) = self {
if let Some(left) = left {
// Try to add the gate to the left if there's already a left subtree.
if left.try_add_gate_at_depth(g, depth - 1).is_some() {
return Some(());
}
} else {
// Add a new left subtree and try to add the gate to it.
let mut new_left = Tree::default();
if new_left.try_add_gate_at_depth(g, depth - 1).is_some() {
*left = Some(Box::new(new_left));
return Some(());
}
}
if let Some(right) = right {
// Try to add the gate to the right if there's already a right subtree.
if right.try_add_gate_at_depth(g, depth - 1).is_some() {
return Some(());
}
} else {
// Add a new right subtree and try to add the gate to it.
let mut new_right = Tree::default();
if new_right.try_add_gate_at_depth(g, depth - 1).is_some() {
*right = Some(Box::new(new_right));
return Some(());
}
}
}
None
}
/// `Self::find_tree` returns a tree where each gate has `F(gate)=M` (see `Self::from_gates` comment).
/// This can produce subtrees with more nodes than necessary. This function removes useless nodes,
/// i.e., nodes that have a left but no right subtree.
fn shorten(&mut self) {
if let Tree::Bifurcation(left, right) = self {
if let (Some(left), None) = (left, right) {
// If the node has a left but no right subtree, set the node to its (shortened) left subtree.
let mut new = *left.clone();
new.shorten();
*self = new;
}
}
if let Tree::Bifurcation(left, right) = self {
if let Some(left) = left {
// Shorten the left subtree if there is one.
left.shorten();
}
if let Some(right) = right {
// Shorten the right subtree if there is one.
right.shorten();
}
}
}
/// Returns the tree's maximum filtered constraint degree.
pub fn max_filtered_degree(&self) -> usize {
self.traversal()
.into_iter()
.map(|(g, p)| g.0.degree() + p.len())
.max()
.expect("Empty tree.")
}
/// Returns the number of constant wires needed to fit all prefixes and gate constants.
fn num_constants(&self) -> usize {
self.traversal()
.into_iter()
.map(|(g, p)| g.0.num_constants() + p.len())
.max()
.expect("Empty tree.")
}
}
#[cfg(test)]
mod tests {
use log::info;
use super::*;
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::interpolation::HighDegreeInterpolationGate;
use crate::gates::noop::NoopGate;
use crate::gates::poseidon::PoseidonGate;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
#[test]
fn test_prefix_generation() {
env_logger::init();
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
let gates = vec![
GateRef::new(NoopGate),
GateRef::new(ConstantGate { num_consts: 4 }),
GateRef::new(ArithmeticExtensionGate { num_ops: 4 }),
GateRef::new(BaseSumGate::<4>::new(4)),
GateRef::new(PoseidonGate::<F, D>::new()),
GateRef::new(HighDegreeInterpolationGate::new(2)),
];
let (tree, _, _) = Tree::from_gates(gates.clone());
let mut gates_with_prefix = tree.traversal();
for (g, p) in &gates_with_prefix {
info!(
"\nGate: {}, prefix: {:?}.\n\
Filtered constraint degree: {}, Num constant wires: {}",
&g.0.id()[..20.min(g.0.id().len())],
p,
g.0.degree() + p.len(),
g.0.num_constants() + p.len()
);
}
assert_eq!(
gates_with_prefix.len(),
gates.len(),
"The tree has too much or too little gates."
);
assert!(
gates
.iter()
.all(|g| gates_with_prefix.iter().map(|(gg, _)| gg).any(|gg| gg == g)),
"Some gates are not in the tree."
);
assert!(
gates_with_prefix
.iter()
.all(|(g, p)| g.0.degree() + g.0.num_constants() + p.len() <= 9),
"Total degree is larger than 8."
);
gates_with_prefix.sort_unstable_by_key(|(_g, p)| p.len());
for i in 0..gates_with_prefix.len() {
for j in i + 1..gates_with_prefix.len() {
assert_ne!(
&gates_with_prefix[i].1,
&gates_with_prefix[j].1[0..gates_with_prefix[i].1.len()],
"Some gates share an overlapping prefix"
);
}
}
}
}

View File

@ -11,7 +11,6 @@ pub mod comparison;
pub mod constant;
pub mod exponentiation;
pub mod gate;
pub mod gate_tree;
pub mod interpolation;
pub mod low_degree_interpolation;
pub mod multiplication_extension;

View File

@ -67,22 +67,22 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for MulExtensionGa
constraints
}
// fn eval_unfiltered_base_one(
// &self,
// vars: EvaluationVarsBase<F>,
// mut yield_constr: StridedConstraintConsumer<F>,
// ) {
// let const_0 = vars.get_constant(0);
//
// for i in 0..self.num_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 output = vars.get_local_ext(Self::wires_ith_output(i));
// let computed_output = (multiplicand_0 * multiplicand_1).scalar_mul(const_0);
//
// yield_constr.many((output - computed_output).to_basefield_array());
// }
// }
fn eval_unfiltered_base_one(
&self,
vars: EvaluationVarsBase<F>,
mut yield_constr: StridedConstraintConsumer<F>,
) {
let const_0 = vars.local_constants[0];
for i in 0..self.num_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 output = vars.get_local_ext(Self::wires_ith_output(i));
let computed_output = (multiplicand_0 * multiplicand_1).scalar_mul(const_0);
yield_constr.many((output - computed_output).to_basefield_array());
}
}
fn eval_unfiltered_recursively(
&self,

View File

@ -36,17 +36,17 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for PublicInputGat
.collect()
}
// fn eval_unfiltered_base_one(
// &self,
// _vars: EvaluationVarsBase<F>,
// _yield_constr: StridedConstraintConsumer<F>,
// ) {
// panic!("use eval_unfiltered_base_packed instead");
// }
//
// fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch<F>) -> Vec<F> {
// self.eval_unfiltered_base_batch_packed(vars_base)
// }
fn eval_unfiltered_base_one(
&self,
_vars: EvaluationVarsBase<F>,
_yield_constr: StridedConstraintConsumer<F>,
) {
panic!("use eval_unfiltered_base_packed instead");
}
fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch<F>) -> Vec<F> {
self.eval_unfiltered_base_batch_packed(vars_base)
}
fn eval_unfiltered_recursively(
&self,

View File

@ -5,7 +5,7 @@ use crate::gates::gate::{GateInstance, GateRef};
use crate::hash::hash_types::RichField;
pub(crate) fn compute_selectors<F: RichField + Extendable<D>, const D: usize>(
mut gates: Vec<GateRef<F, D>>,
gates: Vec<GateRef<F, D>>,
instances: &[GateInstance<F, D>],
max_degree: usize,
) -> (
@ -21,13 +21,12 @@ pub(crate) fn compute_selectors<F: RichField + Extendable<D>, const D: usize>(
while pos < gates.len() {
let mut i = 0;
while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() + 1 <= max_degree) {
while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() < max_degree) {
i += 1;
}
combinations.push((pos, pos + i));
pos += i;
}
dbg!(&combinations);
let bad = F::from_canonical_usize(u32::MAX as usize);
let num_constants_polynomials = gates.iter().map(|g| g.0.num_constants()).max().unwrap();

View File

@ -19,8 +19,7 @@ use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
use crate::gates::arithmetic_base::ArithmeticGate;
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
use crate::gates::constant::ConstantGate;
use crate::gates::gate::{CurrentSlot, Gate, GateInstance, GateRef, PrefixedGate};
use crate::gates::gate_tree::Tree;
use crate::gates::gate::{CurrentSlot, Gate, GateInstance, GateRef};
use crate::gates::noop::NoopGate;
use crate::gates::public_input::PublicInputGate;
use crate::gates::selectors::compute_selectors;
@ -45,22 +44,22 @@ use crate::util::context_tree::ContextTree;
use crate::util::marking::{Markable, MarkedTargets};
use crate::util::partial_products::num_partial_products;
use crate::util::timing::TimingTree;
use crate::util::{transpose, transpose_poly_values};
use crate::util::transpose_poly_values;
pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
pub config: CircuitConfig,
/// The types of gates used in this circuit.
pub(crate) gates: HashSet<GateRef<F, D>>,
gates: HashSet<GateRef<F, D>>,
/// The concrete placement of each gate.
pub(crate) gate_instances: Vec<GateInstance<F, D>>,
/// Targets to be made public.
pub(crate) public_inputs: Vec<Target>,
public_inputs: Vec<Target>,
/// The next available index for a `VirtualTarget`.
pub(crate) virtual_target_index: usize,
virtual_target_index: usize,
copy_constraints: Vec<CopyConstraint>,
@ -68,10 +67,10 @@ pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
context_log: ContextTree,
/// A vector of marked targets. The values assigned to these targets will be displayed by the prover.
pub(crate) marked_targets: Vec<MarkedTargets<D>>,
marked_targets: Vec<MarkedTargets<D>>,
/// Generators used to generate the witness.
pub(crate) generators: Vec<Box<dyn WitnessGenerator<F>>>,
generators: Vec<Box<dyn WitnessGenerator<F>>>,
constants_to_targets: HashMap<F, Target>,
targets_to_constants: HashMap<Target, F>,
@ -83,7 +82,7 @@ pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
pub(crate) arithmetic_results: HashMap<ExtensionArithmeticOperation<F, D>, ExtensionTarget<D>>,
/// Map between gate type and the current gate of this type with available slots.
pub(crate) current_slots: HashMap<GateRef<F, D>, CurrentSlot<F, D>>,
current_slots: HashMap<GateRef<F, D>, CurrentSlot<F, D>>,
}
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
@ -424,7 +423,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
(gate_idx, slot_idx)
}
pub(crate) fn fri_params(&self, degree_bits: usize) -> FriParams {
fn fri_params(&self, degree_bits: usize) -> FriParams {
self.config
.fri_config
.fri_params(degree_bits, self.config.zero_knowledge)
@ -493,7 +492,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
pub(crate) fn blind_and_pad(&mut self) {
fn blind_and_pad(&mut self) {
if self.config.zero_knowledge {
self.blind();
}
@ -552,39 +551,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
fn constant_polys(
&self,
gates: &[PrefixedGate<F, D>],
num_constants: usize,
) -> Vec<PolynomialValues<F>> {
let constants_per_gate = self
.gate_instances
.iter()
.map(|gate| {
let prefix = &gates
.iter()
.find(|g| g.gate.0.id() == gate.gate_ref.0.id())
.unwrap()
.prefix;
let mut prefixed_constants = Vec::with_capacity(num_constants);
prefixed_constants.extend(prefix.iter().map(|&b| if b { F::ONE } else { F::ZERO }));
prefixed_constants.extend_from_slice(&gate.constants);
prefixed_constants.resize(num_constants, F::ZERO);
prefixed_constants
})
.collect::<Vec<_>>();
transpose(&constants_per_gate)
.into_iter()
.map(PolynomialValues::new)
.collect()
}
pub(crate) fn sigma_vecs(
&self,
k_is: &[F],
subgroup: &[F],
) -> (Vec<PolynomialValues<F>>, Forest) {
fn sigma_vecs(&self, k_is: &[F], subgroup: &[F]) -> (Vec<PolynomialValues<F>>, Forest) {
let degree = self.gate_instances.len();
let degree_log = log2_strict(degree);
let config = &self.config;
@ -682,29 +649,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
&self.gate_instances,
self.config.max_quotient_degree_factor + 1,
);
// dbg!(&constant_vecs, &selector_indices, &combination_ranges);
let num_constants = constant_vecs.len();
// let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates);
// let prefixed_gates = PrefixedGate::from_tree(gate_tree);
//
// // `quotient_degree_factor` has to be between `max_filtered_constraint_degree-1` and `1<<rate_bits`.
// // We find the value that minimizes `num_partial_product + quotient_degree_factor`.
// let min_quotient_degree_factor = (max_filtered_constraint_degree - 1).max(2);
// let max_quotient_degree_factor = self.config.max_quotient_degree_factor.min(1 << rate_bits);
// let quotient_degree_factor = (min_quotient_degree_factor..=max_quotient_degree_factor)
// .min_by_key(|&q| num_partial_products(self.config.num_routed_wires, q) + q)
// .unwrap();
let quotient_degree_factor = self.config.max_quotient_degree_factor;
debug!("Quotient degree factor set to: {}.", quotient_degree_factor);
let subgroup = F::two_adic_subgroup(degree_bits);
// let constant_vecs = timed!(
// timing,
// "generate constant polynomials",
// self.constant_polys(&prefixed_gates, num_constants)
// );
let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires);
let (sigma_vecs, forest) = timed!(
timing,

View File

@ -12,7 +12,7 @@ use crate::fri::structure::{
FriBatchInfo, FriBatchInfoTarget, FriInstanceInfo, FriInstanceInfoTarget, FriPolynomialInfo,
};
use crate::fri::{FriConfig, FriParams};
use crate::gates::gate::{Gate, GateRef, PrefixedGate};
use crate::gates::gate::GateRef;
use crate::hash::hash_types::{MerkleCapTarget, RichField};
use crate::hash::merkle_tree::MerkleCap;
use crate::iop::ext_target::ExtensionTarget;

View File

@ -1,7 +1,6 @@
pub mod circuit_builder;
pub mod circuit_data;
pub mod config;
pub mod constest;
pub(crate) mod copy_constraint;
mod get_challenges;
pub(crate) mod permutation_argument;

View File

@ -224,13 +224,11 @@ mod tests {
// Start with a degree 2^14 proof
let (proof, vd, cd) = dummy_proof::<F, C, D>(&config, 16_000)?;
assert_eq!(cd.degree_bits, 14);
test_serialization(&proof, &cd)?;
// Shrink it to 2^13.
let (proof, vd, cd) =
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, Some(13), false, false)?;
assert_eq!(cd.degree_bits, 13);
test_serialization(&proof, &cd)?;
// Shrink it to 2^12.
let (proof, _vd, cd) =

View File

@ -3,7 +3,6 @@ use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::field_types::Field;
use plonky2_field::zero_poly_coset::ZeroPolyOnCoset;
use crate::gates::gate::{Gate, GateRef, PrefixedGate};
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::target::Target;
@ -127,7 +126,7 @@ pub(crate) fn eval_vanishing_poly_base_batch<
let num_gate_constraints = common_data.num_gate_constraints;
let constraint_terms_batch = evaluate_gate_constraints_base_batch(&common_data, vars_batch);
let constraint_terms_batch = evaluate_gate_constraints_base_batch(common_data, vars_batch);
debug_assert!(constraint_terms_batch.len() == n * num_gate_constraints);
let num_challenges = common_data.config.num_challenges;
@ -250,7 +249,7 @@ pub fn evaluate_gate_constraints_base_batch<
let mut constraints_batch = vec![F::ZERO; common_data.num_gate_constraints * vars_batch.len()];
for (i, gate) in common_data.gates.iter().enumerate() {
let gate_constraints_batch = gate.0.eval_filtered_base_batch(
vars_batch.clone(),
vars_batch,
i,
common_data.selector_indices[i],
common_data.combination_ranges[i],

View File

@ -21,7 +21,7 @@ pub struct EvaluationVars<'a, F: RichField + Extendable<D>, const D: usize> {
/// evaluation points, then wire 1 for all points, and so on).
#[derive(Debug, Copy, Clone)]
pub struct EvaluationVarsBaseBatch<'a, F: Field> {
pub(crate) batch_size: usize,
batch_size: usize,
pub local_constants: &'a [F],
pub local_wires: &'a [F],
pub public_inputs_hash: &'a HashOut<F>,