diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index e6a1e296..221aa27b 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -11,7 +11,7 @@ use crate::field::cosets::get_unique_coset_shifts; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::gates::constant::ConstantGate; -use crate::gates::gate::{GateInstance, GatePrefixes, GateRef}; +use crate::gates::gate::{GateInstance, GateRef, PrefixedGate}; use crate::gates::gate_tree::Tree; use crate::gates::noop::NoopGate; use crate::generator::{CopyGenerator, WitnessGenerator}; @@ -230,26 +230,24 @@ impl, const D: usize> CircuitBuilder { } } - fn constant_polys(&self, prefixes: &GatePrefixes) -> Vec> { - let num_constants = self - .gate_instances + fn constant_polys(&self, gates: &[PrefixedGate]) -> Vec> { + let num_constants = gates .iter() - .map(|gate_inst| gate_inst.constants.len() + prefixes[&gate_inst.gate_type].len()) + .map(|gate| gate.gate.0.num_constants() + gate.prefix.len()) .max() .unwrap(); let constants_per_gate = self .gate_instances .iter() - .map(|gate_inst| { + .map(|gate| { + let prefix = &gates + .iter() + .find(|g| g.gate.0.id() == gate.gate_type.0.id()) + .unwrap() + .prefix; let mut prefixed_constants = Vec::new(); - prefixed_constants.extend(prefixes[&gate_inst.gate_type].iter().map(|&b| { - if b { - F::ONE - } else { - F::ZERO - } - })); - prefixed_constants.extend_from_slice(&gate_inst.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 }) @@ -297,9 +295,9 @@ impl, const D: usize> CircuitBuilder { let gates = self.gates.iter().cloned().collect(); let gate_tree = Tree::from_gates(gates); - let gate_prefixes = gate_tree.into(); + let prefixed_gates = PrefixedGate::from_tree(gate_tree); - let constant_vecs = self.constant_polys(&gate_prefixes); + let constant_vecs = self.constant_polys(&prefixed_gates); let constants_commitment = ListPolynomialCommitment::new( constant_vecs.into_iter().map(|v| v.ifft()).collect(), self.config.fri_config.rate_bits, @@ -348,8 +346,7 @@ impl, const D: usize> CircuitBuilder { let common = CommonCircuitData { config: self.config, degree_bits, - gates, - gate_prefixes, + gates: prefixed_gates, num_gate_constraints, k_is, circuit_digest, diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 3b314281..e54acd4f 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -3,7 +3,7 @@ use anyhow::Result; use crate::field::extension_field::Extendable; use crate::field::field::Field; use crate::fri::FriConfig; -use crate::gates::gate::{GatePrefixes, GateRef}; +use crate::gates::gate::{GateRef, PrefixedGate}; use crate::generator::WitnessGenerator; use crate::polynomial::commitment::ListPolynomialCommitment; use crate::proof::{Hash, HashTarget, Proof}; @@ -136,11 +136,8 @@ pub(crate) struct CommonCircuitData, const D: usize> { pub(crate) degree_bits: usize, - /// The types of gates used in this circuit. - pub(crate) gates: Vec>, - - /// The gate prefixes used to construct the selector polynomials. - pub(crate) gate_prefixes: GatePrefixes, + /// The types of gates used in this circuit, along with their prefixes. + pub(crate) gates: Vec>, /// The largest number of constraints imposed by any gate. pub(crate) num_gate_constraints: usize, @@ -169,7 +166,7 @@ impl, const D: usize> CommonCircuitData { pub fn constraint_degree(&self) -> usize { self.gates .iter() - .map(|g| g.0.degree()) + .map(|g| g.gate.0.degree()) .max() .expect("No gates?") } diff --git a/src/gates/gate.rs b/src/gates/gate.rs index 831927e1..5882ce00 100644 --- a/src/gates/gate.rs +++ b/src/gates/gate.rs @@ -142,23 +142,17 @@ pub struct GateInstance, const D: usize> { /// Map each gate to a boolean prefix used to construct the gate's selector polynomial. #[derive(Debug, Clone)] -pub struct GatePrefixes, const D: usize> { - pub prefixes: HashMap, Vec>, +pub struct PrefixedGate, const D: usize> { + pub gate: GateRef, + pub prefix: Vec, } -impl, const D: usize> From>> for GatePrefixes { - fn from(tree: Tree>) -> Self { - GatePrefixes { - prefixes: HashMap::from_iter(tree.traversal()), - } - } -} - -impl, T: Borrow>, const D: usize> Index for GatePrefixes { - type Output = Vec; - - fn index(&self, index: T) -> &Self::Output { - &self.prefixes[index.borrow()] +impl, const D: usize> PrefixedGate { + pub fn from_tree(tree: Tree>) -> Vec { + tree.traversal() + .into_iter() + .map(|(gate, prefix)| PrefixedGate { gate, prefix }) + .collect() } } diff --git a/src/plonk_common.rs b/src/plonk_common.rs index 2edd2add..617ba530 100644 --- a/src/plonk_common.rs +++ b/src/plonk_common.rs @@ -5,7 +5,7 @@ use crate::circuit_data::CommonCircuitData; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field::Field; -use crate::gates::gate::{GatePrefixes, GateRef}; +use crate::gates::gate::{GateRef, PrefixedGate}; use crate::polynomial::commitment::SALT_SIZE; use crate::polynomial::polynomial::PolynomialCoeffs; use crate::target::Target; @@ -76,12 +76,8 @@ pub(crate) fn eval_vanishing_poly, const D: usize>( gammas: &[F], alphas: &[F], ) -> Vec { - let constraint_terms = evaluate_gate_constraints( - &common_data.gates, - common_data.num_gate_constraints, - vars, - &common_data.gate_prefixes, - ); + let constraint_terms = + evaluate_gate_constraints(&common_data.gates, common_data.num_gate_constraints, vars); // The L_1(x) (Z(x) - 1) vanishing terms. let mut vanishing_z_1_terms = Vec::new(); @@ -129,12 +125,8 @@ pub(crate) fn eval_vanishing_poly_base, const D: usize>( gammas: &[F], alphas: &[F], ) -> Vec { - let constraint_terms = evaluate_gate_constraints_base( - &common_data.gates, - common_data.num_gate_constraints, - vars, - &common_data.gate_prefixes, - ); + let constraint_terms = + evaluate_gate_constraints_base(&common_data.gates, common_data.num_gate_constraints, vars); // The L_1(x) (Z(x) - 1) vanishing terms. let mut vanishing_z_1_terms = Vec::new(); @@ -175,14 +167,13 @@ pub(crate) fn eval_vanishing_poly_base, const D: usize>( /// strictly necessary, but it helps performance by ensuring that we allocate a vector with exactly /// the capacity that we need. pub fn evaluate_gate_constraints, const D: usize>( - gates: &[GateRef], + gates: &[PrefixedGate], num_gate_constraints: usize, vars: EvaluationVars, - prefixes: &GatePrefixes, ) -> Vec { let mut constraints = vec![F::Extension::ZERO; num_gate_constraints]; for gate in gates { - let gate_constraints = gate.0.eval_filtered(vars, &prefixes[gate]); + let gate_constraints = gate.gate.0.eval_filtered(vars, &gate.prefix); for (i, c) in gate_constraints.into_iter().enumerate() { debug_assert!( i < num_gate_constraints, @@ -195,14 +186,13 @@ pub fn evaluate_gate_constraints, const D: usize>( } pub fn evaluate_gate_constraints_base, const D: usize>( - gates: &[GateRef], + gates: &[PrefixedGate], num_gate_constraints: usize, vars: EvaluationVarsBase, - prefixes: &GatePrefixes, ) -> Vec { let mut constraints = vec![F::ZERO; num_gate_constraints]; for gate in gates { - let gate_constraints = gate.0.eval_filtered_base(vars, &prefixes[gate]); + let gate_constraints = gate.gate.0.eval_filtered_base(vars, &gate.prefix); for (i, c) in gate_constraints.into_iter().enumerate() { debug_assert!( i < num_gate_constraints,