diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index 5222bbfe..7d1b6c57 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -35,7 +35,7 @@ fn bench_prove, const D: usize>() -> Result<()> { }, }; - let inputs = PartialWitness::new(config.num_wires); + let inputs = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let zero = builder.zero(); diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index 94b37eaa..e63b520a 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -7,7 +7,7 @@ use crate::field::field_types::Field; use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS}; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; @@ -433,6 +433,7 @@ impl, const D: usize> CircuitBuilder { } } +#[derive(Debug)] struct QuotientGeneratorExtension { numerator: ExtensionTarget, denominator: ExtensionTarget, @@ -446,7 +447,7 @@ impl, const D: usize> SimpleGenerator for QuotientGeneratorE deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let num = witness.get_extension_target(self.numerator); let dem = witness.get_extension_target(self.denominator); let quotient = num / dem; @@ -503,7 +504,7 @@ mod tests { use crate::field::extension_field::algebra::ExtensionAlgebra; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field_types::Field; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::verifier::verify; @@ -516,7 +517,7 @@ mod tests { let config = CircuitConfig::large_config(); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let vs = FF::rand_vec(3); @@ -551,7 +552,7 @@ mod tests { let config = CircuitConfig::large_zk_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let x = FF::rand(); @@ -579,7 +580,7 @@ mod tests { let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let x = FF::rand_vec(4); diff --git a/src/gadgets/insert.rs b/src/gadgets/insert.rs index bdc8bde7..4018644d 100644 --- a/src/gadgets/insert.rs +++ b/src/gadgets/insert.rs @@ -64,7 +64,7 @@ mod tests { type FF = QuarticCrandallField; let len = 1 << len_log; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let v = (0..len - 1) .map(|_| builder.constant_extension(FF::rand())) diff --git a/src/gadgets/interpolation.rs b/src/gadgets/interpolation.rs index 8901b9f8..2175d0ce 100644 --- a/src/gadgets/interpolation.rs +++ b/src/gadgets/interpolation.rs @@ -49,7 +49,7 @@ mod tests { type F = CrandallField; type FF = QuarticCrandallField; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let len = 4; diff --git a/src/gadgets/random_access.rs b/src/gadgets/random_access.rs index 99c2ae5a..cdc8bdfd 100644 --- a/src/gadgets/random_access.rs +++ b/src/gadgets/random_access.rs @@ -66,7 +66,7 @@ mod tests { type FF = QuarticCrandallField; let len = 1 << len_log; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let vec = FF::rand_vec(len); let v: Vec<_> = vec.iter().map(|x| builder.constant_extension(*x)).collect(); diff --git a/src/gadgets/range_check.rs b/src/gadgets/range_check.rs index be7eaf2e..c878e799 100644 --- a/src/gadgets/range_check.rs +++ b/src/gadgets/range_check.rs @@ -3,7 +3,7 @@ use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; impl, const D: usize> CircuitBuilder { @@ -56,7 +56,7 @@ impl SimpleGenerator for LowHighGenerator { vec![self.integer] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let integer_value = witness.get_target(self.integer).to_canonical_u64(); let low = integer_value & ((1 << self.n_log) - 1); let high = integer_value >> self.n_log; diff --git a/src/gadgets/select.rs b/src/gadgets/select.rs index 3be3455c..a888d105 100644 --- a/src/gadgets/select.rs +++ b/src/gadgets/select.rs @@ -43,7 +43,7 @@ mod tests { use crate::field::crandall_field::CrandallField; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field_types::Field; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::verifier::verify; @@ -53,7 +53,7 @@ mod tests { type F = CrandallField; type FF = QuarticCrandallField; let config = CircuitConfig::large_config(); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let (x, y) = (FF::rand(), FF::rand()); diff --git a/src/gadgets/split_base.rs b/src/gadgets/split_base.rs index 72964826..41ed8799 100644 --- a/src/gadgets/split_base.rs +++ b/src/gadgets/split_base.rs @@ -5,7 +5,7 @@ use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; impl, const D: usize> CircuitBuilder { @@ -64,7 +64,7 @@ impl SimpleGenerator for BaseSumGenerator { self.limbs.iter().map(|b| b.target).collect() } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let sum = self .limbs .iter() @@ -97,7 +97,7 @@ mod tests { fn test_split_base() -> Result<()> { type F = CrandallField; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let x = F::from_canonical_usize(0b110100000); // 416 = 1532 in base 6. let xt = builder.constant(x); @@ -123,7 +123,7 @@ mod tests { fn test_base_sum() -> Result<()> { type F = CrandallField; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let n = thread_rng().gen_range(0..(1 << 10)); diff --git a/src/gadgets/split_join.rs b/src/gadgets/split_join.rs index 71c171f0..fe3d724a 100644 --- a/src/gadgets/split_join.rs +++ b/src/gadgets/split_join.rs @@ -3,7 +3,7 @@ use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::ceil_div_usize; @@ -68,7 +68,7 @@ impl SimpleGenerator for SplitGenerator { vec![self.integer] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let mut integer_value = witness.get_target(self.integer).to_canonical_u64(); for &b in &self.bits { @@ -96,7 +96,7 @@ impl SimpleGenerator for WireSplitGenerator { vec![self.integer] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let mut integer_value = witness.get_target(self.integer).to_canonical_u64(); for &gate in &self.gates { diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index dcabcee8..3c9dcb18 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -6,7 +6,7 @@ use crate::field::extension_field::FieldExtension; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -138,7 +138,7 @@ impl, const D: usize> Gate for ArithmeticExtensionGate } } -#[derive(Clone)] +#[derive(Clone, Debug)] struct ArithmeticExtensionGenerator, const D: usize> { gate_index: usize, const_0: F, @@ -157,7 +157,7 @@ impl, const D: usize> SimpleGenerator for ArithmeticExtensio .collect() } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let extract_extension = |range: Range| -> F::Extension { let t = ExtensionTarget::from_range(self.gate_index, range); witness.get_extension_target(t) diff --git a/src/gates/base_sum.rs b/src/gates/base_sum.rs index fe4e51a2..641a8150 100644 --- a/src/gates/base_sum.rs +++ b/src/gates/base_sum.rs @@ -6,7 +6,7 @@ use crate::field::field_types::Field; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_recursive}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -132,7 +132,7 @@ impl SimpleGenerator for BaseSplitGenerator { vec![Target::wire(self.gate_index, BaseSumGate::::WIRE_SUM)] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let sum_value = witness .get_target(Target::wire(self.gate_index, BaseSumGate::::WIRE_SUM)) .to_canonical_u64() as usize; diff --git a/src/gates/constant.rs b/src/gates/constant.rs index 0cc22b22..894016d6 100644 --- a/src/gates/constant.rs +++ b/src/gates/constant.rs @@ -5,7 +5,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::PartitionWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -85,7 +85,7 @@ impl SimpleGenerator for ConstantGenerator { Vec::new() } - fn run_once(&self, _witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let wire = Wire { gate: self.gate_index, input: ConstantGate::WIRE_OUTPUT, diff --git a/src/gates/exponentiation.rs b/src/gates/exponentiation.rs index 468f58e2..d57c9001 100644 --- a/src/gates/exponentiation.rs +++ b/src/gates/exponentiation.rs @@ -7,7 +7,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -218,7 +218,7 @@ impl, const D: usize> SimpleGenerator for ExponentiationGene deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/gate_testing.rs b/src/gates/gate_testing.rs index 4d336454..b45cb745 100644 --- a/src/gates/gate_testing.rs +++ b/src/gates/gate_testing.rs @@ -4,7 +4,7 @@ use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; use crate::gates::gate::Gate; use crate::hash::hash_types::HashOut; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -124,7 +124,7 @@ pub(crate) fn test_eval_fns, G: Gate, const D: usize>( let constants = F::Extension::rand_vec(gate.num_constants()); let config = CircuitConfig::large_config(); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let wires_t = builder.add_virtual_extension_targets(wires.len()); diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 1830b9c7..682bd1fa 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -8,7 +8,7 @@ use crate::hash::gmimc::gmimc_automatic_constants; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -264,7 +264,7 @@ impl, const D: usize, const R: usize> SimpleGenerator .collect() } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let mut state = (0..W) .map(|i| { witness.get_wire(Wire { @@ -331,8 +331,9 @@ mod tests { use crate::gates::gmimc::{GMiMCGate, W}; use crate::hash::gmimc::gmimc_permute_naive; use crate::iop::generator::generate_partial_witness; + use crate::iop::target::Target; use crate::iop::wire::Wire; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::util::timing::TimingTree; #[test] @@ -345,7 +346,7 @@ mod tests { let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::>(); - let mut witness = PartialWitness::new(gate.num_wires()); + let mut witness = PartialWitness::new(); witness.set_wire( Wire { gate: 0, @@ -363,13 +364,17 @@ mod tests { ); } + let mut partition_witness = PartitionWitness::new(gate.num_wires(), gate.num_wires(), 1, 0); + for input in 0..gate.num_wires() { + partition_witness.add(Target::Wire(Wire { gate: 0, input })); + } + for (&t, &v) in witness.target_values.iter() { + partition_witness.set_target(t, v); + } let generators = gate.generators(0, &[]); generate_partial_witness( - &mut witness, + &mut partition_witness, &generators, - gate.num_wires(), - 1, - 1, &mut TimingTree::default(), ); @@ -377,7 +382,7 @@ mod tests { gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants); for i in 0..W { - let out = witness.get_wire(Wire { + let out = partition_witness.get_wire(Wire { gate: 0, input: Gate::wire_output(i), }); diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index 7a42be41..4c1e6fdf 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -9,7 +9,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -261,7 +261,7 @@ impl, const D: usize> SimpleGenerator for InsertionGenerator deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index 9356d428..56924742 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -11,7 +11,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::polynomial::polynomial::PolynomialCoeffs; @@ -213,6 +213,7 @@ impl, const D: usize> Gate for InterpolationGate { } } +#[derive(Debug)] struct InterpolationGenerator, const D: usize> { gate_index: usize, gate: InterpolationGate, @@ -239,7 +240,7 @@ impl, const D: usize> SimpleGenerator for InterpolationGener deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let n = self.gate.num_points; let local_wire = |input| Wire { diff --git a/src/gates/random_access.rs b/src/gates/random_access.rs index 32d1a8fa..3bba5ad2 100644 --- a/src/gates/random_access.rs +++ b/src/gates/random_access.rs @@ -8,7 +8,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -208,7 +208,7 @@ impl, const D: usize> SimpleGenerator for RandomAccessGenera deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/reducing.rs b/src/gates/reducing.rs index 8bfdc0c4..ee3232b2 100644 --- a/src/gates/reducing.rs +++ b/src/gates/reducing.rs @@ -6,7 +6,7 @@ use crate::field::extension_field::FieldExtension; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -159,6 +159,7 @@ impl, const D: usize> Gate for ReducingGate { } } +#[derive(Debug)] struct ReducingGenerator { gate_index: usize, gate: ReducingGate, @@ -173,7 +174,7 @@ impl, const D: usize> SimpleGenerator for ReducingGenerator< .collect() } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let extract_extension = |range: Range| -> F::Extension { let t = ExtensionTarget::from_range(self.gate_index, range); witness.get_extension_target(t) diff --git a/src/hash/merkle_proofs.rs b/src/hash/merkle_proofs.rs index 8b4ca621..cfdef5ff 100644 --- a/src/hash/merkle_proofs.rs +++ b/src/hash/merkle_proofs.rs @@ -78,7 +78,7 @@ impl, const D: usize> CircuitBuilder { gate, input: swap_wire, }); - self.generate_copy(bit.target, swap_wire); + self.route(bit.target, swap_wire); let input_wires = (0..12) .map(|i| { @@ -211,7 +211,7 @@ mod tests { use super::*; use crate::field::crandall_field::CrandallField; use crate::hash::merkle_tree::MerkleTree; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::verifier::verify; @@ -224,7 +224,7 @@ mod tests { fn test_recursive_merkle_proof() -> Result<()> { type F = CrandallField; let config = CircuitConfig::large_config(); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let log_n = 8; diff --git a/src/iop/challenger.rs b/src/iop/challenger.rs index 19b20717..3a90f72b 100644 --- a/src/iop/challenger.rs +++ b/src/iop/challenger.rs @@ -330,7 +330,7 @@ mod tests { use crate::iop::challenger::{Challenger, RecursiveChallenger}; use crate::iop::generator::generate_partial_witness; use crate::iop::target::Target; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::Witness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::util::timing::TimingTree; @@ -382,7 +382,6 @@ mod tests { num_routed_wires: 27, ..CircuitConfig::default() }; - let mut witness = PartialWitness::new(config.num_wires); let mut builder = CircuitBuilder::::new(config.clone()); let mut recursive_challenger = RecursiveChallenger::new(&mut builder); let mut recursive_outputs_per_round: Vec> = Vec::new(); @@ -393,17 +392,15 @@ mod tests { ); } let circuit = builder.build(); + let mut partition_witness = circuit.prover_only.partition_witness.clone(); generate_partial_witness( - &mut witness, + &mut partition_witness, &circuit.prover_only.generators, - config.num_wires, - circuit.common.degree(), - circuit.prover_only.num_virtual_targets, &mut TimingTree::default(), ); let recursive_output_values_per_round: Vec> = recursive_outputs_per_round .iter() - .map(|outputs| witness.get_targets(outputs)) + .map(|outputs| partition_witness.get_targets(outputs)) .collect(); assert_eq!(outputs_per_round, recursive_output_values_per_round); diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 6ab1b412..8174981c 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -1,4 +1,3 @@ -use std::convert::identity; use std::fmt::Debug; use crate::field::extension_field::target::ExtensionTarget; @@ -7,35 +6,24 @@ use crate::field::field_types::Field; use crate::hash::hash_types::{HashOut, HashOutTarget}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::timed; use crate::util::timing::TimingTree; -/// Given a `PartialWitness` that has only inputs set, populates the rest of the witness using the +/// Given a `PartitionWitness` that has only inputs set, populates the rest of the witness using the /// given set of generators. pub(crate) fn generate_partial_witness( - witness: &mut PartialWitness, + witness: &mut PartitionWitness, generators: &[Box>], - num_wires: usize, - degree: usize, - max_virtual_target: usize, timing: &mut TimingTree, ) { - let target_index = |t: Target| -> usize { - match t { - Target::Wire(Wire { gate, input }) => gate * num_wires + input, - Target::VirtualTarget { index } => degree * num_wires + index, - } - }; - let max_target_index = target_index(Target::VirtualTarget { - index: max_virtual_target, - }); + let max_target_index = witness.forest.len(); // Index generator indices by their watched targets. let mut generator_indices_by_watches = vec![Vec::new(); max_target_index]; timed!(timing, "index generators by their watched targets", { for (i, generator) in generators.iter().enumerate() { for watch in generator.watch_list() { - generator_indices_by_watches[target_index(watch)].push(i); + generator_indices_by_watches[witness.target_index(watch)].push(i); } } }); @@ -46,11 +34,12 @@ pub(crate) fn generate_partial_witness( // We also track a list of "expired" generators which have already returned false. let mut generator_is_expired = vec![false; generators.len()]; + let mut remaining_generators = generators.len(); let mut buffer = GeneratedValues::empty(); - // Keep running generators until no generators are queued. - while !pending_generator_indices.is_empty() { + // Keep running generators until all generators have been run. + while remaining_generators > 0 { let mut next_pending_generator_indices = Vec::new(); for &generator_idx in &pending_generator_indices { @@ -61,29 +50,35 @@ pub(crate) fn generate_partial_witness( let finished = generators[generator_idx].run(&witness, &mut buffer); if finished { generator_is_expired[generator_idx] = true; + remaining_generators -= 1; } // Enqueue unfinished generators that were watching one of the newly populated targets. for &(watch, _) in &buffer.target_values { - for &watching_generator_idx in &generator_indices_by_watches[target_index(watch)] { - next_pending_generator_indices.push(watching_generator_idx); + for &watching_generator_idx in + &generator_indices_by_watches[witness.target_index(watch)] + { + if !generator_is_expired[watching_generator_idx] { + next_pending_generator_indices.push(watching_generator_idx); + } } } witness.extend(buffer.target_values.drain(..)); } - pending_generator_indices = next_pending_generator_indices; + // If we still need to run som generators, but none were enqueued, we enqueue all generators. + pending_generator_indices = + if remaining_generators > 0 && next_pending_generator_indices.is_empty() { + (0..generators.len()).collect() + } else { + next_pending_generator_indices + }; } - - assert!( - generator_is_expired.into_iter().all(identity), - "Some generators weren't run." - ); } /// A generator participates in the generation of the witness. -pub trait WitnessGenerator: 'static + Send + Sync { +pub trait WitnessGenerator: 'static + Send + Sync + Debug { /// Targets to be "watched" by this generator. Whenever a target in the watch list is populated, /// the generator will be queued to run. fn watch_list(&self) -> Vec; @@ -91,10 +86,11 @@ pub trait WitnessGenerator: 'static + Send + Sync { /// Run this generator, returning a flag indicating whether the generator is finished. If the /// flag is true, the generator will never be run again, otherwise it will be queued for another /// run next time a target in its watch list is populated. - fn run(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) -> bool; + fn run(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) -> bool; } /// Values generated by a generator invocation. +#[derive(Debug)] pub struct GeneratedValues { pub(crate) target_values: Vec<(Target, F)>, } @@ -186,10 +182,10 @@ impl GeneratedValues { } /// A generator which runs once after a list of dependencies is present in the witness. -pub trait SimpleGenerator: 'static + Send + Sync { +pub trait SimpleGenerator: 'static + Send + Sync + Debug { fn dependencies(&self) -> Vec; - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues); + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues); } impl> WitnessGenerator for SG { @@ -197,7 +193,7 @@ impl> WitnessGenerator for SG { self.dependencies() } - fn run(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) -> bool { + fn run(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) -> bool { if witness.contains_all(&self.dependencies()) { self.run_once(witness, out_buffer); true @@ -219,13 +215,14 @@ impl SimpleGenerator for CopyGenerator { vec![self.src] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let value = witness.get_target(self.src); out_buffer.set_target(self.dst, value); } } /// A generator for including a random value +#[derive(Debug)] pub(crate) struct RandomValueGenerator { pub(crate) target: Target, } @@ -235,7 +232,7 @@ impl SimpleGenerator for RandomValueGenerator { Vec::new() } - fn run_once(&self, _witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let random_value = F::rand(); out_buffer.set_target(self.target, random_value); @@ -243,6 +240,7 @@ impl SimpleGenerator for RandomValueGenerator { } /// A generator for testing if a value equals zero +#[derive(Debug)] pub(crate) struct NonzeroTestGenerator { pub(crate) to_test: Target, pub(crate) dummy: Target, @@ -253,7 +251,7 @@ impl SimpleGenerator for NonzeroTestGenerator { vec![self.to_test] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let to_test_value = witness.get_target(self.to_test); let dummy_value = if to_test_value == F::ZERO { diff --git a/src/iop/witness.rs b/src/iop/witness.rs index 51b5a182..f1aca8a1 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -1,55 +1,31 @@ +use std::collections::HashMap; use std::convert::TryInto; -use anyhow::{ensure, Result}; - use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; -use crate::gates::gate::GateInstance; use crate::hash::hash_types::HashOutTarget; use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; -use crate::plonk::copy_constraint::CopyConstraint; +use crate::plonk::permutation_argument::ForestNode; -#[derive(Clone, Debug)] -pub struct Witness { - pub(crate) wire_values: Vec>, -} +/// A witness holds information on the values of targets in a circuit. +pub trait Witness { + fn try_get_target(&self, target: Target) -> Option; -impl Witness { - pub fn get_wire(&self, gate: usize, input: usize) -> F { - self.wire_values[input][gate] - } -} + fn set_target(&mut self, target: Target, value: F); -#[derive(Clone, Debug)] -pub struct PartialWitness { - pub(crate) wire_values: Vec>>, - pub(crate) virtual_target_values: Vec>, -} - -impl PartialWitness { - pub fn new(num_wires: usize) -> Self { - PartialWitness { - wire_values: vec![vec![None; num_wires]], - virtual_target_values: vec![], - } + fn get_target(&self, target: Target) -> F { + self.try_get_target(target).unwrap() } - pub fn get_target(&self, target: Target) -> F { - match target { - Target::Wire(Wire { gate, input }) => self.wire_values[gate][input].unwrap(), - Target::VirtualTarget { index } => self.virtual_target_values[index].unwrap(), - } - } - - pub fn get_targets(&self, targets: &[Target]) -> Vec { + fn get_targets(&self, targets: &[Target]) -> Vec { targets.iter().map(|&t| self.get_target(t)).collect() } - pub fn get_extension_target(&self, et: ExtensionTarget) -> F::Extension + fn get_extension_target(&self, et: ExtensionTarget) -> F::Extension where F: Extendable, { @@ -58,10 +34,7 @@ impl PartialWitness { ) } - pub fn get_extension_targets( - &self, - ets: &[ExtensionTarget], - ) -> Vec + fn get_extension_targets(&self, ets: &[ExtensionTarget]) -> Vec where F: Extendable, { @@ -70,7 +43,7 @@ impl PartialWitness { .collect() } - pub fn get_bool_target(&self, target: BoolTarget) -> bool { + fn get_bool_target(&self, target: BoolTarget) -> bool { let value = self.get_target(target.target).to_canonical_u64(); match value { 0 => false, @@ -79,95 +52,43 @@ impl PartialWitness { } } - pub fn get_hash_target(&self, ht: HashOutTarget) -> HashOut { + fn get_hash_target(&self, ht: HashOutTarget) -> HashOut { HashOut { elements: self.get_targets(&ht.elements).try_into().unwrap(), } } - pub fn try_get_target(&self, target: Target) -> Option { - match target { - Target::Wire(Wire { gate, input }) => self.wire_values[gate][input], - Target::VirtualTarget { index } => self.virtual_target_values[index], - } - } - - pub fn get_wire(&self, wire: Wire) -> F { + fn get_wire(&self, wire: Wire) -> F { self.get_target(Target::Wire(wire)) } - pub fn try_get_wire(&self, wire: Wire) -> Option { + fn try_get_wire(&self, wire: Wire) -> Option { self.try_get_target(Target::Wire(wire)) } - pub fn contains(&self, target: Target) -> bool { - match target { - Target::Wire(Wire { gate, input }) => { - self.wire_values.len() > gate && self.wire_values[gate][input].is_some() - } - Target::VirtualTarget { index } => { - self.virtual_target_values.len() > index - && self.virtual_target_values[index].is_some() - } - } + fn contains(&self, target: Target) -> bool { + self.try_get_target(target).is_some() } - pub fn contains_all(&self, targets: &[Target]) -> bool { + fn contains_all(&self, targets: &[Target]) -> bool { targets.iter().all(|&t| self.contains(t)) } - pub fn set_target(&mut self, target: Target, value: F) { - match target { - Target::Wire(Wire { gate, input }) => { - if gate >= self.wire_values.len() { - self.wire_values - .resize(gate + 1, vec![None; self.wire_values[0].len()]); - } - if let Some(old_value) = self.wire_values[gate][input] { - assert_eq!( - old_value, value, - "Target was set twice with different values: {:?}", - target - ); - } else { - self.wire_values[gate][input] = Some(value); - } - } - Target::VirtualTarget { index } => { - if index >= self.virtual_target_values.len() { - self.virtual_target_values.resize(index + 1, None); - } - if let Some(old_value) = self.virtual_target_values[index] { - assert_eq!( - old_value, value, - "Target was set twice with different values: {:?}", - target - ); - } else { - self.virtual_target_values[index] = Some(value); - } - } - } - } - - pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { + fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { ht.elements .iter() .zip(value.elements) .for_each(|(&t, x)| self.set_target(t, x)); } - pub fn set_cap_target(&mut self, ct: &MerkleCapTarget, value: &MerkleCap) { + fn set_cap_target(&mut self, ct: &MerkleCapTarget, value: &MerkleCap) { for (ht, h) in ct.0.iter().zip(&value.0) { self.set_hash_target(*ht, *h); } } - pub fn set_extension_target( - &mut self, - et: ExtensionTarget, - value: F::Extension, - ) where + fn set_extension_target(&mut self, et: ExtensionTarget, value: F::Extension) + where F: Extendable, { let limbs = value.to_basefield_array(); @@ -176,7 +97,7 @@ impl PartialWitness { }); } - pub fn set_extension_targets( + fn set_extension_targets( &mut self, ets: &[ExtensionTarget], values: &[F::Extension], @@ -189,15 +110,15 @@ impl PartialWitness { .for_each(|(&et, &v)| self.set_extension_target(et, v)); } - pub fn set_bool_target(&mut self, target: BoolTarget, value: bool) { + fn set_bool_target(&mut self, target: BoolTarget, value: bool) { self.set_target(target.target, F::from_bool(value)) } - pub fn set_wire(&mut self, wire: Wire, value: F) { + fn set_wire(&mut self, wire: Wire, value: F) { self.set_target(Target::Wire(wire), value) } - pub fn set_wires(&mut self, wires: W, values: &[F]) + fn set_wires(&mut self, wires: W, values: &[F]) where W: IntoIterator, { @@ -207,7 +128,7 @@ impl PartialWitness { } } - pub fn set_ext_wires(&mut self, wires: W, value: F::Extension) + fn set_ext_wires(&mut self, wires: W, value: F::Extension) where F: Extendable, W: IntoIterator, @@ -215,57 +136,104 @@ impl PartialWitness { self.set_wires(wires, &value.to_basefield_array()); } - pub fn extend>(&mut self, pairs: I) { + fn extend>(&mut self, pairs: I) { for (t, v) in pairs { self.set_target(t, v); } } +} - pub fn full_witness(self, degree: usize, num_wires: usize) -> Witness { - let mut wire_values = vec![vec![F::ZERO; degree]; num_wires]; - assert!(self.wire_values.len() <= degree); - for i in 0..self.wire_values.len() { - for j in 0..num_wires { - wire_values[j][i] = self.wire_values[i][j].unwrap_or(F::ZERO); - } - } - Witness { wire_values } - } +#[derive(Clone, Debug)] +pub struct MatrixWitness { + pub(crate) wire_values: Vec>, +} - /// Checks that the copy constraints are satisfied in the witness. - pub fn check_copy_constraints( - &self, - copy_constraints: &[CopyConstraint], - gate_instances: &[GateInstance], - ) -> Result<()> - where - F: Extendable, - { - for CopyConstraint { pair: (a, b), name } in copy_constraints { - let va = self.try_get_target(*a).unwrap_or(F::ZERO); - let vb = self.try_get_target(*b).unwrap_or(F::ZERO); - let desc = |t: &Target| -> String { - match t { - Target::Wire(Wire { gate, input }) => format!( - "wire {} of gate #{} (`{}`)", - input, - gate, - gate_instances[*gate].gate_ref.0.id() - ), - Target::VirtualTarget { index } => format!("{}-th virtual target", index), - } - }; - ensure!( - va == vb, - "Copy constraint '{}' between {} and {} is not satisfied. \ - Got values of {} and {} respectively.", - name, - desc(a), - desc(b), - va, - vb - ); - } - Ok(()) +impl MatrixWitness { + pub fn get_wire(&self, gate: usize, input: usize) -> F { + self.wire_values[input][gate] + } +} + +#[derive(Clone, Debug)] +pub struct PartialWitness { + pub(crate) target_values: HashMap, +} + +impl PartialWitness { + pub fn new() -> Self { + PartialWitness { + target_values: HashMap::new(), + } + } +} + +impl Witness for PartialWitness { + fn try_get_target(&self, target: Target) -> Option { + self.target_values.get(&target).copied() + } + + fn set_target(&mut self, target: Target, value: F) { + let opt_old_value = self.target_values.insert(target, value); + if let Some(old_value) = opt_old_value { + assert_eq!( + old_value, value, + "Target {:?} was set twice with different values", + target + ); + } + } +} + +/// `PartitionWitness` holds a disjoint-set forest of the targets respecting a circuit's copy constraints. +/// The value of a target is defined to be the value of its root in the forest. +#[derive(Clone)] +pub struct PartitionWitness { + pub forest: Vec>, + pub num_wires: usize, + pub num_routed_wires: usize, + pub degree: usize, +} + +impl Witness for PartitionWitness { + fn try_get_target(&self, target: Target) -> Option { + let parent_index = self.forest[self.target_index(target)].parent; + self.forest[parent_index].value + } + + fn set_target(&mut self, target: Target, value: F) { + let parent_index = self.forest[self.target_index(target)].parent; + let parent_value = &mut self.forest[parent_index].value; + if let Some(old_value) = *parent_value { + assert_eq!( + value, old_value, + "Partition containing {:?} was set twice with different values", + target + ); + } else { + *parent_value = Some(value); + } + } +} + +impl PartitionWitness { + pub fn target_index(&self, target: Target) -> usize { + match target { + Target::Wire(Wire { gate, input }) => gate * self.num_wires + input, + Target::VirtualTarget { index } => self.degree * self.num_wires + index, + } + } + + pub fn full_witness(self) -> MatrixWitness { + let mut wire_values = vec![vec![F::ZERO; self.degree]; self.num_wires]; + for i in 0..self.degree { + for j in 0..self.num_wires { + let t = Target::Wire(Wire { gate: i, input: j }); + if let Some(x) = self.try_get_target(t) { + wire_values[j][i] = x; + } + } + } + + MatrixWitness { wire_values } } } diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 8afec0e4..56bee0a5 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -19,12 +19,12 @@ use crate::hash::hashing::hash_n_to_hash; use crate::iop::generator::{CopyGenerator, RandomValueGenerator, WitnessGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; +use crate::iop::witness::PartitionWitness; use crate::plonk::circuit_data::{ CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, VerifierCircuitData, VerifierOnlyCircuitData, }; use crate::plonk::copy_constraint::CopyConstraint; -use crate::plonk::permutation_argument::TargetPartition; use crate::plonk::plonk_common::PlonkPolynomials; use crate::polynomial::polynomial::PolynomialValues; use crate::util::context_tree::ContextTree; @@ -173,16 +173,13 @@ impl, const D: usize> CircuitBuilder { ); } - /// Shorthand for `generate_copy` and `assert_equal`. /// Both elements must be routable, otherwise this method will panic. pub fn route(&mut self, src: Target, dst: Target) { - self.generate_copy(src, dst); self.assert_equal(src, dst); } /// Same as `route` with a named copy constraint. pub fn named_route(&mut self, src: Target, dst: Target, name: String) { - self.generate_copy(src, dst); self.named_assert_equal(src, dst, name); } @@ -502,30 +499,39 @@ impl, const D: usize> CircuitBuilder { .collect() } - fn sigma_vecs(&self, k_is: &[F], subgroup: &[F]) -> Vec> { + fn sigma_vecs( + &self, + k_is: &[F], + subgroup: &[F], + ) -> (Vec>, PartitionWitness) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); - let mut target_partition = TargetPartition::new(|t| match t { - Target::Wire(Wire { gate, input }) => gate * self.config.num_routed_wires + input, - Target::VirtualTarget { index } => degree * self.config.num_routed_wires + index, - }); + let mut partition_witness = PartitionWitness::new( + self.config.num_wires, + self.config.num_routed_wires, + degree, + self.virtual_target_index, + ); for gate in 0..degree { - for input in 0..self.config.num_routed_wires { - target_partition.add(Target::Wire(Wire { gate, input })); + for input in 0..self.config.num_wires { + partition_witness.add(Target::Wire(Wire { gate, input })); } } for index in 0..self.virtual_target_index { - target_partition.add(Target::VirtualTarget { index }); + partition_witness.add(Target::VirtualTarget { index }); } for &CopyConstraint { pair: (a, b), .. } in &self.copy_constraints { - target_partition.merge(a, b); + partition_witness.merge(a, b); } - let wire_partition = target_partition.wire_partition(); - wire_partition.get_sigma_polys(degree_log, k_is, subgroup) + let wire_partition = partition_witness.wire_partition(); + ( + wire_partition.get_sigma_polys(degree_log, k_is, subgroup), + partition_witness, + ) } /// Fill the remaining unused arithmetic operations with zeros, so that all @@ -614,7 +620,7 @@ impl, const D: usize> CircuitBuilder { let constant_vecs = self.constant_polys(&prefixed_gates, num_constants); let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires); - let sigma_vecs = self.sigma_vecs(&k_is, &subgroup); + let (sigma_vecs, partition_witness) = self.sigma_vecs(&k_is, &subgroup); let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat(); let constants_sigmas_commitment = PolynomialBatchCommitment::from_values( @@ -635,11 +641,10 @@ impl, const D: usize> CircuitBuilder { constants_sigmas_commitment, sigmas: transpose_poly_values(sigma_vecs), subgroup, - copy_constraints: self.copy_constraints, gate_instances: self.gate_instances, public_inputs: self.public_inputs, marked_targets: self.marked_targets, - num_virtual_targets: self.virtual_target_index, + partition_witness, }; // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index 21ab39d6..e6df4ae8 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -11,8 +11,7 @@ use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; -use crate::plonk::copy_constraint::CopyConstraint; +use crate::iop::witness::{PartialWitness, PartitionWitness}; use crate::plonk::proof::ProofWithPublicInputs; use crate::plonk::prover::prove; use crate::plonk::verifier::verify; @@ -148,16 +147,14 @@ pub(crate) struct ProverOnlyCircuitData, const D: usize> { pub sigmas: Vec>, /// Subgroup of order `degree`. pub subgroup: Vec, - /// The circuit's copy constraints. - pub copy_constraints: Vec, /// The concrete placement of each gate in the circuit. pub gate_instances: Vec>, /// Targets to be made public. pub public_inputs: Vec, /// A vector of marked targets. The values assigned to these targets will be displayed by the prover. pub marked_targets: Vec>, - /// Number of virtual targets used in the circuit. - pub num_virtual_targets: usize, + /// Partial witness holding the copy constraints information. + pub partition_witness: PartitionWitness, } /// Circuit data required by the verifier, but not the prover. diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index 08ebcd48..3d7d68b8 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -1,52 +1,55 @@ use std::collections::HashMap; use std::fmt::Debug; -use std::hash::Hash; use rayon::prelude::*; use crate::field::field_types::Field; use crate::iop::target::Target; use crate::iop::wire::Wire; +use crate::iop::witness::PartitionWitness; use crate::polynomial::polynomial::PolynomialValues; /// Node in the Disjoint Set Forest. #[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct ForestNode { - t: T, - parent: usize, - size: usize, - index: usize, +pub struct ForestNode { + pub t: T, + pub parent: usize, + pub size: usize, + pub index: usize, + pub value: Option, } /// Disjoint Set Forest data-structure following https://en.wikipedia.org/wiki/Disjoint-set_data_structure. -#[derive(Debug, Clone)] -pub struct TargetPartition usize> { - forest: Vec>, - /// Function to compute a node's index in the forest. - indices: F, -} - -impl usize> TargetPartition { - pub fn new(f: F) -> Self { +impl PartitionWitness { + pub fn new( + num_wires: usize, + num_routed_wires: usize, + degree: usize, + num_virtual_targets: usize, + ) -> Self { Self { - forest: Vec::new(), - indices: f, + forest: Vec::with_capacity(degree * num_wires + num_virtual_targets), + num_wires, + num_routed_wires, + degree, } } + /// Add a new partition with a single member. - pub fn add(&mut self, t: T) { + pub fn add(&mut self, t: Target) { let index = self.forest.len(); - debug_assert_eq!((self.indices)(t), index); + debug_assert_eq!(self.target_index(t), index); self.forest.push(ForestNode { t, parent: index, size: 1, index, + value: None, }); } /// Path compression method, see https://en.wikipedia.org/wiki/Disjoint-set_data_structure#Finding_set_representatives. - pub fn find(&mut self, x: ForestNode) -> ForestNode { + pub fn find(&mut self, x: ForestNode) -> ForestNode { if x.parent != x.index { let root = self.find(self.forest[x.parent]); self.forest[x.index].parent = root.index; @@ -57,9 +60,9 @@ impl usize> TargetPartition } /// Merge two sets. - pub fn merge(&mut self, tx: T, ty: T) { - let mut x = self.forest[(self.indices)(tx)]; - let mut y = self.forest[(self.indices)(ty)]; + pub fn merge(&mut self, tx: Target, ty: Target) { + let mut x = self.forest[self.target_index(tx)]; + let mut y = self.forest[self.target_index(ty)]; x = self.find(x); y = self.find(y); @@ -79,44 +82,36 @@ impl usize> TargetPartition self.forest[x.index] = x; self.forest[y.index] = y; } -} -impl usize> TargetPartition { - pub fn wire_partition(&mut self) -> WirePartitions { + + pub fn wire_partition(&mut self) -> WirePartition { let mut partition = HashMap::<_, Vec<_>>::new(); - let nodes = self.forest.clone(); - for x in nodes { - let v = partition.entry(self.find(x).t).or_default(); - v.push(x.t); + for gate in 0..self.degree { + for input in 0..self.num_routed_wires { + let w = Wire { gate, input }; + let t = Target::Wire(w); + let x = self.forest[self.target_index(t)]; + partition.entry(self.find(x).t).or_default().push(w); + } + } + // I'm not 100% sure this loop is needed, but I'm afraid removing it might lead to subtle bugs. + for index in 0..self.forest.len() - self.degree * self.num_wires { + let t = Target::VirtualTarget { index }; + let x = self.forest[self.target_index(t)]; + self.find(x); } - let mut indices = HashMap::new(); // Here we keep just the Wire targets, filtering out everything else. - let partition = partition - .into_values() - .map(|v| { - v.into_iter() - .filter_map(|t| match t { - Target::Wire(w) => Some(w), - _ => None, - }) - .collect::>() - }) - .collect::>(); - partition.iter().enumerate().for_each(|(i, v)| { - v.iter().for_each(|t| { - indices.insert(*t, i); - }); - }); + let partition = partition.into_values().collect::>(); - WirePartitions { partition } + WirePartition { partition } } } -pub struct WirePartitions { +pub struct WirePartition { partition: Vec>, } -impl WirePartitions { +impl WirePartition { pub(crate) fn get_sigma_polys( &self, degree_log: usize, diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 0d66daa8..a7a939bc 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -8,7 +8,7 @@ use crate::hash::hash_types::HashOut; use crate::hash::hashing::hash_n_to_hash; use crate::iop::challenger::Challenger; use crate::iop::generator::generate_partial_witness; -use crate::iop::witness::{PartialWitness, Witness}; +use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::plonk_common::ZeroPolyOnCoset; @@ -28,44 +28,39 @@ pub(crate) fn prove, const D: usize>( ) -> Result> { let mut timing = TimingTree::new("prove", Level::Debug); let config = &common_data.config; - let num_wires = config.num_wires; let num_challenges = config.num_challenges; let quotient_degree = common_data.quotient_degree(); let degree = common_data.degree(); - let mut partial_witness = inputs; + let mut partition_witness = prover_data.partition_witness.clone(); + timed!( + timing, + "fill partition witness", + for (t, v) in inputs.target_values.into_iter() { + partition_witness.set_target(t, v); + } + ); + timed!( timing, &format!("run {} generators", prover_data.generators.len()), - generate_partial_witness( - &mut partial_witness, - &prover_data.generators, - config.num_wires, - degree, - prover_data.num_virtual_targets, - &mut timing - ) + generate_partial_witness(&mut partition_witness, &prover_data.generators, &mut timing) ); - let public_inputs = partial_witness.get_targets(&prover_data.public_inputs); + let public_inputs = partition_witness.get_targets(&prover_data.public_inputs); let public_inputs_hash = hash_n_to_hash(public_inputs.clone(), true); - // Display the marked targets for debugging purposes. - for m in &prover_data.marked_targets { - m.display(&partial_witness); + if cfg!(debug_assertions) { + // Display the marked targets for debugging purposes. + for m in &prover_data.marked_targets { + m.display(&partition_witness); + } } - timed!( - timing, - "check copy constraints", - partial_witness - .check_copy_constraints(&prover_data.copy_constraints, &prover_data.gate_instances)? - ); - let witness = timed!( timing, "compute full witness", - partial_witness.full_witness(degree, num_wires) + partition_witness.full_witness() ); let wires_values: Vec> = timed!( @@ -222,7 +217,7 @@ pub(crate) fn prove, const D: usize>( /// Compute the partial products used in the `Z` polynomials. fn all_wires_permutation_partial_products, const D: usize>( - witness: &Witness, + witness: &MatrixWitness, betas: &[F], gammas: &[F], prover_data: &ProverOnlyCircuitData, @@ -245,7 +240,7 @@ fn all_wires_permutation_partial_products, const D: usize>( /// Returns the polynomials interpolating `partial_products(f / g)` /// where `f, g` are the products in the definition of `Z`: `Z(g^i) = f / g`. fn wires_permutation_partial_products, const D: usize>( - witness: &Witness, + witness: &MatrixWitness, beta: F, gamma: F, prover_data: &ProverOnlyCircuitData, @@ -259,14 +254,12 @@ fn wires_permutation_partial_products, const D: usize>( .enumerate() .map(|(i, &x)| { let s_sigmas = &prover_data.sigmas[i]; - let numerators = (0..common_data.config.num_routed_wires) - .map(|j| { - let wire_value = witness.get_wire(i, j); - let k_i = k_is[j]; - let s_id = k_i * x; - wire_value + beta * s_id + gamma - }) - .collect::>(); + let numerators = (0..common_data.config.num_routed_wires).map(|j| { + let wire_value = witness.get_wire(i, j); + let k_i = k_is[j]; + let s_id = k_i * x; + wire_value + beta * s_id + gamma + }); let denominators = (0..common_data.config.num_routed_wires) .map(|j| { let wire_value = witness.get_wire(i, j); @@ -276,7 +269,6 @@ fn wires_permutation_partial_products, const D: usize>( .collect::>(); let denominator_invs = F::batch_multiplicative_inverse(&denominators); let quotient_values = numerators - .into_iter() .zip(denominator_invs) .map(|(num, den_inv)| num * den_inv) .collect::>(); diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 5f45af7e..14a60df3 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -137,7 +137,7 @@ mod tests { use crate::fri::FriConfig; use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; use crate::hash::merkle_proofs::MerkleProofTarget; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::proof::{OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs}; use crate::plonk::verifier::verify; use crate::util::log2_strict; @@ -386,7 +386,7 @@ mod tests { } let data = builder.build(); ( - data.prove(PartialWitness::new(config.num_wires))?, + data.prove(PartialWitness::new())?, data.verifier_only, data.common, ) @@ -394,7 +394,7 @@ mod tests { verify(proof_with_pis.clone(), &vd, &cd)?; let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let pt = proof_to_proof_target(&proof_with_pis, &mut builder); set_proof_target(&proof_with_pis, &pt, &mut pw); @@ -442,7 +442,7 @@ mod tests { } let data = builder.build(); ( - data.prove(PartialWitness::new(config.num_wires))?, + data.prove(PartialWitness::new())?, data.verifier_only, data.common, ) @@ -450,7 +450,7 @@ mod tests { verify(proof_with_pis.clone(), &vd, &cd)?; let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let pt = proof_to_proof_target(&proof_with_pis, &mut builder); set_proof_target(&proof_with_pis, &pt, &mut pw); @@ -468,7 +468,7 @@ mod tests { verify(proof_with_pis.clone(), &vd, &cd)?; let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let pt = proof_to_proof_target(&proof_with_pis, &mut builder); set_proof_target(&proof_with_pis, &pt, &mut pw); diff --git a/src/util/marking.rs b/src/util/marking.rs index e98f7cbc..acbf8543 100644 --- a/src/util/marking.rs +++ b/src/util/marking.rs @@ -2,7 +2,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::hash::hash_types::HashOutTarget; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartitionWitness, Witness}; /// Enum representing all types of targets, so that they can be marked. #[derive(Clone)] @@ -36,7 +36,7 @@ impl>, const D: usize> From> for Markable { impl Markable { /// Display a `Markable` by querying a partial witness. - fn print_markable>(&self, pw: &PartialWitness) { + fn print_markable>(&self, pw: &PartitionWitness) { match self { Markable::Target(t) => println!("{}", pw.get_target(*t)), Markable::ExtensionTarget(et) => println!("{}", pw.get_extension_target(*et)), @@ -55,7 +55,7 @@ pub struct MarkedTargets { impl MarkedTargets { /// Display the collection of targets along with its name by querying a partial witness. - pub fn display>(&self, pw: &PartialWitness) { + pub fn display>(&self, pw: &PartitionWitness) { println!("Values for {}:", self.name); self.targets.print_markable(pw); println!("End of values for {}", self.name); diff --git a/src/util/reducing.rs b/src/util/reducing.rs index ac8cdd6a..1952d8cb 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -200,7 +200,7 @@ mod tests { let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let alpha = FF::rand(); @@ -228,7 +228,7 @@ mod tests { let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let alpha = FF::rand();