From b26a0ae48100f7bbc2f74af9169d83bb6b0c9459 Mon Sep 17 00:00:00 2001 From: Eduard S Date: Thu, 20 Apr 2023 15:20:09 +0200 Subject: [PATCH] Extend Circuit trait to take parameters in config (#168) * Extend Circuit trait to take parameters in config The Circuit trait is extended with the following: ``` pub trait Circuit { /// [...] type Params: Default; fn params(&self) -> Self::Params { Self::Params::default() } fn configure_with_params(meta: &mut ConstraintSystem, params: &Self::Params) -> Self::Config { Self::configure(meta) } fn configure(meta: &mut ConstraintSystem) -> Self::Config; } ``` This allows runtime parametrization of the circuit configuration. The extension to the Circuit trait has been designed to minimize the breaking change: existing circuits only need to define the associated `type Params`. Unfortunately "Associated type defaults" are unstable in Rust, otherwise this would be a non-breaking change. See https://github.com/rust-lang/rust/issues/29661 * Implement circuit params under feature flag * Don't overwrite configure method * Fix doc test --- halo2_gadgets/Cargo.toml | 1 + halo2_gadgets/benches/poseidon.rs | 2 ++ halo2_gadgets/benches/sha256.rs | 2 ++ halo2_gadgets/src/ecc.rs | 2 ++ halo2_gadgets/src/ecc/chip/mul_fixed/short.rs | 2 ++ halo2_gadgets/src/poseidon/pow5.rs | 4 +++ halo2_gadgets/src/sha256/table16.rs | 2 ++ .../src/sha256/table16/compression.rs | 2 ++ .../src/sha256/table16/message_schedule.rs | 2 ++ .../src/sha256/table16/spread_table.rs | 2 ++ halo2_gadgets/src/sinsemilla.rs | 2 ++ halo2_gadgets/src/sinsemilla/merkle.rs | 2 ++ halo2_gadgets/src/utilities.rs | 2 ++ halo2_gadgets/src/utilities/cond_swap.rs | 2 ++ .../src/utilities/decompose_running_sum.rs | 2 ++ .../src/utilities/lookup_range_check.rs | 4 +++ halo2_proofs/Cargo.toml | 1 + halo2_proofs/benches/dev_lookup.rs | 2 ++ halo2_proofs/benches/plonk.rs | 2 ++ halo2_proofs/examples/circuit-layout.rs | 2 ++ halo2_proofs/examples/serialization.rs | 12 +++++-- halo2_proofs/examples/shuffle.rs | 2 ++ halo2_proofs/examples/simple-example.rs | 2 ++ halo2_proofs/examples/two-chip.rs | 2 ++ .../src/circuit/floor_planner/single_pass.rs | 2 ++ halo2_proofs/src/circuit/floor_planner/v1.rs | 2 ++ halo2_proofs/src/dev.rs | 13 ++++++++ halo2_proofs/src/dev/cost.rs | 3 ++ halo2_proofs/src/dev/gates.rs | 12 ++++++- halo2_proofs/src/dev/graph.rs | 3 ++ halo2_proofs/src/dev/graph/layout.rs | 3 ++ halo2_proofs/src/plonk.rs | 31 ++++++++++++++++--- halo2_proofs/src/plonk/circuit.rs | 22 +++++++++++++ halo2_proofs/src/plonk/keygen.rs | 16 ++++++++-- halo2_proofs/src/plonk/prover.rs | 3 ++ halo2_proofs/tests/plonk_api.rs | 2 ++ 36 files changed, 163 insertions(+), 9 deletions(-) diff --git a/halo2_gadgets/Cargo.toml b/halo2_gadgets/Cargo.toml index 136ef63a16..c4ebf6fae3 100644 --- a/halo2_gadgets/Cargo.toml +++ b/halo2_gadgets/Cargo.toml @@ -49,6 +49,7 @@ bench = false [features] dev-graph = ["halo2_proofs/dev-graph", "plotters"] +circuit-params = ["halo2_proofs/circuit-params"] test-dependencies = ["proptest"] unstable = [] diff --git a/halo2_gadgets/benches/poseidon.rs b/halo2_gadgets/benches/poseidon.rs index 4494e77a0f..03e595fe0f 100644 --- a/halo2_gadgets/benches/poseidon.rs +++ b/halo2_gadgets/benches/poseidon.rs @@ -53,6 +53,8 @@ where { type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self { diff --git a/halo2_gadgets/benches/sha256.rs b/halo2_gadgets/benches/sha256.rs index 670956cb0d..0e14d61946 100644 --- a/halo2_gadgets/benches/sha256.rs +++ b/halo2_gadgets/benches/sha256.rs @@ -37,6 +37,8 @@ fn bench(name: &str, k: u32, c: &mut Criterion) { impl Circuit for MyCircuit { type Config = Table16Config; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() diff --git a/halo2_gadgets/src/ecc.rs b/halo2_gadgets/src/ecc.rs index 08f34b15f2..05ea999053 100644 --- a/halo2_gadgets/src/ecc.rs +++ b/halo2_gadgets/src/ecc.rs @@ -731,6 +731,8 @@ pub(crate) mod tests { impl Circuit for MyCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit { test_errors: false } diff --git a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs index 4c92becb86..42363baa11 100644 --- a/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs +++ b/halo2_gadgets/src/ecc/chip/mul_fixed/short.rs @@ -434,6 +434,8 @@ pub mod tests { impl Circuit for MyCircuit { type Config = EccConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() diff --git a/halo2_gadgets/src/poseidon/pow5.rs b/halo2_gadgets/src/poseidon/pow5.rs index 52b0d27312..7abd86329d 100644 --- a/halo2_gadgets/src/poseidon/pow5.rs +++ b/halo2_gadgets/src/poseidon/pow5.rs @@ -620,6 +620,8 @@ mod tests { { type Config = Pow5Config; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { PermuteCircuit::(PhantomData) @@ -735,6 +737,8 @@ mod tests { { type Config = Pow5Config; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self { diff --git a/halo2_gadgets/src/sha256/table16.rs b/halo2_gadgets/src/sha256/table16.rs index c4919158bc..76b8e3476f 100644 --- a/halo2_gadgets/src/sha256/table16.rs +++ b/halo2_gadgets/src/sha256/table16.rs @@ -468,6 +468,8 @@ mod tests { impl Circuit for MyCircuit { type Config = Table16Config; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit {} diff --git a/halo2_gadgets/src/sha256/table16/compression.rs b/halo2_gadgets/src/sha256/table16/compression.rs index 62deb42937..874452a418 100644 --- a/halo2_gadgets/src/sha256/table16/compression.rs +++ b/halo2_gadgets/src/sha256/table16/compression.rs @@ -954,6 +954,8 @@ mod tests { impl Circuit for MyCircuit { type Config = Table16Config; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit {} diff --git a/halo2_gadgets/src/sha256/table16/message_schedule.rs b/halo2_gadgets/src/sha256/table16/message_schedule.rs index 690e086c49..3da70c0add 100644 --- a/halo2_gadgets/src/sha256/table16/message_schedule.rs +++ b/halo2_gadgets/src/sha256/table16/message_schedule.rs @@ -411,6 +411,8 @@ mod tests { impl Circuit for MyCircuit { type Config = Table16Config; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit {} diff --git a/halo2_gadgets/src/sha256/table16/spread_table.rs b/halo2_gadgets/src/sha256/table16/spread_table.rs index 031f088084..9b8a313cc2 100644 --- a/halo2_gadgets/src/sha256/table16/spread_table.rs +++ b/halo2_gadgets/src/sha256/table16/spread_table.rs @@ -304,6 +304,8 @@ mod tests { impl Circuit for MyCircuit { type Config = SpreadTableConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit {} diff --git a/halo2_gadgets/src/sinsemilla.rs b/halo2_gadgets/src/sinsemilla.rs index 2670529229..543d49f55f 100644 --- a/halo2_gadgets/src/sinsemilla.rs +++ b/halo2_gadgets/src/sinsemilla.rs @@ -525,6 +525,8 @@ pub(crate) mod tests { SinsemillaConfig, ); type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit {} diff --git a/halo2_gadgets/src/sinsemilla/merkle.rs b/halo2_gadgets/src/sinsemilla/merkle.rs index a9ae781d5c..219a9025af 100644 --- a/halo2_gadgets/src/sinsemilla/merkle.rs +++ b/halo2_gadgets/src/sinsemilla/merkle.rs @@ -213,6 +213,8 @@ pub mod tests { MerkleConfig, ); type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() diff --git a/halo2_gadgets/src/utilities.rs b/halo2_gadgets/src/utilities.rs index 683a553b7e..887ee92475 100644 --- a/halo2_gadgets/src/utilities.rs +++ b/halo2_gadgets/src/utilities.rs @@ -271,6 +271,8 @@ mod tests { impl Circuit for MyCircuit { type Config = Config; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit(self.0) diff --git a/halo2_gadgets/src/utilities/cond_swap.rs b/halo2_gadgets/src/utilities/cond_swap.rs index 2dc96d5904..d71b2599a7 100644 --- a/halo2_gadgets/src/utilities/cond_swap.rs +++ b/halo2_gadgets/src/utilities/cond_swap.rs @@ -217,6 +217,8 @@ mod tests { impl Circuit for MyCircuit { type Config = CondSwapConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() diff --git a/halo2_gadgets/src/utilities/decompose_running_sum.rs b/halo2_gadgets/src/utilities/decompose_running_sum.rs index 96fd279942..041044ffcb 100644 --- a/halo2_gadgets/src/utilities/decompose_running_sum.rs +++ b/halo2_gadgets/src/utilities/decompose_running_sum.rs @@ -243,6 +243,8 @@ mod tests { { type Config = RunningSumConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self { diff --git a/halo2_gadgets/src/utilities/lookup_range_check.rs b/halo2_gadgets/src/utilities/lookup_range_check.rs index 36be7c7745..e5990b3433 100644 --- a/halo2_gadgets/src/utilities/lookup_range_check.rs +++ b/halo2_gadgets/src/utilities/lookup_range_check.rs @@ -410,6 +410,8 @@ mod tests { impl Circuit for MyCircuit { type Config = LookupRangeCheckConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { *self @@ -506,6 +508,8 @@ mod tests { impl Circuit for MyCircuit { type Config = LookupRangeCheckConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit { diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index c26b8c5227..7acad5c474 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -91,6 +91,7 @@ parallel_syn = [] phase-check = [] profile = ["ark-std/print-trace"] mock-batch-inv = [] +circuit-params = [] [lib] bench = false diff --git a/halo2_proofs/benches/dev_lookup.rs b/halo2_proofs/benches/dev_lookup.rs index 745a36b928..62ed5a7f19 100644 --- a/halo2_proofs/benches/dev_lookup.rs +++ b/halo2_proofs/benches/dev_lookup.rs @@ -28,6 +28,8 @@ fn criterion_benchmark(c: &mut Criterion) { impl Circuit for MyCircuit { type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() diff --git a/halo2_proofs/benches/plonk.rs b/halo2_proofs/benches/plonk.rs index cf02cf87e8..9c9bd2618a 100644 --- a/halo2_proofs/benches/plonk.rs +++ b/halo2_proofs/benches/plonk.rs @@ -183,6 +183,8 @@ fn criterion_benchmark(c: &mut Criterion) { impl Circuit for MyCircuit { type Config = PlonkConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self { diff --git a/halo2_proofs/examples/circuit-layout.rs b/halo2_proofs/examples/circuit-layout.rs index 6a73f51ff8..18de27a783 100644 --- a/halo2_proofs/examples/circuit-layout.rs +++ b/halo2_proofs/examples/circuit-layout.rs @@ -161,6 +161,8 @@ impl StandardCs for StandardPlonk { impl Circuit for MyCircuit { type Config = PlonkConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self { diff --git a/halo2_proofs/examples/serialization.rs b/halo2_proofs/examples/serialization.rs index 91ed5464e4..39b6b1192f 100644 --- a/halo2_proofs/examples/serialization.rs +++ b/halo2_proofs/examples/serialization.rs @@ -86,6 +86,8 @@ struct StandardPlonk(Fr); impl Circuit for StandardPlonk { type Config = StandardPlonkConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() @@ -140,8 +142,14 @@ fn main() { let f = File::open("serialization-test.pk").unwrap(); let mut reader = BufReader::new(f); - let pk = ProvingKey::::read::<_, StandardPlonk>(&mut reader, SerdeFormat::RawBytes) - .unwrap(); + #[allow(clippy::unit_arg)] + let pk = ProvingKey::::read::<_, StandardPlonk>( + &mut reader, + SerdeFormat::RawBytes, + #[cfg(feature = "circuit-params")] + circuit.params(), + ) + .unwrap(); std::fs::remove_file("serialization-test.pk").unwrap(); diff --git a/halo2_proofs/examples/shuffle.rs b/halo2_proofs/examples/shuffle.rs index 08d16b9f27..eaa8826f0a 100644 --- a/halo2_proofs/examples/shuffle.rs +++ b/halo2_proofs/examples/shuffle.rs @@ -136,6 +136,8 @@ impl MyCircuit { impl Circuit for MyCircuit { type Config = MyConfig; type FloorPlanner = V1; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() diff --git a/halo2_proofs/examples/simple-example.rs b/halo2_proofs/examples/simple-example.rs index 2273ce9759..242257a692 100644 --- a/halo2_proofs/examples/simple-example.rs +++ b/halo2_proofs/examples/simple-example.rs @@ -248,6 +248,8 @@ impl Circuit for MyCircuit { // Since we are using a single chip for everything, we can just reuse its config. type Config = FieldConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() diff --git a/halo2_proofs/examples/two-chip.rs b/halo2_proofs/examples/two-chip.rs index 4113d94143..336f9c4957 100644 --- a/halo2_proofs/examples/two-chip.rs +++ b/halo2_proofs/examples/two-chip.rs @@ -458,6 +458,8 @@ impl Circuit for MyCircuit { // Since we are using a single chip for everything, we can just reuse its config. type Config = FieldConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self::default() diff --git a/halo2_proofs/src/circuit/floor_planner/single_pass.rs b/halo2_proofs/src/circuit/floor_planner/single_pass.rs index 0761957bfc..1ef0a6af81 100644 --- a/halo2_proofs/src/circuit/floor_planner/single_pass.rs +++ b/halo2_proofs/src/circuit/floor_planner/single_pass.rs @@ -681,6 +681,8 @@ mod tests { impl Circuit for MyCircuit { type Config = Column; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit {} diff --git a/halo2_proofs/src/circuit/floor_planner/v1.rs b/halo2_proofs/src/circuit/floor_planner/v1.rs index 0fd28c196f..463d119196 100644 --- a/halo2_proofs/src/circuit/floor_planner/v1.rs +++ b/halo2_proofs/src/circuit/floor_planner/v1.rs @@ -546,6 +546,8 @@ mod tests { impl Circuit for MyCircuit { type Config = Column; type FloorPlanner = super::V1; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { MyCircuit {} diff --git a/halo2_proofs/src/dev.rs b/halo2_proofs/src/dev.rs index 440796bb6d..f2580de180 100644 --- a/halo2_proofs/src/dev.rs +++ b/halo2_proofs/src/dev.rs @@ -346,6 +346,8 @@ impl Mul for Value { /// impl Circuit for MyCircuit { /// type Config = MyConfig; /// type FloorPlanner = SimpleFloorPlanner; +/// #[cfg(feature = "circuit-params")] +/// type Params = (); /// /// fn without_witnesses(&self) -> Self { /// Self::default() @@ -925,6 +927,9 @@ impl<'a, F: FromUniformBytes<64> + Ord> MockProver<'a, F> { let n = 1 << k; let mut cs = ConstraintSystem::default(); + #[cfg(feature = "circuit-params")] + let config = ConcreteCircuit::configure_with_params(&mut cs, circuit.params()); + #[cfg(not(feature = "circuit-params"))] let config = ConcreteCircuit::configure(&mut cs); let cs = cs; @@ -1983,6 +1988,8 @@ mod tests { impl Circuit for FaultyCircuit { type Config = FaultyCircuitConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn configure(meta: &mut ConstraintSystem) -> Self::Config { let a = meta.advice_column(); @@ -2069,6 +2076,8 @@ mod tests { impl Circuit for FaultyCircuit { type Config = FaultyCircuitConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn configure(meta: &mut ConstraintSystem) -> Self::Config { let a = meta.advice_column(); @@ -2238,6 +2247,8 @@ mod tests { impl Circuit for FaultyCircuit { type Config = FaultyCircuitConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn configure(meta: &mut ConstraintSystem) -> Self::Config { let a = meta.advice_column(); @@ -2372,6 +2383,8 @@ mod tests { impl Circuit for FaultyCircuit { type Config = FaultyCircuitConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn configure(meta: &mut ConstraintSystem) -> Self::Config { let a = meta.advice_column(); diff --git a/halo2_proofs/src/dev/cost.rs b/halo2_proofs/src/dev/cost.rs index 2a39cc5182..815e66c9c2 100644 --- a/halo2_proofs/src/dev/cost.rs +++ b/halo2_proofs/src/dev/cost.rs @@ -159,6 +159,9 @@ impl> CircuitCost Self { // Collect the layout details. let mut cs = ConstraintSystem::default(); + #[cfg(feature = "circuit-params")] + let config = ConcreteCircuit::configure_with_params(&mut cs, circuit.params()); + #[cfg(not(feature = "circuit-params"))] let config = ConcreteCircuit::configure(&mut cs); let mut assembly = Assembly { selectors: vec![vec![false; 1 << k]; cs.num_selectors], diff --git a/halo2_proofs/src/dev/gates.rs b/halo2_proofs/src/dev/gates.rs index cfc71c021e..119019a60a 100644 --- a/halo2_proofs/src/dev/gates.rs +++ b/halo2_proofs/src/dev/gates.rs @@ -49,6 +49,8 @@ struct Gate { /// impl Circuit for MyCircuit { /// type Config = MyConfig; /// type FloorPlanner = SimpleFloorPlanner; +/// #[cfg(feature = "circuit-params")] +/// type Params = (); /// /// fn without_witnesses(&self) -> Self { /// Self::default() @@ -79,6 +81,9 @@ struct Gate { /// } /// } /// +/// #[cfg(feature = "circuit-params")] +/// let gates = CircuitGates::collect::(()); +/// #[cfg(not(feature = "circuit-params"))] /// let gates = CircuitGates::collect::(); /// assert_eq!( /// format!("{}", gates), @@ -103,9 +108,14 @@ pub struct CircuitGates { impl CircuitGates { /// Collects the gates from within the circuit. - pub fn collect>() -> Self { + pub fn collect>( + #[cfg(feature = "circuit-params")] params: C::Params, + ) -> Self { // Collect the graph details. let mut cs = ConstraintSystem::default(); + #[cfg(feature = "circuit-params")] + let _ = C::configure_with_params(&mut cs, params); + #[cfg(not(feature = "circuit-params"))] let _ = C::configure(&mut cs); let gates = cs diff --git a/halo2_proofs/src/dev/graph.rs b/halo2_proofs/src/dev/graph.rs index 8482879913..7fbf9f2f6b 100644 --- a/halo2_proofs/src/dev/graph.rs +++ b/halo2_proofs/src/dev/graph.rs @@ -23,6 +23,9 @@ pub fn circuit_dot_graph>( ) -> String { // Collect the graph details. let mut cs = ConstraintSystem::default(); + #[cfg(feature = "circuit-params")] + let config = ConcreteCircuit::configure_with_params(&mut cs, circuit.params()); + #[cfg(not(feature = "circuit-params"))] let config = ConcreteCircuit::configure(&mut cs); let mut graph = Graph::default(); ConcreteCircuit::FloorPlanner::synthesize(&mut graph, circuit, config, cs.constants).unwrap(); diff --git a/halo2_proofs/src/dev/graph/layout.rs b/halo2_proofs/src/dev/graph/layout.rs index ad989eab10..e1bbe77faf 100644 --- a/halo2_proofs/src/dev/graph/layout.rs +++ b/halo2_proofs/src/dev/graph/layout.rs @@ -97,6 +97,9 @@ impl CircuitLayout { let n = 1 << k; // Collect the layout details. let mut cs = ConstraintSystem::default(); + #[cfg(feature = "circuit-params")] + let config = ConcreteCircuit::configure_with_params(&mut cs, circuit.params()); + #[cfg(not(feature = "circuit-params"))] let config = ConcreteCircuit::configure(&mut cs); let mut layout = Layout::new(k, n, cs.num_selectors); ConcreteCircuit::FloorPlanner::synthesize( diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 786ca29a42..c718e4a97f 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -104,11 +104,16 @@ where pub fn read>( reader: &mut R, format: SerdeFormat, + #[cfg(feature = "circuit-params")] params: ConcreteCircuit::Params, ) -> io::Result { let mut k = [0u8; 4]; reader.read_exact(&mut k)?; let k = u32::from_be_bytes(k); - let (domain, cs, _) = keygen::create_domain::(k); + let (domain, cs, _) = keygen::create_domain::( + k, + #[cfg(feature = "circuit-params")] + params, + ); let mut num_fixed_columns = [0u8; 4]; reader.read_exact(&mut num_fixed_columns)?; let num_fixed_columns = u32::from_be_bytes(num_fixed_columns); @@ -145,8 +150,14 @@ where pub fn from_bytes>( mut bytes: &[u8], format: SerdeFormat, + #[cfg(feature = "circuit-params")] params: ConcreteCircuit::Params, ) -> io::Result { - Self::read::<_, ConcreteCircuit>(&mut bytes, format) + Self::read::<_, ConcreteCircuit>( + &mut bytes, + format, + #[cfg(feature = "circuit-params")] + params, + ) } } @@ -331,8 +342,14 @@ where pub fn read>( reader: &mut R, format: SerdeFormat, + #[cfg(feature = "circuit-params")] params: ConcreteCircuit::Params, ) -> io::Result { - let vk = VerifyingKey::::read::(reader, format)?; + let vk = VerifyingKey::::read::( + reader, + format, + #[cfg(feature = "circuit-params")] + params, + )?; let l0 = Polynomial::read(reader, format)?; let l_last = Polynomial::read(reader, format)?; let l_active_row = Polynomial::read(reader, format)?; @@ -365,8 +382,14 @@ where pub fn from_bytes>( mut bytes: &[u8], format: SerdeFormat, + #[cfg(feature = "circuit-params")] params: ConcreteCircuit::Params, ) -> io::Result { - Self::read::<_, ConcreteCircuit>(&mut bytes, format) + Self::read::<_, ConcreteCircuit>( + &mut bytes, + format, + #[cfg(feature = "circuit-params")] + params, + ) } } diff --git a/halo2_proofs/src/plonk/circuit.rs b/halo2_proofs/src/plonk/circuit.rs index 9b132b4ea0..62a915babe 100644 --- a/halo2_proofs/src/plonk/circuit.rs +++ b/halo2_proofs/src/plonk/circuit.rs @@ -687,11 +687,33 @@ pub trait Circuit { /// The floor planner used for this circuit. This is an associated type of the /// `Circuit` trait because its behaviour is circuit-critical. type FloorPlanner: FloorPlanner; + /// Optional circuit configuration parameters. Requires the `circuit-params` feature. + #[cfg(feature = "circuit-params")] + type Params: Default; /// Returns a copy of this circuit with no witness values (i.e. all witnesses set to /// `None`). For most circuits, this will be equal to `Self::default()`. fn without_witnesses(&self) -> Self; + /// Returns a reference to the parameters that should be used to configure the circuit. + /// Requires the `circuit-params` feature. + #[cfg(feature = "circuit-params")] + fn params(&self) -> Self::Params { + Self::Params::default() + } + + /// The circuit is given an opportunity to describe the exact gate + /// arrangement, column arrangement, etc. Takes a runtime parameter. The default + /// implementation calls `configure` ignoring the `_params` argument in order to easily support + /// circuits that don't use configuration parameters. + #[cfg(feature = "circuit-params")] + fn configure_with_params( + meta: &mut ConstraintSystem, + _params: Self::Params, + ) -> Self::Config { + Self::configure(meta) + } + /// The circuit is given an opportunity to describe the exact gate /// arrangement, column arrangement, etc. fn configure(meta: &mut ConstraintSystem) -> Self::Config; diff --git a/halo2_proofs/src/plonk/keygen.rs b/halo2_proofs/src/plonk/keygen.rs index ec11fa62f7..42f0fabccd 100644 --- a/halo2_proofs/src/plonk/keygen.rs +++ b/halo2_proofs/src/plonk/keygen.rs @@ -29,6 +29,7 @@ use crate::{ pub(crate) fn create_domain( k: u32, + #[cfg(feature = "circuit-params")] params: ConcreteCircuit::Params, ) -> ( EvaluationDomain, ConstraintSystem, @@ -39,6 +40,9 @@ where ConcreteCircuit: Circuit, { let mut cs = ConstraintSystem::default(); + #[cfg(feature = "circuit-params")] + let config = ConcreteCircuit::configure_with_params(&mut cs, params); + #[cfg(not(feature = "circuit-params"))] let config = ConcreteCircuit::configure(&mut cs); let degree = cs.degree(); @@ -331,7 +335,11 @@ where ConcreteCircuit: Circuit, C::Scalar: FromUniformBytes<64>, { - let (domain, cs, config) = create_domain::(params.k()); + let (domain, cs, config) = create_domain::( + params.k(), + #[cfg(feature = "circuit-params")] + circuit.params(), + ); if (params.n() as usize) < cs.minimum_rows() { return Err(Error::not_enough_rows_available(params.k())); @@ -456,7 +464,11 @@ where ConcreteCircuit: Circuit, ::ScalarExt: FromUniformBytes<64>, { - let (domain, cs, config) = create_domain::(params.k()); + let (domain, cs, config) = create_domain::( + params.k(), + #[cfg(feature = "circuit-params")] + circuit.params(), + ); if (params.n() as usize) < cs.minimum_rows() { return Err(Error::not_enough_rows_available(params.k())); diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index c522947820..bc78600f4f 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -70,6 +70,9 @@ where let domain = &pk.vk.domain; let mut meta = ConstraintSystem::default(); + #[cfg(feature = "circuit-params")] + let config = ConcreteCircuit::configure_with_params(&mut meta, circuits[0].params()); + #[cfg(not(feature = "circuit-params"))] let config = ConcreteCircuit::configure(&mut meta); // Selector optimizations cannot be applied here; use the ConstraintSystem diff --git a/halo2_proofs/tests/plonk_api.rs b/halo2_proofs/tests/plonk_api.rs index 6c69a472ab..b58d562910 100644 --- a/halo2_proofs/tests/plonk_api.rs +++ b/halo2_proofs/tests/plonk_api.rs @@ -266,6 +266,8 @@ fn plonk_api() { impl Circuit for MyCircuit { type Config = PlonkConfig; type FloorPlanner = SimpleFloorPlanner; + #[cfg(feature = "circuit-params")] + type Params = (); fn without_witnesses(&self) -> Self { Self {