Merge pull request #195 from mir-protocol/partition_witness

Remove `CopyGenerator`s and add new `PartitionWitness`
This commit is contained in:
wborgeaud 2021-08-24 08:16:35 +02:00 committed by GitHub
commit cd1bd9e77b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 325 additions and 365 deletions

View File

@ -35,7 +35,7 @@ fn bench_prove<F: Field + Extendable<D>, const D: usize>() -> Result<()> {
},
};
let inputs = PartialWitness::new(config.num_wires);
let inputs = PartialWitness::new();
let mut builder = CircuitBuilder::<F, D>::new(config);
let zero = builder.zero();

View File

@ -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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
#[derive(Debug)]
struct QuotientGeneratorExtension<const D: usize> {
numerator: ExtensionTarget<D>,
denominator: ExtensionTarget<D>,
@ -446,7 +447,7 @@ impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for QuotientGeneratorE
deps
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
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::<F, D>::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::<F, D>::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::<F, D>::new(config);
let x = FF::rand_vec(4);

View File

@ -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::<F, 4>::new(config);
let v = (0..len - 1)
.map(|_| builder.constant_extension(FF::rand()))

View File

@ -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::<F, 4>::new(config);
let len = 4;

View File

@ -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::<F, 4>::new(config);
let vec = FF::rand_vec(len);
let v: Vec<_> = vec.iter().map(|x| builder.constant_extension(*x)).collect();

View File

@ -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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
@ -56,7 +56,7 @@ impl<F: Field> SimpleGenerator<F> for LowHighGenerator {
vec![self.integer]
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
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;

View File

@ -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::<F, 4>::new(config);
let (x, y) = (FF::rand(), FF::rand());

View File

@ -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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
@ -64,7 +64,7 @@ impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSumGenerator<B> {
self.limbs.iter().map(|b| b.target).collect()
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
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::<F, 4>::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::<F, 4>::new(config);
let n = thread_rng().gen_range(0..(1 << 10));

View File

@ -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<F: Field> SimpleGenerator<F> for SplitGenerator {
vec![self.integer]
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let mut integer_value = witness.get_target(self.integer).to_canonical_u64();
for &b in &self.bits {
@ -96,7 +96,7 @@ impl<F: Field> SimpleGenerator<F> for WireSplitGenerator {
vec![self.integer]
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let mut integer_value = witness.get_target(self.integer).to_canonical_u64();
for &gate in &self.gates {

View File

@ -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<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
}
}
#[derive(Clone)]
#[derive(Clone, Debug)]
struct ArithmeticExtensionGenerator<F: Extendable<D>, const D: usize> {
gate_index: usize,
const_0: F,
@ -157,7 +157,7 @@ impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensio
.collect()
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let extract_extension = |range: Range<usize>| -> F::Extension {
let t = ExtensionTarget::from_range(self.gate_index, range);
witness.get_extension_target(t)

View File

@ -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<F: Field, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B> {
vec![Target::wire(self.gate_index, BaseSumGate::<B>::WIRE_SUM)]
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let sum_value = witness
.get_target(Target::wire(self.gate_index, BaseSumGate::<B>::WIRE_SUM))
.to_canonical_u64() as usize;

View File

@ -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<F: Field> SimpleGenerator<F> for ConstantGenerator<F> {
Vec::new()
}
fn run_once(&self, _witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, _witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let wire = Wire {
gate: self.gate_index,
input: ConstantGate::WIRE_OUTPUT,

View File

@ -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<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ExponentiationGene
deps
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let local_wire = |input| Wire {
gate: self.gate_index,
input,

View File

@ -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<F: Extendable<D>, G: Gate<F, D>, 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::<F, D>::new(config);
let wires_t = builder.add_virtual_extension_targets(wires.len());

View File

@ -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<F: Extendable<D>, const D: usize, const R: usize> SimpleGenerator<F>
.collect()
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
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::<Vec<_>>();
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),
});

View File

@ -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<F: Extendable<D>, const D: usize> SimpleGenerator<F> for InsertionGenerator
deps
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let local_wire = |input| Wire {
gate: self.gate_index,
input,

View File

@ -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<F: Extendable<D>, const D: usize> Gate<F, D> for InterpolationGate<F, D> {
}
}
#[derive(Debug)]
struct InterpolationGenerator<F: Extendable<D>, const D: usize> {
gate_index: usize,
gate: InterpolationGate<F, D>,
@ -239,7 +240,7 @@ impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for InterpolationGener
deps
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let n = self.gate.num_points;
let local_wire = |input| Wire {

View File

@ -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<F: Extendable<D>, const D: usize> SimpleGenerator<F> for RandomAccessGenera
deps
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let local_wire = |input| Wire {
gate: self.gate_index,
input,

View File

@ -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<F: Extendable<D>, const D: usize> Gate<F, D> for ReducingGate<D> {
}
}
#[derive(Debug)]
struct ReducingGenerator<const D: usize> {
gate_index: usize,
gate: ReducingGate<D>,
@ -173,7 +174,7 @@ impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ReducingGenerator<
.collect()
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let extract_extension = |range: Range<usize>| -> F::Extension {
let t = ExtensionTarget::from_range(self.gate_index, range);
witness.get_extension_target(t)

View File

@ -78,7 +78,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
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::<F, 4>::new(config);
let log_n = 8;

View File

@ -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::<F, 4>::new(config.clone());
let mut recursive_challenger = RecursiveChallenger::new(&mut builder);
let mut recursive_outputs_per_round: Vec<Vec<Target>> = 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<Vec<F>> = 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);

View File

@ -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<F: Field>(
witness: &mut PartialWitness<F>,
witness: &mut PartitionWitness<F>,
generators: &[Box<dyn WitnessGenerator<F>>],
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<F: Field>(
// 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<F: Field>(
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<F: Field>: 'static + Send + Sync {
pub trait WitnessGenerator<F: Field>: '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<Target>;
@ -91,10 +86,11 @@ pub trait WitnessGenerator<F: Field>: '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<F>, out_buffer: &mut GeneratedValues<F>) -> bool;
fn run(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) -> bool;
}
/// Values generated by a generator invocation.
#[derive(Debug)]
pub struct GeneratedValues<F: Field> {
pub(crate) target_values: Vec<(Target, F)>,
}
@ -186,10 +182,10 @@ impl<F: Field> GeneratedValues<F> {
}
/// A generator which runs once after a list of dependencies is present in the witness.
pub trait SimpleGenerator<F: Field>: 'static + Send + Sync {
pub trait SimpleGenerator<F: Field>: 'static + Send + Sync + Debug {
fn dependencies(&self) -> Vec<Target>;
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>);
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>);
}
impl<F: Field, SG: SimpleGenerator<F>> WitnessGenerator<F> for SG {
@ -197,7 +193,7 @@ impl<F: Field, SG: SimpleGenerator<F>> WitnessGenerator<F> for SG {
self.dependencies()
}
fn run(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) -> bool {
fn run(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) -> bool {
if witness.contains_all(&self.dependencies()) {
self.run_once(witness, out_buffer);
true
@ -219,13 +215,14 @@ impl<F: Field> SimpleGenerator<F> for CopyGenerator {
vec![self.src]
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
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<F: Field> SimpleGenerator<F> for RandomValueGenerator {
Vec::new()
}
fn run_once(&self, _witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, _witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let random_value = F::rand();
out_buffer.set_target(self.target, random_value);
@ -243,6 +240,7 @@ impl<F: Field> SimpleGenerator<F> 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<F: Field> SimpleGenerator<F> for NonzeroTestGenerator {
vec![self.to_test]
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let to_test_value = witness.get_target(self.to_test);
let dummy_value = if to_test_value == F::ZERO {

View File

@ -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<F: Field> {
pub(crate) wire_values: Vec<Vec<F>>,
}
/// A witness holds information on the values of targets in a circuit.
pub trait Witness<F: Field> {
fn try_get_target(&self, target: Target) -> Option<F>;
impl<F: Field> Witness<F> {
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<F: Field> {
pub(crate) wire_values: Vec<Vec<Option<F>>>,
pub(crate) virtual_target_values: Vec<Option<F>>,
}
impl<F: Field> PartialWitness<F> {
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<F> {
fn get_targets(&self, targets: &[Target]) -> Vec<F> {
targets.iter().map(|&t| self.get_target(t)).collect()
}
pub fn get_extension_target<const D: usize>(&self, et: ExtensionTarget<D>) -> F::Extension
fn get_extension_target<const D: usize>(&self, et: ExtensionTarget<D>) -> F::Extension
where
F: Extendable<D>,
{
@ -58,10 +34,7 @@ impl<F: Field> PartialWitness<F> {
)
}
pub fn get_extension_targets<const D: usize>(
&self,
ets: &[ExtensionTarget<D>],
) -> Vec<F::Extension>
fn get_extension_targets<const D: usize>(&self, ets: &[ExtensionTarget<D>]) -> Vec<F::Extension>
where
F: Extendable<D>,
{
@ -70,7 +43,7 @@ impl<F: Field> PartialWitness<F> {
.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<F: Field> PartialWitness<F> {
}
}
pub fn get_hash_target(&self, ht: HashOutTarget) -> HashOut<F> {
fn get_hash_target(&self, ht: HashOutTarget) -> HashOut<F> {
HashOut {
elements: self.get_targets(&ht.elements).try_into().unwrap(),
}
}
pub fn try_get_target(&self, target: Target) -> Option<F> {
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<F> {
fn try_get_wire(&self, wire: Wire) -> Option<F> {
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<F>) {
fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut<F>) {
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<F>) {
fn set_cap_target(&mut self, ct: &MerkleCapTarget, value: &MerkleCap<F>) {
for (ht, h) in ct.0.iter().zip(&value.0) {
self.set_hash_target(*ht, *h);
}
}
pub fn set_extension_target<const D: usize>(
&mut self,
et: ExtensionTarget<D>,
value: F::Extension,
) where
fn set_extension_target<const D: usize>(&mut self, et: ExtensionTarget<D>, value: F::Extension)
where
F: Extendable<D>,
{
let limbs = value.to_basefield_array();
@ -176,7 +97,7 @@ impl<F: Field> PartialWitness<F> {
});
}
pub fn set_extension_targets<const D: usize>(
fn set_extension_targets<const D: usize>(
&mut self,
ets: &[ExtensionTarget<D>],
values: &[F::Extension],
@ -189,15 +110,15 @@ impl<F: Field> PartialWitness<F> {
.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<W>(&mut self, wires: W, values: &[F])
fn set_wires<W>(&mut self, wires: W, values: &[F])
where
W: IntoIterator<Item = Wire>,
{
@ -207,7 +128,7 @@ impl<F: Field> PartialWitness<F> {
}
}
pub fn set_ext_wires<W, const D: usize>(&mut self, wires: W, value: F::Extension)
fn set_ext_wires<W, const D: usize>(&mut self, wires: W, value: F::Extension)
where
F: Extendable<D>,
W: IntoIterator<Item = Wire>,
@ -215,57 +136,104 @@ impl<F: Field> PartialWitness<F> {
self.set_wires(wires, &value.to_basefield_array());
}
pub fn extend<I: Iterator<Item = (Target, F)>>(&mut self, pairs: I) {
fn extend<I: Iterator<Item = (Target, F)>>(&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<F> {
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<F: Field> {
pub(crate) wire_values: Vec<Vec<F>>,
}
/// Checks that the copy constraints are satisfied in the witness.
pub fn check_copy_constraints<const D: usize>(
&self,
copy_constraints: &[CopyConstraint],
gate_instances: &[GateInstance<F, D>],
) -> Result<()>
where
F: Extendable<D>,
{
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<F: Field> MatrixWitness<F> {
pub fn get_wire(&self, gate: usize, input: usize) -> F {
self.wire_values[input][gate]
}
}
#[derive(Clone, Debug)]
pub struct PartialWitness<F: Field> {
pub(crate) target_values: HashMap<Target, F>,
}
impl<F: Field> PartialWitness<F> {
pub fn new() -> Self {
PartialWitness {
target_values: HashMap::new(),
}
}
}
impl<F: Field> Witness<F> for PartialWitness<F> {
fn try_get_target(&self, target: Target) -> Option<F> {
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<F: Field> {
pub forest: Vec<ForestNode<Target, F>>,
pub num_wires: usize,
pub num_routed_wires: usize,
pub degree: usize,
}
impl<F: Field> Witness<F> for PartitionWitness<F> {
fn try_get_target(&self, target: Target) -> Option<F> {
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<F: Field> PartitionWitness<F> {
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<F> {
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 }
}
}

View File

@ -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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
);
}
/// 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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
.collect()
}
fn sigma_vecs(&self, k_is: &[F], subgroup: &[F]) -> Vec<PolynomialValues<F>> {
fn sigma_vecs(
&self,
k_is: &[F],
subgroup: &[F],
) -> (Vec<PolynomialValues<F>>, PartitionWitness<F>) {
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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
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

View File

@ -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<F: Extendable<D>, const D: usize> {
pub sigmas: Vec<Vec<F>>,
/// Subgroup of order `degree`.
pub subgroup: Vec<F>,
/// The circuit's copy constraints.
pub copy_constraints: Vec<CopyConstraint>,
/// The concrete placement of each gate in the circuit.
pub gate_instances: Vec<GateInstance<F, D>>,
/// Targets to be made public.
pub public_inputs: Vec<Target>,
/// A vector of marked targets. The values assigned to these targets will be displayed by the prover.
pub marked_targets: Vec<MarkedTargets<D>>,
/// Number of virtual targets used in the circuit.
pub num_virtual_targets: usize,
/// Partial witness holding the copy constraints information.
pub partition_witness: PartitionWitness<F>,
}
/// Circuit data required by the verifier, but not the prover.

View File

@ -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: Debug + Copy + Eq + PartialEq> {
t: T,
parent: usize,
size: usize,
index: usize,
pub struct ForestNode<T: Debug + Copy + Eq + PartialEq, V: Field> {
pub t: T,
pub parent: usize,
pub size: usize,
pub index: usize,
pub value: Option<V>,
}
/// Disjoint Set Forest data-structure following https://en.wikipedia.org/wiki/Disjoint-set_data_structure.
#[derive(Debug, Clone)]
pub struct TargetPartition<T: Debug + Copy + Eq + PartialEq + Hash, F: Fn(T) -> usize> {
forest: Vec<ForestNode<T>>,
/// Function to compute a node's index in the forest.
indices: F,
}
impl<T: Debug + Copy + Eq + PartialEq + Hash, F: Fn(T) -> usize> TargetPartition<T, F> {
pub fn new(f: F) -> Self {
impl<F: Field> PartitionWitness<F> {
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<T>) -> ForestNode<T> {
pub fn find(&mut self, x: ForestNode<Target, F>) -> ForestNode<Target, F> {
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<T: Debug + Copy + Eq + PartialEq + Hash, F: Fn(T) -> 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<T: Debug + Copy + Eq + PartialEq + Hash, F: Fn(T) -> usize> TargetPartition
self.forest[x.index] = x;
self.forest[y.index] = y;
}
}
impl<F: Fn(Target) -> usize> TargetPartition<Target, F> {
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::<Vec<_>>()
})
.collect::<Vec<_>>();
partition.iter().enumerate().for_each(|(i, v)| {
v.iter().for_each(|t| {
indices.insert(*t, i);
});
});
let partition = partition.into_values().collect::<Vec<_>>();
WirePartitions { partition }
WirePartition { partition }
}
}
pub struct WirePartitions {
pub struct WirePartition {
partition: Vec<Vec<Wire>>,
}
impl WirePartitions {
impl WirePartition {
pub(crate) fn get_sigma_polys<F: Field>(
&self,
degree_log: usize,

View File

@ -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<F: Extendable<D>, const D: usize>(
) -> Result<ProofWithPublicInputs<F, D>> {
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<PolynomialValues<F>> = timed!(
@ -222,7 +217,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
/// Compute the partial products used in the `Z` polynomials.
fn all_wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
witness: &Witness<F>,
witness: &MatrixWitness<F>,
betas: &[F],
gammas: &[F],
prover_data: &ProverOnlyCircuitData<F, D>,
@ -245,7 +240,7 @@ fn all_wires_permutation_partial_products<F: Extendable<D>, 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<F: Extendable<D>, const D: usize>(
witness: &Witness<F>,
witness: &MatrixWitness<F>,
beta: F,
gamma: F,
prover_data: &ProverOnlyCircuitData<F, D>,
@ -259,14 +254,12 @@ fn wires_permutation_partial_products<F: Extendable<D>, 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::<Vec<_>>();
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<F: Extendable<D>, const D: usize>(
.collect::<Vec<_>>();
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::<Vec<_>>();

View File

@ -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::<F, D>::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::<F, D>::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::<F, D>::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);

View File

@ -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<M: Into<Markable<D>>, const D: usize> From<Vec<M>> for Markable<D> {
impl<const D: usize> Markable<D> {
/// Display a `Markable` by querying a partial witness.
fn print_markable<F: Extendable<D>>(&self, pw: &PartialWitness<F>) {
fn print_markable<F: Extendable<D>>(&self, pw: &PartitionWitness<F>) {
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<const D: usize> {
impl<const D: usize> MarkedTargets<D> {
/// Display the collection of targets along with its name by querying a partial witness.
pub fn display<F: Extendable<D>>(&self, pw: &PartialWitness<F>) {
pub fn display<F: Extendable<D>>(&self, pw: &PartitionWitness<F>) {
println!("Values for {}:", self.name);
self.targets.print_markable(pw);
println!("End of values for {}", self.name);

View File

@ -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::<F, D>::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::<F, D>::new(config);
let alpha = FF::rand();