First pass

This commit is contained in:
wborgeaud 2021-08-19 14:54:11 +02:00
parent 7c97751c13
commit 74c2be5090
20 changed files with 499 additions and 262 deletions

View File

@ -5,7 +5,7 @@ use crate::field::extension_field::FieldExtension;
use crate::field::extension_field::{Extendable, OEF};
use crate::field::field_types::Field;
use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS};
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -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: &Yo<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;

View File

@ -1,7 +1,7 @@
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::base_sum::BaseSumGate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo};
use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -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: &Yo<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

@ -3,7 +3,7 @@ use std::borrow::Borrow;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::base_sum::BaseSumGate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo};
use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -68,7 +68,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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) {
let sum = self
.limbs
.iter()

View File

@ -1,7 +1,7 @@
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::base_sum::BaseSumGate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo};
use crate::iop::target::{BoolTarget, Target};
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -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: &Yo<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: &Yo<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

@ -4,7 +4,7 @@ use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::extension_field::FieldExtension;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -138,7 +138,7 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
}
}
#[derive(Clone)]
#[derive(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: &Yo<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

@ -4,7 +4,7 @@ use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -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: &Yo<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

@ -2,7 +2,7 @@ use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::PartialWitness;
@ -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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) {
let wire = Wire {
gate: self.gate_index,
input: ConstantGate::WIRE_OUTPUT,

View File

@ -4,7 +4,7 @@ use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::PartialWitness;
@ -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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) {
let local_wire = |input| Wire {
gate: self.gate_index,
input,

View File

@ -5,7 +5,7 @@ use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::hash::gmimc::gmimc_automatic_constants;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::PartialWitness;
@ -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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) {
let mut state = (0..W)
.map(|i| {
witness.get_wire(Wire {
@ -317,89 +317,89 @@ impl<F: Extendable<D>, const D: usize, const R: usize> SimpleGenerator<F>
}
}
#[cfg(test)]
mod tests {
use std::convert::TryInto;
use std::sync::Arc;
use anyhow::Result;
use crate::field::crandall_field::CrandallField;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::gates::gmimc::{GMiMCGate, W};
use crate::hash::gmimc::gmimc_permute_naive;
use crate::iop::generator::generate_partial_witness;
use crate::iop::wire::Wire;
use crate::iop::witness::PartialWitness;
use crate::util::timing::TimingTree;
#[test]
fn generated_output() {
type F = CrandallField;
const R: usize = 101;
let constants = Arc::new([F::TWO; R]);
type Gate = GMiMCGate<F, 4, R>;
let gate = Gate::new(constants.clone());
let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::<Vec<_>>();
let mut witness = PartialWitness::new(gate.num_wires());
witness.set_wire(
Wire {
gate: 0,
input: Gate::WIRE_SWAP,
},
F::ZERO,
);
for i in 0..W {
witness.set_wire(
Wire {
gate: 0,
input: Gate::wire_input(i),
},
permutation_inputs[i],
);
}
let generators = gate.generators(0, &[]);
generate_partial_witness(
&mut witness,
&generators,
gate.num_wires(),
1,
1,
&mut TimingTree::default(),
);
let expected_outputs: [F; W] =
gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants);
for i in 0..W {
let out = witness.get_wire(Wire {
gate: 0,
input: Gate::wire_output(i),
});
assert_eq!(out, expected_outputs[i]);
}
}
#[test]
fn low_degree() {
type F = CrandallField;
const R: usize = 101;
let constants = Arc::new([F::TWO; R]);
let gate = GMiMCGate::<F, 4, R>::new(constants);
test_low_degree(gate)
}
#[test]
fn eval_fns() -> Result<()> {
type F = CrandallField;
const R: usize = 101;
let constants = Arc::new([F::TWO; R]);
let gate = GMiMCGate::<F, 4, R>::new(constants);
test_eval_fns(gate)
}
}
// #[cfg(test)]
// mod tests {
// use std::convert::TryInto;
// use std::sync::Arc;
//
// use anyhow::Result;
//
// use crate::field::crandall_field::CrandallField;
// use crate::field::field_types::Field;
// use crate::gates::gate::Gate;
// use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
// use crate::gates::gmimc::{GMiMCGate, W};
// use crate::hash::gmimc::gmimc_permute_naive;
// use crate::iop::generator::generate_partial_witness;
// use crate::iop::wire::Wire;
// use crate::iop::witness::PartialWitness;
// use crate::util::timing::TimingTree;
//
// #[test]
// fn generated_output() {
// type F = CrandallField;
// const R: usize = 101;
// let constants = Arc::new([F::TWO; R]);
// type Gate = GMiMCGate<F, 4, R>;
// let gate = Gate::new(constants.clone());
//
// let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::<Vec<_>>();
//
// let mut witness = PartialWitness::new(gate.num_wires());
// witness.set_wire(
// Wire {
// gate: 0,
// input: Gate::WIRE_SWAP,
// },
// F::ZERO,
// );
// for i in 0..W {
// witness.set_wire(
// Wire {
// gate: 0,
// input: Gate::wire_input(i),
// },
// permutation_inputs[i],
// );
// }
//
// let generators = gate.generators(0, &[]);
// generate_partial_witness(
// &mut witness,
// &generators,
// gate.num_wires(),
// 1,
// 1,
// &mut TimingTree::default(),
// );
//
// let expected_outputs: [F; W] =
// gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants);
//
// for i in 0..W {
// let out = witness.get_wire(Wire {
// gate: 0,
// input: Gate::wire_output(i),
// });
// assert_eq!(out, expected_outputs[i]);
// }
// }
//
// #[test]
// fn low_degree() {
// type F = CrandallField;
// const R: usize = 101;
// let constants = Arc::new([F::TWO; R]);
// let gate = GMiMCGate::<F, 4, R>::new(constants);
// test_low_degree(gate)
// }
//
// #[test]
// fn eval_fns() -> Result<()> {
// type F = CrandallField;
// const R: usize = 101;
// let constants = Arc::new([F::TWO; R]);
// let gate = GMiMCGate::<F, 4, R>::new(constants);
// test_eval_fns(gate)
// }
// }

View File

@ -6,7 +6,7 @@ use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::PartialWitness;
@ -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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) {
let local_wire = |input| Wire {
gate: self.gate_index,
input,

View File

@ -8,7 +8,7 @@ use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::interpolation::interpolant;
use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::PartialWitness;
@ -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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) {
let n = self.gate.num_points;
let local_wire = |input| Wire {

View File

@ -5,7 +5,7 @@ use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::PartialWitness;
@ -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: &Yo<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::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::extension_field::FieldExtension;
use crate::gates::gate::Gate;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo};
use crate::iop::target::Target;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -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: &Yo<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

@ -353,89 +353,89 @@ impl RecursiveChallenger {
}
}
#[cfg(test)]
mod tests {
use crate::field::crandall_field::CrandallField;
use crate::field::field_types::Field;
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::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::util::timing::TimingTree;
#[test]
fn no_duplicate_challenges() {
type F = CrandallField;
let mut challenger = Challenger::new();
let mut challenges = Vec::new();
for i in 1..10 {
challenges.extend(challenger.get_n_challenges(i));
challenger.observe_element(F::rand());
}
let dedup_challenges = {
let mut dedup = challenges.clone();
dedup.dedup();
dedup
};
assert_eq!(dedup_challenges, challenges);
}
/// Tests for consistency between `Challenger` and `RecursiveChallenger`.
#[test]
fn test_consistency() {
type F = CrandallField;
// These are mostly arbitrary, but we want to test some rounds with enough inputs/outputs to
// trigger multiple absorptions/squeezes.
let num_inputs_per_round = vec![2, 5, 3];
let num_outputs_per_round = vec![1, 2, 4];
// Generate random input messages.
let inputs_per_round: Vec<Vec<F>> = num_inputs_per_round
.iter()
.map(|&n| F::rand_vec(n))
.collect();
let mut challenger = Challenger::new();
let mut outputs_per_round: Vec<Vec<F>> = Vec::new();
for (r, inputs) in inputs_per_round.iter().enumerate() {
challenger.observe_elements(inputs);
outputs_per_round.push(challenger.get_n_challenges(num_outputs_per_round[r]));
}
let config = CircuitConfig {
num_wires: 12 + 12 + 1 + 101,
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();
for (r, inputs) in inputs_per_round.iter().enumerate() {
recursive_challenger.observe_elements(&builder.constants(inputs));
recursive_outputs_per_round.push(
recursive_challenger.get_n_challenges(&mut builder, num_outputs_per_round[r]),
);
}
let circuit = builder.build();
generate_partial_witness(
&mut 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))
.collect();
assert_eq!(outputs_per_round, recursive_output_values_per_round);
}
}
// #[cfg(test)]
// mod tests {
// use crate::field::crandall_field::CrandallField;
// use crate::field::field_types::Field;
// 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::plonk::circuit_builder::CircuitBuilder;
// use crate::plonk::circuit_data::CircuitConfig;
// use crate::util::timing::TimingTree;
//
// #[test]
// fn no_duplicate_challenges() {
// type F = CrandallField;
// let mut challenger = Challenger::new();
// let mut challenges = Vec::new();
//
// for i in 1..10 {
// challenges.extend(challenger.get_n_challenges(i));
// challenger.observe_element(F::rand());
// }
//
// let dedup_challenges = {
// let mut dedup = challenges.clone();
// dedup.dedup();
// dedup
// };
// assert_eq!(dedup_challenges, challenges);
// }
//
// /// Tests for consistency between `Challenger` and `RecursiveChallenger`.
// #[test]
// fn test_consistency() {
// type F = CrandallField;
//
// // These are mostly arbitrary, but we want to test some rounds with enough inputs/outputs to
// // trigger multiple absorptions/squeezes.
// let num_inputs_per_round = vec![2, 5, 3];
// let num_outputs_per_round = vec![1, 2, 4];
//
// // Generate random input messages.
// let inputs_per_round: Vec<Vec<F>> = num_inputs_per_round
// .iter()
// .map(|&n| F::rand_vec(n))
// .collect();
//
// let mut challenger = Challenger::new();
// let mut outputs_per_round: Vec<Vec<F>> = Vec::new();
// for (r, inputs) in inputs_per_round.iter().enumerate() {
// challenger.observe_elements(inputs);
// outputs_per_round.push(challenger.get_n_challenges(num_outputs_per_round[r]));
// }
//
// let config = CircuitConfig {
// num_wires: 12 + 12 + 1 + 101,
// 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();
// for (r, inputs) in inputs_per_round.iter().enumerate() {
// recursive_challenger.observe_elements(&builder.constants(inputs));
// recursive_outputs_per_round.push(
// recursive_challenger.get_n_challenges(&mut builder, num_outputs_per_round[r]),
// );
// }
// let circuit = builder.build();
// generate_partial_witness(
// &mut 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))
// .collect();
//
// assert_eq!(outputs_per_round, recursive_output_values_per_round);
// }
// }

View File

@ -1,41 +1,199 @@
use std::convert::identity;
use std::convert::{identity, TryInto};
use std::fmt::Debug;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::hash::hash_types::{HashOut, HashOutTarget};
use crate::iop::target::Target;
use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget};
use crate::hash::merkle_tree::MerkleCap;
use crate::iop::target::{BoolTarget, Target};
use crate::iop::wire::Wire;
use crate::iop::witness::PartialWitness;
use crate::iop::witness::{PartialWitness, Witness};
use crate::plonk::permutation_argument::ForestNode;
use crate::timed;
use crate::util::timing::TimingTree;
pub struct Yo<F: Field>(
pub Vec<ForestNode<Target, F>>,
pub Box<dyn Fn(Target) -> usize>,
);
impl<F: Field> Yo<F> {
pub fn get_target(&self, target: Target) -> F {
self.0[self.0[self.1(target)].parent].value.unwrap()
}
pub 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
where
F: Extendable<D>,
{
F::Extension::from_basefield_array(
self.get_targets(&et.to_target_array()).try_into().unwrap(),
)
}
pub fn get_extension_targets<const D: usize>(
&self,
ets: &[ExtensionTarget<D>],
) -> Vec<F::Extension>
where
F: Extendable<D>,
{
ets.iter()
.map(|&et| self.get_extension_target(et))
.collect()
}
pub fn get_bool_target(&self, target: BoolTarget) -> bool {
let value = self.get_target(target.target).to_canonical_u64();
match value {
0 => false,
1 => true,
_ => panic!("not a bool"),
}
}
pub 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> {
self.0[self.0[self.1(target)].parent].value
}
pub fn get_wire(&self, wire: Wire) -> F {
self.get_target(Target::Wire(wire))
}
pub fn try_get_wire(&self, wire: Wire) -> Option<F> {
self.try_get_target(Target::Wire(wire))
}
pub fn contains(&self, target: Target) -> bool {
self.0[self.0[self.1(target)].parent].value.is_some()
}
pub fn contains_all(&self, targets: &[Target]) -> bool {
targets.iter().all(|&t| self.contains(t))
}
pub fn set_target(&mut self, target: Target, value: F) {
let i = self.0[self.1(target)].parent;
self.0[i].value = Some(value);
}
pub 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>) {
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
F: Extendable<D>,
{
let limbs = value.to_basefield_array();
(0..D).for_each(|i| {
self.set_target(et.0[i], limbs[i]);
});
}
pub fn set_extension_targets<const D: usize>(
&mut self,
ets: &[ExtensionTarget<D>],
values: &[F::Extension],
) where
F: Extendable<D>,
{
debug_assert_eq!(ets.len(), values.len());
ets.iter()
.zip(values)
.for_each(|(&et, &v)| self.set_extension_target(et, v));
}
pub 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) {
self.set_target(Target::Wire(wire), value)
}
pub fn set_wires<W>(&mut self, wires: W, values: &[F])
where
W: IntoIterator<Item = Wire>,
{
// If we used itertools, we could use zip_eq for extra safety.
for (wire, &value) in wires.into_iter().zip(values) {
self.set_wire(wire, value);
}
}
pub fn set_ext_wires<W, const D: usize>(&mut self, wires: W, value: F::Extension)
where
F: Extendable<D>,
W: IntoIterator<Item = Wire>,
{
self.set_wires(wires, &value.to_basefield_array());
}
pub 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..degree {
for j in 0..num_wires {
let t = Target::Wire(Wire { gate: i, input: j });
wire_values[j][i] = self.0[self.0[self.1(t)].parent].value.unwrap_or(F::ZERO);
}
}
Witness { wire_values }
}
}
/// Given a `PartialWitness` 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 Yo<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 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 = witness.0.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.1(watch)].push(i);
}
}
});
@ -65,7 +223,7 @@ pub(crate) fn generate_partial_witness<F: Field>(
// 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)] {
for &watching_generator_idx in &generator_indices_by_watches[witness.1(watch)] {
next_pending_generator_indices.push(watching_generator_idx);
}
}
@ -76,6 +234,19 @@ pub(crate) fn generate_partial_witness<F: Field>(
pending_generator_indices = next_pending_generator_indices;
}
for i in 0..degree {
for j in 0..num_wires {
if !witness.contains(Target::Wire(Wire { gate: i, input: j })) {
println!("{} {}", i, j);
}
}
}
// for i in 0..generator_is_expired.len() {
// if !generator_is_expired[i] {
// println!("{:?}", generators[i]);
// println!("{:?}", generators[i].watch_list());
// }
// }
assert!(
generator_is_expired.into_iter().all(identity),
"Some generators weren't run."
@ -83,7 +254,7 @@ pub(crate) fn generate_partial_witness<F: Field>(
}
/// 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,7 +262,7 @@ 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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) -> bool;
}
/// Values generated by a generator invocation.
@ -186,10 +357,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: &Yo<F>, out_buffer: &mut GeneratedValues<F>);
}
impl<F: Field, SG: SimpleGenerator<F>> WitnessGenerator<F> for SG {
@ -197,7 +368,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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) -> bool {
if witness.contains_all(&self.dependencies()) {
self.run_once(witness, out_buffer);
true
@ -219,13 +390,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: &Yo<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 +407,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: &Yo<F>, out_buffer: &mut GeneratedValues<F>) {
let random_value = F::rand();
out_buffer.set_target(self.target, random_value);
@ -243,6 +415,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 +426,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: &Yo<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

@ -28,6 +28,7 @@ impl<F: Field> Witness<F> {
pub struct PartialWitness<F: Field> {
pub(crate) wire_values: Vec<Vec<Option<F>>>,
pub(crate) virtual_target_values: Vec<Option<F>>,
pub(crate) set_targets: Vec<(Target, F)>,
}
impl<F: Field> PartialWitness<F> {
@ -35,6 +36,7 @@ impl<F: Field> PartialWitness<F> {
PartialWitness {
wire_values: vec![vec![None; num_wires]],
virtual_target_values: vec![],
set_targets: vec![],
}
}
@ -148,6 +150,7 @@ impl<F: Field> PartialWitness<F> {
}
}
}
self.set_targets.push((target, value));
}
pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut<F>) {

View File

@ -24,7 +24,7 @@ use crate::plonk::circuit_data::{
VerifierCircuitData, VerifierOnlyCircuitData,
};
use crate::plonk::copy_constraint::CopyConstraint;
use crate::plonk::permutation_argument::TargetPartition;
use crate::plonk::permutation_argument::{ForestNode, TargetPartition};
use crate::plonk::plonk_common::PlonkPolynomials;
use crate::polynomial::polynomial::PolynomialValues;
use crate::util::context_tree::ContextTree;
@ -176,13 +176,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.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.generate_copy(src, dst);
self.named_assert_equal(src, dst, name);
}
@ -263,10 +263,14 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
pub fn add_generators(&mut self, generators: Vec<Box<dyn WitnessGenerator<F>>>) {
// for g in &generators {
// println!("{:?}", g);
// }
self.generators.extend(generators);
}
pub fn add_generator<G: WitnessGenerator<F>>(&mut self, generator: G) {
// println!("{:?}", generator);
self.generators.push(Box::new(generator));
}
@ -502,7 +506,11 @@ 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>>, Vec<ForestNode<Target, F>>) {
let degree = self.gate_instances.len();
let degree_log = log2_strict(degree);
let mut target_partition = TargetPartition::new(|t| match t {
@ -524,8 +532,11 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
target_partition.merge(a, b);
}
let wire_partition = target_partition.wire_partition();
wire_partition.get_sigma_polys(degree_log, k_is, subgroup)
let (wire_partition, partition) = target_partition.wire_partition();
(
wire_partition.get_sigma_polys(degree_log, k_is, subgroup),
partition,
)
}
/// Fill the remaining unused arithmetic operations with zeros, so that all
@ -614,7 +625,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) = self.sigma_vecs(&k_is, &subgroup);
let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat();
let constants_sigmas_commitment = PolynomialBatchCommitment::from_values(
@ -640,6 +651,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
public_inputs: self.public_inputs,
marked_targets: self.marked_targets,
num_virtual_targets: self.virtual_target_index,
partition,
};
// The HashSet of gates will have a non-deterministic order. When converting to a Vec, we

View File

@ -13,6 +13,7 @@ use crate::iop::generator::WitnessGenerator;
use crate::iop::target::Target;
use crate::iop::witness::PartialWitness;
use crate::plonk::copy_constraint::CopyConstraint;
use crate::plonk::permutation_argument::ForestNode;
use crate::plonk::proof::ProofWithPublicInputs;
use crate::plonk::prover::prove;
use crate::plonk::verifier::verify;
@ -155,6 +156,8 @@ pub(crate) struct ProverOnlyCircuitData<F: Extendable<D>, const D: usize> {
pub marked_targets: Vec<MarkedTargets<D>>,
/// Number of virtual targets used in the circuit.
pub num_virtual_targets: usize,
pub partition: Vec<ForestNode<Target, F>>,
}
/// Circuit data required by the verifier, but not the prover.

View File

@ -11,22 +11,25 @@ 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>>,
pub struct TargetPartition<T: Debug + Copy + Eq + PartialEq + Hash, V: Field, F: Fn(T) -> usize> {
forest: Vec<ForestNode<T, V>>,
/// 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> {
impl<T: Debug + Copy + Eq + PartialEq + Hash, V: Field, F: Fn(T) -> usize>
TargetPartition<T, V, F>
{
pub fn new(f: F) -> Self {
Self {
forest: Vec::new(),
@ -42,11 +45,12 @@ impl<T: Debug + Copy + Eq + PartialEq + Hash, F: Fn(T) -> usize> TargetPartition
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<T, V>) -> ForestNode<T, V> {
if x.parent != x.index {
let root = self.find(self.forest[x.parent]);
self.forest[x.index].parent = root.index;
@ -80,8 +84,8 @@ impl<T: Debug + Copy + Eq + PartialEq + Hash, F: Fn(T) -> usize> TargetPartition
self.forest[y.index] = y;
}
}
impl<F: Fn(Target) -> usize> TargetPartition<Target, F> {
pub fn wire_partition(&mut self) -> WirePartitions {
impl<V: Field, F: Fn(Target) -> usize> TargetPartition<Target, V, F> {
pub fn wire_partition(mut self) -> (WirePartitions, Vec<ForestNode<Target, V>>) {
let mut partition = HashMap::<_, Vec<_>>::new();
let nodes = self.forest.clone();
for x in nodes {
@ -89,7 +93,7 @@ impl<F: Fn(Target) -> usize> TargetPartition<Target, F> {
v.push(x.t);
}
let mut indices = HashMap::new();
// let mut indices = HashMap::new();
// Here we keep just the Wire targets, filtering out everything else.
let partition = partition
.into_values()
@ -102,13 +106,13 @@ impl<F: Fn(Target) -> usize> TargetPartition<Target, F> {
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
partition.iter().enumerate().for_each(|(i, v)| {
v.iter().for_each(|t| {
indices.insert(*t, i);
});
});
// partition.iter().enumerate().for_each(|(i, v)| {
// v.iter().for_each(|t| {
// indices.insert(*t, i);
// });
// });
WirePartitions { partition }
(WirePartitions { partition }, self.forest)
}
}

View File

@ -7,9 +7,12 @@ use crate::fri::commitment::PolynomialBatchCommitment;
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::generator::{generate_partial_witness, Yo};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartialWitness, Witness};
use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
use crate::plonk::permutation_argument::ForestNode;
use crate::plonk::plonk_common::PlonkPolynomials;
use crate::plonk::plonk_common::ZeroPolyOnCoset;
use crate::plonk::proof::{Proof, ProofWithPublicInputs};
@ -32,8 +35,44 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let num_challenges = config.num_challenges;
let quotient_degree = common_data.quotient_degree();
let degree = common_data.degree();
println!("{}", prover_data.gate_instances[0].gate_ref.0.id());
println!("{}", prover_data.gate_instances[1].gate_ref.0.id());
let mut partial_witness = inputs;
let nrw = config.num_routed_wires;
let nw = config.num_wires;
let nvt = prover_data.num_virtual_targets;
let target_index = move |t: Target| -> usize {
match t {
Target::Wire(Wire { gate, input }) if input < nrw => gate * nrw + input,
Target::Wire(Wire { gate, input }) if input >= nrw => {
degree * nrw + nvt + gate * (nw - nrw) + input - nrw
}
Target::VirtualTarget { index } => degree * nrw + index,
_ => unreachable!(),
}
};
let mut partial_witness = prover_data.partition.clone();
let n = partial_witness.len();
timed!(timing, "fill partition", {
partial_witness.reserve_exact(degree * (config.num_wires - config.num_routed_wires));
for i in 0..degree * (config.num_wires - config.num_routed_wires) {
partial_witness.push(ForestNode {
t: Target::Wire(Wire { gate: 0, input: 0 }),
parent: n + i,
size: 0,
index: n + i,
value: None,
})
}
for &(t, v) in &inputs.set_targets {
// println!("{:?} {} {}", t, target_index(t), partial_witness.len());
let parent = partial_witness[target_index(t)].parent;
// println!("{} {}", parent, partial_witness.len());
partial_witness[parent].value = Some(v);
}
});
// let mut partial_witness = inputs;
let mut partial_witness = Yo(partial_witness, Box::new(target_index));
timed!(
timing,
&format!("run {} generators", prover_data.generators.len()),
@ -50,17 +89,17 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let public_inputs = partial_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);
}
timed!(
timing,
"check copy constraints",
partial_witness
.check_copy_constraints(&prover_data.copy_constraints, &prover_data.gate_instances)?
);
// // Display the marked targets for debugging purposes.
// for m in &prover_data.marked_targets {
// m.display(&partial_witness);
// }
//
// timed!(
// timing,
// "check copy constraints",
// partial_witness
// .check_copy_constraints(&prover_data.copy_constraints, &prover_data.gate_instances)?
// );
let witness = timed!(
timing,