diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 1cccc68c..5d286a46 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -14,7 +14,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, GateRef, PrefixedGate}; +use crate::gates::gate::{Gate, GateInstance, GateRef, PrefixedGate}; use crate::gates::gate_tree::Tree; use crate::gates::noop::NoopGate; use crate::gates::public_input::PublicInputGate; @@ -124,41 +124,35 @@ impl, const D: usize> CircuitBuilder { .collect() } - pub fn add_gate_no_constants(&mut self, gate_type: GateRef) -> usize { - self.add_gate(gate_type, Vec::new()) - } - /// Adds a gate to the circuit, and returns its index. - pub fn add_gate(&mut self, gate_type: GateRef, constants: Vec) -> usize { + pub fn add_gate>(&mut self, gate_type: G, constants: Vec) -> usize { + self.check_gate_compatibility(&gate_type); assert_eq!( - gate_type.0.num_constants(), + gate_type.num_constants(), constants.len(), "Number of constants doesn't match." ); - // If we haven't seen a gate of this type before, check that it's compatible with our - // circuit configuration, then register it. - if !self.gates.contains(&gate_type) { - self.check_gate_compatibility(&gate_type); - self.gates.insert(gate_type.clone()); - } let index = self.gate_instances.len(); + self.add_generators(gate_type.generators(index, &constants)); - self.add_generators(gate_type.0.generators(index, &constants)); + // Register this gate type if we haven't seen it before. + let gate_ref = GateRef::new(gate_type); + self.gates.insert(gate_ref.clone()); self.gate_instances.push(GateInstance { - gate_type, + gate_ref, constants, }); index } - fn check_gate_compatibility(&self, gate: &GateRef) { + fn check_gate_compatibility>(&self, gate: &G) { assert!( - gate.0.num_wires() <= self.config.num_wires, + gate.num_wires() <= self.config.num_wires, "{:?} requires {} wires, but our GateConfig has only {}", - gate.0.id(), - gate.0.num_wires(), + gate.id(), + gate.num_wires(), self.config.num_wires ); } @@ -287,7 +281,7 @@ impl, const D: usize> CircuitBuilder { return target; } - let gate = self.add_gate(ConstantGate::get(), vec![c]); + let gate = self.add_gate(ConstantGate, vec![c]); let target = Target::Wire(Wire { gate, input: ConstantGate::WIRE_OUTPUT, @@ -377,7 +371,7 @@ impl, const D: usize> CircuitBuilder { } while !self.gate_instances.len().is_power_of_two() { - self.add_gate_no_constants(NoopGate::get()); + self.add_gate(NoopGate, vec![]); } } @@ -394,7 +388,7 @@ impl, const D: usize> CircuitBuilder { // For each "regular" blinding factor, we simply add a no-op gate, and insert a random value // for each wire. for _ in 0..regular_poly_openings { - let gate = self.add_gate_no_constants(NoopGate::get()); + let gate = self.add_gate(NoopGate, vec![]); for w in 0..num_wires { self.add_generator(RandomValueGenerator { target: Target::Wire(Wire { gate, input: w }), @@ -406,8 +400,8 @@ impl, const D: usize> CircuitBuilder { // enforce a copy constraint between them. // See https://mirprotocol.org/blog/Adding-zero-knowledge-to-Plonk-Halo for _ in 0..z_openings { - let gate_1 = self.add_gate_no_constants(NoopGate::get()); - let gate_2 = self.add_gate_no_constants(NoopGate::get()); + let gate_1 = self.add_gate(NoopGate, vec![]); + let gate_2 = self.add_gate(NoopGate, vec![]); for w in 0..num_routed_wires { self.add_generator(RandomValueGenerator { @@ -441,7 +435,7 @@ impl, const D: usize> CircuitBuilder { .map(|gate| { let prefix = &gates .iter() - .find(|g| g.gate.0.id() == gate.gate_type.0.id()) + .find(|g| g.gate.0.id() == gate.gate_ref.0.id()) .unwrap() .prefix; let mut prefixed_constants = Vec::with_capacity(num_constants); @@ -498,7 +492,7 @@ impl, const D: usize> CircuitBuilder { // Hash the public inputs, and route them to a `PublicInputGate` which will enforce that // those hash wires match the claimed public inputs. let public_inputs_hash = self.hash_n_to_hash(self.public_inputs.clone(), true); - let pi_gate = self.add_gate_no_constants(PublicInputGate::get()); + let pi_gate = self.add_gate(PublicInputGate, vec![]); for (&hash_part, wire) in public_inputs_hash .elements .iter() diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index e6efb451..7d43dbfb 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -24,7 +24,7 @@ impl, const D: usize> CircuitBuilder { second_multiplicand_1: ExtensionTarget, second_addend: ExtensionTarget, ) -> (ExtensionTarget, ExtensionTarget) { - let gate = self.add_gate(ArithmeticExtensionGate::new(), vec![const_0, const_1]); + let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]); let wire_first_multiplicand_0 = ExtensionTarget::from_range( gate, diff --git a/src/gadgets/hash.rs b/src/gadgets/hash.rs index 136bfef8..dfe46772 100644 --- a/src/gadgets/hash.rs +++ b/src/gadgets/hash.rs @@ -11,8 +11,8 @@ use crate::wire::Wire; impl, const D: usize> CircuitBuilder { pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] { let zero = self.zero(); - let gate = - self.add_gate_no_constants(GMiMCGate::::with_automatic_constants()); + let gate_type = GMiMCGate::::new_automatic_constants(); + let gate = self.add_gate(gate_type, vec![]); // We don't want to swap any inputs, so set that wire to 0. let swap_wire = GMiMCGate::::WIRE_SWAP; diff --git a/src/gadgets/insert.rs b/src/gadgets/insert.rs index bcdf16cc..8406b83a 100644 --- a/src/gadgets/insert.rs +++ b/src/gadgets/insert.rs @@ -15,11 +15,8 @@ impl, const D: usize> CircuitBuilder { element: ExtensionTarget, v: Vec>, ) -> Vec> { - let gate = InsertionGate:: { - vec_size: v.len(), - _phantom: PhantomData, - }; - let gate_index = self.add_gate_no_constants(InsertionGate::new(v.len())); + let gate = InsertionGate::new(v.len()); + let gate_index = self.add_gate(gate.clone(), vec![]); v.iter().enumerate().for_each(|(i, &val)| { self.route_extension( diff --git a/src/gadgets/interpolation.rs b/src/gadgets/interpolation.rs index 26e049d2..5de2c651 100644 --- a/src/gadgets/interpolation.rs +++ b/src/gadgets/interpolation.rs @@ -1,5 +1,3 @@ -use std::marker::PhantomData; - use crate::circuit_builder::CircuitBuilder; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; @@ -33,12 +31,8 @@ impl, const D: usize> CircuitBuilder { interpolation_points: &[(Target, ExtensionTarget)], evaluation_point: ExtensionTarget, ) -> ExtensionTarget { - let gate = InterpolationGate:: { - num_points: interpolation_points.len(), - _phantom: PhantomData, - }; - let gate_index = - self.add_gate_no_constants(InterpolationGate::new(interpolation_points.len())); + let gate = InterpolationGate::new(interpolation_points.len()); + let gate_index = self.add_gate(gate.clone(), vec![]); for (i, &(p, v)) in interpolation_points.iter().enumerate() { self.route(p, Target::wire(gate_index, gate.wire_point(i))); self.route_extension( diff --git a/src/gadgets/split_base.rs b/src/gadgets/split_base.rs index 46d7c5b1..1929fd1c 100644 --- a/src/gadgets/split_base.rs +++ b/src/gadgets/split_base.rs @@ -16,14 +16,12 @@ impl, const D: usize> CircuitBuilder { x: Target, num_limbs: usize, ) -> Vec { - let gate = self.add_gate(BaseSumGate::::new(num_limbs), vec![]); + let gate_type = BaseSumGate::::new(num_limbs); + let gate = self.add_gate(gate_type.clone(), vec![]); let sum = Target::wire(gate, BaseSumGate::::WIRE_SUM); self.route(x, sum); - Target::wires_from_range( - gate, - BaseSumGate::::START_LIMBS..BaseSumGate::::START_LIMBS + num_limbs, - ) + Target::wires_from_range(gate, gate_type.limbs()) } /// Asserts that `x`'s big-endian bit representation has at least `leading_zeros` leading zeros. diff --git a/src/gadgets/split_join.rs b/src/gadgets/split_join.rs index 9cc6ab7c..2cf5b9b2 100644 --- a/src/gadgets/split_join.rs +++ b/src/gadgets/split_join.rs @@ -35,7 +35,7 @@ impl, const D: usize> CircuitBuilder { let bits_per_gate = self.config.num_routed_wires - BaseSumGate::<2>::START_LIMBS; let k = ceil_div_usize(num_bits, bits_per_gate); let gates = (0..k) - .map(|_| self.add_gate_no_constants(BaseSumGate::<2>::new(bits_per_gate))) + .map(|_| self.add_gate(BaseSumGate::<2>::new(bits_per_gate), vec![])) .collect::>(); let mut bits = Vec::with_capacity(num_bits); diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index a3739ee5..4964fbd0 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -2,8 +2,9 @@ use std::ops::Range; use crate::circuit_builder::CircuitBuilder; use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::gates::gate::{Gate, GateRef}; +use crate::field::extension_field::Extendable; +use crate::field::extension_field::FieldExtension; +use crate::gates::gate::Gate; use crate::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::target::Target; use crate::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -14,10 +15,6 @@ use crate::witness::PartialWitness; pub struct ArithmeticExtensionGate; impl ArithmeticExtensionGate { - pub fn new>() -> GateRef { - GateRef::new(ArithmeticExtensionGate) - } - pub fn wires_first_multiplicand_0() -> Range { 0..D } @@ -259,6 +256,6 @@ mod tests { #[test] fn low_degree() { - test_low_degree(ArithmeticExtensionGate::<4>::new::()) + test_low_degree::(ArithmeticExtensionGate) } } diff --git a/src/gates/base_sum.rs b/src/gates/base_sum.rs index b6645959..cd1694e4 100644 --- a/src/gates/base_sum.rs +++ b/src/gates/base_sum.rs @@ -13,14 +13,14 @@ use crate::witness::PartialWitness; /// A gate which can decompose a number into base B little-endian limbs, /// and compute the limb-reversed (i.e. big-endian) sum. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct BaseSumGate { num_limbs: usize, } impl BaseSumGate { - pub fn new, const D: usize>(num_limbs: usize) -> GateRef { - GateRef::new(BaseSumGate:: { num_limbs }) + pub fn new(num_limbs: usize) -> Self { + Self { num_limbs } } pub const WIRE_SUM: usize = 0; @@ -186,10 +186,11 @@ impl SimpleGenerator for BaseSplitGenerator { mod tests { use crate::field::crandall_field::CrandallField; use crate::gates::base_sum::BaseSumGate; + use crate::gates::gate::GateRef; use crate::gates::gate_testing::test_low_degree; #[test] fn low_degree() { - test_low_degree(BaseSumGate::<6>::new::(11)) + test_low_degree::(BaseSumGate::<6>::new(11)) } } diff --git a/src/gates/constant.rs b/src/gates/constant.rs index 4a5c4373..1d8f50dd 100644 --- a/src/gates/constant.rs +++ b/src/gates/constant.rs @@ -13,10 +13,6 @@ use crate::witness::PartialWitness; pub struct ConstantGate; impl ConstantGate { - pub fn get, const D: usize>() -> GateRef { - GateRef::new(ConstantGate) - } - pub const CONST_INPUT: usize = 0; pub const WIRE_OUTPUT: usize = 0; @@ -106,6 +102,6 @@ mod tests { #[test] fn low_degree() { - test_low_degree(ConstantGate::get::()) + test_low_degree::(ConstantGate) } } diff --git a/src/gates/gate.rs b/src/gates/gate.rs index 17059332..d961fb58 100644 --- a/src/gates/gate.rs +++ b/src/gates/gate.rs @@ -139,7 +139,7 @@ impl, const D: usize> Debug for GateRef { /// A gate along with any constants used to configure it. pub struct GateInstance, const D: usize> { - pub gate_type: GateRef, + pub gate_ref: GateRef, pub constants: Vec, } diff --git a/src/gates/gate_testing.rs b/src/gates/gate_testing.rs index 2f7a3020..b71d1509 100644 --- a/src/gates/gate_testing.rs +++ b/src/gates/gate_testing.rs @@ -1,6 +1,6 @@ use crate::field::extension_field::Extendable; use crate::field::field::Field; -use crate::gates::gate::GateRef; +use crate::gates::gate::{Gate, GateRef}; use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::proof::Hash; use crate::util::{log2_ceil, transpose}; @@ -11,8 +11,7 @@ const WITNESS_DEGREE: usize = WITNESS_SIZE - 1; /// Tests that the constraints imposed by the given gate are low-degree by applying them to random /// low-degree witness polynomials. -pub(crate) fn test_low_degree, const D: usize>(gate: GateRef) { - let gate = gate.0; +pub(crate) fn test_low_degree, G: Gate, const D: usize>(gate: G) { let rate_bits = log2_ceil(gate.degree() + 1); let wire_ldes = random_low_degree_matrix::(gate.num_wires(), rate_bits); diff --git a/src/gates/gate_tree.rs b/src/gates/gate_tree.rs index 0c10ed70..50a6f39e 100644 --- a/src/gates/gate_tree.rs +++ b/src/gates/gate_tree.rs @@ -237,12 +237,12 @@ mod tests { const D: usize = 4; let gates = vec![ - NoopGate::get::(), - ConstantGate::get(), - ArithmeticExtensionGate::new(), - BaseSumGate::<4>::new(4), - GMiMCGate::::with_automatic_constants(), - InterpolationGate::new(4), + GateRef::new(NoopGate), + GateRef::new(ConstantGate), + GateRef::new(ArithmeticExtensionGate), + GateRef::new(BaseSumGate::<4>::new(4)), + GateRef::new(GMiMCGate::::new_automatic_constants()), + GateRef::new(InterpolationGate::new(4)), ]; let len = gates.len(); diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index a7651a2a..2c8ca297 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -4,7 +4,7 @@ use crate::circuit_builder::CircuitBuilder; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field::Field; -use crate::gates::gate::{Gate, GateRef}; +use crate::gates::gate::Gate; use crate::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::gmimc::gmimc_automatic_constants; use crate::target::Target; @@ -28,14 +28,13 @@ pub struct GMiMCGate, const D: usize, const R: usize> { } impl, const D: usize, const R: usize> GMiMCGate { - pub fn with_constants(constants: Arc<[F; R]>) -> GateRef { - let gate = GMiMCGate:: { constants }; - GateRef::new(gate) + pub fn new(constants: Arc<[F; R]>) -> Self { + Self { constants } } - pub fn with_automatic_constants() -> GateRef { + pub fn new_automatic_constants() -> Self { let constants = Arc::new(gmimc_automatic_constants::()); - Self::with_constants(constants) + Self::new(constants) } /// The wire index for the `i`th input to the permutation. @@ -335,6 +334,7 @@ mod tests { use crate::field::crandall_field::CrandallField; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field::Field; + use crate::gates::gate::{Gate, GateRef}; use crate::gates::gate_testing::test_low_degree; use crate::gates::gmimc::{GMiMCGate, W}; use crate::generator::generate_partial_witness; @@ -351,7 +351,7 @@ mod tests { const R: usize = 101; let constants = Arc::new([F::TWO; R]); type Gate = GMiMCGate; - let gate = Gate::with_constants(constants.clone()); + let gate = Gate::new(constants.clone()); let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::>(); @@ -373,7 +373,7 @@ mod tests { ); } - let generators = gate.0.generators(0, &[]); + let generators = gate.generators(0, &[]); generate_partial_witness(&mut witness, &generators); let expected_outputs: [F; W] = @@ -393,8 +393,7 @@ mod tests { type F = CrandallField; const R: usize = 101; let constants = Arc::new([F::TWO; R]); - type Gate = GMiMCGate; - let gate = Gate::with_constants(constants); + let gate = GMiMCGate::::new(constants); test_low_degree(gate) } @@ -408,7 +407,7 @@ mod tests { let mut pw = PartialWitness::::new(); let constants = Arc::new([F::TWO; R]); type Gate = GMiMCGate; - let gate = Gate::with_constants(constants); + let gate = Gate::new(constants); let wires = FF::rand_vec(Gate::end()); let public_inputs_hash = &Hash::rand(); @@ -418,7 +417,7 @@ mod tests { public_inputs_hash, }; - let ev = gate.0.eval_unfiltered(vars); + let ev = gate.eval_unfiltered(vars); let wires_t = builder.add_virtual_extension_targets(Gate::end()); for i in 0..Gate::end() { @@ -434,7 +433,7 @@ mod tests { public_inputs_hash: &public_inputs_hash_t, }; - let ev_t = gate.0.eval_unfiltered_recursively(&mut builder, vars_t); + let ev_t = gate.eval_unfiltered_recursively(&mut builder, vars_t); assert_eq!(ev.len(), ev_t.len()); for (e, e_t) in ev.into_iter().zip(ev_t) { diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index 4bfe97a9..17df4024 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -17,16 +17,15 @@ use crate::witness::PartialWitness; #[derive(Clone, Debug)] pub(crate) struct InsertionGate, const D: usize> { pub vec_size: usize, - pub _phantom: PhantomData, + _phantom: PhantomData, } impl, const D: usize> InsertionGate { - pub fn new(vec_size: usize) -> GateRef { - let gate = Self { + pub fn new(vec_size: usize) -> Self { + Self { vec_size, _phantom: PhantomData, - }; - GateRef::new(gate) + } } pub fn wires_insertion_index(&self) -> usize { @@ -350,8 +349,7 @@ mod tests { #[test] fn low_degree() { - type F = CrandallField; - test_low_degree(InsertionGate::::new(4)); + test_low_degree::(InsertionGate::new(4)); } #[test] diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index 6d6594b4..47fa6d4a 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -24,16 +24,15 @@ use crate::witness::PartialWitness; #[derive(Clone, Debug)] pub(crate) struct InterpolationGate, const D: usize> { pub num_points: usize, - pub _phantom: PhantomData, + _phantom: PhantomData, } impl, const D: usize> InterpolationGate { - pub fn new(num_points: usize) -> GateRef { - let gate = Self { + pub fn new(num_points: usize) -> Self { + Self { num_points, _phantom: PhantomData, - }; - GateRef::new(gate) + } } fn start_points(&self) -> usize { @@ -321,7 +320,7 @@ mod tests { #[test] fn low_degree() { type F = CrandallField; - test_low_degree(InterpolationGate::::new(4)); + test_low_degree::(InterpolationGate::new(4)); } #[test] diff --git a/src/gates/noop.rs b/src/gates/noop.rs index c27b22bf..0787c9fa 100644 --- a/src/gates/noop.rs +++ b/src/gates/noop.rs @@ -8,12 +8,6 @@ use crate::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate which does nothing. pub struct NoopGate; -impl NoopGate { - pub fn get, const D: usize>() -> GateRef { - GateRef::new(NoopGate) - } -} - impl, const D: usize> Gate for NoopGate { fn id(&self) -> String { "NoopGate".into() @@ -68,6 +62,6 @@ mod tests { #[test] fn low_degree() { - test_low_degree(NoopGate::get::()) + test_low_degree::(NoopGate) } } diff --git a/src/gates/public_input.rs b/src/gates/public_input.rs index e1ce9271..e8299b26 100644 --- a/src/gates/public_input.rs +++ b/src/gates/public_input.rs @@ -11,10 +11,6 @@ use crate::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; pub struct PublicInputGate; impl PublicInputGate { - pub fn get, const D: usize>() -> GateRef { - GateRef::new(PublicInputGate) - } - pub fn wires_public_inputs_hash() -> Range { 0..4 } @@ -86,6 +82,6 @@ mod tests { #[test] fn low_degree() { - test_low_degree(PublicInputGate::get::()) + test_low_degree::(PublicInputGate) } } diff --git a/src/merkle_proofs.rs b/src/merkle_proofs.rs index 233f4af5..6a352dec 100644 --- a/src/merkle_proofs.rs +++ b/src/merkle_proofs.rs @@ -72,8 +72,8 @@ impl, const D: usize> CircuitBuilder { let mut state: HashTarget = self.hash_or_noop(leaf_data); for (&bit, &sibling) in leaf_index_bits.iter().zip(&proof.siblings) { - let gate = self - .add_gate_no_constants(GMiMCGate::::with_automatic_constants()); + let gate_type = GMiMCGate::::new_automatic_constants(); + let gate = self.add_gate(gate_type, vec![]); let swap_wire = GMiMCGate::::WIRE_SWAP; let swap_wire = Target::Wire(Wire { diff --git a/src/witness.rs b/src/witness.rs index ce4a95af..2ef9d8b3 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -170,7 +170,7 @@ impl PartialWitness { "wire {} of gate #{} (`{}`)", input, gate, - gate_instances[*gate].gate_type.0.id() + gate_instances[*gate].gate_ref.0.id() ), Target::VirtualTarget { index } => format!("{}-th virtual target", index), }