From 5caf92a39a4422d9a7622d3295a2f44f9e543e6c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 6 Jan 2022 10:37:09 +0100 Subject: [PATCH 01/14] First try --- plonky2/src/gates/batchable.rs | 28 ++++++++++++++++++++++++++++ plonky2/src/gates/mod.rs | 1 + plonky2/src/plonk/circuit_builder.rs | 2 ++ 3 files changed, 31 insertions(+) create mode 100644 plonky2/src/gates/batchable.rs diff --git a/plonky2/src/gates/batchable.rs b/plonky2/src/gates/batchable.rs new file mode 100644 index 00000000..b0aaa87a --- /dev/null +++ b/plonky2/src/gates/batchable.rs @@ -0,0 +1,28 @@ +use std::collections::HashMap; +use std::hash::Hash; +use std::sync::Arc; + +use plonky2_field::extension_field::Extendable; + +use crate::gates::gate::Gate; +use crate::hash::hash_types::RichField; +use crate::plonk::circuit_builder::CircuitBuilder; + +pub trait BatchableGate, const D: usize>: Gate { + type Parameters: Copy; + + fn find_available_slot(&self, params: Self::Parameters) -> (usize, usize); + + fn fill_gate(&self, params: Self::Parameters, builder: &mut CircuitBuilder); +} + +pub struct CurrentSlot, const D: usize, G: BatchableGate> { + current_slot: HashMap, +} + +// pub struct Yo, const D: usize>( +// CurrentSlot>, +// ); +pub struct GateRef, const D: usize>( + pub(crate) Arc>, +); diff --git a/plonky2/src/gates/mod.rs b/plonky2/src/gates/mod.rs index aae46dc5..3070b087 100644 --- a/plonky2/src/gates/mod.rs +++ b/plonky2/src/gates/mod.rs @@ -6,6 +6,7 @@ pub mod arithmetic_extension; pub mod arithmetic_u32; pub mod assert_le; pub mod base_sum; +pub mod batchable; pub mod comparison; pub mod constant; pub mod exponentiation; diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 2456d6fd..cc4a19a4 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -18,6 +18,7 @@ use crate::gadgets::arithmetic_u32::U32Target; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::arithmetic_u32::U32ArithmeticGate; +use crate::gates::batchable::{BatchableGate, CurrentSlot}; use crate::gates::constant::ConstantGate; use crate::gates::gate::{Gate, GateInstance, GateRef, PrefixedGate}; use crate::gates::gate_tree::Tree; @@ -83,6 +84,7 @@ pub struct CircuitBuilder, const D: usize> { /// Memoized results of `arithmetic_extension` calls. pub(crate) arithmetic_results: HashMap, ExtensionTarget>, + // yo: Vec>, batched_gates: BatchedGates, } From cdea0d9f96fcfa49e1c25a8e64cfb355de4a50f1 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 28 Jan 2022 12:07:02 +0100 Subject: [PATCH 02/14] Compiles --- insertion/src/insertion_gate.rs | 11 +++ plonky2/src/gadgets/interpolation.rs | 3 +- plonky2/src/gates/arithmetic_base.rs | 15 ++++ plonky2/src/gates/arithmetic_extension.rs | 18 ++++ plonky2/src/gates/arithmetic_u32.rs | 15 ++++ plonky2/src/gates/assert_le.rs | 11 +++ plonky2/src/gates/base_sum.rs | 12 +++ plonky2/src/gates/batchable.rs | 88 ++++++++++++++++--- plonky2/src/gates/comparison.rs | 21 +++++ plonky2/src/gates/constant.rs | 11 +++ plonky2/src/gates/exponentiation.rs | 11 +++ plonky2/src/gates/gate.rs | 59 +++++++------ plonky2/src/gates/gate_tree.rs | 2 +- plonky2/src/gates/gmimc.rs | 12 +++ plonky2/src/gates/interpolation.rs | 12 +++ plonky2/src/gates/low_degree_interpolation.rs | 13 +++ plonky2/src/gates/multiplication_extension.rs | 15 ++++ plonky2/src/gates/noop.rs | 12 +++ plonky2/src/gates/poseidon.rs | 10 +++ plonky2/src/gates/poseidon_mds.rs | 12 +++ plonky2/src/gates/public_input.rs | 12 +++ plonky2/src/gates/random_access.rs | 16 ++++ plonky2/src/gates/reducing.rs | 11 +++ plonky2/src/gates/reducing_extension.rs | 11 +++ plonky2/src/gates/subtraction_u32.rs | 17 ++++ plonky2/src/gates/switch.rs | 11 +++ plonky2/src/plonk/circuit_builder.rs | 9 +- 27 files changed, 405 insertions(+), 45 deletions(-) diff --git a/insertion/src/insertion_gate.rs b/insertion/src/insertion_gate.rs index 8ee60483..cb5fdc22 100644 --- a/insertion/src/insertion_gate.rs +++ b/insertion/src/insertion_gate.rs @@ -3,6 +3,7 @@ use std::ops::Range; use plonky2::field::extension_field::{Extendable, FieldExtension}; use plonky2::field::field_types::Field; +use plonky2::gates::batchable::MultiOpsGate; use plonky2::gates::gate::Gate; use plonky2::gates::util::StridedConstraintConsumer; use plonky2::hash::hash_types::RichField; @@ -242,6 +243,16 @@ impl, const D: usize> Gate for InsertionGate< } } +impl, const D: usize> MultiOpsGate for InsertionGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + #[derive(Debug)] struct InsertionGenerator, const D: usize> { gate_index: usize, diff --git a/plonky2/src/gadgets/interpolation.rs b/plonky2/src/gadgets/interpolation.rs index 7907a337..92b17098 100644 --- a/plonky2/src/gadgets/interpolation.rs +++ b/plonky2/src/gadgets/interpolation.rs @@ -2,6 +2,7 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; +use crate::gates::batchable::BatchableGate; use crate::gates::gate::Gate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; @@ -12,7 +13,7 @@ use crate::plonk::circuit_builder::CircuitBuilder; /// 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. pub(crate) trait InterpolationGate, const D: usize>: - Gate + Copy + BatchableGate + Copy { fn new(subgroup_bits: usize) -> Self; diff --git a/plonky2/src/gates/arithmetic_base.rs b/plonky2/src/gates/arithmetic_base.rs index 8f67dab2..ca308923 100644 --- a/plonky2/src/gates/arithmetic_base.rs +++ b/plonky2/src/gates/arithmetic_base.rs @@ -1,6 +1,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -151,6 +152,20 @@ impl, const D: usize> Gate for ArithmeticGate } } +impl, const D: usize> MultiOpsGate for ArithmeticGate { + fn num_ops(&self) -> usize { + self.num_ops + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + vec![ + Target::wire(gate_index, Self::wire_ith_multiplicand_0(i)), + Target::wire(gate_index, Self::wire_ith_multiplicand_1(i)), + Target::wire(gate_index, Self::wire_ith_addend(i)), + ] + } +} + impl, const D: usize> PackedEvaluableBase for ArithmeticGate { fn eval_unfiltered_base_packed>( &self, diff --git a/plonky2/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs index 93f7277c..bd575272 100644 --- a/plonky2/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -3,6 +3,7 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -158,6 +159,23 @@ impl, const D: usize> Gate for ArithmeticExte } } +impl, const D: usize> MultiOpsGate + for ArithmeticExtensionGate +{ + fn num_ops(&self) -> usize { + self.num_ops + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + [ + ExtensionTarget::::from_range(gate_index, Self::wires_ith_multiplicand_0(i)).0, + ExtensionTarget::::from_range(gate_index, Self::wires_ith_multiplicand_1(i)).0, + ExtensionTarget::::from_range(gate_index, Self::wires_ith_addend(i)).0, + ] + .concat() + } +} + #[derive(Clone, Debug)] struct ArithmeticExtensionGenerator, const D: usize> { gate_index: usize, diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index 1d4a834c..10d16ec2 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -5,6 +5,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -232,6 +233,20 @@ impl, const D: usize> Gate for U32ArithmeticG } } +impl, const D: usize> MultiOpsGate for U32ArithmeticGate { + fn num_ops(&self) -> usize { + self.num_ops + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + vec![ + Target::wire(gate_index, self.wire_ith_multiplicand_0(i)), + Target::wire(gate_index, self.wire_ith_multiplicand_1(i)), + Target::wire(gate_index, self.wire_ith_addend(i)), + ] + } +} + impl, const D: usize> PackedEvaluableBase for U32ArithmeticGate { diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index 6a99acd9..759faf51 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -5,6 +5,7 @@ use plonky2_field::field_types::{Field, PrimeField}; use plonky2_field::packed_field::PackedField; use plonky2_util::{bits_u64, ceil_div_usize}; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -280,6 +281,16 @@ impl, const D: usize> Gate for AssertLessThan } } +impl, const D: usize> MultiOpsGate for AssertLessThanGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + impl, const D: usize> PackedEvaluableBase for AssertLessThanGate { diff --git a/plonky2/src/gates/base_sum.rs b/plonky2/src/gates/base_sum.rs index a5391abf..87db3c61 100644 --- a/plonky2/src/gates/base_sum.rs +++ b/plonky2/src/gates/base_sum.rs @@ -4,6 +4,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::{Field, PrimeField}; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -135,6 +136,17 @@ impl, const D: usize, const B: usize> Gate fo 1 + self.num_limbs } } +impl, const D: usize, const B: usize> MultiOpsGate + for BaseSumGate +{ + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} impl, const D: usize, const B: usize> PackedEvaluableBase for BaseSumGate diff --git a/plonky2/src/gates/batchable.rs b/plonky2/src/gates/batchable.rs index b0aaa87a..a2daef6f 100644 --- a/plonky2/src/gates/batchable.rs +++ b/plonky2/src/gates/batchable.rs @@ -1,28 +1,94 @@ use std::collections::HashMap; -use std::hash::Hash; +use std::fmt::{Debug, Error, Formatter}; +use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; use std::sync::Arc; use plonky2_field::extension_field::Extendable; use crate::gates::gate::Gate; use crate::hash::hash_types::RichField; +use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; pub trait BatchableGate, const D: usize>: Gate { - type Parameters: Copy; - - fn find_available_slot(&self, params: Self::Parameters) -> (usize, usize); - - fn fill_gate(&self, params: Self::Parameters, builder: &mut CircuitBuilder); + // TODO: It would be nice to have a `Parameters` associated type. + fn fill_gate( + &self, + params: &[F], + current_slot: &CurrentSlot, + builder: &mut CircuitBuilder, + ); } -pub struct CurrentSlot, const D: usize, G: BatchableGate> { - current_slot: HashMap, +pub struct CurrentSlot, const D: usize> { + current_slot: HashMap, (usize, usize)>, } -// pub struct Yo, const D: usize>( -// CurrentSlot>, -// ); +#[derive(Clone)] pub struct GateRef, const D: usize>( pub(crate) Arc>, ); + +impl, const D: usize> GateRef { + pub fn new>(gate: G) -> GateRef { + GateRef(Arc::new(gate)) + } +} + +impl, const D: usize> PartialEq for GateRef { + fn eq(&self, other: &Self) -> bool { + self.0.id() == other.0.id() + } +} + +impl, const D: usize> Hash for GateRef { + fn hash(&self, state: &mut H) { + self.0.id().hash(state) + } +} + +impl, const D: usize> Eq for GateRef {} + +impl, const D: usize> Debug for GateRef { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + write!(f, "{}", self.0.id()) + } +} + +// pub trait SingleOpGate, const D: usize>: Gate {} +// impl, G: SingleOpGate, const D: usize> MultiOpsGate for G { +// fn num_ops(&self) -> usize { +// 1 +// } +// +// fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { +// unreachable!() +// } +// } + +pub trait MultiOpsGate, const D: usize>: Gate { + fn num_ops(&self) -> usize; + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec; +} + +impl, G: MultiOpsGate, const D: usize> BatchableGate + for G +{ + fn fill_gate( + &self, + params: &[F], + current_slot: &CurrentSlot, + builder: &mut CircuitBuilder, + ) { + if let Some(&(gate_index, op)) = current_slot.current_slot.get(params) { + let zero = builder.zero(); + for i in op..self.num_ops() { + for dep in self.dependencies_ith_op(gate_index, i) { + builder.connect(dep, zero); + } + } + } + } +} diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index 9a119b1d..f0ab000f 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -5,6 +5,7 @@ use plonky2_field::field_types::{Field, PrimeField}; use plonky2_field::packed_field::PackedField; use plonky2_util::{bits_u64, ceil_div_usize}; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -313,6 +314,26 @@ impl, const D: usize> Gate for ComparisonGate } } +impl, const D: usize> MultiOpsGate for ComparisonGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + +// impl, const D: usize> Singleopgate for multiopsgate { +// fn num_ops(&self) -> usize { +// 1 +// } +// +// fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { +// unreachable!() +// } +// } + impl, const D: usize> PackedEvaluableBase for ComparisonGate { diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index 14b21867..f59f3604 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -4,6 +4,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -102,6 +103,16 @@ impl, const D: usize> Gate for ConstantGate { } } +impl, const D: usize> MultiOpsGate for ConstantGate { + fn num_ops(&self) -> usize { + self.num_consts + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + vec![] + } +} + impl, const D: usize> PackedEvaluableBase for ConstantGate { fn eval_unfiltered_base_packed>( &self, diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index 51558a21..6d72e21b 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -5,6 +5,7 @@ use plonky2_field::field_types::Field; use plonky2_field::ops::Square; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::{BatchableGate, MultiOpsGate}; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -190,6 +191,16 @@ impl, const D: usize> Gate for Exponentiation } } +impl, const D: usize> MultiOpsGate for ExponentiationGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + impl, const D: usize> PackedEvaluableBase for ExponentiationGate { diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 9ae2a271..5cc15216 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -6,6 +6,7 @@ use plonky2_field::batch_util::batch_multiply_inplace; use plonky2_field::extension_field::{Extendable, FieldExtension}; use plonky2_field::field_types::Field; +use crate::gates::batchable::GateRef; use crate::gates::gate_tree::Tree; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -141,35 +142,35 @@ pub trait Gate, const D: usize>: 'static + Send + S fn num_constraints(&self) -> usize; } -/// A wrapper around an `Rc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. -#[derive(Clone)] -pub struct GateRef, const D: usize>(pub(crate) Arc>); - -impl, const D: usize> GateRef { - pub fn new>(gate: G) -> GateRef { - GateRef(Arc::new(gate)) - } -} - -impl, const D: usize> PartialEq for GateRef { - fn eq(&self, other: &Self) -> bool { - self.0.id() == other.0.id() - } -} - -impl, const D: usize> Hash for GateRef { - fn hash(&self, state: &mut H) { - self.0.id().hash(state) - } -} - -impl, const D: usize> Eq for GateRef {} - -impl, const D: usize> Debug for GateRef { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - write!(f, "{}", self.0.id()) - } -} +// /// A wrapper around an `Rc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. +// #[derive(Clone)] +// pub struct GateRef, const D: usize>(pub(crate) Arc>); +// +// impl, const D: usize> GateRef { +// pub fn new>(gate: G) -> GateRef { +// GateRef(Arc::new(gate)) +// } +// } +// +// impl, const D: usize> PartialEq for GateRef { +// fn eq(&self, other: &Self) -> bool { +// self.0.id() == other.0.id() +// } +// } +// +// impl, const D: usize> Hash for GateRef { +// fn hash(&self, state: &mut H) { +// self.0.id().hash(state) +// } +// } +// +// impl, const D: usize> Eq for GateRef {} +// +// impl, const D: usize> Debug for GateRef { +// fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { +// write!(f, "{}", self.0.id()) +// } +// } /// A gate along with any constants used to configure it. pub struct GateInstance, const D: usize> { diff --git a/plonky2/src/gates/gate_tree.rs b/plonky2/src/gates/gate_tree.rs index 029616a8..8c8ecfe1 100644 --- a/plonky2/src/gates/gate_tree.rs +++ b/plonky2/src/gates/gate_tree.rs @@ -1,7 +1,7 @@ use log::debug; use plonky2_field::extension_field::Extendable; -use crate::gates::gate::GateRef; +use crate::gates::batchable::GateRef; use crate::hash::hash_types::RichField; /// A binary tree where leaves hold some type `T` and other nodes are empty. diff --git a/plonky2/src/gates/gmimc.rs b/plonky2/src/gates/gmimc.rs index fdfb8673..a27f4b71 100644 --- a/plonky2/src/gates/gmimc.rs +++ b/plonky2/src/gates/gmimc.rs @@ -4,6 +4,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -215,6 +216,17 @@ impl + GMiMC, const D: usize, const WIDTH: u gmimc::NUM_ROUNDS + WIDTH + 1 } } +impl + GMiMC, const D: usize, const WIDTH: usize> + MultiOpsGate for GMiMCGate +{ + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} impl + GMiMC, const D: usize, const WIDTH: usize> PackedEvaluableBase for GMiMCGate diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index 9d3d6e3f..c1ac866c 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -8,6 +8,7 @@ use plonky2_field::polynomial::PolynomialCoeffs; use crate::gadgets::interpolation::InterpolationGate; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -202,6 +203,17 @@ impl, const D: usize> Gate self.num_points() * D + D } } +impl, const D: usize> MultiOpsGate + for HighDegreeInterpolationGate +{ + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} #[derive(Debug)] struct InterpolationGenerator, const D: usize> { diff --git a/plonky2/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs index b7307470..5f707fdb 100644 --- a/plonky2/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -9,6 +9,7 @@ use plonky2_field::polynomial::PolynomialCoeffs; use crate::gadgets::interpolation::InterpolationGate; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -294,6 +295,18 @@ impl, const D: usize> Gate for LowDegreeInter } } +impl, const D: usize> MultiOpsGate + for LowDegreeInterpolationGate +{ + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + #[derive(Debug)] struct InterpolationGenerator, const D: usize> { gate_index: usize, diff --git a/plonky2/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs index 9ccfe637..031edfdc 100644 --- a/plonky2/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -3,6 +3,7 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -145,6 +146,20 @@ impl, const D: usize> Gate for MulExtensionGa } } +impl, const D: usize> MultiOpsGate for MulExtensionGate { + fn num_ops(&self) -> usize { + self.num_ops + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + [ + ExtensionTarget::::from_range(gate_index, Self::wires_ith_multiplicand_0(i)).0, + ExtensionTarget::::from_range(gate_index, Self::wires_ith_multiplicand_1(i)).0, + ] + .concat() + } +} + #[derive(Clone, Debug)] struct MulExtensionGenerator, const D: usize> { gate_index: usize, diff --git a/plonky2/src/gates/noop.rs b/plonky2/src/gates/noop.rs index 4cd872d8..56942308 100644 --- a/plonky2/src/gates/noop.rs +++ b/plonky2/src/gates/noop.rs @@ -1,9 +1,11 @@ use plonky2_field::extension_field::Extendable; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; +use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch}; @@ -56,6 +58,16 @@ impl, const D: usize> Gate for NoopGate { } } +impl, const D: usize> MultiOpsGate for NoopGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + #[cfg(test)] mod tests { use plonky2_field::goldilocks_field::GoldilocksField; diff --git a/plonky2/src/gates/poseidon.rs b/plonky2/src/gates/poseidon.rs index 366e200e..f2e3ebbf 100644 --- a/plonky2/src/gates/poseidon.rs +++ b/plonky2/src/gates/poseidon.rs @@ -3,6 +3,7 @@ use std::marker::PhantomData; use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::poseidon_mds::PoseidonMdsGate; use crate::gates::util::StridedConstraintConsumer; @@ -406,6 +407,15 @@ impl, const D: usize> Gate for PoseidonGate, const D: usize> MultiOpsGate for PoseidonGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} #[derive(Debug)] struct PoseidonGenerator + Poseidon, const D: usize> { diff --git a/plonky2/src/gates/poseidon_mds.rs b/plonky2/src/gates/poseidon_mds.rs index 81583f88..8b1fe9c4 100644 --- a/plonky2/src/gates/poseidon_mds.rs +++ b/plonky2/src/gates/poseidon_mds.rs @@ -6,6 +6,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; use plonky2_field::field_types::Field; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -196,6 +197,17 @@ impl + Poseidon, const D: usize> Gate for Pos SPONGE_WIDTH * D } } +impl + Poseidon, const D: usize> MultiOpsGate + for PoseidonMdsGate +{ + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} #[derive(Clone, Debug)] struct PoseidonMdsGenerator { diff --git a/plonky2/src/gates/public_input.rs b/plonky2/src/gates/public_input.rs index 20fc59c8..d8fd0355 100644 --- a/plonky2/src/gates/public_input.rs +++ b/plonky2/src/gates/public_input.rs @@ -3,12 +3,14 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; +use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, @@ -87,6 +89,16 @@ impl, const D: usize> Gate for PublicInputGat } } +impl, const D: usize> MultiOpsGate for PublicInputGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + impl, const D: usize> PackedEvaluableBase for PublicInputGate { fn eval_unfiltered_base_packed>( &self, diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 77359a19..6a93b259 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -5,6 +5,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -230,6 +231,21 @@ impl, const D: usize> Gate for RandomAccessGa } } +impl, const D: usize> MultiOpsGate for RandomAccessGate { + fn num_ops(&self) -> usize { + self.num_copies + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + RandomAccessGenerator { + gate_index, + gate: *self, + copy: i, + } + .dependencies() + } +} + impl, const D: usize> PackedEvaluableBase for RandomAccessGate { diff --git a/plonky2/src/gates/reducing.rs b/plonky2/src/gates/reducing.rs index 2abf8425..ed75bfb5 100644 --- a/plonky2/src/gates/reducing.rs +++ b/plonky2/src/gates/reducing.rs @@ -3,6 +3,7 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -166,6 +167,16 @@ impl, const D: usize> Gate for ReducingGate, const D: usize> MultiOpsGate for ReducingGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + #[derive(Debug)] struct ReducingGenerator { gate_index: usize, diff --git a/plonky2/src/gates/reducing_extension.rs b/plonky2/src/gates/reducing_extension.rs index 6655f1d7..de8b15b6 100644 --- a/plonky2/src/gates/reducing_extension.rs +++ b/plonky2/src/gates/reducing_extension.rs @@ -3,6 +3,7 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -166,6 +167,16 @@ impl, const D: usize> Gate for ReducingExtens } } +impl, const D: usize> MultiOpsGate for ReducingExtensionGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + unreachable!() + } +} + #[derive(Debug)] struct ReducingGenerator { gate_index: usize, diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index fa817ce4..a6fa5e74 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -4,6 +4,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -221,6 +222,22 @@ impl, const D: usize> Gate for U32Subtraction } } +impl, const D: usize> MultiOpsGate for U32SubtractionGate { + fn num_ops(&self) -> usize { + self.num_ops + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + U32SubtractionGenerator { + gate: *self, + gate_index, + i, + _phantom: Default::default(), + } + .dependencies() + } +} + impl, const D: usize> PackedEvaluableBase for U32SubtractionGate { diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index c5271a60..f782947a 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -5,6 +5,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -189,6 +190,16 @@ impl, const D: usize> Gate for SwitchGate, const D: usize> MultiOpsGate for SwitchGate { + fn num_ops(&self) -> usize { + self.num_copies + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + todo!() + } +} + impl, const D: usize> PackedEvaluableBase for SwitchGate { fn eval_unfiltered_base_packed>( &self, diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index cc4a19a4..cdd169ff 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -18,9 +18,9 @@ use crate::gadgets::arithmetic_u32::U32Target; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::arithmetic_u32::U32ArithmeticGate; -use crate::gates::batchable::{BatchableGate, CurrentSlot}; +use crate::gates::batchable::{BatchableGate, CurrentSlot, GateRef}; use crate::gates::constant::ConstantGate; -use crate::gates::gate::{Gate, GateInstance, GateRef, PrefixedGate}; +use crate::gates::gate::{Gate, GateInstance, PrefixedGate}; use crate::gates::gate_tree::Tree; use crate::gates::multiplication_extension::MulExtensionGate; use crate::gates::noop::NoopGate; @@ -86,6 +86,8 @@ pub struct CircuitBuilder, const D: usize> { // yo: Vec>, batched_gates: BatchedGates, + + current_slots: HashMap, CurrentSlot>, } impl, const D: usize> CircuitBuilder { @@ -105,6 +107,7 @@ impl, const D: usize> CircuitBuilder { arithmetic_results: HashMap::new(), targets_to_constants: HashMap::new(), batched_gates: BatchedGates::new(), + current_slots: HashMap::new(), }; builder.check_config(); builder @@ -189,7 +192,7 @@ impl, const D: usize> CircuitBuilder { } /// Adds a gate to the circuit, and returns its index. - pub fn add_gate>(&mut self, gate_type: G, 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.num_constants(), From ff949f40bcfe3cd07c1bf11f480b39a2cdfef0c9 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 2 Feb 2022 16:02:22 +0100 Subject: [PATCH 03/14] Works everywhere except Waksman --- plonky2/src/gadgets/arithmetic.rs | 4 +- plonky2/src/gadgets/arithmetic_extension.rs | 7 +- plonky2/src/gadgets/arithmetic_u32.rs | 4 +- plonky2/src/gadgets/random_access.rs | 2 +- plonky2/src/gates/arithmetic_base.rs | 2 +- plonky2/src/gates/arithmetic_extension.rs | 2 +- plonky2/src/gates/batchable.rs | 9 +- plonky2/src/gates/gate.rs | 1 + plonky2/src/gates/multiplication_extension.rs | 2 +- plonky2/src/plonk/circuit_builder.rs | 711 +++++++++--------- waksman/src/permutation.rs | 51 +- 11 files changed, 424 insertions(+), 371 deletions(-) diff --git a/plonky2/src/gadgets/arithmetic.rs b/plonky2/src/gadgets/arithmetic.rs index e280fa5e..0d844af9 100644 --- a/plonky2/src/gadgets/arithmetic.rs +++ b/plonky2/src/gadgets/arithmetic.rs @@ -4,6 +4,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::PrimeField; use crate::gates::arithmetic_base::ArithmeticGate; +use crate::gates::batchable::GateRef; use crate::gates::exponentiation::ExponentiationGate; use crate::hash::hash_types::RichField; use crate::iop::target::{BoolTarget, Target}; @@ -78,7 +79,8 @@ impl, const D: usize> CircuitBuilder { } fn add_base_arithmetic_operation(&mut self, operation: BaseArithmeticOperation) -> Target { - let (gate, i) = self.find_base_arithmetic_gate(operation.const_0, operation.const_1); + let gate = ArithmeticGate::new_from_config(&self.config); + let (gate, i) = self.find_slot(gate, vec![operation.const_0, operation.const_1]); let wires_multiplicand_0 = Target::wire(gate, ArithmeticGate::wire_ith_multiplicand_0(i)); let wires_multiplicand_1 = Target::wire(gate, ArithmeticGate::wire_ith_multiplicand_1(i)); let wires_addend = Target::wire(gate, ArithmeticGate::wire_ith_addend(i)); diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index 125fb49a..1ccbb6bd 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -4,6 +4,7 @@ use plonky2_field::field_types::{Field, PrimeField}; use plonky2_util::bits_u64; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; +use crate::gates::batchable::GateRef; use crate::gates::multiplication_extension::MulExtensionGate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; @@ -60,7 +61,8 @@ impl, const D: usize> CircuitBuilder { &mut self, operation: ExtensionArithmeticOperation, ) -> ExtensionTarget { - let (gate, i) = self.find_arithmetic_gate(operation.const_0, operation.const_1); + let gate = ArithmeticExtensionGate::new_from_config(&self.config); + let (gate, i) = self.find_slot(gate, vec![operation.const_0, operation.const_1]); let wires_multiplicand_0 = ExtensionTarget::from_range( gate, ArithmeticExtensionGate::::wires_ith_multiplicand_0(i), @@ -83,7 +85,8 @@ impl, const D: usize> CircuitBuilder { &mut self, operation: ExtensionArithmeticOperation, ) -> ExtensionTarget { - let (gate, i) = self.find_mul_gate(operation.const_0); + let gate = MulExtensionGate::new_from_config(&self.config); + let (gate, i) = self.find_slot(gate, vec![operation.const_0]); let wires_multiplicand_0 = ExtensionTarget::from_range(gate, MulExtensionGate::::wires_ith_multiplicand_0(i)); let wires_multiplicand_1 = diff --git a/plonky2/src/gadgets/arithmetic_u32.rs b/plonky2/src/gadgets/arithmetic_u32.rs index 6116f61b..1c8df3b6 100644 --- a/plonky2/src/gadgets/arithmetic_u32.rs +++ b/plonky2/src/gadgets/arithmetic_u32.rs @@ -78,7 +78,7 @@ impl, const D: usize> CircuitBuilder { } let gate = U32ArithmeticGate::::new_from_config(&self.config); - let (gate_index, copy) = self.find_u32_arithmetic_gate(); + let (gate_index, copy) = self.find_slot(gate, vec![]); self.connect( Target::wire(gate_index, gate.wire_ith_multiplicand_0(copy)), @@ -138,7 +138,7 @@ impl, const D: usize> CircuitBuilder { borrow: U32Target, ) -> (U32Target, U32Target) { let gate = U32SubtractionGate::::new_from_config(&self.config); - let (gate_index, copy) = self.find_u32_subtraction_gate(); + let (gate_index, copy) = self.find_slot(gate, vec![]); self.connect(Target::wire(gate_index, gate.wire_ith_input_x(copy)), x.0); self.connect(Target::wire(gate_index, gate.wire_ith_input_y(copy)), y.0); diff --git a/plonky2/src/gadgets/random_access.rs b/plonky2/src/gadgets/random_access.rs index a688292d..1a142844 100644 --- a/plonky2/src/gadgets/random_access.rs +++ b/plonky2/src/gadgets/random_access.rs @@ -17,8 +17,8 @@ impl, const D: usize> CircuitBuilder { if vec_size == 1 { return self.connect(claimed_element, v[0]); } - let (gate_index, copy) = self.find_random_access_gate(bits); let dummy_gate = RandomAccessGate::::new_from_config(&self.config, bits); + let (gate_index, copy) = self.find_slot(dummy_gate, vec![]); v.iter().enumerate().for_each(|(i, &val)| { self.connect( diff --git a/plonky2/src/gates/arithmetic_base.rs b/plonky2/src/gates/arithmetic_base.rs index ca308923..455dbc81 100644 --- a/plonky2/src/gates/arithmetic_base.rs +++ b/plonky2/src/gates/arithmetic_base.rs @@ -19,7 +19,7 @@ use crate::plonk::vars::{ /// A gate which can perform a weighted multiply-add, i.e. `result = c0 x y + c1 z`. If the config /// supports enough routed wires, it can support several such operations in one gate. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ArithmeticGate { /// Number of arithmetic operations performed by an arithmetic gate. pub num_ops: usize, diff --git a/plonky2/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs index bd575272..530b030c 100644 --- a/plonky2/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -17,7 +17,7 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate which can perform a weighted multiply-add, i.e. `result = c0 x y + c1 z`. If the config /// supports enough routed wires, it can support several such operations in one gate. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ArithmeticExtensionGate { /// Number of arithmetic operations performed by an arithmetic gate. pub num_ops: usize, diff --git a/plonky2/src/gates/batchable.rs b/plonky2/src/gates/batchable.rs index a2daef6f..6bae6a88 100644 --- a/plonky2/src/gates/batchable.rs +++ b/plonky2/src/gates/batchable.rs @@ -12,6 +12,8 @@ use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; pub trait BatchableGate, const D: usize>: Gate { + fn num_ops(&self) -> usize; + // TODO: It would be nice to have a `Parameters` associated type. fn fill_gate( &self, @@ -21,8 +23,9 @@ pub trait BatchableGate, const D: usize>: Gate, const D: usize> { - current_slot: HashMap, (usize, usize)>, + pub current_slot: HashMap, (usize, usize)>, } #[derive(Clone)] @@ -76,6 +79,10 @@ pub trait MultiOpsGate, const D: usize>: Gate impl, G: MultiOpsGate, const D: usize> BatchableGate for G { + fn num_ops(&self) -> usize { + self.num_ops() + } + fn fill_gate( &self, params: &[F], diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 5cc15216..db73f6ce 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -173,6 +173,7 @@ pub trait Gate, const D: usize>: 'static + Send + S // } /// A gate along with any constants used to configure it. +#[derive(Clone)] pub struct GateInstance, const D: usize> { pub gate_ref: GateRef, pub constants: Vec, diff --git a/plonky2/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs index 031edfdc..0b93359d 100644 --- a/plonky2/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -17,7 +17,7 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate which can perform a weighted multiplication, i.e. `result = c0 x y`. If the config /// supports enough routed wires, it can support several such operations in one gate. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct MulExtensionGate { /// Number of multiplications performed by the gate. pub num_ops: usize, diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index cdd169ff..bfe5ee3a 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -84,9 +84,6 @@ pub struct CircuitBuilder, const D: usize> { /// Memoized results of `arithmetic_extension` calls. pub(crate) arithmetic_results: HashMap, ExtensionTarget>, - // yo: Vec>, - batched_gates: BatchedGates, - current_slots: HashMap, CurrentSlot>, } @@ -106,7 +103,6 @@ impl, const D: usize> CircuitBuilder { base_arithmetic_results: HashMap::new(), arithmetic_results: HashMap::new(), targets_to_constants: HashMap::new(), - batched_gates: BatchedGates::new(), current_slots: HashMap::new(), }; builder.check_config(); @@ -193,6 +189,7 @@ impl, const D: usize> CircuitBuilder { /// Adds a gate to the circuit, and returns its index. pub fn add_gate>(&mut self, gate_type: G, constants: Vec) -> usize { + // println!("{} {}", self.num_gates(), gate_type.id()); self.check_gate_compatibility(&gate_type); assert_eq!( gate_type.num_constants(), @@ -307,7 +304,11 @@ impl, const D: usize> CircuitBuilder { return target; } - let (gate, instance) = self.constant_gate_instance(); + let num_consts = self.config.constant_gate_size; + // We will fill this `ConstantGate` with zero constants initially. + // These will be overwritten by `constant` as the gate instances are filled. + let gate = ConstantGate { num_consts }; + let (gate, instance) = self.find_slot(gate, vec![F::ZERO; num_consts]); let target = Target::wire(gate, instance); self.gate_instances[gate].constants[instance] = c; @@ -373,6 +374,44 @@ impl, const D: usize> CircuitBuilder { }) } + pub fn find_slot + Clone>( + &mut self, + gate: G, + params: Vec, + ) -> (usize, usize) { + let num_gates = self.num_gates(); + let num_ops = gate.num_ops(); + let gate_ref = GateRef::new(gate.clone()); + let gate_slot = self + .current_slots + .entry(gate_ref.clone()) + .or_insert(CurrentSlot { + current_slot: HashMap::new(), + }); + let slot = gate_slot.current_slot.get(¶ms); + let res = if let Some(&s) = slot { + s + } else { + self.add_gate(gate, params.clone()); + (num_gates, 0) + }; + if res.1 == num_ops - 1 { + self.current_slots + .get_mut(&gate_ref) + .unwrap() + .current_slot + .remove(¶ms); + } else { + self.current_slots + .get_mut(&gate_ref) + .unwrap() + .current_slot + .insert(params, (res.0, res.1 + 1)); + } + + res + } + fn fri_params(&self, degree_bits: usize) -> FriParams { let fri_config = &self.config.fri_config; let reduction_arity_bits = fri_config.reduction_strategy.reduction_arity_bits( @@ -815,337 +854,337 @@ impl, const D: usize> BatchedGates { } impl, const D: usize> CircuitBuilder { - /// 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. - pub(crate) fn find_base_arithmetic_gate(&mut self, const_0: F, const_1: F) -> (usize, usize) { - let (gate, i) = self - .batched_gates - .free_base_arithmetic - .get(&(const_0, const_1)) - .copied() - .unwrap_or_else(|| { - let gate = self.add_gate( - ArithmeticGate::new_from_config(&self.config), - vec![const_0, const_1], - ); - (gate, 0) - }); - - // Update `free_arithmetic` with new values. - if i < ArithmeticGate::num_ops(&self.config) - 1 { - self.batched_gates - .free_base_arithmetic - .insert((const_0, const_1), (gate, i + 1)); - } else { - self.batched_gates - .free_base_arithmetic - .remove(&(const_0, const_1)); - } - - (gate, i) - } - - /// 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. - pub(crate) fn find_arithmetic_gate(&mut self, const_0: F, const_1: F) -> (usize, usize) { - let (gate, i) = self - .batched_gates - .free_arithmetic - .get(&(const_0, const_1)) - .copied() - .unwrap_or_else(|| { - let gate = self.add_gate( - ArithmeticExtensionGate::new_from_config(&self.config), - vec![const_0, const_1], - ); - (gate, 0) - }); - - // Update `free_arithmetic` with new values. - if i < ArithmeticExtensionGate::::num_ops(&self.config) - 1 { - self.batched_gates - .free_arithmetic - .insert((const_0, const_1), (gate, i + 1)); - } else { - self.batched_gates - .free_arithmetic - .remove(&(const_0, const_1)); - } - - (gate, i) - } - - /// 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. - pub(crate) fn find_mul_gate(&mut self, const_0: F) -> (usize, usize) { - let (gate, i) = self - .batched_gates - .free_mul - .get(&const_0) - .copied() - .unwrap_or_else(|| { - let gate = self.add_gate( - MulExtensionGate::new_from_config(&self.config), - vec![const_0], - ); - (gate, 0) - }); - - // Update `free_arithmetic` with new values. - if i < MulExtensionGate::::num_ops(&self.config) - 1 { - self.batched_gates.free_mul.insert(const_0, (gate, i + 1)); - } else { - self.batched_gates.free_mul.remove(&const_0); - } - - (gate, i) - } - - /// Finds the last available random access gate with the given `vec_size` or add one if there aren't any. - /// Returns `(g,i)` such that there is a random access gate with the given `vec_size` at index - /// `g` and the gate's `i`-th random access is available. - pub(crate) fn find_random_access_gate(&mut self, bits: usize) -> (usize, usize) { - let (gate, i) = self - .batched_gates - .free_random_access - .get(&bits) - .copied() - .unwrap_or_else(|| { - let gate = self.add_gate( - RandomAccessGate::new_from_config(&self.config, bits), - vec![], - ); - (gate, 0) - }); - - // Update `free_random_access` with new values. - if i + 1 < RandomAccessGate::::new_from_config(&self.config, bits).num_copies { - self.batched_gates - .free_random_access - .insert(bits, (gate, i + 1)); - } else { - self.batched_gates.free_random_access.remove(&bits); - } - - (gate, i) - } - - pub fn find_switch_gate(&mut self, chunk_size: usize) -> (SwitchGate, usize, usize) { - if self.batched_gates.current_switch_gates.len() < chunk_size { - self.batched_gates.current_switch_gates.extend(vec![ - None; - chunk_size - - self - .batched_gates - .current_switch_gates - .len() - ]); - } - - let (gate, gate_index, next_copy) = - match self.batched_gates.current_switch_gates[chunk_size - 1].clone() { - None => { - let gate = SwitchGate::::new_from_config(&self.config, chunk_size); - let gate_index = self.add_gate(gate.clone(), vec![]); - (gate, gate_index, 0) - } - Some((gate, idx, next_copy)) => (gate, idx, next_copy), - }; - - let num_copies = gate.num_copies; - - if next_copy == num_copies - 1 { - self.batched_gates.current_switch_gates[chunk_size - 1] = None; - } else { - self.batched_gates.current_switch_gates[chunk_size - 1] = - Some((gate.clone(), gate_index, next_copy + 1)); - } - - (gate, gate_index, next_copy) - } - - pub(crate) fn find_u32_arithmetic_gate(&mut self) -> (usize, usize) { - let (gate_index, copy) = match self.batched_gates.current_u32_arithmetic_gate { - None => { - let gate = U32ArithmeticGate::new_from_config(&self.config); - let gate_index = self.add_gate(gate, vec![]); - (gate_index, 0) - } - Some((gate_index, copy)) => (gate_index, copy), - }; - - if copy == U32ArithmeticGate::::num_ops(&self.config) - 1 { - self.batched_gates.current_u32_arithmetic_gate = None; - } else { - self.batched_gates.current_u32_arithmetic_gate = Some((gate_index, copy + 1)); - } - - (gate_index, copy) - } - - pub(crate) fn find_u32_subtraction_gate(&mut self) -> (usize, usize) { - let (gate_index, copy) = match self.batched_gates.current_u32_subtraction_gate { - None => { - let gate = U32SubtractionGate::new_from_config(&self.config); - let gate_index = self.add_gate(gate, vec![]); - (gate_index, 0) - } - Some((gate_index, copy)) => (gate_index, copy), - }; - - if copy == U32SubtractionGate::::num_ops(&self.config) - 1 { - self.batched_gates.current_u32_subtraction_gate = None; - } else { - self.batched_gates.current_u32_subtraction_gate = Some((gate_index, copy + 1)); - } - - (gate_index, copy) - } - - /// Returns the gate index and copy index of a free `ConstantGate` slot, potentially adding a - /// new `ConstantGate` if needed. - fn constant_gate_instance(&mut self) -> (usize, usize) { - if self.batched_gates.free_constant.is_none() { - let num_consts = self.config.constant_gate_size; - // We will fill this `ConstantGate` with zero constants initially. - // These will be overwritten by `constant` as the gate instances are filled. - let gate = self.add_gate(ConstantGate { num_consts }, vec![F::ZERO; num_consts]); - self.batched_gates.free_constant = Some((gate, 0)); - } - - let (gate, instance) = self.batched_gates.free_constant.unwrap(); - if instance + 1 < self.config.constant_gate_size { - self.batched_gates.free_constant = Some((gate, instance + 1)); - } else { - self.batched_gates.free_constant = None; - } - (gate, instance) - } - - /// Fill the remaining unused arithmetic operations with zeros, so that all - /// `ArithmeticGate` are run. - fn fill_base_arithmetic_gates(&mut self) { - let zero = self.zero(); - for ((c0, c1), (_gate, i)) in self.batched_gates.free_base_arithmetic.clone() { - for _ in i..ArithmeticGate::num_ops(&self.config) { - // If we directly wire in zero, an optimization will skip doing anything and return - // zero. So we pass in a virtual target and connect it to zero afterward. - let dummy = self.add_virtual_target(); - self.arithmetic(c0, c1, dummy, dummy, dummy); - self.connect(dummy, zero); - } - } - assert!(self.batched_gates.free_base_arithmetic.is_empty()); - } - - /// Fill the remaining unused arithmetic operations with zeros, so that all - /// `ArithmeticExtensionGenerator`s are run. - fn fill_arithmetic_gates(&mut self) { - let zero = self.zero_extension(); - for ((c0, c1), (_gate, i)) in self.batched_gates.free_arithmetic.clone() { - for _ in i..ArithmeticExtensionGate::::num_ops(&self.config) { - // If we directly wire in zero, an optimization will skip doing anything and return - // zero. So we pass in a virtual target and connect it to zero afterward. - let dummy = self.add_virtual_extension_target(); - self.arithmetic_extension(c0, c1, dummy, dummy, dummy); - self.connect_extension(dummy, zero); - } - } - assert!(self.batched_gates.free_arithmetic.is_empty()); - } - - /// Fill the remaining unused arithmetic operations with zeros, so that all - /// `ArithmeticExtensionGenerator`s are run. - fn fill_mul_gates(&mut self) { - let zero = self.zero_extension(); - for (c0, (_gate, i)) in self.batched_gates.free_mul.clone() { - for _ in i..MulExtensionGate::::num_ops(&self.config) { - // If we directly wire in zero, an optimization will skip doing anything and return - // zero. So we pass in a virtual target and connect it to zero afterward. - let dummy = self.add_virtual_extension_target(); - self.arithmetic_extension(c0, F::ZERO, dummy, dummy, zero); - self.connect_extension(dummy, zero); - } - } - assert!(self.batched_gates.free_mul.is_empty()); - } - - /// Fill the remaining unused random access operations with zeros, so that all - /// `RandomAccessGenerator`s are run. - fn fill_random_access_gates(&mut self) { - let zero = self.zero(); - for (bits, (_, i)) in self.batched_gates.free_random_access.clone() { - let max_copies = - RandomAccessGate::::new_from_config(&self.config, bits).num_copies; - for _ in i..max_copies { - self.random_access(zero, zero, vec![zero; 1 << bits]); - } - } - } - - /// Fill the remaining unused switch gates with dummy values, so that all - /// `SwitchGenerator`s are run. - fn fill_switch_gates(&mut self) { - let zero = self.zero(); - - for chunk_size in 1..=self.batched_gates.current_switch_gates.len() { - if let Some((gate, gate_index, mut copy)) = - self.batched_gates.current_switch_gates[chunk_size - 1].clone() - { - while copy < gate.num_copies { - for element in 0..chunk_size { - let wire_first_input = - Target::wire(gate_index, gate.wire_first_input(copy, element)); - let wire_second_input = - Target::wire(gate_index, gate.wire_second_input(copy, element)); - let wire_switch_bool = - Target::wire(gate_index, gate.wire_switch_bool(copy)); - self.connect(zero, wire_first_input); - self.connect(zero, wire_second_input); - self.connect(zero, wire_switch_bool); - } - copy += 1; - } - } - } - } - - /// Fill the remaining unused U32 arithmetic operations with zeros, so that all - /// `U32ArithmeticGenerator`s are run. - fn fill_u32_arithmetic_gates(&mut self) { - let zero = self.zero_u32(); - if let Some((_gate_index, copy)) = self.batched_gates.current_u32_arithmetic_gate { - for _ in copy..U32ArithmeticGate::::num_ops(&self.config) { - let dummy = self.add_virtual_u32_target(); - self.mul_add_u32(dummy, dummy, dummy); - self.connect_u32(dummy, zero); - } - } - } - - /// Fill the remaining unused U32 subtraction operations with zeros, so that all - /// `U32SubtractionGenerator`s are run. - fn fill_u32_subtraction_gates(&mut self) { - let zero = self.zero_u32(); - if let Some((_gate_index, copy)) = self.batched_gates.current_u32_subtraction_gate { - for _i in copy..U32SubtractionGate::::num_ops(&self.config) { - let dummy = self.add_virtual_u32_target(); - self.sub_u32(dummy, dummy, dummy); - self.connect_u32(dummy, zero); - } - } - } - + // /// 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. + // pub(crate) fn find_base_arithmetic_gate(&mut self, const_0: F, const_1: F) -> (usize, usize) { + // let (gate, i) = self + // .batched_gates + // .free_base_arithmetic + // .get(&(const_0, const_1)) + // .copied() + // .unwrap_or_else(|| { + // let gate = self.add_gate( + // ArithmeticGate::new_from_config(&self.config), + // vec![const_0, const_1], + // ); + // (gate, 0) + // }); + // + // // Update `free_arithmetic` with new values. + // if i < ArithmeticGate::num_ops(&self.config) - 1 { + // self.batched_gates + // .free_base_arithmetic + // .insert((const_0, const_1), (gate, i + 1)); + // } else { + // self.batched_gates + // .free_base_arithmetic + // .remove(&(const_0, const_1)); + // } + // + // (gate, i) + // } + // + // /// 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. + // pub(crate) fn find_arithmetic_gate(&mut self, const_0: F, const_1: F) -> (usize, usize) { + // let (gate, i) = self + // .batched_gates + // .free_arithmetic + // .get(&(const_0, const_1)) + // .copied() + // .unwrap_or_else(|| { + // let gate = self.add_gate( + // ArithmeticExtensionGate::new_from_config(&self.config), + // vec![const_0, const_1], + // ); + // (gate, 0) + // }); + // + // // Update `free_arithmetic` with new values. + // if i < ArithmeticExtensionGate::::num_ops(&self.config) - 1 { + // self.batched_gates + // .free_arithmetic + // .insert((const_0, const_1), (gate, i + 1)); + // } else { + // self.batched_gates + // .free_arithmetic + // .remove(&(const_0, const_1)); + // } + // + // (gate, i) + // } + // + // /// 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. + // pub(crate) fn find_mul_gate(&mut self, const_0: F) -> (usize, usize) { + // let (gate, i) = self + // .batched_gates + // .free_mul + // .get(&const_0) + // .copied() + // .unwrap_or_else(|| { + // let gate = self.add_gate( + // MulExtensionGate::new_from_config(&self.config), + // vec![const_0], + // ); + // (gate, 0) + // }); + // + // // Update `free_arithmetic` with new values. + // if i < MulExtensionGate::::num_ops(&self.config) - 1 { + // self.batched_gates.free_mul.insert(const_0, (gate, i + 1)); + // } else { + // self.batched_gates.free_mul.remove(&const_0); + // } + // + // (gate, i) + // } + // + // /// Finds the last available random access gate with the given `vec_size` or add one if there aren't any. + // /// Returns `(g,i)` such that there is a random access gate with the given `vec_size` at index + // /// `g` and the gate's `i`-th random access is available. + // pub(crate) fn find_random_access_gate(&mut self, bits: usize) -> (usize, usize) { + // let (gate, i) = self + // .batched_gates + // .free_random_access + // .get(&bits) + // .copied() + // .unwrap_or_else(|| { + // let gate = self.add_gate( + // RandomAccessGate::new_from_config(&self.config, bits), + // vec![], + // ); + // (gate, 0) + // }); + // + // // Update `free_random_access` with new values. + // if i + 1 < RandomAccessGate::::new_from_config(&self.config, bits).num_copies { + // self.batched_gates + // .free_random_access + // .insert(bits, (gate, i + 1)); + // } else { + // self.batched_gates.free_random_access.remove(&bits); + // } + // + // (gate, i) + // } + // + // pub fn find_switch_gate(&mut self, chunk_size: usize) -> (SwitchGate, usize, usize) { + // if self.batched_gates.current_switch_gates.len() < chunk_size { + // self.batched_gates.current_switch_gates.extend(vec![ + // None; + // chunk_size + // - self + // .batched_gates + // .current_switch_gates + // .len() + // ]); + // } + // + // let (gate, gate_index, next_copy) = + // match self.batched_gates.current_switch_gates[chunk_size - 1].clone() { + // None => { + // let gate = SwitchGate::::new_from_config(&self.config, chunk_size); + // let gate_index = self.add_gate(gate.clone(), vec![]); + // (gate, gate_index, 0) + // } + // Some((gate, idx, next_copy)) => (gate, idx, next_copy), + // }; + // + // let num_copies = gate.num_copies; + // + // if next_copy == num_copies - 1 { + // self.batched_gates.current_switch_gates[chunk_size - 1] = None; + // } else { + // self.batched_gates.current_switch_gates[chunk_size - 1] = + // Some((gate.clone(), gate_index, next_copy + 1)); + // } + // + // (gate, gate_index, next_copy) + // } + // + // pub(crate) fn find_u32_arithmetic_gate(&mut self) -> (usize, usize) { + // let (gate_index, copy) = match self.batched_gates.current_u32_arithmetic_gate { + // None => { + // let gate = U32ArithmeticGate::new_from_config(&self.config); + // let gate_index = self.add_gate(gate, vec![]); + // (gate_index, 0) + // } + // Some((gate_index, copy)) => (gate_index, copy), + // }; + // + // if copy == U32ArithmeticGate::::num_ops(&self.config) - 1 { + // self.batched_gates.current_u32_arithmetic_gate = None; + // } else { + // self.batched_gates.current_u32_arithmetic_gate = Some((gate_index, copy + 1)); + // } + // + // (gate_index, copy) + // } + // + // pub(crate) fn find_u32_subtraction_gate(&mut self) -> (usize, usize) { + // let (gate_index, copy) = match self.batched_gates.current_u32_subtraction_gate { + // None => { + // let gate = U32SubtractionGate::new_from_config(&self.config); + // let gate_index = self.add_gate(gate, vec![]); + // (gate_index, 0) + // } + // Some((gate_index, copy)) => (gate_index, copy), + // }; + // + // if copy == U32SubtractionGate::::num_ops(&self.config) - 1 { + // self.batched_gates.current_u32_subtraction_gate = None; + // } else { + // self.batched_gates.current_u32_subtraction_gate = Some((gate_index, copy + 1)); + // } + // + // (gate_index, copy) + // } + // + // /// Returns the gate index and copy index of a free `ConstantGate` slot, potentially adding a + // /// new `ConstantGate` if needed. + // fn constant_gate_instance(&mut self) -> (usize, usize) { + // if self.batched_gates.free_constant.is_none() { + // let num_consts = self.config.constant_gate_size; + // // We will fill this `ConstantGate` with zero constants initially. + // // These will be overwritten by `constant` as the gate instances are filled. + // let gate = self.add_gate(ConstantGate { num_consts }, vec![F::ZERO; num_consts]); + // self.batched_gates.free_constant = Some((gate, 0)); + // } + // + // let (gate, instance) = self.batched_gates.free_constant.unwrap(); + // if instance + 1 < self.config.constant_gate_size { + // self.batched_gates.free_constant = Some((gate, instance + 1)); + // } else { + // self.batched_gates.free_constant = None; + // } + // (gate, instance) + // } + // + // /// Fill the remaining unused arithmetic operations with zeros, so that all + // /// `ArithmeticGate` are run. + // fn fill_base_arithmetic_gates(&mut self) { + // let zero = self.zero(); + // for ((c0, c1), (_gate, i)) in self.batched_gates.free_base_arithmetic.clone() { + // for _ in i..ArithmeticGate::num_ops(&self.config) { + // // If we directly wire in zero, an optimization will skip doing anything and return + // // zero. So we pass in a virtual target and connect it to zero afterward. + // let dummy = self.add_virtual_target(); + // self.arithmetic(c0, c1, dummy, dummy, dummy); + // self.connect(dummy, zero); + // } + // } + // assert!(self.batched_gates.free_base_arithmetic.is_empty()); + // } + // + // /// Fill the remaining unused arithmetic operations with zeros, so that all + // /// `ArithmeticExtensionGenerator`s are run. + // fn fill_arithmetic_gates(&mut self) { + // let zero = self.zero_extension(); + // for ((c0, c1), (_gate, i)) in self.batched_gates.free_arithmetic.clone() { + // for _ in i..ArithmeticExtensionGate::::num_ops(&self.config) { + // // If we directly wire in zero, an optimization will skip doing anything and return + // // zero. So we pass in a virtual target and connect it to zero afterward. + // let dummy = self.add_virtual_extension_target(); + // self.arithmetic_extension(c0, c1, dummy, dummy, dummy); + // self.connect_extension(dummy, zero); + // } + // } + // assert!(self.batched_gates.free_arithmetic.is_empty()); + // } + // + // /// Fill the remaining unused arithmetic operations with zeros, so that all + // /// `ArithmeticExtensionGenerator`s are run. + // fn fill_mul_gates(&mut self) { + // let zero = self.zero_extension(); + // for (c0, (_gate, i)) in self.batched_gates.free_mul.clone() { + // for _ in i..MulExtensionGate::::num_ops(&self.config) { + // // If we directly wire in zero, an optimization will skip doing anything and return + // // zero. So we pass in a virtual target and connect it to zero afterward. + // let dummy = self.add_virtual_extension_target(); + // self.arithmetic_extension(c0, F::ZERO, dummy, dummy, zero); + // self.connect_extension(dummy, zero); + // } + // } + // assert!(self.batched_gates.free_mul.is_empty()); + // } + // + // /// Fill the remaining unused random access operations with zeros, so that all + // /// `RandomAccessGenerator`s are run. + // fn fill_random_access_gates(&mut self) { + // let zero = self.zero(); + // for (bits, (_, i)) in self.batched_gates.free_random_access.clone() { + // let max_copies = + // RandomAccessGate::::new_from_config(&self.config, bits).num_copies; + // for _ in i..max_copies { + // self.random_access(zero, zero, vec![zero; 1 << bits]); + // } + // } + // } + // + // /// Fill the remaining unused switch gates with dummy values, so that all + // /// `SwitchGenerator`s are run. + // fn fill_switch_gates(&mut self) { + // let zero = self.zero(); + // + // for chunk_size in 1..=self.batched_gates.current_switch_gates.len() { + // if let Some((gate, gate_index, mut copy)) = + // self.batched_gates.current_switch_gates[chunk_size - 1].clone() + // { + // while copy < gate.num_copies { + // for element in 0..chunk_size { + // let wire_first_input = + // Target::wire(gate_index, gate.wire_first_input(copy, element)); + // let wire_second_input = + // Target::wire(gate_index, gate.wire_second_input(copy, element)); + // let wire_switch_bool = + // Target::wire(gate_index, gate.wire_switch_bool(copy)); + // self.connect(zero, wire_first_input); + // self.connect(zero, wire_second_input); + // self.connect(zero, wire_switch_bool); + // } + // copy += 1; + // } + // } + // } + // } + // + // /// Fill the remaining unused U32 arithmetic operations with zeros, so that all + // /// `U32ArithmeticGenerator`s are run. + // fn fill_u32_arithmetic_gates(&mut self) { + // let zero = self.zero_u32(); + // if let Some((_gate_index, copy)) = self.batched_gates.current_u32_arithmetic_gate { + // for _ in copy..U32ArithmeticGate::::num_ops(&self.config) { + // let dummy = self.add_virtual_u32_target(); + // self.mul_add_u32(dummy, dummy, dummy); + // self.connect_u32(dummy, zero); + // } + // } + // } + // + // /// Fill the remaining unused U32 subtraction operations with zeros, so that all + // /// `U32SubtractionGenerator`s are run. + // fn fill_u32_subtraction_gates(&mut self) { + // let zero = self.zero_u32(); + // if let Some((_gate_index, copy)) = self.batched_gates.current_u32_subtraction_gate { + // for _i in copy..U32SubtractionGate::::num_ops(&self.config) { + // let dummy = self.add_virtual_u32_target(); + // self.sub_u32(dummy, dummy, dummy); + // self.connect_u32(dummy, zero); + // } + // } + // } + // fn fill_batched_gates(&mut self) { - self.fill_arithmetic_gates(); - self.fill_base_arithmetic_gates(); - self.fill_mul_gates(); - self.fill_random_access_gates(); - self.fill_switch_gates(); - self.fill_u32_arithmetic_gates(); - self.fill_u32_subtraction_gates(); + let instances = self.gate_instances.clone(); + for gate in instances { + if let Some(slot) = self.current_slots.get(&gate.gate_ref) { + let cloned = slot.clone(); + gate.gate_ref.0.fill_gate(&gate.constants, &cloned, self); + } + } } } diff --git a/waksman/src/permutation.rs b/waksman/src/permutation.rs index 666342d7..877038dd 100644 --- a/waksman/src/permutation.rs +++ b/waksman/src/permutation.rs @@ -79,32 +79,33 @@ fn create_switch, const D: usize>( let chunk_size = a1.len(); - let (gate, gate_index, next_copy) = builder.find_switch_gate(chunk_size); + todo!() + // let (gate, gate_index, next_copy) = builder.find_switch_gate(chunk_size); + // + // let mut c = Vec::new(); + // let mut d = Vec::new(); + // for e in 0..chunk_size { + // builder.connect( + // a1[e], + // Target::wire(gate_index, gate.wire_first_input(next_copy, e)), + // ); + // builder.connect( + // a2[e], + // Target::wire(gate_index, gate.wire_second_input(next_copy, e)), + // ); + // c.push(Target::wire( + // gate_index, + // gate.wire_first_output(next_copy, e), + // )); + // d.push(Target::wire( + // gate_index, + // gate.wire_second_output(next_copy, e), + // )); + // } - let mut c = Vec::new(); - let mut d = Vec::new(); - for e in 0..chunk_size { - builder.connect( - a1[e], - Target::wire(gate_index, gate.wire_first_input(next_copy, e)), - ); - builder.connect( - a2[e], - Target::wire(gate_index, gate.wire_second_input(next_copy, e)), - ); - c.push(Target::wire( - gate_index, - gate.wire_first_output(next_copy, e), - )); - d.push(Target::wire( - gate_index, - gate.wire_second_output(next_copy, e), - )); - } - - let switch = Target::wire(gate_index, gate.wire_switch_bool(next_copy)); - - (switch, c, d) + // let switch = Target::wire(gate_index, gate.wire_switch_bool(next_copy)); + // + // (switch, c, d) } fn assert_permutation_recursive, const D: usize>( From c0cfff148055230e048277aa152e98066cee4f37 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 2 Feb 2022 16:07:16 +0100 Subject: [PATCH 04/14] Clippy --- insertion/src/insertion_gate.rs | 2 +- plonky2/src/gadgets/arithmetic.rs | 1 - plonky2/src/gadgets/arithmetic_extension.rs | 1 - plonky2/src/gadgets/interpolation.rs | 1 - plonky2/src/gates/assert_le.rs | 2 +- plonky2/src/gates/base_sum.rs | 2 +- plonky2/src/gates/batchable.rs | 1 - plonky2/src/gates/comparison.rs | 2 +- plonky2/src/gates/constant.rs | 2 +- plonky2/src/gates/exponentiation.rs | 4 +- plonky2/src/gates/gate.rs | 4 +- plonky2/src/gates/gmimc.rs | 2 +- plonky2/src/gates/interpolation.rs | 2 +- plonky2/src/gates/low_degree_interpolation.rs | 2 +- plonky2/src/gates/noop.rs | 2 +- plonky2/src/gates/poseidon.rs | 2 +- plonky2/src/gates/poseidon_mds.rs | 2 +- plonky2/src/gates/public_input.rs | 2 +- plonky2/src/gates/reducing.rs | 2 +- plonky2/src/gates/reducing_extension.rs | 2 +- plonky2/src/gates/switch.rs | 2 +- plonky2/src/plonk/circuit_builder.rs | 49 ------------------- waksman/src/permutation.rs | 4 +- 23 files changed, 20 insertions(+), 75 deletions(-) diff --git a/insertion/src/insertion_gate.rs b/insertion/src/insertion_gate.rs index cb5fdc22..33859e70 100644 --- a/insertion/src/insertion_gate.rs +++ b/insertion/src/insertion_gate.rs @@ -248,7 +248,7 @@ impl, const D: usize> MultiOpsGate for Insert 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gadgets/arithmetic.rs b/plonky2/src/gadgets/arithmetic.rs index 0d844af9..c00220c3 100644 --- a/plonky2/src/gadgets/arithmetic.rs +++ b/plonky2/src/gadgets/arithmetic.rs @@ -4,7 +4,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::PrimeField; use crate::gates::arithmetic_base::ArithmeticGate; -use crate::gates::batchable::GateRef; use crate::gates::exponentiation::ExponentiationGate; use crate::hash::hash_types::RichField; use crate::iop::target::{BoolTarget, Target}; diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index 1ccbb6bd..e1a17988 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -4,7 +4,6 @@ use plonky2_field::field_types::{Field, PrimeField}; use plonky2_util::bits_u64; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; -use crate::gates::batchable::GateRef; use crate::gates::multiplication_extension::MulExtensionGate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; diff --git a/plonky2/src/gadgets/interpolation.rs b/plonky2/src/gadgets/interpolation.rs index 92b17098..2d2c2273 100644 --- a/plonky2/src/gadgets/interpolation.rs +++ b/plonky2/src/gadgets/interpolation.rs @@ -3,7 +3,6 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use crate::gates::batchable::BatchableGate; -use crate::gates::gate::Gate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index 759faf51..6d7ad508 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -286,7 +286,7 @@ impl, const D: usize> MultiOpsGate for Assert 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/base_sum.rs b/plonky2/src/gates/base_sum.rs index 87db3c61..c1cf6a49 100644 --- a/plonky2/src/gates/base_sum.rs +++ b/plonky2/src/gates/base_sum.rs @@ -143,7 +143,7 @@ impl, const D: usize, const B: usize> MultiOpsGate< 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/batchable.rs b/plonky2/src/gates/batchable.rs index 6bae6a88..d40fd73c 100644 --- a/plonky2/src/gates/batchable.rs +++ b/plonky2/src/gates/batchable.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use std::fmt::{Debug, Error, Formatter}; use std::hash::{Hash, Hasher}; -use std::marker::PhantomData; use std::sync::Arc; use plonky2_field::extension_field::Extendable; diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index f0ab000f..7d3dd70f 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -319,7 +319,7 @@ impl, const D: usize> MultiOpsGate for Compar 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index f59f3604..e813d573 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -108,7 +108,7 @@ impl, const D: usize> MultiOpsGate for Consta self.num_consts } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { vec![] } } diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index 6d72e21b..9803181a 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -5,7 +5,7 @@ use plonky2_field::field_types::Field; use plonky2_field::ops::Square; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::{BatchableGate, MultiOpsGate}; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -196,7 +196,7 @@ impl, const D: usize> MultiOpsGate for Expone 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index db73f6ce..34684194 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -1,6 +1,4 @@ -use std::fmt::{Debug, Error, Formatter}; -use std::hash::{Hash, Hasher}; -use std::sync::Arc; +use std::fmt::Debug; use plonky2_field::batch_util::batch_multiply_inplace; use plonky2_field::extension_field::{Extendable, FieldExtension}; diff --git a/plonky2/src/gates/gmimc.rs b/plonky2/src/gates/gmimc.rs index a27f4b71..47a82e62 100644 --- a/plonky2/src/gates/gmimc.rs +++ b/plonky2/src/gates/gmimc.rs @@ -223,7 +223,7 @@ impl + GMiMC, const D: usize, const WIDTH: u 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index c1ac866c..325624b4 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -210,7 +210,7 @@ impl, const D: usize> MultiOpsGate 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs index 5f707fdb..5c640775 100644 --- a/plonky2/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -302,7 +302,7 @@ impl, const D: usize> MultiOpsGate 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/noop.rs b/plonky2/src/gates/noop.rs index 56942308..5de05991 100644 --- a/plonky2/src/gates/noop.rs +++ b/plonky2/src/gates/noop.rs @@ -63,7 +63,7 @@ impl, const D: usize> MultiOpsGate for NoopGa 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/poseidon.rs b/plonky2/src/gates/poseidon.rs index f2e3ebbf..4a2ffee7 100644 --- a/plonky2/src/gates/poseidon.rs +++ b/plonky2/src/gates/poseidon.rs @@ -412,7 +412,7 @@ impl, const D: usize> MultiOpsGate for Poseid 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/poseidon_mds.rs b/plonky2/src/gates/poseidon_mds.rs index 8b1fe9c4..ad899599 100644 --- a/plonky2/src/gates/poseidon_mds.rs +++ b/plonky2/src/gates/poseidon_mds.rs @@ -204,7 +204,7 @@ impl + Poseidon, const D: usize> MultiOpsGate 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/public_input.rs b/plonky2/src/gates/public_input.rs index d8fd0355..85145e31 100644 --- a/plonky2/src/gates/public_input.rs +++ b/plonky2/src/gates/public_input.rs @@ -94,7 +94,7 @@ impl, const D: usize> MultiOpsGate for Public 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/reducing.rs b/plonky2/src/gates/reducing.rs index ed75bfb5..cf07d3a7 100644 --- a/plonky2/src/gates/reducing.rs +++ b/plonky2/src/gates/reducing.rs @@ -172,7 +172,7 @@ impl, const D: usize> MultiOpsGate for Reduci 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/reducing_extension.rs b/plonky2/src/gates/reducing_extension.rs index de8b15b6..65eec526 100644 --- a/plonky2/src/gates/reducing_extension.rs +++ b/plonky2/src/gates/reducing_extension.rs @@ -172,7 +172,7 @@ impl, const D: usize> MultiOpsGate for Reduci 1 } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { unreachable!() } } diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index f782947a..e9048edd 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -195,7 +195,7 @@ impl, const D: usize> MultiOpsGate for Switch self.num_copies } - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { todo!() } } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index bfe5ee3a..80a951c7 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -17,17 +17,12 @@ use crate::gadgets::arithmetic_extension::ExtensionArithmeticOperation; use crate::gadgets::arithmetic_u32::U32Target; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; -use crate::gates::arithmetic_u32::U32ArithmeticGate; use crate::gates::batchable::{BatchableGate, CurrentSlot, GateRef}; use crate::gates::constant::ConstantGate; use crate::gates::gate::{Gate, GateInstance, PrefixedGate}; use crate::gates::gate_tree::Tree; -use crate::gates::multiplication_extension::MulExtensionGate; use crate::gates::noop::NoopGate; use crate::gates::public_input::PublicInputGate; -use crate::gates::random_access::RandomAccessGate; -use crate::gates::subtraction_u32::U32SubtractionGate; -use crate::gates::switch::SwitchGate; use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{ @@ -809,50 +804,6 @@ impl, const D: usize> CircuitBuilder { } } -/// Various gate types can contain multiple copies in a single Gate. This helper struct lets a -/// CircuitBuilder track such gates that are currently being "filled up." -pub struct BatchedGates, const D: usize> { - /// 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)>, - pub(crate) free_base_arithmetic: HashMap<(F, F), (usize, usize)>, - - pub(crate) free_mul: HashMap, - - /// A map `b -> (g, i)` from `b` bits to an available random access gate of that size with gate - /// index `g` and already using `i` random accesses. - pub(crate) free_random_access: HashMap, - - /// `current_switch_gates[chunk_size - 1]` contains None if we have no switch gates with the value - /// chunk_size, and contains `(g, i, c)`, if the gate `g`, at index `i`, already contains `c` copies - /// of switches - pub(crate) current_switch_gates: Vec, usize, usize)>>, - - /// The `U32ArithmeticGate` currently being filled (so new u32 arithmetic operations will be added to this gate before creating a new one) - pub(crate) current_u32_arithmetic_gate: Option<(usize, usize)>, - - /// The `U32SubtractionGate` currently being filled (so new u32 subtraction operations will be added to this gate before creating a new one) - pub(crate) current_u32_subtraction_gate: Option<(usize, usize)>, - - /// An available `ConstantGate` instance, if any. - pub(crate) free_constant: Option<(usize, usize)>, -} - -impl, const D: usize> BatchedGates { - pub fn new() -> Self { - Self { - free_arithmetic: HashMap::new(), - free_base_arithmetic: HashMap::new(), - free_mul: HashMap::new(), - free_random_access: HashMap::new(), - current_switch_gates: Vec::new(), - current_u32_arithmetic_gate: None, - current_u32_subtraction_gate: None, - free_constant: None, - } - } -} - impl, const D: usize> CircuitBuilder { // /// 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 diff --git a/waksman/src/permutation.rs b/waksman/src/permutation.rs index 877038dd..b0e725d2 100644 --- a/waksman/src/permutation.rs +++ b/waksman/src/permutation.rs @@ -71,13 +71,13 @@ fn assert_permutation_2x2, const D: usize>( /// Given two input wire chunks, add a new switch to the circuit (by adding one copy to a switch /// gate). Returns the wire for the switch boolean, and the two output wire chunks. fn create_switch, const D: usize>( - builder: &mut CircuitBuilder, + _builder: &mut CircuitBuilder, a1: Vec, a2: Vec, ) -> (Target, Vec, Vec) { assert_eq!(a1.len(), a2.len(), "Chunk size must be the same"); - let chunk_size = a1.len(); + let _chunk_size = a1.len(); todo!() // let (gate, gate_index, next_copy) = builder.find_switch_gate(chunk_size); From b104dfce2ac6be536a456d2f7d5035f1bea117a3 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 14 Feb 2022 19:37:24 +0100 Subject: [PATCH 05/14] Working --- insertion/src/insert_gadget.rs | 2 +- plonky2/src/gadgets/arithmetic.rs | 5 +- plonky2/src/gadgets/arithmetic_extension.rs | 6 ++- plonky2/src/gadgets/arithmetic_u32.rs | 4 +- plonky2/src/gadgets/interpolation.rs | 2 +- plonky2/src/gadgets/multiple_comparison.rs | 4 +- plonky2/src/gadgets/random_access.rs | 2 +- plonky2/src/gadgets/split_base.rs | 4 +- plonky2/src/gadgets/split_join.rs | 2 +- plonky2/src/gates/batchable.rs | 3 +- plonky2/src/gates/gate.rs | 1 + plonky2/src/gates/gmimc.rs | 2 +- plonky2/src/gates/poseidon.rs | 2 +- plonky2/src/gates/switch.rs | 13 +++-- plonky2/src/hash/gmimc.rs | 2 +- plonky2/src/hash/poseidon.rs | 4 +- plonky2/src/iop/generator.rs | 5 ++ plonky2/src/plonk/circuit_builder.rs | 41 ++++++++++----- plonky2/src/plonk/proof.rs | 2 +- plonky2/src/plonk/recursive_verifier.rs | 4 +- plonky2/src/util/reducing.rs | 4 +- waksman/src/permutation.rs | 58 +++++++++++---------- waksman/src/sorting.rs | 2 +- 23 files changed, 102 insertions(+), 72 deletions(-) diff --git a/insertion/src/insert_gadget.rs b/insertion/src/insert_gadget.rs index 9f8aa4bf..76cb4410 100644 --- a/insertion/src/insert_gadget.rs +++ b/insertion/src/insert_gadget.rs @@ -27,7 +27,7 @@ impl, const D: usize> CircuitBuilderInsert v: Vec>, ) -> Vec> { let gate = InsertionGate::new(v.len()); - let gate_index = self.add_gate(gate.clone(), vec![]); + let gate_index = self.add_gate(gate.clone(), vec![], vec![]); v.iter().enumerate().for_each(|(i, &val)| { self.connect_extension( diff --git a/plonky2/src/gadgets/arithmetic.rs b/plonky2/src/gadgets/arithmetic.rs index c00220c3..734e2705 100644 --- a/plonky2/src/gadgets/arithmetic.rs +++ b/plonky2/src/gadgets/arithmetic.rs @@ -79,7 +79,8 @@ impl, const D: usize> CircuitBuilder { fn add_base_arithmetic_operation(&mut self, operation: BaseArithmeticOperation) -> Target { let gate = ArithmeticGate::new_from_config(&self.config); - let (gate, i) = self.find_slot(gate, vec![operation.const_0, operation.const_1]); + let constants = vec![operation.const_0, operation.const_1]; + let (gate, i) = self.find_slot(gate, &constants, &constants); let wires_multiplicand_0 = Target::wire(gate, ArithmeticGate::wire_ith_multiplicand_0(i)); let wires_multiplicand_1 = Target::wire(gate, ArithmeticGate::wire_ith_multiplicand_1(i)); let wires_addend = Target::wire(gate, ArithmeticGate::wire_ith_addend(i)); @@ -240,7 +241,7 @@ impl, const D: usize> CircuitBuilder { while exp_bits_vec.len() < num_power_bits { exp_bits_vec.push(_false); } - let gate_index = self.add_gate(gate.clone(), vec![]); + let gate_index = self.add_gate(gate.clone(), vec![], vec![]); self.connect(base, Target::wire(gate_index, gate.wire_base())); exp_bits_vec.iter().enumerate().for_each(|(i, bit)| { diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index e1a17988..d29f8f8f 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -61,7 +61,8 @@ impl, const D: usize> CircuitBuilder { operation: ExtensionArithmeticOperation, ) -> ExtensionTarget { let gate = ArithmeticExtensionGate::new_from_config(&self.config); - let (gate, i) = self.find_slot(gate, vec![operation.const_0, operation.const_1]); + let constants = vec![operation.const_0, operation.const_1]; + let (gate, i) = self.find_slot(gate, &constants, &constants); let wires_multiplicand_0 = ExtensionTarget::from_range( gate, ArithmeticExtensionGate::::wires_ith_multiplicand_0(i), @@ -85,7 +86,8 @@ impl, const D: usize> CircuitBuilder { operation: ExtensionArithmeticOperation, ) -> ExtensionTarget { let gate = MulExtensionGate::new_from_config(&self.config); - let (gate, i) = self.find_slot(gate, vec![operation.const_0]); + let constants = vec![operation.const_0]; + let (gate, i) = self.find_slot(gate, &constants, &constants); let wires_multiplicand_0 = ExtensionTarget::from_range(gate, MulExtensionGate::::wires_ith_multiplicand_0(i)); let wires_multiplicand_1 = diff --git a/plonky2/src/gadgets/arithmetic_u32.rs b/plonky2/src/gadgets/arithmetic_u32.rs index 1c8df3b6..dfdbb5fb 100644 --- a/plonky2/src/gadgets/arithmetic_u32.rs +++ b/plonky2/src/gadgets/arithmetic_u32.rs @@ -78,7 +78,7 @@ impl, const D: usize> CircuitBuilder { } let gate = U32ArithmeticGate::::new_from_config(&self.config); - let (gate_index, copy) = self.find_slot(gate, vec![]); + let (gate_index, copy) = self.find_slot(gate, &[], &[]); self.connect( Target::wire(gate_index, gate.wire_ith_multiplicand_0(copy)), @@ -138,7 +138,7 @@ impl, const D: usize> CircuitBuilder { borrow: U32Target, ) -> (U32Target, U32Target) { let gate = U32SubtractionGate::::new_from_config(&self.config); - let (gate_index, copy) = self.find_slot(gate, vec![]); + let (gate_index, copy) = self.find_slot(gate, &[], &[]); self.connect(Target::wire(gate_index, gate.wire_ith_input_x(copy)), x.0); self.connect(Target::wire(gate_index, gate.wire_ith_input_y(copy)), y.0); diff --git a/plonky2/src/gadgets/interpolation.rs b/plonky2/src/gadgets/interpolation.rs index 2d2c2273..473361aa 100644 --- a/plonky2/src/gadgets/interpolation.rs +++ b/plonky2/src/gadgets/interpolation.rs @@ -88,7 +88,7 @@ impl, const D: usize> CircuitBuilder { evaluation_point: ExtensionTarget, ) -> ExtensionTarget { let gate = G::new(subgroup_bits); - let gate_index = self.add_gate(gate, vec![]); + let gate_index = self.add_gate(gate, vec![], vec![]); self.connect(coset_shift, Target::wire(gate_index, gate.wire_shift())); for (i, &v) in values.iter().enumerate() { self.connect_extension( diff --git a/plonky2/src/gadgets/multiple_comparison.rs b/plonky2/src/gadgets/multiple_comparison.rs index 88b94f3f..7d637d87 100644 --- a/plonky2/src/gadgets/multiple_comparison.rs +++ b/plonky2/src/gadgets/multiple_comparison.rs @@ -25,7 +25,7 @@ impl, const D: usize> CircuitBuilder { let mut result = one; for i in 0..n { let a_le_b_gate = ComparisonGate::new(num_bits, num_chunks); - let a_le_b_gate_index = self.add_gate(a_le_b_gate.clone(), vec![]); + let a_le_b_gate_index = self.add_gate(a_le_b_gate.clone(), vec![], vec![]); self.connect( Target::wire(a_le_b_gate_index, a_le_b_gate.wire_first_input()), a[i], @@ -37,7 +37,7 @@ impl, const D: usize> CircuitBuilder { let a_le_b_result = Target::wire(a_le_b_gate_index, a_le_b_gate.wire_result_bool()); let b_le_a_gate = ComparisonGate::new(num_bits, num_chunks); - let b_le_a_gate_index = self.add_gate(b_le_a_gate.clone(), vec![]); + let b_le_a_gate_index = self.add_gate(b_le_a_gate.clone(), vec![], vec![]); self.connect( Target::wire(b_le_a_gate_index, b_le_a_gate.wire_first_input()), b[i], diff --git a/plonky2/src/gadgets/random_access.rs b/plonky2/src/gadgets/random_access.rs index 1a142844..9518e9fa 100644 --- a/plonky2/src/gadgets/random_access.rs +++ b/plonky2/src/gadgets/random_access.rs @@ -18,7 +18,7 @@ impl, const D: usize> CircuitBuilder { return self.connect(claimed_element, v[0]); } let dummy_gate = RandomAccessGate::::new_from_config(&self.config, bits); - let (gate_index, copy) = self.find_slot(dummy_gate, vec![]); + let (gate_index, copy) = self.find_slot(dummy_gate, &[], &[]); v.iter().enumerate().for_each(|(i, &val)| { self.connect( diff --git a/plonky2/src/gadgets/split_base.rs b/plonky2/src/gadgets/split_base.rs index d4589476..db6fe69d 100644 --- a/plonky2/src/gadgets/split_base.rs +++ b/plonky2/src/gadgets/split_base.rs @@ -16,7 +16,7 @@ impl, const D: usize> CircuitBuilder { /// base-B limb of the element, with little-endian ordering. pub fn split_le_base(&mut self, x: Target, num_limbs: usize) -> Vec { let gate_type = BaseSumGate::::new(num_limbs); - let gate = self.add_gate(gate_type, vec![]); + let gate = self.add_gate(gate_type, vec![], vec![]); let sum = Target::wire(gate, BaseSumGate::::WIRE_SUM); self.connect(x, sum); @@ -54,7 +54,7 @@ impl, const D: usize> CircuitBuilder { "Not enough routed wires." ); let gate_type = BaseSumGate::<2>::new_from_config::(&self.config); - let gate_index = self.add_gate(gate_type, vec![]); + let gate_index = self.add_gate(gate_type, vec![], vec![]); for (limb, wire) in bits .iter() .zip(BaseSumGate::<2>::START_LIMBS..BaseSumGate::<2>::START_LIMBS + num_bits) diff --git a/plonky2/src/gadgets/split_join.rs b/plonky2/src/gadgets/split_join.rs index 8c7c9c3f..dd7a0a39 100644 --- a/plonky2/src/gadgets/split_join.rs +++ b/plonky2/src/gadgets/split_join.rs @@ -20,7 +20,7 @@ impl, const D: usize> CircuitBuilder { let gate_type = BaseSumGate::<2>::new_from_config::(&self.config); let k = ceil_div_usize(num_bits, gate_type.num_limbs); let gates = (0..k) - .map(|_| self.add_gate(gate_type, vec![])) + .map(|_| self.add_gate(gate_type, vec![], vec![])) .collect::>(); let mut bits = Vec::with_capacity(num_bits); diff --git a/plonky2/src/gates/batchable.rs b/plonky2/src/gates/batchable.rs index d40fd73c..c37cd2c8 100644 --- a/plonky2/src/gates/batchable.rs +++ b/plonky2/src/gates/batchable.rs @@ -22,7 +22,7 @@ pub trait BatchableGate, const D: usize>: Gate, const D: usize> { pub current_slot: HashMap, (usize, usize)>, } @@ -88,6 +88,7 @@ impl, G: MultiOpsGate, const D: usize> Batcha current_slot: &CurrentSlot, builder: &mut CircuitBuilder, ) { + dbg!(self.id(), ¤t_slot, params); if let Some(&(gate_index, op)) = current_slot.current_slot.get(params) { let zero = builder.zero(); for i in op..self.num_ops() { diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 34684194..e5d3943f 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -175,6 +175,7 @@ pub trait Gate, const D: usize>: 'static + Send + S pub struct GateInstance, const D: usize> { pub gate_ref: GateRef, pub constants: Vec, + pub params: Vec, } /// Map each gate to a boolean prefix used to construct the gate's selector polynomial. diff --git a/plonky2/src/gates/gmimc.rs b/plonky2/src/gates/gmimc.rs index 47a82e62..b3ff8969 100644 --- a/plonky2/src/gates/gmimc.rs +++ b/plonky2/src/gates/gmimc.rs @@ -389,7 +389,7 @@ mod tests { let mut builder = CircuitBuilder::new(config); type Gate = GMiMCGate; let gate = Gate::new(); - let gate_index = builder.add_gate(gate, vec![]); + let gate_index = builder.add_gate(gate, vec![], vec![]); let circuit = builder.build_prover::(); let permutation_inputs = (0..WIDTH).map(F::from_canonical_usize).collect::>(); diff --git a/plonky2/src/gates/poseidon.rs b/plonky2/src/gates/poseidon.rs index 4a2ffee7..82fedcbb 100644 --- a/plonky2/src/gates/poseidon.rs +++ b/plonky2/src/gates/poseidon.rs @@ -569,7 +569,7 @@ mod tests { let mut builder = CircuitBuilder::new(config); type Gate = PoseidonGate; let gate = Gate::new(); - let gate_index = builder.add_gate(gate, vec![]); + let gate_index = builder.add_gate(gate, vec![], vec![]); let circuit = builder.build_prover::(); let permutation_inputs = (0..SPONGE_WIDTH) diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index e9048edd..62209720 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -23,7 +23,7 @@ use crate::plonk::vars::{ }; /// A gate for conditionally swapping input values based on a boolean. -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] pub struct SwitchGate, const D: usize> { pub(crate) chunk_size: usize, pub(crate) num_copies: usize, @@ -165,7 +165,7 @@ impl, const D: usize> Gate for SwitchGate> = Box::new(SwitchGenerator:: { gate_index, - gate: self.clone(), + gate: *self, copy: c, }); g @@ -195,8 +195,13 @@ impl, const D: usize> MultiOpsGate for Switch self.num_copies } - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - todo!() + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + SwitchGenerator:: { + gate_index, + gate: *self, + copy: i, + } + .watch_list() } } diff --git a/plonky2/src/hash/gmimc.rs b/plonky2/src/hash/gmimc.rs index 3492e08f..13f7807f 100644 --- a/plonky2/src/hash/gmimc.rs +++ b/plonky2/src/hash/gmimc.rs @@ -126,7 +126,7 @@ impl AlgebraicHasher for GMiMCHash { F: RichField + Extendable, { let gate_type = GMiMCGate::::new(); - let gate = builder.add_gate(gate_type, vec![]); + let gate = builder.add_gate(gate_type, vec![], vec![]); let swap_wire = GMiMCGate::::WIRE_SWAP; let swap_wire = Target::wire(gate, swap_wire); diff --git a/plonky2/src/hash/poseidon.rs b/plonky2/src/hash/poseidon.rs index 606dfd13..8e8d6ba5 100644 --- a/plonky2/src/hash/poseidon.rs +++ b/plonky2/src/hash/poseidon.rs @@ -269,7 +269,7 @@ pub trait Poseidon: PrimeField { // If we have enough routed wires, we will use PoseidonMdsGate. let mds_gate = PoseidonMdsGate::::new(); if builder.config.num_routed_wires >= mds_gate.num_wires() { - let index = builder.add_gate(mds_gate, vec![]); + let index = builder.add_gate(mds_gate, vec![], vec![]); for i in 0..WIDTH { let input_wire = PoseidonMdsGate::::wires_input(i); builder.connect_extension(state[i], ExtensionTarget::from_range(index, input_wire)); @@ -652,7 +652,7 @@ impl AlgebraicHasher for PoseidonHash { F: RichField + Extendable, { let gate_type = PoseidonGate::::new(); - let gate = builder.add_gate(gate_type, vec![]); + let gate = builder.add_gate(gate_type, vec![], vec![]); let swap_wire = PoseidonGate::::WIRE_SWAP; let swap_wire = Target::wire(gate, swap_wire); diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index 368232fd..1c7779c6 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -91,6 +91,11 @@ pub(crate) fn generate_partial_witness< pending_generator_indices = next_pending_generator_indices; } + for i in 0..generator_is_expired.len() { + if !generator_is_expired[i] { + dbg!(i); + } + } assert_eq!( remaining_generators, 0, "{} generators weren't run", diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 80a951c7..b658e339 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -45,7 +45,7 @@ use crate::util::timing::TimingTree; use crate::util::{transpose, transpose_poly_values}; pub struct CircuitBuilder, const D: usize> { - pub(crate) config: CircuitConfig, + pub config: CircuitConfig, /// The types of gates used in this circuit. gates: HashSet>, @@ -183,7 +183,12 @@ impl, const D: usize> CircuitBuilder { } /// Adds a gate to the circuit, and returns its index. - pub fn add_gate>(&mut self, gate_type: G, constants: Vec) -> usize { + pub fn add_gate>( + &mut self, + gate_type: G, + constants: Vec, + params: Vec, + ) -> usize { // println!("{} {}", self.num_gates(), gate_type.id()); self.check_gate_compatibility(&gate_type); assert_eq!( @@ -205,6 +210,7 @@ impl, const D: usize> CircuitBuilder { self.gate_instances.push(GateInstance { gate_ref, constants, + params, }); index @@ -303,7 +309,7 @@ impl, const D: usize> CircuitBuilder { // We will fill this `ConstantGate` with zero constants initially. // These will be overwritten by `constant` as the gate instances are filled. let gate = ConstantGate { num_consts }; - let (gate, instance) = self.find_slot(gate, vec![F::ZERO; num_consts]); + let (gate, instance) = self.find_slot(gate, &[], &vec![F::ZERO; num_consts]); let target = Target::wire(gate, instance); self.gate_instances[gate].constants[instance] = c; @@ -372,7 +378,8 @@ impl, const D: usize> CircuitBuilder { pub fn find_slot + Clone>( &mut self, gate: G, - params: Vec, + params: &[F], + constants: &[F], ) -> (usize, usize) { let num_gates = self.num_gates(); let num_ops = gate.num_ops(); @@ -383,11 +390,11 @@ impl, const D: usize> CircuitBuilder { .or_insert(CurrentSlot { current_slot: HashMap::new(), }); - let slot = gate_slot.current_slot.get(¶ms); + let slot = gate_slot.current_slot.get(params); let res = if let Some(&s) = slot { s } else { - self.add_gate(gate, params.clone()); + self.add_gate(gate, constants.to_vec(), params.to_vec()); (num_gates, 0) }; if res.1 == num_ops - 1 { @@ -395,13 +402,13 @@ impl, const D: usize> CircuitBuilder { .get_mut(&gate_ref) .unwrap() .current_slot - .remove(¶ms); + .remove(params); } else { self.current_slots .get_mut(&gate_ref) .unwrap() .current_slot - .insert(params, (res.0, res.1 + 1)); + .insert(params.to_vec(), (res.0, res.1 + 1)); } res @@ -490,7 +497,7 @@ impl, const D: usize> CircuitBuilder { } while !self.gate_instances.len().is_power_of_two() { - self.add_gate(NoopGate, vec![]); + self.add_gate(NoopGate, vec![], vec![]); } } @@ -507,7 +514,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(NoopGate, vec![]); + let gate = self.add_gate(NoopGate, vec![], vec![]); for w in 0..num_wires { self.add_simple_generator(RandomValueGenerator { target: Target::Wire(Wire { gate, input: w }), @@ -519,8 +526,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(NoopGate, vec![]); - let gate_2 = self.add_gate(NoopGate, vec![]); + let gate_1 = self.add_gate(NoopGate, vec![], vec![]); + let gate_2 = self.add_gate(NoopGate, vec![], vec![]); for w in 0..num_routed_wires { self.add_simple_generator(RandomValueGenerator { @@ -634,7 +641,7 @@ impl, const D: usize> CircuitBuilder { // 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(PublicInputGate, vec![]); + let pi_gate = self.add_gate(PublicInputGate, vec![], vec![]); for (&hash_part, wire) in public_inputs_hash .elements .iter() @@ -694,6 +701,11 @@ impl, const D: usize> CircuitBuilder { constants_sigmas_cap: constants_sigmas_cap.clone(), }; + let mut gens = self.generators.len(); + for (i, g) in self.gate_instances.iter().enumerate() { + gens += g.gate_ref.0.generators(i, &g.constants).len(); + dbg!(g.gate_ref.0.id(), gens); + } // Add gate generators. self.add_generators( self.gate_instances @@ -1130,11 +1142,12 @@ impl, const D: usize> CircuitBuilder { // } // fn fill_batched_gates(&mut self) { + dbg!(&self.current_slots); let instances = self.gate_instances.clone(); for gate in instances { if let Some(slot) = self.current_slots.get(&gate.gate_ref) { let cloned = slot.clone(); - gate.gate_ref.0.fill_gate(&gate.constants, &cloned, self); + gate.gate_ref.0.fill_gate(&gate.params, &cloned, self); } } } diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 91db2b25..b494f324 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -353,7 +353,7 @@ mod tests { let comp_zt = builder.mul(xt, yt); builder.connect(zt, comp_zt); for _ in 0..100 { - builder.add_gate(NoopGate, vec![]); + builder.add_gate(NoopGate, vec![], vec![]); } let data = builder.build::(); let proof = data.prove(pw)?; diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index dc6f5039..a9af478c 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -546,7 +546,7 @@ mod tests { )> { let mut builder = CircuitBuilder::::new(config.clone()); for _ in 0..num_dummy_gates { - builder.add_gate(NoopGate, vec![]); + builder.add_gate(NoopGate, vec![], vec![]); } let data = builder.build::(); @@ -601,7 +601,7 @@ mod tests { // builder will pad to the next power of two, 2^min_degree_bits. let min_gates = (1 << (min_degree_bits - 1)) + 1; for _ in builder.num_gates()..min_gates { - builder.add_gate(NoopGate, vec![]); + builder.add_gate(NoopGate, vec![], vec![]); } } diff --git a/plonky2/src/util/reducing.rs b/plonky2/src/util/reducing.rs index 8bfe45d1..a2d4e4cf 100644 --- a/plonky2/src/util/reducing.rs +++ b/plonky2/src/util/reducing.rs @@ -132,7 +132,7 @@ impl ReducingFactorTarget { reversed_terms.reverse(); for chunk in reversed_terms.chunks_exact(max_coeffs_len) { let gate = ReducingGate::new(max_coeffs_len); - let gate_index = builder.add_gate(gate.clone(), Vec::new()); + let gate_index = builder.add_gate(gate.clone(), vec![], vec![]); builder.connect_extension( self.base, @@ -182,7 +182,7 @@ impl ReducingFactorTarget { reversed_terms.reverse(); for chunk in reversed_terms.chunks_exact(max_coeffs_len) { let gate = ReducingExtensionGate::new(max_coeffs_len); - let gate_index = builder.add_gate(gate.clone(), Vec::new()); + let gate_index = builder.add_gate(gate.clone(), vec![], vec![]); builder.connect_extension( self.base, diff --git a/waksman/src/permutation.rs b/waksman/src/permutation.rs index b0e725d2..b25c2980 100644 --- a/waksman/src/permutation.rs +++ b/waksman/src/permutation.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use std::marker::PhantomData; use plonky2::field::{extension_field::Extendable, field_types::Field}; +use plonky2::gates::switch::SwitchGate; use plonky2::hash::hash_types::RichField; use plonky2::iop::generator::{GeneratedValues, SimpleGenerator}; use plonky2::iop::target::Target; @@ -71,41 +72,42 @@ fn assert_permutation_2x2, const D: usize>( /// Given two input wire chunks, add a new switch to the circuit (by adding one copy to a switch /// gate). Returns the wire for the switch boolean, and the two output wire chunks. fn create_switch, const D: usize>( - _builder: &mut CircuitBuilder, + builder: &mut CircuitBuilder, a1: Vec, a2: Vec, ) -> (Target, Vec, Vec) { assert_eq!(a1.len(), a2.len(), "Chunk size must be the same"); - let _chunk_size = a1.len(); + let chunk_size = a1.len(); - todo!() - // let (gate, gate_index, next_copy) = builder.find_switch_gate(chunk_size); - // - // let mut c = Vec::new(); - // let mut d = Vec::new(); - // for e in 0..chunk_size { - // builder.connect( - // a1[e], - // Target::wire(gate_index, gate.wire_first_input(next_copy, e)), - // ); - // builder.connect( - // a2[e], - // Target::wire(gate_index, gate.wire_second_input(next_copy, e)), - // ); - // c.push(Target::wire( - // gate_index, - // gate.wire_first_output(next_copy, e), - // )); - // d.push(Target::wire( - // gate_index, - // gate.wire_second_output(next_copy, e), - // )); - // } + let gate = SwitchGate::new_from_config(&builder.config, chunk_size); + let params = vec![F::from_canonical_usize(chunk_size)]; + let (gate_index, next_copy) = builder.find_slot(gate, ¶ms, &[]); - // let switch = Target::wire(gate_index, gate.wire_switch_bool(next_copy)); - // - // (switch, c, d) + let mut c = Vec::new(); + let mut d = Vec::new(); + for e in 0..chunk_size { + builder.connect( + a1[e], + Target::wire(gate_index, gate.wire_first_input(next_copy, e)), + ); + builder.connect( + a2[e], + Target::wire(gate_index, gate.wire_second_input(next_copy, e)), + ); + c.push(Target::wire( + gate_index, + gate.wire_first_output(next_copy, e), + )); + d.push(Target::wire( + gate_index, + gate.wire_second_output(next_copy, e), + )); + } + + let switch = Target::wire(gate_index, gate.wire_switch_bool(next_copy)); + + (switch, c, d) } fn assert_permutation_recursive, const D: usize>( diff --git a/waksman/src/sorting.rs b/waksman/src/sorting.rs index b3e616d5..4270ebc7 100644 --- a/waksman/src/sorting.rs +++ b/waksman/src/sorting.rs @@ -54,7 +54,7 @@ pub fn assert_le, const D: usize>( num_chunks: usize, ) { let gate = AssertLessThanGate::new(bits, num_chunks); - let gate_index = builder.add_gate(gate.clone(), vec![]); + let gate_index = builder.add_gate(gate.clone(), vec![], vec![]); builder.connect(Target::wire(gate_index, gate.wire_first_input()), lhs); builder.connect(Target::wire(gate_index, gate.wire_second_input()), rhs); From 5e3177520bd701891fa46192f4fee747a64b4bb2 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 15 Feb 2022 15:08:53 +0100 Subject: [PATCH 06/14] Fixes --- plonky2/src/gadgets/arithmetic_u32.rs | 5 +++-- plonky2/src/gadgets/range_check.rs | 2 +- plonky2/src/gates/add_many_u32.rs | 17 +++++++++++++++++ plonky2/src/gates/arithmetic_u32.rs | 12 +++++++----- plonky2/src/gates/range_check_u32.rs | 11 +++++++++++ plonky2/src/plonk/circuit_builder.rs | 1 - 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/plonky2/src/gadgets/arithmetic_u32.rs b/plonky2/src/gadgets/arithmetic_u32.rs index 649c0624..8a6d7296 100644 --- a/plonky2/src/gadgets/arithmetic_u32.rs +++ b/plonky2/src/gadgets/arithmetic_u32.rs @@ -120,7 +120,8 @@ impl, const D: usize> CircuitBuilder { _ => { let num_addends = to_add.len(); let gate = U32AddManyGate::::new_from_config(&self.config, num_addends); - let (gate_index, copy) = self.find_u32_add_many_gate(num_addends); + let (gate_index, copy) = + self.find_slot(gate, &[F::from_canonical_usize(num_addends)], &[]); for j in 0..num_addends { self.connect( @@ -153,7 +154,7 @@ impl, const D: usize> CircuitBuilder { let num_addends = to_add.len(); let gate = U32AddManyGate::::new_from_config(&self.config, num_addends); - let (gate_index, copy) = self.find_u32_add_many_gate(num_addends); + let (gate_index, copy) = self.find_slot(gate, &[F::from_canonical_usize(num_addends)], &[]); for j in 0..num_addends { self.connect( diff --git a/plonky2/src/gadgets/range_check.rs b/plonky2/src/gadgets/range_check.rs index 0776fc68..1aec39ce 100644 --- a/plonky2/src/gadgets/range_check.rs +++ b/plonky2/src/gadgets/range_check.rs @@ -47,7 +47,7 @@ impl, const D: usize> CircuitBuilder { pub fn range_check_u32(&mut self, vals: Vec) { let num_input_limbs = vals.len(); let gate = U32RangeCheckGate::::new(num_input_limbs); - let gate_index = self.add_gate(gate, vec![]); + let gate_index = self.add_gate(gate, vec![], vec![]); for i in 0..num_input_limbs { self.connect( diff --git a/plonky2/src/gates/add_many_u32.rs b/plonky2/src/gates/add_many_u32.rs index 4f9c4293..532dd97a 100644 --- a/plonky2/src/gates/add_many_u32.rs +++ b/plonky2/src/gates/add_many_u32.rs @@ -5,6 +5,7 @@ use plonky2_util::ceil_div_usize; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -271,6 +272,22 @@ impl, const D: usize> Gate for U32AddManyGate } } +impl, const D: usize> MultiOpsGate for U32AddManyGate { + fn num_ops(&self) -> usize { + self.num_ops + } + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { + U32AddManyGenerator { + gate: *self, + gate_index, + i, + _phantom: PhantomData, + } + .dependencies() + } +} + #[derive(Clone, Debug)] struct U32AddManyGenerator, const D: usize> { gate: U32AddManyGate, diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index 6f61b7b4..b4b714f0 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -239,11 +239,13 @@ impl, const D: usize> MultiOpsGate for U32Ari } fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - vec![ - Target::wire(gate_index, self.wire_ith_multiplicand_0(i)), - Target::wire(gate_index, self.wire_ith_multiplicand_1(i)), - Target::wire(gate_index, self.wire_ith_addend(i)), - ] + U32ArithmeticGenerator { + gate: *self, + gate_index, + i, + _phantom: PhantomData, + } + .dependencies() } } diff --git a/plonky2/src/gates/range_check_u32.rs b/plonky2/src/gates/range_check_u32.rs index 79e91de8..38731189 100644 --- a/plonky2/src/gates/range_check_u32.rs +++ b/plonky2/src/gates/range_check_u32.rs @@ -4,6 +4,7 @@ use plonky2_util::ceil_div_usize; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; +use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -166,6 +167,16 @@ impl, const D: usize> Gate for U32RangeCheckG } } +impl, const D: usize> MultiOpsGate for U32RangeCheckGate { + fn num_ops(&self) -> usize { + 1 + } + + fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { + unreachable!() + } +} + #[derive(Debug)] pub struct U32RangeCheckGenerator, const D: usize> { gate: U32RangeCheckGate, diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index b5db44a7..e0a4aba2 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -16,7 +16,6 @@ use crate::gadgets::arithmetic::BaseArithmeticOperation; use crate::gadgets::arithmetic_extension::ExtensionArithmeticOperation; use crate::gadgets::arithmetic_u32::U32Target; use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; -use crate::gates::add_many_u32::U32AddManyGate; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::batchable::{BatchableGate, CurrentSlot, GateRef}; From 0aefe92b8c2704b0613994afd9aa9b4acb10a97c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 15 Feb 2022 15:30:34 +0100 Subject: [PATCH 07/14] Merge MultiOpsGate into Gate --- insertion/src/insertion_gate.rs | 3 - plonky2/src/gadgets/interpolation.rs | 4 +- plonky2/src/gates/add_many_u32.rs | 3 - plonky2/src/gates/arithmetic_base.rs | 3 - plonky2/src/gates/arithmetic_extension.rs | 5 - plonky2/src/gates/arithmetic_u32.rs | 3 - plonky2/src/gates/assert_le.rs | 3 - plonky2/src/gates/base_sum.rs | 6 +- plonky2/src/gates/batchable.rs | 175 ++++++++---------- plonky2/src/gates/comparison.rs | 3 - plonky2/src/gates/constant.rs | 3 - plonky2/src/gates/exponentiation.rs | 3 - plonky2/src/gates/gate.rs | 90 +++++---- plonky2/src/gates/gate_tree.rs | 2 +- plonky2/src/gates/interpolation.rs | 6 +- plonky2/src/gates/low_degree_interpolation.rs | 5 - plonky2/src/gates/multiplication_extension.rs | 3 - plonky2/src/gates/noop.rs | 3 - plonky2/src/gates/poseidon.rs | 4 +- plonky2/src/gates/poseidon_mds.rs | 6 +- plonky2/src/gates/public_input.rs | 3 - plonky2/src/gates/random_access.rs | 3 - plonky2/src/gates/range_check_u32.rs | 3 - plonky2/src/gates/reducing.rs | 3 - plonky2/src/gates/reducing_extension.rs | 3 - plonky2/src/gates/subtraction_u32.rs | 3 - plonky2/src/gates/switch.rs | 3 - plonky2/src/plonk/circuit_builder.rs | 7 +- 28 files changed, 146 insertions(+), 215 deletions(-) diff --git a/insertion/src/insertion_gate.rs b/insertion/src/insertion_gate.rs index 6fd98307..5b60f13b 100644 --- a/insertion/src/insertion_gate.rs +++ b/insertion/src/insertion_gate.rs @@ -3,7 +3,6 @@ use std::ops::Range; use plonky2::field::extension_field::{Extendable, FieldExtension}; use plonky2::field::field_types::Field; -use plonky2::gates::batchable::MultiOpsGate; use plonky2::gates::gate::Gate; use plonky2::gates::util::StridedConstraintConsumer; use plonky2::hash::hash_types::RichField; @@ -241,9 +240,7 @@ impl, const D: usize> Gate for InsertionGate< fn num_constraints(&self) -> usize { (self.vec_size + 1) * (2 + D) } -} -impl, const D: usize> MultiOpsGate for InsertionGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gadgets/interpolation.rs b/plonky2/src/gadgets/interpolation.rs index 473361aa..9dccd666 100644 --- a/plonky2/src/gadgets/interpolation.rs +++ b/plonky2/src/gadgets/interpolation.rs @@ -2,7 +2,7 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; -use crate::gates::batchable::BatchableGate; +use crate::gates::gate::Gate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; @@ -12,7 +12,7 @@ use crate::plonk::circuit_builder::CircuitBuilder; /// 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. pub(crate) trait InterpolationGate, const D: usize>: - BatchableGate + Copy + Gate + Copy { fn new(subgroup_bits: usize) -> Self; diff --git a/plonky2/src/gates/add_many_u32.rs b/plonky2/src/gates/add_many_u32.rs index 532dd97a..3ea52988 100644 --- a/plonky2/src/gates/add_many_u32.rs +++ b/plonky2/src/gates/add_many_u32.rs @@ -5,7 +5,6 @@ use plonky2_util::ceil_div_usize; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -270,9 +269,7 @@ impl, const D: usize> Gate for U32AddManyGate fn num_constraints(&self) -> usize { self.num_ops * (3 + Self::num_limbs()) } -} -impl, const D: usize> MultiOpsGate for U32AddManyGate { fn num_ops(&self) -> usize { self.num_ops } diff --git a/plonky2/src/gates/arithmetic_base.rs b/plonky2/src/gates/arithmetic_base.rs index 006f32ef..7062ef84 100644 --- a/plonky2/src/gates/arithmetic_base.rs +++ b/plonky2/src/gates/arithmetic_base.rs @@ -1,7 +1,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -150,9 +149,7 @@ impl, const D: usize> Gate for ArithmeticGate fn num_constraints(&self) -> usize { self.num_ops } -} -impl, const D: usize> MultiOpsGate for ArithmeticGate { fn num_ops(&self) -> usize { self.num_ops } diff --git a/plonky2/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs index acb480d5..fcedb6de 100644 --- a/plonky2/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -3,7 +3,6 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -157,11 +156,7 @@ impl, const D: usize> Gate for ArithmeticExte fn num_constraints(&self) -> usize { self.num_ops * D } -} -impl, const D: usize> MultiOpsGate - for ArithmeticExtensionGate -{ fn num_ops(&self) -> usize { self.num_ops } diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index b4b714f0..1432d20e 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -5,7 +5,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -231,9 +230,7 @@ impl, const D: usize> Gate for U32ArithmeticG fn num_constraints(&self) -> usize { self.num_ops * (3 + Self::num_limbs()) } -} -impl, const D: usize> MultiOpsGate for U32ArithmeticGate { fn num_ops(&self) -> usize { self.num_ops } diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index b240df85..08c9c8e3 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -5,7 +5,6 @@ use plonky2_field::field_types::{Field, Field64}; use plonky2_field::packed_field::PackedField; use plonky2_util::{bits_u64, ceil_div_usize}; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -279,9 +278,7 @@ impl, const D: usize> Gate for AssertLessThan fn num_constraints(&self) -> usize { 4 + 5 * self.num_chunks } -} -impl, const D: usize> MultiOpsGate for AssertLessThanGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/base_sum.rs b/plonky2/src/gates/base_sum.rs index c9b0b0f6..be81044a 100644 --- a/plonky2/src/gates/base_sum.rs +++ b/plonky2/src/gates/base_sum.rs @@ -4,7 +4,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::{Field, Field64}; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -135,10 +134,7 @@ impl, const D: usize, const B: usize> Gate fo fn num_constraints(&self) -> usize { 1 + self.num_limbs } -} -impl, const D: usize, const B: usize> MultiOpsGate - for BaseSumGate -{ + fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/batchable.rs b/plonky2/src/gates/batchable.rs index c37cd2c8..20ab39f3 100644 --- a/plonky2/src/gates/batchable.rs +++ b/plonky2/src/gates/batchable.rs @@ -1,101 +1,80 @@ -use std::collections::HashMap; -use std::fmt::{Debug, Error, Formatter}; -use std::hash::{Hash, Hasher}; -use std::sync::Arc; - -use plonky2_field::extension_field::Extendable; - -use crate::gates::gate::Gate; -use crate::hash::hash_types::RichField; -use crate::iop::target::Target; -use crate::plonk::circuit_builder::CircuitBuilder; - -pub trait BatchableGate, const D: usize>: Gate { - fn num_ops(&self) -> usize; - - // TODO: It would be nice to have a `Parameters` associated type. - fn fill_gate( - &self, - params: &[F], - current_slot: &CurrentSlot, - builder: &mut CircuitBuilder, - ); -} - -#[derive(Clone, Debug)] -pub struct CurrentSlot, const D: usize> { - pub current_slot: HashMap, (usize, usize)>, -} - -#[derive(Clone)] -pub struct GateRef, const D: usize>( - pub(crate) Arc>, -); - -impl, const D: usize> GateRef { - pub fn new>(gate: G) -> GateRef { - GateRef(Arc::new(gate)) - } -} - -impl, const D: usize> PartialEq for GateRef { - fn eq(&self, other: &Self) -> bool { - self.0.id() == other.0.id() - } -} - -impl, const D: usize> Hash for GateRef { - fn hash(&self, state: &mut H) { - self.0.id().hash(state) - } -} - -impl, const D: usize> Eq for GateRef {} - -impl, const D: usize> Debug for GateRef { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - write!(f, "{}", self.0.id()) - } -} - -// pub trait SingleOpGate, const D: usize>: Gate {} -// impl, G: SingleOpGate, const D: usize> MultiOpsGate for G { -// fn num_ops(&self) -> usize { -// 1 -// } +// use std::collections::HashMap; +// use std::fmt::{Debug, Error, Formatter}; +// use std::hash::{Hash, Hasher}; +// use std::sync::Arc; // -// fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { -// unreachable!() +// use plonky2_field::extension_field::Extendable; +// +// use crate::gates::gate::Gate; +// use crate::hash::hash_types::RichField; +// use crate::iop::target::Target; +// use crate::plonk::circuit_builder::CircuitBuilder; +// +// pub trait BatchableGate, const D: usize>: Gate { +// fn num_ops(&self) -> usize; +// +// // TODO: It would be nice to have a `Parameters` associated type. +// fn fill_gate( +// &self, +// params: &[F], +// current_slot: &CurrentSlot, +// builder: &mut CircuitBuilder, +// ); +// } +// +// #[derive(Clone, Debug)] +// pub struct CurrentSlot, const D: usize> { +// pub current_slot: HashMap, (usize, usize)>, +// } +// +// #[derive(Clone)] +// pub struct GateRef, const D: usize>( +// pub(crate) Arc>, +// ); +// +// impl, const D: usize> GateRef { +// pub fn new>(gate: G) -> GateRef { +// GateRef(Arc::new(gate)) +// } +// } +// +// impl, const D: usize> PartialEq for GateRef { +// fn eq(&self, other: &Self) -> bool { +// self.0.id() == other.0.id() +// } +// } +// +// impl, const D: usize> Hash for GateRef { +// fn hash(&self, state: &mut H) { +// self.0.id().hash(state) +// } +// } +// +// impl, const D: usize> Eq for GateRef {} +// +// impl, const D: usize> Debug for GateRef { +// fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { +// write!(f, "{}", self.0.id()) +// } +// } +// +// // pub trait SingleOpGate, const D: usize>: Gate {} +// // impl, G: SingleOpGate, const D: usize> MultiOpsGate for G { +// // fn num_ops(&self) -> usize { +// // 1 +// // } +// // +// // fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { +// // unreachable!() +// // } +// // } +// +// pub trait MultiOpsGate, const D: usize>: Gate {} +// +// impl, G: MultiOpsGate, const D: usize> BatchableGate +// for G +// { +// fn num_ops(&self) -> usize { +// self.num_ops() // } // } - -pub trait MultiOpsGate, const D: usize>: Gate { - fn num_ops(&self) -> usize; - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec; -} - -impl, G: MultiOpsGate, const D: usize> BatchableGate - for G -{ - fn num_ops(&self) -> usize { - self.num_ops() - } - - fn fill_gate( - &self, - params: &[F], - current_slot: &CurrentSlot, - builder: &mut CircuitBuilder, - ) { - dbg!(self.id(), ¤t_slot, params); - if let Some(&(gate_index, op)) = current_slot.current_slot.get(params) { - let zero = builder.zero(); - for i in op..self.num_ops() { - for dep in self.dependencies_ith_op(gate_index, i) { - builder.connect(dep, zero); - } - } - } - } -} diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index b64a5394..00e7f4d3 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -5,7 +5,6 @@ use plonky2_field::field_types::{Field, Field64}; use plonky2_field::packed_field::PackedField; use plonky2_util::{bits_u64, ceil_div_usize}; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -312,9 +311,7 @@ impl, const D: usize> Gate for ComparisonGate fn num_constraints(&self) -> usize { 6 + 5 * self.num_chunks + self.chunk_bits() } -} -impl, const D: usize> MultiOpsGate for ComparisonGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index e813d573..455e5349 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -4,7 +4,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -101,9 +100,7 @@ impl, const D: usize> Gate for ConstantGate { fn num_constraints(&self) -> usize { self.num_consts } -} -impl, const D: usize> MultiOpsGate for ConstantGate { fn num_ops(&self) -> usize { self.num_consts } diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index 9803181a..fd37249f 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -5,7 +5,6 @@ use plonky2_field::field_types::Field; use plonky2_field::ops::Square; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -189,9 +188,7 @@ impl, const D: usize> Gate for Exponentiation fn num_constraints(&self) -> usize { self.num_power_bits + 1 } -} -impl, const D: usize> MultiOpsGate for ExponentiationGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 5e9f28a8..391533a7 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -1,15 +1,18 @@ -use std::fmt::Debug; +use std::collections::HashMap; +use std::fmt::{Debug, Error, Formatter}; +use std::hash::{Hash, Hasher}; +use std::sync::Arc; use plonky2_field::batch_util::batch_multiply_inplace; use plonky2_field::extension_field::{Extendable, FieldExtension}; use plonky2_field::field_types::Field; -use crate::gates::batchable::GateRef; use crate::gates::gate_tree::Tree; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; +use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, @@ -138,37 +141,62 @@ pub trait Gate, const D: usize>: 'static + Send + S fn degree(&self) -> usize; fn num_constraints(&self) -> usize; + + fn num_ops(&self) -> usize; + + fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec; + + fn fill_gate( + &self, + params: &[F], + current_slot: &CurrentSlot, + builder: &mut CircuitBuilder, + ) { + if let Some(&(gate_index, op)) = current_slot.current_slot.get(params) { + let zero = builder.zero(); + for i in op..self.num_ops() { + for dep in self.dependencies_ith_op(gate_index, i) { + builder.connect(dep, zero); + } + } + } + } } -// /// A wrapper around an `Rc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. -// #[derive(Clone)] -// pub struct GateRef, const D: usize>(pub(crate) Arc>); -// -// impl, const D: usize> GateRef { -// pub fn new>(gate: G) -> GateRef { -// GateRef(Arc::new(gate)) -// } -// } -// -// impl, const D: usize> PartialEq for GateRef { -// fn eq(&self, other: &Self) -> bool { -// self.0.id() == other.0.id() -// } -// } -// -// impl, const D: usize> Hash for GateRef { -// fn hash(&self, state: &mut H) { -// self.0.id().hash(state) -// } -// } -// -// impl, const D: usize> Eq for GateRef {} -// -// impl, const D: usize> Debug for GateRef { -// fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { -// write!(f, "{}", self.0.id()) -// } -// } +/// A wrapper around an `Rc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. +#[derive(Clone)] +pub struct GateRef, const D: usize>(pub(crate) Arc>); + +impl, const D: usize> GateRef { + pub fn new>(gate: G) -> GateRef { + GateRef(Arc::new(gate)) + } +} + +impl, const D: usize> PartialEq for GateRef { + fn eq(&self, other: &Self) -> bool { + self.0.id() == other.0.id() + } +} + +impl, const D: usize> Hash for GateRef { + fn hash(&self, state: &mut H) { + self.0.id().hash(state) + } +} + +impl, const D: usize> Eq for GateRef {} + +impl, const D: usize> Debug for GateRef { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + write!(f, "{}", self.0.id()) + } +} + +#[derive(Clone, Debug)] +pub struct CurrentSlot, const D: usize> { + pub current_slot: HashMap, (usize, usize)>, +} /// A gate along with any constants used to configure it. #[derive(Clone)] diff --git a/plonky2/src/gates/gate_tree.rs b/plonky2/src/gates/gate_tree.rs index 66161333..2f670337 100644 --- a/plonky2/src/gates/gate_tree.rs +++ b/plonky2/src/gates/gate_tree.rs @@ -1,7 +1,7 @@ use log::debug; use plonky2_field::extension_field::Extendable; -use crate::gates::batchable::GateRef; +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. diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index c8743050..0edb7276 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -8,7 +8,6 @@ use plonky2_field::polynomial::PolynomialCoeffs; use crate::gadgets::interpolation::InterpolationGate; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -202,10 +201,7 @@ impl, const D: usize> Gate // point-value pairs, plus D constraints for the evaluation value. self.num_points() * D + D } -} -impl, const D: usize> MultiOpsGate - for HighDegreeInterpolationGate -{ + fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs index 8e7d91c8..3821d5f1 100644 --- a/plonky2/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -9,7 +9,6 @@ use plonky2_field::polynomial::PolynomialCoeffs; use crate::gadgets::interpolation::InterpolationGate; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -293,11 +292,7 @@ impl, const D: usize> Gate for LowDegreeInter // to check power constraints for evaluation point and shift. self.num_points() * D + D + (D + 1) * (self.num_points() - 2) } -} -impl, const D: usize> MultiOpsGate - for LowDegreeInterpolationGate -{ fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs index 02e93eb1..d4dd8645 100644 --- a/plonky2/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -3,7 +3,6 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -144,9 +143,7 @@ impl, const D: usize> Gate for MulExtensionGa fn num_constraints(&self) -> usize { self.num_ops * D } -} -impl, const D: usize> MultiOpsGate for MulExtensionGate { fn num_ops(&self) -> usize { self.num_ops } diff --git a/plonky2/src/gates/noop.rs b/plonky2/src/gates/noop.rs index 5de05991..e9507a31 100644 --- a/plonky2/src/gates/noop.rs +++ b/plonky2/src/gates/noop.rs @@ -1,6 +1,5 @@ use plonky2_field::extension_field::Extendable; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; @@ -56,9 +55,7 @@ impl, const D: usize> Gate for NoopGate { fn num_constraints(&self) -> usize { 0 } -} -impl, const D: usize> MultiOpsGate for NoopGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/poseidon.rs b/plonky2/src/gates/poseidon.rs index 82fedcbb..4a5f119a 100644 --- a/plonky2/src/gates/poseidon.rs +++ b/plonky2/src/gates/poseidon.rs @@ -3,7 +3,6 @@ use std::marker::PhantomData; use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::poseidon_mds::PoseidonMdsGate; use crate::gates::util::StridedConstraintConsumer; @@ -406,8 +405,7 @@ impl, const D: usize> Gate for PoseidonGate, const D: usize> MultiOpsGate for PoseidonGate { + fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/poseidon_mds.rs b/plonky2/src/gates/poseidon_mds.rs index ad899599..772059ce 100644 --- a/plonky2/src/gates/poseidon_mds.rs +++ b/plonky2/src/gates/poseidon_mds.rs @@ -6,7 +6,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; use plonky2_field::field_types::Field; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -196,10 +195,7 @@ impl + Poseidon, const D: usize> Gate for Pos fn num_constraints(&self) -> usize { SPONGE_WIDTH * D } -} -impl + Poseidon, const D: usize> MultiOpsGate - for PoseidonMdsGate -{ + fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/public_input.rs b/plonky2/src/gates/public_input.rs index 85145e31..e7e37663 100644 --- a/plonky2/src/gates/public_input.rs +++ b/plonky2/src/gates/public_input.rs @@ -3,7 +3,6 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -87,9 +86,7 @@ impl, const D: usize> Gate for PublicInputGat fn num_constraints(&self) -> usize { 4 } -} -impl, const D: usize> MultiOpsGate for PublicInputGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 4a17aae8..6579b590 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -5,7 +5,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -229,9 +228,7 @@ impl, const D: usize> Gate for RandomAccessGa let constraints_per_copy = self.bits + 2; self.num_copies * constraints_per_copy } -} -impl, const D: usize> MultiOpsGate for RandomAccessGate { fn num_ops(&self) -> usize { self.num_copies } diff --git a/plonky2/src/gates/range_check_u32.rs b/plonky2/src/gates/range_check_u32.rs index 38731189..73cc0d98 100644 --- a/plonky2/src/gates/range_check_u32.rs +++ b/plonky2/src/gates/range_check_u32.rs @@ -4,7 +4,6 @@ use plonky2_util::ceil_div_usize; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -165,9 +164,7 @@ impl, const D: usize> Gate for U32RangeCheckG fn num_constraints(&self) -> usize { self.num_input_limbs * (1 + self.aux_limbs_per_input_limb()) } -} -impl, const D: usize> MultiOpsGate for U32RangeCheckGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/reducing.rs b/plonky2/src/gates/reducing.rs index cf07d3a7..c53609de 100644 --- a/plonky2/src/gates/reducing.rs +++ b/plonky2/src/gates/reducing.rs @@ -3,7 +3,6 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -165,9 +164,7 @@ impl, const D: usize> Gate for ReducingGate usize { D * self.num_coeffs } -} -impl, const D: usize> MultiOpsGate for ReducingGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/reducing_extension.rs b/plonky2/src/gates/reducing_extension.rs index 65eec526..c455a5cd 100644 --- a/plonky2/src/gates/reducing_extension.rs +++ b/plonky2/src/gates/reducing_extension.rs @@ -3,7 +3,6 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; use plonky2_field::extension_field::FieldExtension; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; @@ -165,9 +164,7 @@ impl, const D: usize> Gate for ReducingExtens fn num_constraints(&self) -> usize { D * self.num_coeffs } -} -impl, const D: usize> MultiOpsGate for ReducingExtensionGate { fn num_ops(&self) -> usize { 1 } diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index a37648c4..03e8d652 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -4,7 +4,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -220,9 +219,7 @@ impl, const D: usize> Gate for U32Subtraction fn num_constraints(&self) -> usize { self.num_ops * (3 + Self::num_limbs()) } -} -impl, const D: usize> MultiOpsGate for U32SubtractionGate { fn num_ops(&self) -> usize { self.num_ops } diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index ae4419df..f5fb8828 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -5,7 +5,6 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; -use crate::gates::batchable::MultiOpsGate; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; @@ -188,9 +187,7 @@ impl, const D: usize> Gate for SwitchGate usize { 4 * self.num_copies * self.chunk_size } -} -impl, const D: usize> MultiOpsGate for SwitchGate { fn num_ops(&self) -> usize { self.num_copies } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index e0a4aba2..c749ba4e 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -18,9 +18,8 @@ use crate::gadgets::arithmetic_u32::U32Target; use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; -use crate::gates::batchable::{BatchableGate, CurrentSlot, GateRef}; use crate::gates::constant::ConstantGate; -use crate::gates::gate::{Gate, GateInstance, PrefixedGate}; +use crate::gates::gate::{CurrentSlot, Gate, GateInstance, GateRef, PrefixedGate}; use crate::gates::gate_tree::Tree; use crate::gates::noop::NoopGate; use crate::gates::public_input::PublicInputGate; @@ -206,7 +205,7 @@ impl, const D: usize> CircuitBuilder { } /// Adds a gate to the circuit, and returns its index. - pub fn add_gate>( + pub fn add_gate>( &mut self, gate_type: G, constants: Vec, @@ -398,7 +397,7 @@ impl, const D: usize> CircuitBuilder { }) } - pub fn find_slot + Clone>( + pub fn find_slot + Clone>( &mut self, gate: G, params: &[F], From c74b0c91c82392e7b87b7eef1d4bc6203a89db71 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 15 Feb 2022 16:59:17 +0100 Subject: [PATCH 08/14] Progress towards using generators --- plonky2/src/gates/batchable.rs | 80 ---------------------------- plonky2/src/gates/comparison.rs | 10 ---- plonky2/src/gates/constant.rs | 72 ++++++++++++++----------- plonky2/src/gates/gate.rs | 3 ++ plonky2/src/gates/mod.rs | 1 - plonky2/src/gates/noop.rs | 2 +- plonky2/src/plonk/circuit_builder.rs | 14 +++-- 7 files changed, 53 insertions(+), 129 deletions(-) delete mode 100644 plonky2/src/gates/batchable.rs diff --git a/plonky2/src/gates/batchable.rs b/plonky2/src/gates/batchable.rs deleted file mode 100644 index 20ab39f3..00000000 --- a/plonky2/src/gates/batchable.rs +++ /dev/null @@ -1,80 +0,0 @@ -// use std::collections::HashMap; -// use std::fmt::{Debug, Error, Formatter}; -// use std::hash::{Hash, Hasher}; -// use std::sync::Arc; -// -// use plonky2_field::extension_field::Extendable; -// -// use crate::gates::gate::Gate; -// use crate::hash::hash_types::RichField; -// use crate::iop::target::Target; -// use crate::plonk::circuit_builder::CircuitBuilder; -// -// pub trait BatchableGate, const D: usize>: Gate { -// fn num_ops(&self) -> usize; -// -// // TODO: It would be nice to have a `Parameters` associated type. -// fn fill_gate( -// &self, -// params: &[F], -// current_slot: &CurrentSlot, -// builder: &mut CircuitBuilder, -// ); -// } -// -// #[derive(Clone, Debug)] -// pub struct CurrentSlot, const D: usize> { -// pub current_slot: HashMap, (usize, usize)>, -// } -// -// #[derive(Clone)] -// pub struct GateRef, const D: usize>( -// pub(crate) Arc>, -// ); -// -// impl, const D: usize> GateRef { -// pub fn new>(gate: G) -> GateRef { -// GateRef(Arc::new(gate)) -// } -// } -// -// impl, const D: usize> PartialEq for GateRef { -// fn eq(&self, other: &Self) -> bool { -// self.0.id() == other.0.id() -// } -// } -// -// impl, const D: usize> Hash for GateRef { -// fn hash(&self, state: &mut H) { -// self.0.id().hash(state) -// } -// } -// -// impl, const D: usize> Eq for GateRef {} -// -// impl, const D: usize> Debug for GateRef { -// fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { -// write!(f, "{}", self.0.id()) -// } -// } -// -// // pub trait SingleOpGate, const D: usize>: Gate {} -// // impl, G: SingleOpGate, const D: usize> MultiOpsGate for G { -// // fn num_ops(&self) -> usize { -// // 1 -// // } -// // -// // fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { -// // unreachable!() -// // } -// // } -// -// pub trait MultiOpsGate, const D: usize>: Gate {} -// -// impl, G: MultiOpsGate, const D: usize> BatchableGate -// for G -// { -// fn num_ops(&self) -> usize { -// self.num_ops() -// } -// } diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index 00e7f4d3..4a68adb7 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -321,16 +321,6 @@ impl, const D: usize> Gate for ComparisonGate } } -// impl, const D: usize> Singleopgate for multiopsgate { -// fn num_ops(&self) -> usize { -// 1 -// } -// -// fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { -// unreachable!() -// } -// } - impl, const D: usize> PackedEvaluableBase for ComparisonGate { diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index 455e5349..d62befc4 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -1,5 +1,3 @@ -use std::ops::Range; - use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; @@ -26,12 +24,14 @@ pub struct ConstantGate { } impl ConstantGate { - pub fn consts_inputs(&self) -> Range { - 0..self.num_consts + pub fn const_input(&self, i: usize) -> usize { + debug_assert!(i < self.num_consts); + i } - pub fn wires_outputs(&self) -> Range { - 0..self.num_consts + pub fn wire_output(&self, i: usize) -> usize { + debug_assert!(i < self.num_consts); + i } } @@ -41,9 +41,10 @@ impl, const D: usize> Gate for ConstantGate { } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - self.consts_inputs() - .zip(self.wires_outputs()) - .map(|(con, out)| vars.local_constants[con] - vars.local_wires[out]) + (0..self.num_consts) + .map(|i| { + vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)] + }) .collect() } @@ -64,10 +65,12 @@ impl, const D: usize> Gate for ConstantGate { builder: &mut CircuitBuilder, vars: EvaluationTargets, ) -> Vec> { - self.consts_inputs() - .zip(self.wires_outputs()) - .map(|(con, out)| { - builder.sub_extension(vars.local_constants[con], vars.local_wires[out]) + (0..self.num_consts) + .map(|i| { + builder.sub_extension( + vars.local_constants[self.const_input(i)], + vars.local_wires[self.wire_output(i)], + ) }) .collect() } @@ -77,12 +80,20 @@ impl, const D: usize> Gate for ConstantGate { gate_index: usize, local_constants: &[F], ) -> Vec>> { - let gen = ConstantGenerator { - gate_index, - gate: *self, - constants: local_constants[self.consts_inputs()].to_vec(), - }; - vec![Box::new(gen.adapter())] + (0..self.num_consts) + .map(|i| { + let g: Box> = Box::new( + ConstantGenerator { + gate_index, + gate: *self, + i, + constant: local_constants[self.const_input(i)], + } + .adapter(), + ); + g + }) + .collect() } fn num_wires(&self) -> usize { @@ -116,11 +127,9 @@ impl, const D: usize> PackedEvaluableBase for vars: EvaluationVarsBasePacked

, mut yield_constr: StridedConstraintConsumer

, ) { - yield_constr.many( - self.consts_inputs() - .zip(self.wires_outputs()) - .map(|(con, out)| vars.local_constants[con] - vars.local_wires[out]), - ); + yield_constr.many((0..self.num_consts).map(|i| { + vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)] + })); } } @@ -128,7 +137,8 @@ impl, const D: usize> PackedEvaluableBase for struct ConstantGenerator { gate_index: usize, gate: ConstantGate, - constants: Vec, + i: usize, + constant: F, } impl SimpleGenerator for ConstantGenerator { @@ -137,13 +147,11 @@ impl SimpleGenerator for ConstantGenerator { } fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { - for (con, out) in self.gate.consts_inputs().zip(self.gate.wires_outputs()) { - let wire = Wire { - gate: self.gate_index, - input: out, - }; - out_buffer.set_wire(wire, self.constants[con]); - } + let wire = Wire { + gate: self.gate_index, + input: self.gate.wire_output(self.i), + }; + out_buffer.set_wire(wire, self.constant); } } diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 391533a7..1d487db7 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -142,10 +142,13 @@ pub trait Gate, const D: usize>: 'static + Send + S fn num_constraints(&self) -> usize; + /// Number of operations performed by the gate. fn num_ops(&self) -> usize; + /// Dependencies (inputs) for the i-th operation. fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec; + /// Fill the dependencies of the fn fill_gate( &self, params: &[F], diff --git a/plonky2/src/gates/mod.rs b/plonky2/src/gates/mod.rs index 4f01b7ce..18e3e99b 100644 --- a/plonky2/src/gates/mod.rs +++ b/plonky2/src/gates/mod.rs @@ -7,7 +7,6 @@ pub mod arithmetic_extension; pub mod arithmetic_u32; pub mod assert_le; pub mod base_sum; -pub mod batchable; pub mod comparison; pub mod constant; pub mod exponentiation; diff --git a/plonky2/src/gates/noop.rs b/plonky2/src/gates/noop.rs index e9507a31..5ef7c318 100644 --- a/plonky2/src/gates/noop.rs +++ b/plonky2/src/gates/noop.rs @@ -57,7 +57,7 @@ impl, const D: usize> Gate for NoopGate { } fn num_ops(&self) -> usize { - 1 + 0 } fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index c749ba4e..aa0c19a2 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -662,6 +662,15 @@ impl, const D: usize> CircuitBuilder { let start = Instant::now(); let rate_bits = self.config.fri_config.rate_bits; + for g in &self.gate_instances { + assert_eq!( + g.gate_ref.0.generators(0, &[F::ZERO; 100]).len(), + g.gate_ref.0.num_ops(), + "{}", + g.gate_ref.0.id() + ); + } + self.fill_batched_gates(); // Hash the public inputs, and route them to a `PublicInputGate` which will enforce that @@ -739,11 +748,6 @@ impl, const D: usize> CircuitBuilder { constants_sigmas_cap: constants_sigmas_cap.clone(), }; - let mut gens = self.generators.len(); - for (i, g) in self.gate_instances.iter().enumerate() { - gens += g.gate_ref.0.generators(i, &g.constants).len(); - dbg!(g.gate_ref.0.id(), gens); - } // Add gate generators. self.add_generators( self.gate_instances From d0da2fe1adeaac51ac629f4bbe559fff29de6267 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 15 Feb 2022 17:01:16 +0100 Subject: [PATCH 09/14] Remove debug info --- plonky2/src/plonk/circuit_builder.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index aa0c19a2..a46ddb4e 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -662,15 +662,6 @@ impl, const D: usize> CircuitBuilder { let start = Instant::now(); let rate_bits = self.config.fri_config.rate_bits; - for g in &self.gate_instances { - assert_eq!( - g.gate_ref.0.generators(0, &[F::ZERO; 100]).len(), - g.gate_ref.0.num_ops(), - "{}", - g.gate_ref.0.id() - ); - } - self.fill_batched_gates(); // Hash the public inputs, and route them to a `PublicInputGate` which will enforce that From 2d4d2d21a092a2032ec7b620cceba1de27757e94 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 15 Feb 2022 17:35:12 +0100 Subject: [PATCH 10/14] Simplification --- insertion/src/insertion_gate.rs | 8 ------ plonky2/src/gates/add_many_u32.rs | 14 ---------- plonky2/src/gates/arithmetic_base.rs | 12 -------- plonky2/src/gates/arithmetic_extension.rs | 13 --------- plonky2/src/gates/arithmetic_u32.rs | 14 ---------- plonky2/src/gates/assert_le.rs | 8 ------ plonky2/src/gates/base_sum.rs | 8 ------ plonky2/src/gates/comparison.rs | 8 ------ plonky2/src/gates/constant.rs | 8 ------ plonky2/src/gates/exponentiation.rs | 8 ------ plonky2/src/gates/gate.rs | 23 ++------------- plonky2/src/gates/interpolation.rs | 8 ------ plonky2/src/gates/low_degree_interpolation.rs | 8 ------ plonky2/src/gates/multiplication_extension.rs | 12 -------- plonky2/src/gates/noop.rs | 9 ------ plonky2/src/gates/poseidon.rs | 8 ------ plonky2/src/gates/poseidon_mds.rs | 8 ------ plonky2/src/gates/public_input.rs | 9 ------ plonky2/src/gates/random_access.rs | 13 --------- plonky2/src/gates/range_check_u32.rs | 8 ------ plonky2/src/gates/reducing.rs | 8 ------ plonky2/src/gates/reducing_extension.rs | 8 ------ plonky2/src/gates/subtraction_u32.rs | 14 ---------- plonky2/src/gates/switch.rs | 13 --------- plonky2/src/plonk/circuit_builder.rs | 28 +++++++++---------- 25 files changed, 15 insertions(+), 263 deletions(-) diff --git a/insertion/src/insertion_gate.rs b/insertion/src/insertion_gate.rs index 5b60f13b..442416d3 100644 --- a/insertion/src/insertion_gate.rs +++ b/insertion/src/insertion_gate.rs @@ -240,14 +240,6 @@ impl, const D: usize> Gate for InsertionGate< fn num_constraints(&self) -> usize { (self.vec_size + 1) * (2 + D) } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[derive(Debug)] diff --git a/plonky2/src/gates/add_many_u32.rs b/plonky2/src/gates/add_many_u32.rs index 3ea52988..4f9c4293 100644 --- a/plonky2/src/gates/add_many_u32.rs +++ b/plonky2/src/gates/add_many_u32.rs @@ -269,20 +269,6 @@ impl, const D: usize> Gate for U32AddManyGate fn num_constraints(&self) -> usize { self.num_ops * (3 + Self::num_limbs()) } - - fn num_ops(&self) -> usize { - self.num_ops - } - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - U32AddManyGenerator { - gate: *self, - gate_index, - i, - _phantom: PhantomData, - } - .dependencies() - } } #[derive(Clone, Debug)] diff --git a/plonky2/src/gates/arithmetic_base.rs b/plonky2/src/gates/arithmetic_base.rs index 7062ef84..5f73fef0 100644 --- a/plonky2/src/gates/arithmetic_base.rs +++ b/plonky2/src/gates/arithmetic_base.rs @@ -149,18 +149,6 @@ impl, const D: usize> Gate for ArithmeticGate fn num_constraints(&self) -> usize { self.num_ops } - - fn num_ops(&self) -> usize { - self.num_ops - } - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - vec![ - Target::wire(gate_index, Self::wire_ith_multiplicand_0(i)), - Target::wire(gate_index, Self::wire_ith_multiplicand_1(i)), - Target::wire(gate_index, Self::wire_ith_addend(i)), - ] - } } impl, const D: usize> PackedEvaluableBase for ArithmeticGate { diff --git a/plonky2/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs index fcedb6de..6b5af067 100644 --- a/plonky2/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -156,19 +156,6 @@ impl, const D: usize> Gate for ArithmeticExte fn num_constraints(&self) -> usize { self.num_ops * D } - - fn num_ops(&self) -> usize { - self.num_ops - } - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - [ - ExtensionTarget::::from_range(gate_index, Self::wires_ith_multiplicand_0(i)).0, - ExtensionTarget::::from_range(gate_index, Self::wires_ith_multiplicand_1(i)).0, - ExtensionTarget::::from_range(gate_index, Self::wires_ith_addend(i)).0, - ] - .concat() - } } #[derive(Clone, Debug)] diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index 1432d20e..dc03e296 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -230,20 +230,6 @@ impl, const D: usize> Gate for U32ArithmeticG fn num_constraints(&self) -> usize { self.num_ops * (3 + Self::num_limbs()) } - - fn num_ops(&self) -> usize { - self.num_ops - } - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - U32ArithmeticGenerator { - gate: *self, - gate_index, - i, - _phantom: PhantomData, - } - .dependencies() - } } impl, const D: usize> PackedEvaluableBase diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index 08c9c8e3..cec7274b 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -278,14 +278,6 @@ impl, const D: usize> Gate for AssertLessThan fn num_constraints(&self) -> usize { 4 + 5 * self.num_chunks } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } impl, const D: usize> PackedEvaluableBase diff --git a/plonky2/src/gates/base_sum.rs b/plonky2/src/gates/base_sum.rs index be81044a..e03a2c5b 100644 --- a/plonky2/src/gates/base_sum.rs +++ b/plonky2/src/gates/base_sum.rs @@ -134,14 +134,6 @@ impl, const D: usize, const B: usize> Gate fo fn num_constraints(&self) -> usize { 1 + self.num_limbs } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } impl, const D: usize, const B: usize> PackedEvaluableBase diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index 4a68adb7..b1cf7b98 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -311,14 +311,6 @@ impl, const D: usize> Gate for ComparisonGate fn num_constraints(&self) -> usize { 6 + 5 * self.num_chunks + self.chunk_bits() } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } impl, const D: usize> PackedEvaluableBase diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index d62befc4..990a4df8 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -111,14 +111,6 @@ impl, const D: usize> Gate for ConstantGate { fn num_constraints(&self) -> usize { self.num_consts } - - fn num_ops(&self) -> usize { - self.num_consts - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - vec![] - } } impl, const D: usize> PackedEvaluableBase for ConstantGate { diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index fd37249f..51558a21 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -188,14 +188,6 @@ impl, const D: usize> Gate for Exponentiation fn num_constraints(&self) -> usize { self.num_power_bits + 1 } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } impl, const D: usize> PackedEvaluableBase diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 1d487db7..1d6a0e3d 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -12,7 +12,6 @@ use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; -use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, @@ -143,26 +142,8 @@ pub trait Gate, const D: usize>: 'static + Send + S fn num_constraints(&self) -> usize; /// Number of operations performed by the gate. - fn num_ops(&self) -> usize; - - /// Dependencies (inputs) for the i-th operation. - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec; - - /// Fill the dependencies of the - fn fill_gate( - &self, - params: &[F], - current_slot: &CurrentSlot, - builder: &mut CircuitBuilder, - ) { - if let Some(&(gate_index, op)) = current_slot.current_slot.get(params) { - let zero = builder.zero(); - for i in op..self.num_ops() { - for dep in self.dependencies_ith_op(gate_index, i) { - builder.connect(dep, zero); - } - } - } + fn num_ops(&self) -> usize { + self.generators(0, &[F::ZERO; 100]).len() } } diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index 0edb7276..46c42113 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -201,14 +201,6 @@ impl, const D: usize> Gate // point-value pairs, plus D constraints for the evaluation value. self.num_points() * D + D } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[derive(Debug)] diff --git a/plonky2/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs index 3821d5f1..845da5ab 100644 --- a/plonky2/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -292,14 +292,6 @@ impl, const D: usize> Gate for LowDegreeInter // to check power constraints for evaluation point and shift. self.num_points() * D + D + (D + 1) * (self.num_points() - 2) } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[derive(Debug)] diff --git a/plonky2/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs index d4dd8645..09701260 100644 --- a/plonky2/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -143,18 +143,6 @@ impl, const D: usize> Gate for MulExtensionGa fn num_constraints(&self) -> usize { self.num_ops * D } - - fn num_ops(&self) -> usize { - self.num_ops - } - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - [ - ExtensionTarget::::from_range(gate_index, Self::wires_ith_multiplicand_0(i)).0, - ExtensionTarget::::from_range(gate_index, Self::wires_ith_multiplicand_1(i)).0, - ] - .concat() - } } #[derive(Clone, Debug)] diff --git a/plonky2/src/gates/noop.rs b/plonky2/src/gates/noop.rs index 5ef7c318..4cd872d8 100644 --- a/plonky2/src/gates/noop.rs +++ b/plonky2/src/gates/noop.rs @@ -4,7 +4,6 @@ use crate::gates::gate::Gate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; -use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch}; @@ -55,14 +54,6 @@ impl, const D: usize> Gate for NoopGate { fn num_constraints(&self) -> usize { 0 } - - fn num_ops(&self) -> usize { - 0 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[cfg(test)] diff --git a/plonky2/src/gates/poseidon.rs b/plonky2/src/gates/poseidon.rs index 4a5f119a..29971c23 100644 --- a/plonky2/src/gates/poseidon.rs +++ b/plonky2/src/gates/poseidon.rs @@ -405,14 +405,6 @@ impl, const D: usize> Gate for PoseidonGate usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[derive(Debug)] diff --git a/plonky2/src/gates/poseidon_mds.rs b/plonky2/src/gates/poseidon_mds.rs index 772059ce..81583f88 100644 --- a/plonky2/src/gates/poseidon_mds.rs +++ b/plonky2/src/gates/poseidon_mds.rs @@ -195,14 +195,6 @@ impl + Poseidon, const D: usize> Gate for Pos fn num_constraints(&self) -> usize { SPONGE_WIDTH * D } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[derive(Clone, Debug)] diff --git a/plonky2/src/gates/public_input.rs b/plonky2/src/gates/public_input.rs index e7e37663..20fc59c8 100644 --- a/plonky2/src/gates/public_input.rs +++ b/plonky2/src/gates/public_input.rs @@ -9,7 +9,6 @@ use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; -use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, @@ -86,14 +85,6 @@ impl, const D: usize> Gate for PublicInputGat fn num_constraints(&self) -> usize { 4 } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } impl, const D: usize> PackedEvaluableBase for PublicInputGate { diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 6579b590..6379f99f 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -228,19 +228,6 @@ impl, const D: usize> Gate for RandomAccessGa let constraints_per_copy = self.bits + 2; self.num_copies * constraints_per_copy } - - fn num_ops(&self) -> usize { - self.num_copies - } - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - RandomAccessGenerator { - gate_index, - gate: *self, - copy: i, - } - .dependencies() - } } impl, const D: usize> PackedEvaluableBase diff --git a/plonky2/src/gates/range_check_u32.rs b/plonky2/src/gates/range_check_u32.rs index 73cc0d98..79e91de8 100644 --- a/plonky2/src/gates/range_check_u32.rs +++ b/plonky2/src/gates/range_check_u32.rs @@ -164,14 +164,6 @@ impl, const D: usize> Gate for U32RangeCheckG fn num_constraints(&self) -> usize { self.num_input_limbs * (1 + self.aux_limbs_per_input_limb()) } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[derive(Debug)] diff --git a/plonky2/src/gates/reducing.rs b/plonky2/src/gates/reducing.rs index c53609de..2abf8425 100644 --- a/plonky2/src/gates/reducing.rs +++ b/plonky2/src/gates/reducing.rs @@ -164,14 +164,6 @@ impl, const D: usize> Gate for ReducingGate usize { D * self.num_coeffs } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[derive(Debug)] diff --git a/plonky2/src/gates/reducing_extension.rs b/plonky2/src/gates/reducing_extension.rs index c455a5cd..6655f1d7 100644 --- a/plonky2/src/gates/reducing_extension.rs +++ b/plonky2/src/gates/reducing_extension.rs @@ -164,14 +164,6 @@ impl, const D: usize> Gate for ReducingExtens fn num_constraints(&self) -> usize { D * self.num_coeffs } - - fn num_ops(&self) -> usize { - 1 - } - - fn dependencies_ith_op(&self, _gate_index: usize, _i: usize) -> Vec { - unreachable!() - } } #[derive(Debug)] diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index 03e8d652..b1e4d84f 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -219,20 +219,6 @@ impl, const D: usize> Gate for U32Subtraction fn num_constraints(&self) -> usize { self.num_ops * (3 + Self::num_limbs()) } - - fn num_ops(&self) -> usize { - self.num_ops - } - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - U32SubtractionGenerator { - gate: *self, - gate_index, - i, - _phantom: Default::default(), - } - .dependencies() - } } impl, const D: usize> PackedEvaluableBase diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index f5fb8828..bd298762 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -187,19 +187,6 @@ impl, const D: usize> Gate for SwitchGate usize { 4 * self.num_copies * self.chunk_size } - - fn num_ops(&self) -> usize { - self.num_copies - } - - fn dependencies_ith_op(&self, gate_index: usize, i: usize) -> Vec { - SwitchGenerator:: { - gate_index, - gate: *self, - copy: i, - } - .watch_list() - } } impl, const D: usize> PackedEvaluableBase for SwitchGate { diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index a46ddb4e..aa4c67be 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -662,8 +662,6 @@ impl, const D: usize> CircuitBuilder { let start = Instant::now(); let rate_bits = self.config.fri_config.rate_bits; - self.fill_batched_gates(); - // Hash the public inputs, and route them to a `PublicInputGate` which will enforce that // those hash wires match the claimed public inputs. let num_public_inputs = self.public_inputs.len(); @@ -739,12 +737,24 @@ impl, const D: usize> CircuitBuilder { constants_sigmas_cap: constants_sigmas_cap.clone(), }; + let incomplete_gates = self + .current_slots + .values() + .flat_map(|current_slot| current_slot.current_slot.values().copied()) + .collect::>(); + // Add gate generators. self.add_generators( self.gate_instances .iter() .enumerate() - .flat_map(|(index, gate)| gate.gate_ref.0.generators(index, &gate.constants)) + .flat_map(|(index, gate)| { + let mut gens = gate.gate_ref.0.generators(index, &gate.constants); + if let Some(&op) = incomplete_gates.get(&index) { + gens.drain(op..); + } + gens + }) .collect(), ); @@ -856,15 +866,3 @@ impl, const D: usize> CircuitBuilder { } } } - -impl, const D: usize> CircuitBuilder { - fn fill_batched_gates(&mut self) { - let instances = self.gate_instances.clone(); - for gate in instances { - if let Some(slot) = self.current_slots.get(&gate.gate_ref) { - let cloned = slot.clone(); - gate.gate_ref.0.fill_gate(&gate.params, &cloned, self); - } - } - } -} From 3fd52581912991e16c53c7f035fe3874269bdff8 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 15 Feb 2022 18:00:53 +0100 Subject: [PATCH 11/14] Comments --- plonky2/src/gates/gate.rs | 4 +++- plonky2/src/iop/generator.rs | 5 ----- plonky2/src/plonk/circuit_builder.rs | 7 ++++++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 1d6a0e3d..c84c6595 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -143,7 +143,8 @@ pub trait Gate, const D: usize>: 'static + Send + S /// Number of operations performed by the gate. fn num_ops(&self) -> usize { - self.generators(0, &[F::ZERO; 100]).len() + self.generators(0, &vec![F::ZERO; self.num_constants()]) + .len() } } @@ -177,6 +178,7 @@ impl, const D: usize> Debug for GateRef { } } +/// Map between gate parameters and available slots. #[derive(Clone, Debug)] pub struct CurrentSlot, const D: usize> { pub current_slot: HashMap, (usize, usize)>, diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index 0105e031..1569e889 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -91,11 +91,6 @@ pub(crate) fn generate_partial_witness< pending_generator_indices = next_pending_generator_indices; } - for i in 0..generator_is_expired.len() { - if !generator_is_expired[i] { - dbg!(i); - } - } assert_eq!( remaining_generators, 0, "{} generators weren't run", diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index aa4c67be..5c5f66f0 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -81,6 +81,7 @@ pub struct CircuitBuilder, const D: usize> { /// Memoized results of `arithmetic_extension` calls. pub(crate) arithmetic_results: HashMap, ExtensionTarget>, + /// Map between gate type and the current gate of this type with available slots. current_slots: HashMap, CurrentSlot>, } @@ -211,7 +212,6 @@ impl, const D: usize> CircuitBuilder { constants: Vec, params: Vec, ) -> usize { - // println!("{} {}", self.num_gates(), gate_type.id()); self.check_gate_compatibility(&gate_type); assert_eq!( gate_type.num_constants(), @@ -397,6 +397,7 @@ impl, const D: usize> CircuitBuilder { }) } + /// Find an available slot, of the form `(gate_index, op)` for gate `G`. pub fn find_slot + Clone>( &mut self, gate: G, @@ -420,12 +421,14 @@ impl, const D: usize> CircuitBuilder { (num_gates, 0) }; if res.1 == num_ops - 1 { + // We've filled up the slots at this index. self.current_slots .get_mut(&gate_ref) .unwrap() .current_slot .remove(params); } else { + // Increment the slot operation index. self.current_slots .get_mut(&gate_ref) .unwrap() @@ -737,6 +740,7 @@ impl, const D: usize> CircuitBuilder { constants_sigmas_cap: constants_sigmas_cap.clone(), }; + // Map between gates where not all generators are used and the gate's number of used generators. let incomplete_gates = self .current_slots .values() @@ -750,6 +754,7 @@ impl, const D: usize> CircuitBuilder { .enumerate() .flat_map(|(index, gate)| { let mut gens = gate.gate_ref.0.generators(index, &gate.constants); + // Remove unused generators, if any. if let Some(&op) = incomplete_gates.get(&index) { gens.drain(op..); } From 661a6b44efdc2132fea679609ddbf852d83a54c8 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 16 Feb 2022 08:33:52 +0100 Subject: [PATCH 12/14] Delete GMiMC files --- plonky2/src/gates/gmimc.rs | 1 - plonky2/src/hash/gmimc.rs | 1 - 2 files changed, 2 deletions(-) delete mode 100644 plonky2/src/gates/gmimc.rs delete mode 100644 plonky2/src/hash/gmimc.rs diff --git a/plonky2/src/gates/gmimc.rs b/plonky2/src/gates/gmimc.rs deleted file mode 100644 index 8b137891..00000000 --- a/plonky2/src/gates/gmimc.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/plonky2/src/hash/gmimc.rs b/plonky2/src/hash/gmimc.rs deleted file mode 100644 index 8b137891..00000000 --- a/plonky2/src/hash/gmimc.rs +++ /dev/null @@ -1 +0,0 @@ - From 08e255a2bb12ffa31932b26661c9328871e7e78e Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 16 Feb 2022 09:02:21 +0100 Subject: [PATCH 13/14] Remove `params` in `GateInstance` --- insertion/src/insert_gadget.rs | 2 +- plonky2/src/gadgets/arithmetic.rs | 2 +- plonky2/src/gadgets/interpolation.rs | 2 +- plonky2/src/gadgets/multiple_comparison.rs | 4 ++-- plonky2/src/gadgets/range_check.rs | 2 +- plonky2/src/gadgets/split_base.rs | 4 ++-- plonky2/src/gadgets/split_join.rs | 2 +- plonky2/src/gates/gate.rs | 1 - plonky2/src/gates/poseidon.rs | 2 +- plonky2/src/hash/poseidon.rs | 4 ++-- plonky2/src/plonk/circuit_builder.rs | 20 +++++++------------- plonky2/src/plonk/proof.rs | 2 +- plonky2/src/plonk/recursive_verifier.rs | 4 ++-- plonky2/src/util/reducing.rs | 4 ++-- waksman/src/sorting.rs | 2 +- 15 files changed, 25 insertions(+), 32 deletions(-) diff --git a/insertion/src/insert_gadget.rs b/insertion/src/insert_gadget.rs index 76cb4410..9f8aa4bf 100644 --- a/insertion/src/insert_gadget.rs +++ b/insertion/src/insert_gadget.rs @@ -27,7 +27,7 @@ impl, const D: usize> CircuitBuilderInsert v: Vec>, ) -> Vec> { let gate = InsertionGate::new(v.len()); - let gate_index = self.add_gate(gate.clone(), vec![], vec![]); + let gate_index = self.add_gate(gate.clone(), vec![]); v.iter().enumerate().for_each(|(i, &val)| { self.connect_extension( diff --git a/plonky2/src/gadgets/arithmetic.rs b/plonky2/src/gadgets/arithmetic.rs index d8dbaf22..11fc57bf 100644 --- a/plonky2/src/gadgets/arithmetic.rs +++ b/plonky2/src/gadgets/arithmetic.rs @@ -241,7 +241,7 @@ impl, const D: usize> CircuitBuilder { while exp_bits_vec.len() < num_power_bits { exp_bits_vec.push(_false); } - let gate_index = self.add_gate(gate.clone(), vec![], vec![]); + let gate_index = self.add_gate(gate.clone(), vec![]); self.connect(base, Target::wire(gate_index, gate.wire_base())); exp_bits_vec.iter().enumerate().for_each(|(i, bit)| { diff --git a/plonky2/src/gadgets/interpolation.rs b/plonky2/src/gadgets/interpolation.rs index 9dccd666..7907a337 100644 --- a/plonky2/src/gadgets/interpolation.rs +++ b/plonky2/src/gadgets/interpolation.rs @@ -88,7 +88,7 @@ impl, const D: usize> CircuitBuilder { evaluation_point: ExtensionTarget, ) -> ExtensionTarget { let gate = G::new(subgroup_bits); - let gate_index = self.add_gate(gate, vec![], vec![]); + 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( diff --git a/plonky2/src/gadgets/multiple_comparison.rs b/plonky2/src/gadgets/multiple_comparison.rs index 112b0113..434fb6c1 100644 --- a/plonky2/src/gadgets/multiple_comparison.rs +++ b/plonky2/src/gadgets/multiple_comparison.rs @@ -25,7 +25,7 @@ impl, const D: usize> CircuitBuilder { let mut result = one; for i in 0..n { let a_le_b_gate = ComparisonGate::new(num_bits, num_chunks); - let a_le_b_gate_index = self.add_gate(a_le_b_gate.clone(), vec![], vec![]); + let a_le_b_gate_index = self.add_gate(a_le_b_gate.clone(), vec![]); self.connect( Target::wire(a_le_b_gate_index, a_le_b_gate.wire_first_input()), a[i], @@ -37,7 +37,7 @@ impl, const D: usize> CircuitBuilder { let a_le_b_result = Target::wire(a_le_b_gate_index, a_le_b_gate.wire_result_bool()); let b_le_a_gate = ComparisonGate::new(num_bits, num_chunks); - let b_le_a_gate_index = self.add_gate(b_le_a_gate.clone(), vec![], vec![]); + let b_le_a_gate_index = self.add_gate(b_le_a_gate.clone(), vec![]); self.connect( Target::wire(b_le_a_gate_index, b_le_a_gate.wire_first_input()), b[i], diff --git a/plonky2/src/gadgets/range_check.rs b/plonky2/src/gadgets/range_check.rs index 1aec39ce..0776fc68 100644 --- a/plonky2/src/gadgets/range_check.rs +++ b/plonky2/src/gadgets/range_check.rs @@ -47,7 +47,7 @@ impl, const D: usize> CircuitBuilder { pub fn range_check_u32(&mut self, vals: Vec) { let num_input_limbs = vals.len(); let gate = U32RangeCheckGate::::new(num_input_limbs); - let gate_index = self.add_gate(gate, vec![], vec![]); + let gate_index = self.add_gate(gate, vec![]); for i in 0..num_input_limbs { self.connect( diff --git a/plonky2/src/gadgets/split_base.rs b/plonky2/src/gadgets/split_base.rs index db6fe69d..d4589476 100644 --- a/plonky2/src/gadgets/split_base.rs +++ b/plonky2/src/gadgets/split_base.rs @@ -16,7 +16,7 @@ impl, const D: usize> CircuitBuilder { /// base-B limb of the element, with little-endian ordering. pub fn split_le_base(&mut self, x: Target, num_limbs: usize) -> Vec { let gate_type = BaseSumGate::::new(num_limbs); - let gate = self.add_gate(gate_type, vec![], vec![]); + let gate = self.add_gate(gate_type, vec![]); let sum = Target::wire(gate, BaseSumGate::::WIRE_SUM); self.connect(x, sum); @@ -54,7 +54,7 @@ impl, const D: usize> CircuitBuilder { "Not enough routed wires." ); let gate_type = BaseSumGate::<2>::new_from_config::(&self.config); - let gate_index = self.add_gate(gate_type, vec![], vec![]); + let gate_index = self.add_gate(gate_type, vec![]); for (limb, wire) in bits .iter() .zip(BaseSumGate::<2>::START_LIMBS..BaseSumGate::<2>::START_LIMBS + num_bits) diff --git a/plonky2/src/gadgets/split_join.rs b/plonky2/src/gadgets/split_join.rs index dd7a0a39..8c7c9c3f 100644 --- a/plonky2/src/gadgets/split_join.rs +++ b/plonky2/src/gadgets/split_join.rs @@ -20,7 +20,7 @@ impl, const D: usize> CircuitBuilder { let gate_type = BaseSumGate::<2>::new_from_config::(&self.config); let k = ceil_div_usize(num_bits, gate_type.num_limbs); let gates = (0..k) - .map(|_| self.add_gate(gate_type, vec![], vec![])) + .map(|_| self.add_gate(gate_type, vec![])) .collect::>(); let mut bits = Vec::with_capacity(num_bits); diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index c84c6595..132cdd00 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -189,7 +189,6 @@ pub struct CurrentSlot, const D: usize> { pub struct GateInstance, const D: usize> { pub gate_ref: GateRef, pub constants: Vec, - pub params: Vec, } /// Map each gate to a boolean prefix used to construct the gate's selector polynomial. diff --git a/plonky2/src/gates/poseidon.rs b/plonky2/src/gates/poseidon.rs index 29971c23..366e200e 100644 --- a/plonky2/src/gates/poseidon.rs +++ b/plonky2/src/gates/poseidon.rs @@ -559,7 +559,7 @@ mod tests { let mut builder = CircuitBuilder::new(config); type Gate = PoseidonGate; let gate = Gate::new(); - let gate_index = builder.add_gate(gate, vec![], vec![]); + let gate_index = builder.add_gate(gate, vec![]); let circuit = builder.build_prover::(); let permutation_inputs = (0..SPONGE_WIDTH) diff --git a/plonky2/src/hash/poseidon.rs b/plonky2/src/hash/poseidon.rs index 83946b29..09c5d2fc 100644 --- a/plonky2/src/hash/poseidon.rs +++ b/plonky2/src/hash/poseidon.rs @@ -269,7 +269,7 @@ pub trait Poseidon: PrimeField64 { // If we have enough routed wires, we will use PoseidonMdsGate. let mds_gate = PoseidonMdsGate::::new(); if builder.config.num_routed_wires >= mds_gate.num_wires() { - let index = builder.add_gate(mds_gate, vec![], vec![]); + let index = builder.add_gate(mds_gate, vec![]); for i in 0..WIDTH { let input_wire = PoseidonMdsGate::::wires_input(i); builder.connect_extension(state[i], ExtensionTarget::from_range(index, input_wire)); @@ -652,7 +652,7 @@ impl AlgebraicHasher for PoseidonHash { F: RichField + Extendable, { let gate_type = PoseidonGate::::new(); - let gate = builder.add_gate(gate_type, vec![], vec![]); + let gate = builder.add_gate(gate_type, vec![]); let swap_wire = PoseidonGate::::WIRE_SWAP; let swap_wire = Target::wire(gate, swap_wire); diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 5c5f66f0..8d91816d 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -206,12 +206,7 @@ impl, const D: usize> CircuitBuilder { } /// Adds a gate to the circuit, and returns its index. - pub fn add_gate>( - &mut self, - gate_type: G, - constants: Vec, - params: Vec, - ) -> usize { + pub fn add_gate>(&mut self, gate_type: G, constants: Vec) -> usize { self.check_gate_compatibility(&gate_type); assert_eq!( gate_type.num_constants(), @@ -232,7 +227,6 @@ impl, const D: usize> CircuitBuilder { self.gate_instances.push(GateInstance { gate_ref, constants, - params, }); index @@ -417,7 +411,7 @@ impl, const D: usize> CircuitBuilder { let res = if let Some(&s) = slot { s } else { - self.add_gate(gate, constants.to_vec(), params.to_vec()); + self.add_gate(gate, constants.to_vec()); (num_gates, 0) }; if res.1 == num_ops - 1 { @@ -523,7 +517,7 @@ impl, const D: usize> CircuitBuilder { } while !self.gate_instances.len().is_power_of_two() { - self.add_gate(NoopGate, vec![], vec![]); + self.add_gate(NoopGate, vec![]); } } @@ -540,7 +534,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(NoopGate, vec![], vec![]); + let gate = self.add_gate(NoopGate, vec![]); for w in 0..num_wires { self.add_simple_generator(RandomValueGenerator { target: Target::Wire(Wire { gate, input: w }), @@ -552,8 +546,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(NoopGate, vec![], vec![]); - let gate_2 = self.add_gate(NoopGate, vec![], vec![]); + 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_simple_generator(RandomValueGenerator { @@ -670,7 +664,7 @@ impl, const D: usize> CircuitBuilder { let num_public_inputs = self.public_inputs.len(); let public_inputs_hash = self.hash_n_to_hash_no_pad::(self.public_inputs.clone()); - let pi_gate = self.add_gate(PublicInputGate, vec![], vec![]); + let pi_gate = self.add_gate(PublicInputGate, vec![]); for (&hash_part, wire) in public_inputs_hash .elements .iter() diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 27cfd2bb..145ef694 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -411,7 +411,7 @@ mod tests { let comp_zt = builder.mul(xt, yt); builder.connect(zt, comp_zt); for _ in 0..100 { - builder.add_gate(NoopGate, vec![], vec![]); + builder.add_gate(NoopGate, vec![]); } let data = builder.build::(); let proof = data.prove(pw)?; diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index f5fbd2ac..6210bb29 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -330,7 +330,7 @@ mod tests { { let mut builder = CircuitBuilder::::new(config.clone()); for _ in 0..num_dummy_gates { - builder.add_gate(NoopGate, vec![], vec![]); + builder.add_gate(NoopGate, vec![]); } let data = builder.build::(); @@ -388,7 +388,7 @@ mod tests { // builder will pad to the next power of two, 2^min_degree_bits. let min_gates = (1 << (min_degree_bits - 1)) + 1; for _ in builder.num_gates()..min_gates { - builder.add_gate(NoopGate, vec![], vec![]); + builder.add_gate(NoopGate, vec![]); } } diff --git a/plonky2/src/util/reducing.rs b/plonky2/src/util/reducing.rs index 5edd8e1e..f29c6d08 100644 --- a/plonky2/src/util/reducing.rs +++ b/plonky2/src/util/reducing.rs @@ -132,7 +132,7 @@ impl ReducingFactorTarget { reversed_terms.reverse(); for chunk in reversed_terms.chunks_exact(max_coeffs_len) { let gate = ReducingGate::new(max_coeffs_len); - let gate_index = builder.add_gate(gate.clone(), vec![], vec![]); + let gate_index = builder.add_gate(gate.clone(), vec![]); builder.connect_extension( self.base, @@ -182,7 +182,7 @@ impl ReducingFactorTarget { reversed_terms.reverse(); for chunk in reversed_terms.chunks_exact(max_coeffs_len) { let gate = ReducingExtensionGate::new(max_coeffs_len); - let gate_index = builder.add_gate(gate.clone(), vec![], vec![]); + let gate_index = builder.add_gate(gate.clone(), vec![]); builder.connect_extension( self.base, diff --git a/waksman/src/sorting.rs b/waksman/src/sorting.rs index 775df9c5..286205b1 100644 --- a/waksman/src/sorting.rs +++ b/waksman/src/sorting.rs @@ -54,7 +54,7 @@ pub fn assert_le, const D: usize>( num_chunks: usize, ) { let gate = AssertLessThanGate::new(bits, num_chunks); - let gate_index = builder.add_gate(gate.clone(), vec![], vec![]); + let gate_index = builder.add_gate(gate.clone(), vec![]); builder.connect(Target::wire(gate_index, gate.wire_first_input()), lhs); builder.connect(Target::wire(gate_index, gate.wire_second_input()), rhs); From f8dfc3986b3ad7bc6f3ffb6701a5384d9fe1f427 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 16 Feb 2022 09:26:16 +0100 Subject: [PATCH 14/14] PR feedback --- plonky2/src/gates/gate.rs | 6 +++++- plonky2/src/plonk/circuit_builder.rs | 30 ++++++++++------------------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 132cdd00..03bd0a7b 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -124,6 +124,8 @@ pub trait Gate, const D: usize>: 'static + Send + S } } + /// The generators used to populate the witness. + /// Note: This should return exactly 1 generator per operation in the gate. fn generators( &self, gate_index: usize, @@ -179,7 +181,9 @@ impl, const D: usize> Debug for GateRef { } /// Map between gate parameters and available slots. -#[derive(Clone, Debug)] +/// An available slot is of the form `(gate_index, op)`, meaning the current available slot +/// is at gate index `gate_index` in the `op`-th operation. +#[derive(Clone, Debug, Default)] pub struct CurrentSlot, const D: usize> { pub current_slot: HashMap, (usize, usize)>, } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 8d91816d..9b01b144 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -391,7 +391,9 @@ impl, const D: usize> CircuitBuilder { }) } - /// Find an available slot, of the form `(gate_index, op)` for gate `G`. + /// Find an available slot, of the form `(gate_index, op)` for gate `G` using parameters `params` + /// and constants `constants`. Parameters are any data used to differentiate which gate should be + /// used for the given operation. pub fn find_slot + Clone>( &mut self, gate: G, @@ -401,36 +403,24 @@ impl, const D: usize> CircuitBuilder { let num_gates = self.num_gates(); let num_ops = gate.num_ops(); let gate_ref = GateRef::new(gate.clone()); - let gate_slot = self - .current_slots - .entry(gate_ref.clone()) - .or_insert(CurrentSlot { - current_slot: HashMap::new(), - }); + let gate_slot = self.current_slots.entry(gate_ref.clone()).or_default(); let slot = gate_slot.current_slot.get(params); - let res = if let Some(&s) = slot { + let (gate_idx, slot_idx) = if let Some(&s) = slot { s } else { self.add_gate(gate, constants.to_vec()); (num_gates, 0) }; - if res.1 == num_ops - 1 { + let current_slot = &mut self.current_slots.get_mut(&gate_ref).unwrap().current_slot; + if slot_idx == num_ops - 1 { // We've filled up the slots at this index. - self.current_slots - .get_mut(&gate_ref) - .unwrap() - .current_slot - .remove(params); + current_slot.remove(params); } else { // Increment the slot operation index. - self.current_slots - .get_mut(&gate_ref) - .unwrap() - .current_slot - .insert(params.to_vec(), (res.0, res.1 + 1)); + current_slot.insert(params.to_vec(), (gate_idx, slot_idx + 1)); } - res + (gate_idx, slot_idx) } fn fri_params(&self, degree_bits: usize) -> FriParams {