From e2de88d145148a0d6fb9f7b88a01d56459874097 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 31 Mar 2022 08:29:05 +0200 Subject: [PATCH 1/6] Add constants to the RAM gate --- plonky2/src/fri/recursive_verifier.rs | 2 +- plonky2/src/gates/constant.rs | 4 +-- plonky2/src/gates/random_access.rs | 49 ++++++++++++++++++++++----- plonky2/src/plonk/circuit_builder.rs | 9 +---- plonky2/src/plonk/circuit_data.rs | 4 +-- 5 files changed, 46 insertions(+), 22 deletions(-) diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 9b619ea8..5b273ea3 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -86,7 +86,7 @@ impl, const D: usize> CircuitBuilder { let min_wires = random_access.num_wires().max(interpolation_wires); let min_routed_wires = random_access - .num_routed_wires() + .num_ram_wires() .max(interpolation_routed_wires); assert!( diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index 990a4df8..d36a5f4c 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -159,7 +159,7 @@ mod tests { #[test] fn low_degree() { - let num_consts = CircuitConfig::standard_recursion_config().constant_gate_size; + let num_consts = CircuitConfig::standard_recursion_config().num_constants; let gate = ConstantGate { num_consts }; test_low_degree::(gate) } @@ -169,7 +169,7 @@ mod tests { const D: usize = 2; type C = PoseidonGoldilocksConfig; type F = >::F; - let num_consts = CircuitConfig::standard_recursion_config().constant_gate_size; + let num_consts = CircuitConfig::standard_recursion_config().num_constants; let gate = ConstantGate { num_consts }; test_eval_fns::(gate) } diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 6379f99f..2e6cf2f3 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -26,14 +26,16 @@ use crate::plonk::vars::{ pub(crate) struct RandomAccessGate, const D: usize> { pub bits: usize, pub num_copies: usize, + pub num_extra_constants: usize, _phantom: PhantomData, } impl, const D: usize> RandomAccessGate { - fn new(num_copies: usize, bits: usize) -> Self { + fn new(num_copies: usize, bits: usize, num_extra_constants: usize) -> Self { Self { bits, num_copies, + num_extra_constants, _phantom: PhantomData, } } @@ -45,7 +47,7 @@ impl, const D: usize> RandomAccessGate { // Need `(2 + vec_size + bits) * num_copies` wires config.num_wires / (2 + vec_size + bits), ); - Self::new(max_copies, bits) + Self::new(max_copies, bits, config.num_constants) } fn vec_size(&self) -> usize { @@ -68,12 +70,17 @@ impl, const D: usize> RandomAccessGate { (2 + self.vec_size()) * copy + 2 + i } - fn start_of_intermediate_wires(&self) -> usize { + pub(crate) fn num_ram_wires(&self) -> usize { (2 + self.vec_size()) * self.num_copies } - pub(crate) fn num_routed_wires(&self) -> usize { - self.start_of_intermediate_wires() + fn wire_extra_constant(&self, i: usize) -> usize { + debug_assert!(i < self.num_extra_constants); + self.num_ram_wires() + i + } + + fn num_routed_wires(&self) -> usize { + self.num_ram_wires() + self.num_extra_constants } /// An intermediate wire where the prover gives the (purported) binary decomposition of the @@ -81,7 +88,7 @@ impl, const D: usize> RandomAccessGate { pub fn wire_bit(&self, i: usize, copy: usize) -> usize { debug_assert!(i < self.bits); debug_assert!(copy < self.num_copies); - self.start_of_intermediate_wires() + copy * self.bits + i + self.num_routed_wires() + copy * self.bits + i } } @@ -129,6 +136,11 @@ impl, const D: usize> Gate for RandomAccessGa constraints.push(list_items[0] - claimed_element); } + constraints.extend( + (0..self.num_extra_constants) + .map(|i| vars.local_constants[i] - vars.local_wires[self.wire_extra_constant(i)]), + ); + constraints } @@ -189,14 +201,22 @@ impl, const D: usize> Gate for RandomAccessGa constraints.push(builder.sub_extension(list_items[0], claimed_element)); } + constraints.extend((0..self.num_extra_constants).map(|i| { + builder.sub_extension( + vars.local_constants[i], + vars.local_wires[self.wire_extra_constant(i)], + ) + })); + constraints } fn generators( &self, gate_index: usize, - _local_constants: &[F], + local_constants: &[F], ) -> Vec>> { + let constants = local_constants[..self.num_extra_constants].to_vec(); (0..self.num_copies) .map(|copy| { let g: Box> = Box::new( @@ -204,6 +224,7 @@ impl, const D: usize> Gate for RandomAccessGa gate_index, gate: *self, copy, + constants: constants.to_vec(), } .adapter(), ); @@ -270,6 +291,10 @@ impl, const D: usize> PackedEvaluableBase debug_assert_eq!(list_items.len(), 1); yield_constr.one(list_items[0] - claimed_element); } + yield_constr.many( + (0..self.num_extra_constants) + .map(|i| vars.local_constants[i] - vars.local_wires[self.wire_extra_constant(i)]), + ); } } @@ -278,6 +303,7 @@ struct RandomAccessGenerator, const D: usize> { gate_index: usize, gate: RandomAccessGate, copy: usize, + constants: Vec, } impl, const D: usize> SimpleGenerator @@ -323,6 +349,10 @@ impl, const D: usize> SimpleGenerator let bit = F::from_bool(((access_index >> i) & 1) != 0); set_local_wire(self.gate.wire_bit(i, copy), bit); } + + for (i, &c) in self.constants.iter().enumerate() { + set_local_wire(self.gate.wire_extra_constant(i), c); + } } } @@ -344,7 +374,7 @@ mod tests { #[test] fn low_degree() { - test_low_degree::(RandomAccessGate::new(4, 4)); + test_low_degree::(RandomAccessGate::new(4, 4, 1)); } #[test] @@ -352,7 +382,7 @@ mod tests { const D: usize = 2; type C = PoseidonGoldilocksConfig; type F = >::F; - test_eval_fns::(RandomAccessGate::new(4, 4)) + test_eval_fns::(RandomAccessGate::new(4, 4, 1)) } #[test] @@ -404,6 +434,7 @@ mod tests { let gate = RandomAccessGate:: { bits, num_copies, + num_extra_constants: 1, _phantom: PhantomData, }; diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 022e2b12..f2d22e6b 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -321,14 +321,7 @@ impl, const D: usize> CircuitBuilder { return target; } - 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; - + let target = self.add_virtual_target(); self.constants_to_targets.insert(c, target); self.targets_to_constants.insert(target, c); diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 8c33ae98..eb5ef95f 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -33,7 +33,7 @@ use crate::util::timing::TimingTree; pub struct CircuitConfig { pub num_wires: usize, pub num_routed_wires: usize, - pub constant_gate_size: usize, + pub num_constants: usize, /// Whether to use a dedicated gate for base field arithmetic, rather than using a single gate /// for both base field and extension field arithmetic. pub use_base_arithmetic_gate: bool, @@ -64,7 +64,7 @@ impl CircuitConfig { Self { num_wires: 135, num_routed_wires: 80, - constant_gate_size: 5, + num_constants: 5, use_base_arithmetic_gate: true, security_bits: 100, num_challenges: 2, From f81e32f8b4619f8822fef2c6b92a05122d5ff70a Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 31 Mar 2022 14:04:38 +0200 Subject: [PATCH 2/6] semi-working --- plonky2/src/fri/recursive_verifier.rs | 2 +- plonky2/src/gates/constant.rs | 8 ++++ plonky2/src/gates/gate.rs | 4 ++ plonky2/src/gates/random_access.rs | 61 ++++++++++++++++++++++----- plonky2/src/plonk/circuit_builder.rs | 53 ++++++++++++++++++++--- plonky2/src/plonk/circuit_data.rs | 2 +- 6 files changed, 112 insertions(+), 18 deletions(-) diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 5b273ea3..9b619ea8 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -86,7 +86,7 @@ impl, const D: usize> CircuitBuilder { let min_wires = random_access.num_wires().max(interpolation_wires); let min_routed_wires = random_access - .num_ram_wires() + .num_routed_wires() .max(interpolation_routed_wires); assert!( diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index d36a5f4c..3f69ceb1 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -1,3 +1,5 @@ +use std::ops::Range; + use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; @@ -111,6 +113,12 @@ impl, const D: usize> Gate for ConstantGate { fn num_constraints(&self) -> usize { self.num_consts } + + fn extra_constants(&self) -> Vec<(usize, usize)> { + (0..self.num_consts) + .map(|i| (self.const_input(i), self.wire_output(i))) + .collect() + } } impl, const D: usize> PackedEvaluableBase for ConstantGate { diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index e95ec0f8..9d1e4874 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -180,6 +180,10 @@ pub trait Gate, const D: usize>: 'static + Send + S self.generators(0, &vec![F::ZERO; self.num_constants()]) .len() } + + fn extra_constants(&self) -> Vec<(usize, usize)> { + vec![] + } } /// A wrapper around an `Rc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 2e6cf2f3..33d76a54 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -1,4 +1,5 @@ use std::marker::PhantomData; +use std::ops::Range; use itertools::Itertools; use plonky2_field::extension_field::Extendable; @@ -20,6 +21,7 @@ use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; +use crate::with_context; /// A gate for checking that a particular element of a list matches a given value. #[derive(Copy, Clone, Debug)] @@ -70,7 +72,7 @@ impl, const D: usize> RandomAccessGate { (2 + self.vec_size()) * copy + 2 + i } - pub(crate) fn num_ram_wires(&self) -> usize { + fn num_ram_wires(&self) -> usize { (2 + self.vec_size()) * self.num_copies } @@ -79,7 +81,7 @@ impl, const D: usize> RandomAccessGate { self.num_ram_wires() + i } - fn num_routed_wires(&self) -> usize { + pub fn num_routed_wires(&self) -> usize { self.num_ram_wires() + self.num_extra_constants } @@ -216,7 +218,6 @@ impl, const D: usize> Gate for RandomAccessGa gate_index: usize, local_constants: &[F], ) -> Vec>> { - let constants = local_constants[..self.num_extra_constants].to_vec(); (0..self.num_copies) .map(|copy| { let g: Box> = Box::new( @@ -224,12 +225,23 @@ impl, const D: usize> Gate for RandomAccessGa gate_index, gate: *self, copy, - constants: constants.to_vec(), } .adapter(), ); g }) + .chain((0..self.num_extra_constants).map(|i| { + let g: Box> = Box::new( + RandomAccessExtraConstantsGenerator { + gate_index, + gate: *self, + i, + constant: local_constants[i], + } + .adapter(), + ); + g + })) .collect() } @@ -238,7 +250,7 @@ impl, const D: usize> Gate for RandomAccessGa } fn num_constants(&self) -> usize { - 0 + self.num_extra_constants } fn degree(&self) -> usize { @@ -247,7 +259,17 @@ impl, const D: usize> Gate for RandomAccessGa fn num_constraints(&self) -> usize { let constraints_per_copy = self.bits + 2; - self.num_copies * constraints_per_copy + self.num_copies * constraints_per_copy + self.num_extra_constants + } + + fn num_ops(&self) -> usize { + self.num_copies + } + + fn extra_constants(&self) -> Vec<(usize, usize)> { + (0..self.num_extra_constants) + .map(|i| (i, self.wire_extra_constant(i))) + .collect() } } @@ -303,7 +325,6 @@ struct RandomAccessGenerator, const D: usize> { gate_index: usize, gate: RandomAccessGate, copy: usize, - constants: Vec, } impl, const D: usize> SimpleGenerator @@ -349,10 +370,30 @@ impl, const D: usize> SimpleGenerator let bit = F::from_bool(((access_index >> i) & 1) != 0); set_local_wire(self.gate.wire_bit(i, copy), bit); } + } +} - for (i, &c) in self.constants.iter().enumerate() { - set_local_wire(self.gate.wire_extra_constant(i), c); - } +#[derive(Debug)] +struct RandomAccessExtraConstantsGenerator, const D: usize> { + gate_index: usize, + gate: RandomAccessGate, + i: usize, + constant: F, +} + +impl, const D: usize> SimpleGenerator + for RandomAccessExtraConstantsGenerator +{ + fn dependencies(&self) -> Vec { + Vec::new() + } + + fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { + let wire = Wire { + gate: self.gate_index, + input: self.gate.wire_extra_constant(self.i), + }; + out_buffer.set_wire(wire, self.constant); } } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index f2d22e6b..218a836e 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -2,6 +2,7 @@ use std::cmp::max; use std::collections::{BTreeMap, HashMap, HashSet}; use std::time::Instant; +use itertools::{EitherOrBoth, Itertools}; use log::{debug, info, Level}; use plonky2_field::cosets::get_unique_coset_shifts; use plonky2_field::extension_field::{Extendable, FieldExtension}; @@ -83,6 +84,9 @@ pub struct CircuitBuilder, const D: usize> { /// Map between gate type and the current gate of this type with available slots. current_slots: HashMap, CurrentSlot>, + + /// gate_index, constant_index, target_index + constants_slots: Vec<(usize, usize, usize)>, } impl, const D: usize> CircuitBuilder { @@ -102,6 +106,7 @@ impl, const D: usize> CircuitBuilder { arithmetic_results: HashMap::new(), targets_to_constants: HashMap::new(), current_slots: HashMap::new(), + constants_slots: Vec::new(), }; builder.check_config(); builder @@ -206,16 +211,23 @@ 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, mut constants: Vec) -> usize { self.check_gate_compatibility(&gate_type); - assert_eq!( - gate_type.num_constants(), - constants.len(), - "Number of constants doesn't match." - ); + // assert_eq!( + // gate_type.num_constants(), + // constants.len(), + // "Number of constants doesn't match." + // ); + + assert!(constants.len() <= gate_type.num_constants()); + constants.resize(gate_type.num_constants(), F::ZERO); let index = self.gate_instances.len(); + for (ci, ti) in gate_type.extra_constants() { + self.constants_slots.push((index, ci, ti)); + } + // Note that we can't immediately add this gate's generators, because the list of constants // could be modified later, i.e. in the case of `ConstantGate`. We will add them later in // `build` instead. @@ -240,6 +252,13 @@ impl, const D: usize> CircuitBuilder { gate.num_wires(), self.config.num_wires ); + assert!( + gate.num_constants() <= self.config.num_constants, + "{:?} requires {} constants, but our CircuitConfig has only {}", + gate.id(), + gate.num_constants(), + self.config.num_constants + ); } pub fn connect_extension(&mut self, src: ExtensionTarget, dst: ExtensionTarget) { @@ -643,6 +662,28 @@ impl, const D: usize> CircuitBuilder { self.connect(hash_part, Target::wire(pi_gate, wire)) } + // Fill constants + while self.constants_to_targets.len() > self.constants_slots.len() { + dbg!("lfg"); + self.add_gate( + ConstantGate { + num_consts: self.config.num_constants, + }, + vec![], + ); + } + dbg!(self.constants_to_targets.len(), self.constants_slots.len()); + + for ((c, t), (gate_index, const_wire, target_wire)) in self + .constants_to_targets + .clone() + .into_iter() + .zip(self.constants_slots.clone()) + { + self.gate_instances[gate_index].constants[const_wire] = c; + self.generate_copy(Target::wire(gate_index, target_wire), t); + } + info!( "Degree before blinding & padding: {}", self.gate_instances.len() diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index eb5ef95f..8e603625 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -64,7 +64,7 @@ impl CircuitConfig { Self { num_wires: 135, num_routed_wires: 80, - num_constants: 5, + num_constants: 2, use_base_arithmetic_gate: true, security_bits: 100, num_challenges: 2, From fae471f9d881b5ae0389f2296d1cfe078f3db56a Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 31 Mar 2022 15:33:31 +0200 Subject: [PATCH 3/6] Working --- plonky2/src/gates/constant.rs | 84 ++++++++++++++++------------ plonky2/src/gates/gate.rs | 4 +- plonky2/src/gates/random_access.rs | 48 ++++++++++------ plonky2/src/iop/generator.rs | 36 ++++++++++++ plonky2/src/plonk/circuit_builder.rs | 26 +++++---- 5 files changed, 131 insertions(+), 67 deletions(-) diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index 3f69ceb1..a4bc9731 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -9,7 +9,9 @@ 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::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{ + ConstantGenerator, GeneratedValues, SimpleGenerator, WitnessGenerator, +}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::PartitionWitness; @@ -82,20 +84,21 @@ impl, const D: usize> Gate for ConstantGate { gate_index: usize, local_constants: &[F], ) -> Vec>> { - (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() + // (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() + vec![] } fn num_wires(&self) -> usize { @@ -114,9 +117,16 @@ impl, const D: usize> Gate for ConstantGate { self.num_consts } - fn extra_constants(&self) -> Vec<(usize, usize)> { + fn extra_constants(&self, gate_index: usize) -> Vec> { (0..self.num_consts) - .map(|i| (self.const_input(i), self.wire_output(i))) + .map(|i| { + ConstantGenerator::new( + gate_index, + self.const_input(i), + self.wire_output(i), + F::ZERO, + ) + }) .collect() } } @@ -133,27 +143,27 @@ impl, const D: usize> PackedEvaluableBase for } } -#[derive(Debug)] -struct ConstantGenerator { - gate_index: usize, - gate: ConstantGate, - i: usize, - constant: F, -} +// #[derive(Debug)] +// struct ConstantGenerator { +// gate_index: usize, +// gate: ConstantGate, +// i: usize, +// constant: F, +// } -impl SimpleGenerator for ConstantGenerator { - fn dependencies(&self) -> Vec { - Vec::new() - } - - fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { - let wire = Wire { - gate: self.gate_index, - input: self.gate.wire_output(self.i), - }; - out_buffer.set_wire(wire, self.constant); - } -} +// impl SimpleGenerator for ConstantGenerator { +// fn dependencies(&self) -> Vec { +// Vec::new() +// } +// +// fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { +// let wire = Wire { +// gate: self.gate_index, +// input: self.gate.wire_output(self.i), +// }; +// out_buffer.set_wire(wire, self.constant); +// } +// } #[cfg(test)] mod tests { diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 9d1e4874..d41a1721 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -12,7 +12,7 @@ use crate::gates::selectors::UNUSED_SELECTOR; 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::generator::{ConstantGenerator, WitnessGenerator}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, @@ -181,7 +181,7 @@ pub trait Gate, const D: usize>: 'static + Send + S .len() } - fn extra_constants(&self) -> Vec<(usize, usize)> { + fn extra_constants(&self, _gate_index: usize) -> Vec> { vec![] } } diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 33d76a54..687e5e53 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -11,7 +11,9 @@ 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::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{ + ConstantGenerator, GeneratedValues, SimpleGenerator, WitnessGenerator, +}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness}; @@ -230,18 +232,18 @@ impl, const D: usize> Gate for RandomAccessGa ); g }) - .chain((0..self.num_extra_constants).map(|i| { - let g: Box> = Box::new( - RandomAccessExtraConstantsGenerator { - gate_index, - gate: *self, - i, - constant: local_constants[i], - } - .adapter(), - ); - g - })) + // .chain((0..self.num_extra_constants).map(|i| { + // let g: Box> = Box::new( + // RandomAccessExtraConstantsGenerator { + // gate_index, + // gate: *self, + // i, + // constant: local_constants[i], + // } + // .adapter(), + // ); + // g + // })) .collect() } @@ -266,9 +268,9 @@ impl, const D: usize> Gate for RandomAccessGa self.num_copies } - fn extra_constants(&self) -> Vec<(usize, usize)> { + fn extra_constants(&self, gate_index: usize) -> Vec> { (0..self.num_extra_constants) - .map(|i| (i, self.wire_extra_constant(i))) + .map(|i| ConstantGenerator::new(gate_index, i, self.wire_extra_constant(i), F::ZERO)) .collect() } } @@ -440,6 +442,7 @@ mod tests { lists: Vec>, access_indices: Vec, claimed_elements: Vec, + constants: &[F], ) -> Vec { let num_copies = lists.len(); let vec_size = lists[0].len(); @@ -458,6 +461,7 @@ mod tests { bit_vals.push(F::from_bool(((access_index >> i) & 1) != 0)); } } + v.extend(constants); v.extend(bit_vals); v.iter().map(|&x| x.into()).collect() @@ -478,6 +482,7 @@ mod tests { num_extra_constants: 1, _phantom: PhantomData, }; + let constants = F::rand_vec(gate.num_constants()); let good_claimed_elements = lists .iter() @@ -485,19 +490,26 @@ mod tests { .map(|(l, &i)| l[i]) .collect(); let good_vars = EvaluationVars { - local_constants: &[], + local_constants: &constants.iter().map(|&x| x.into()).collect::>(), local_wires: &get_wires( bits, lists.clone(), access_indices.clone(), good_claimed_elements, + &constants, ), public_inputs_hash: &HashOut::rand(), }; let bad_claimed_elements = F::rand_vec(4); let bad_vars = EvaluationVars { - local_constants: &[], - local_wires: &get_wires(bits, lists, access_indices, bad_claimed_elements), + local_constants: &constants.iter().map(|&x| x.into()).collect::>(), + local_wires: &get_wires( + bits, + lists, + access_indices, + bad_claimed_elements, + &constants, + ), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index 1569e889..f38fc65c 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -8,6 +8,7 @@ use plonky2_field::field_types::{Field, PrimeField}; use crate::gadgets::arithmetic_u32::U32Target; use crate::gadgets::biguint::BigUintTarget; use crate::gadgets::nonnative::NonNativeTarget; +use crate::gates::gate::Gate; use crate::hash::hash_types::{HashOut, HashOutTarget, RichField}; use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::{BoolTarget, Target}; @@ -325,3 +326,38 @@ impl SimpleGenerator for NonzeroTestGenerator { out_buffer.set_target(self.dummy, dummy_value); } } + +#[derive(Debug, Clone)] +pub struct ConstantGenerator { + pub gate_index: usize, + pub constant_index: usize, + pub target_index: usize, + pub constant: F, +} + +impl ConstantGenerator { + pub fn new(gate_index: usize, constant_index: usize, target_index: usize, constant: F) -> Self { + ConstantGenerator { + gate_index, + constant_index, + target_index, + constant, + } + } + + pub fn set_constant(&mut self, c: F) { + self.constant = c; + } +} +impl SimpleGenerator for ConstantGenerator { + fn dependencies(&self) -> Vec { + vec![] + } + + fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { + out_buffer.set_target( + Target::wire(self.gate_index, self.target_index), + self.constant, + ); + } +} diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 218a836e..45e51aa0 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -28,7 +28,7 @@ use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; use crate::hash::merkle_proofs::MerkleProofTarget; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{ - CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGenerator, + ConstantGenerator, CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGenerator, }; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; @@ -85,8 +85,8 @@ pub struct CircuitBuilder, const D: usize> { /// Map between gate type and the current gate of this type with available slots. current_slots: HashMap, CurrentSlot>, - /// gate_index, constant_index, target_index - constants_slots: Vec<(usize, usize, usize)>, + /// gate_index, constant_index, target_index, ConstantGen + constants_slots: Vec>, } impl, const D: usize> CircuitBuilder { @@ -224,9 +224,11 @@ impl, const D: usize> CircuitBuilder { let index = self.gate_instances.len(); - for (ci, ti) in gate_type.extra_constants() { - self.constants_slots.push((index, ci, ti)); - } + self.constants_slots + .extend(gate_type.extra_constants(index)); + // for const_gen in gate_type.extra_constants() { + // self.constants_slots.push((index, ci, ti, gen)); + // } // Note that we can't immediately add this gate's generators, because the list of constants // could be modified later, i.e. in the case of `ConstantGate`. We will add them later in @@ -664,7 +666,6 @@ impl, const D: usize> CircuitBuilder { // Fill constants while self.constants_to_targets.len() > self.constants_slots.len() { - dbg!("lfg"); self.add_gate( ConstantGate { num_consts: self.config.num_constants, @@ -674,14 +675,19 @@ impl, const D: usize> CircuitBuilder { } dbg!(self.constants_to_targets.len(), self.constants_slots.len()); - for ((c, t), (gate_index, const_wire, target_wire)) in self + for ((c, t), mut const_gen) in self .constants_to_targets .clone() .into_iter() .zip(self.constants_slots.clone()) { - self.gate_instances[gate_index].constants[const_wire] = c; - self.generate_copy(Target::wire(gate_index, target_wire), t); + self.gate_instances[const_gen.gate_index].constants[const_gen.constant_index] = c; + self.generate_copy( + Target::wire(const_gen.gate_index, const_gen.target_index), + t, + ); + const_gen.set_constant(c); + self.add_simple_generator(const_gen); } info!( From d12417c9f178eb0f24e8ae57dc311f475a528a5f Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 31 Mar 2022 16:11:08 +0200 Subject: [PATCH 4/6] Comments + cleaning + fixes --- plonky2/src/gates/constant.rs | 50 ++------------------------- plonky2/src/gates/gate.rs | 1 + plonky2/src/gates/random_access.rs | 51 ++++------------------------ plonky2/src/iop/generator.rs | 2 +- plonky2/src/plonk/circuit_builder.rs | 35 +++++++++---------- 5 files changed, 28 insertions(+), 111 deletions(-) diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index a4bc9731..5e6cb07a 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -1,7 +1,4 @@ -use std::ops::Range; - use plonky2_field::extension_field::Extendable; -use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; use crate::gates::gate::Gate; @@ -9,12 +6,7 @@ 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::{ - ConstantGenerator, GeneratedValues, SimpleGenerator, WitnessGenerator, -}; -use crate::iop::target::Target; -use crate::iop::wire::Wire; -use crate::iop::witness::PartitionWitness; +use crate::iop::generator::{ConstantGenerator, WitnessGenerator}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, @@ -81,23 +73,9 @@ impl, const D: usize> Gate for ConstantGate { fn generators( &self, - gate_index: usize, - local_constants: &[F], + _gate_index: usize, + _local_constants: &[F], ) -> Vec>> { - // (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() vec![] } @@ -143,28 +121,6 @@ impl, const D: usize> PackedEvaluableBase for } } -// #[derive(Debug)] -// struct ConstantGenerator { -// gate_index: usize, -// gate: ConstantGate, -// i: usize, -// constant: F, -// } - -// impl SimpleGenerator for ConstantGenerator { -// fn dependencies(&self) -> Vec { -// Vec::new() -// } -// -// fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { -// let wire = Wire { -// gate: self.gate_index, -// input: self.gate.wire_output(self.i), -// }; -// out_buffer.set_wire(wire, self.constant); -// } -// } - #[cfg(test)] mod tests { use anyhow::Result; diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index d41a1721..969e3abd 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -181,6 +181,7 @@ pub trait Gate, const D: usize>: 'static + Send + S .len() } + /// Extra constants (i.e. constants that are not used in the gate's core functionality) generated by the gate. fn extra_constants(&self, _gate_index: usize) -> Vec> { vec![] } diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 687e5e53..384d2ee9 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -1,5 +1,4 @@ use std::marker::PhantomData; -use std::ops::Range; use itertools::Itertools; use plonky2_field::extension_field::Extendable; @@ -23,7 +22,6 @@ use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; -use crate::with_context; /// A gate for checking that a particular element of a list matches a given value. #[derive(Copy, Clone, Debug)] @@ -51,7 +49,12 @@ impl, const D: usize> RandomAccessGate { // Need `(2 + vec_size + bits) * num_copies` wires config.num_wires / (2 + vec_size + bits), ); - Self::new(max_copies, bits, config.num_constants) + let max_extra_constants = config.num_routed_wires - (2 + vec_size) * max_copies; + Self::new( + max_copies, + bits, + max_extra_constants.min(config.num_constants), + ) } fn vec_size(&self) -> usize { @@ -218,7 +221,7 @@ impl, const D: usize> Gate for RandomAccessGa fn generators( &self, gate_index: usize, - local_constants: &[F], + _local_constants: &[F], ) -> Vec>> { (0..self.num_copies) .map(|copy| { @@ -232,18 +235,6 @@ impl, const D: usize> Gate for RandomAccessGa ); g }) - // .chain((0..self.num_extra_constants).map(|i| { - // let g: Box> = Box::new( - // RandomAccessExtraConstantsGenerator { - // gate_index, - // gate: *self, - // i, - // constant: local_constants[i], - // } - // .adapter(), - // ); - // g - // })) .collect() } @@ -264,10 +255,6 @@ impl, const D: usize> Gate for RandomAccessGa self.num_copies * constraints_per_copy + self.num_extra_constants } - fn num_ops(&self) -> usize { - self.num_copies - } - fn extra_constants(&self, gate_index: usize) -> Vec> { (0..self.num_extra_constants) .map(|i| ConstantGenerator::new(gate_index, i, self.wire_extra_constant(i), F::ZERO)) @@ -375,30 +362,6 @@ impl, const D: usize> SimpleGenerator } } -#[derive(Debug)] -struct RandomAccessExtraConstantsGenerator, const D: usize> { - gate_index: usize, - gate: RandomAccessGate, - i: usize, - constant: F, -} - -impl, const D: usize> SimpleGenerator - for RandomAccessExtraConstantsGenerator -{ - fn dependencies(&self) -> Vec { - Vec::new() - } - - fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { - let wire = Wire { - gate: self.gate_index, - input: self.gate.wire_extra_constant(self.i), - }; - out_buffer.set_wire(wire, self.constant); - } -} - #[cfg(test)] mod tests { use std::marker::PhantomData; diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index f38fc65c..aab33d1b 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -8,7 +8,6 @@ use plonky2_field::field_types::{Field, PrimeField}; use crate::gadgets::arithmetic_u32::U32Target; use crate::gadgets::biguint::BigUintTarget; use crate::gadgets::nonnative::NonNativeTarget; -use crate::gates::gate::Gate; use crate::hash::hash_types::{HashOut, HashOutTarget, RichField}; use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::{BoolTarget, Target}; @@ -327,6 +326,7 @@ impl SimpleGenerator for NonzeroTestGenerator { } } +/// Generator used fill an extra constant. #[derive(Debug, Clone)] pub struct ConstantGenerator { pub gate_index: usize, diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 45e51aa0..79e2eb2f 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -2,7 +2,6 @@ use std::cmp::max; use std::collections::{BTreeMap, HashMap, HashSet}; use std::time::Instant; -use itertools::{EitherOrBoth, Itertools}; use log::{debug, info, Level}; use plonky2_field::cosets::get_unique_coset_shifts; use plonky2_field::extension_field::{Extendable, FieldExtension}; @@ -85,8 +84,8 @@ pub struct CircuitBuilder, const D: usize> { /// Map between gate type and the current gate of this type with available slots. current_slots: HashMap, CurrentSlot>, - /// gate_index, constant_index, target_index, ConstantGen - constants_slots: Vec>, + /// List of constant generators used to fill the constant wires. + constant_generators: Vec>, } impl, const D: usize> CircuitBuilder { @@ -106,7 +105,7 @@ impl, const D: usize> CircuitBuilder { arithmetic_results: HashMap::new(), targets_to_constants: HashMap::new(), current_slots: HashMap::new(), - constants_slots: Vec::new(), + constant_generators: Vec::new(), }; builder.check_config(); builder @@ -213,22 +212,17 @@ impl, const D: usize> CircuitBuilder { /// Adds a gate to the circuit, and returns its index. pub fn add_gate>(&mut self, gate_type: G, mut constants: Vec) -> usize { self.check_gate_compatibility(&gate_type); - // assert_eq!( - // gate_type.num_constants(), - // constants.len(), - // "Number of constants doesn't match." - // ); - assert!(constants.len() <= gate_type.num_constants()); + assert!( + constants.len() <= gate_type.num_constants(), + "Too many constants." + ); constants.resize(gate_type.num_constants(), F::ZERO); let index = self.gate_instances.len(); - self.constants_slots + self.constant_generators .extend(gate_type.extra_constants(index)); - // for const_gen in gate_type.extra_constants() { - // self.constants_slots.push((index, ci, ti, gen)); - // } // Note that we can't immediately add this gate's generators, because the list of constants // could be modified later, i.e. in the case of `ConstantGate`. We will add them later in @@ -664,8 +658,8 @@ impl, const D: usize> CircuitBuilder { self.connect(hash_part, Target::wire(pi_gate, wire)) } - // Fill constants - while self.constants_to_targets.len() > self.constants_slots.len() { + // Make sure we have enough constant generators. If not, add a `ConstantGate`. + while self.constants_to_targets.len() > self.constant_generators.len() { self.add_gate( ConstantGate { num_consts: self.config.num_constants, @@ -673,19 +667,22 @@ impl, const D: usize> CircuitBuilder { vec![], ); } - dbg!(self.constants_to_targets.len(), self.constants_slots.len()); + // For each constant-target pair used in the circuit, use a constant generator to fill this target. for ((c, t), mut const_gen) in self .constants_to_targets .clone() .into_iter() - .zip(self.constants_slots.clone()) + .zip(self.constant_generators.clone()) { + // Set the constant in the constant polynomial. self.gate_instances[const_gen.gate_index].constants[const_gen.constant_index] = c; - self.generate_copy( + // Generate a copy between the target and the routable wire. + self.connect( Target::wire(const_gen.gate_index, const_gen.target_index), t, ); + // Set the constant in the generator (it's initially set with a dummy value). const_gen.set_constant(c); self.add_simple_generator(const_gen); } From cc95cb5ee1a256e1d9261818056f65ea6ac0d0cf Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 31 Mar 2022 16:15:27 +0200 Subject: [PATCH 5/6] Typo --- plonky2/src/iop/generator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index aab33d1b..49f74e33 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -326,7 +326,7 @@ impl SimpleGenerator for NonzeroTestGenerator { } } -/// Generator used fill an extra constant. +/// Generator used to fill an extra constant. #[derive(Debug, Clone)] pub struct ConstantGenerator { pub gate_index: usize, From 8faf644f87411631d71c7c1e4c0d6f181630c655 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Mon, 4 Apr 2022 14:33:54 -0700 Subject: [PATCH 6/6] Change gate method for extra constants (#528) * Change gate method for extra constants * Rename * feedback --- plonky2/src/gates/constant.rs | 13 +++---------- plonky2/src/gates/gate.rs | 10 +++++++--- plonky2/src/gates/random_access.rs | 14 ++++++-------- plonky2/src/iop/generator.rs | 16 ++++------------ plonky2/src/plonk/circuit_builder.rs | 18 +++++++++++------- 5 files changed, 31 insertions(+), 40 deletions(-) diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index 5e6cb07a..3ca39d43 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -6,7 +6,7 @@ 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::{ConstantGenerator, WitnessGenerator}; +use crate::iop::generator::WitnessGenerator; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, @@ -95,16 +95,9 @@ impl, const D: usize> Gate for ConstantGate { self.num_consts } - fn extra_constants(&self, gate_index: usize) -> Vec> { + fn extra_constant_wires(&self) -> Vec<(usize, usize)> { (0..self.num_consts) - .map(|i| { - ConstantGenerator::new( - gate_index, - self.const_input(i), - self.wire_output(i), - F::ZERO, - ) - }) + .map(|i| (self.const_input(i), self.wire_output(i))) .collect() } } diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 969e3abd..861b67c0 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -12,7 +12,7 @@ use crate::gates::selectors::UNUSED_SELECTOR; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{ConstantGenerator, WitnessGenerator}; +use crate::iop::generator::WitnessGenerator; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, @@ -181,8 +181,12 @@ pub trait Gate, const D: usize>: 'static + Send + S .len() } - /// Extra constants (i.e. constants that are not used in the gate's core functionality) generated by the gate. - fn extra_constants(&self, _gate_index: usize) -> Vec> { + /// Enables gates to store some "routed constants", if they have both unused constants and + /// unused routed wires. + /// + /// Each entry in the returned `Vec` has the form `(constant_index, wire_index)`. `wire_index` + /// must correspond to a *routed* wire. + fn extra_constant_wires(&self) -> Vec<(usize, usize)> { vec![] } } diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 384d2ee9..5b4935d9 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -10,9 +10,7 @@ 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::{ - ConstantGenerator, GeneratedValues, SimpleGenerator, WitnessGenerator, -}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness}; @@ -77,17 +75,17 @@ impl, const D: usize> RandomAccessGate { (2 + self.vec_size()) * copy + 2 + i } - fn num_ram_wires(&self) -> usize { + fn start_extra_constants(&self) -> usize { (2 + self.vec_size()) * self.num_copies } fn wire_extra_constant(&self, i: usize) -> usize { debug_assert!(i < self.num_extra_constants); - self.num_ram_wires() + i + self.start_extra_constants() + i } pub fn num_routed_wires(&self) -> usize { - self.num_ram_wires() + self.num_extra_constants + self.start_extra_constants() + self.num_extra_constants } /// An intermediate wire where the prover gives the (purported) binary decomposition of the @@ -255,9 +253,9 @@ impl, const D: usize> Gate for RandomAccessGa self.num_copies * constraints_per_copy + self.num_extra_constants } - fn extra_constants(&self, gate_index: usize) -> Vec> { + fn extra_constant_wires(&self) -> Vec<(usize, usize)> { (0..self.num_extra_constants) - .map(|i| ConstantGenerator::new(gate_index, i, self.wire_extra_constant(i), F::ZERO)) + .map(|i| (i, self.wire_extra_constant(i))) .collect() } } diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index 49f74e33..5b612d91 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -328,27 +328,19 @@ impl SimpleGenerator for NonzeroTestGenerator { /// Generator used to fill an extra constant. #[derive(Debug, Clone)] -pub struct ConstantGenerator { +pub(crate) struct ConstantGenerator { pub gate_index: usize, pub constant_index: usize, - pub target_index: usize, + pub wire_index: usize, pub constant: F, } impl ConstantGenerator { - pub fn new(gate_index: usize, constant_index: usize, target_index: usize, constant: F) -> Self { - ConstantGenerator { - gate_index, - constant_index, - target_index, - constant, - } - } - pub fn set_constant(&mut self, c: F) { self.constant = c; } } + impl SimpleGenerator for ConstantGenerator { fn dependencies(&self) -> Vec { vec![] @@ -356,7 +348,7 @@ impl SimpleGenerator for ConstantGenerator { fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { out_buffer.set_target( - Target::wire(self.gate_index, self.target_index), + Target::wire(self.gate_index, self.wire_index), self.constant, ); } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 79e2eb2f..74970446 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -219,10 +219,17 @@ impl, const D: usize> CircuitBuilder { ); constants.resize(gate_type.num_constants(), F::ZERO); - let index = self.gate_instances.len(); + let gate_index = self.gate_instances.len(); self.constant_generators - .extend(gate_type.extra_constants(index)); + .extend(gate_type.extra_constant_wires().into_iter().map( + |(constant_index, wire_index)| ConstantGenerator { + gate_index, + constant_index, + wire_index, + constant: F::ZERO, // Placeholder; will be replaced later. + }, + )); // Note that we can't immediately add this gate's generators, because the list of constants // could be modified later, i.e. in the case of `ConstantGate`. We will add them later in @@ -237,7 +244,7 @@ impl, const D: usize> CircuitBuilder { constants, }); - index + gate_index } fn check_gate_compatibility>(&self, gate: &G) { @@ -678,10 +685,7 @@ impl, const D: usize> CircuitBuilder { // Set the constant in the constant polynomial. self.gate_instances[const_gen.gate_index].constants[const_gen.constant_index] = c; // Generate a copy between the target and the routable wire. - self.connect( - Target::wire(const_gen.gate_index, const_gen.target_index), - t, - ); + self.connect(Target::wire(const_gen.gate_index, const_gen.wire_index), t); // Set the constant in the generator (it's initially set with a dummy value). const_gen.set_constant(c); self.add_simple_generator(const_gen);