use std::collections::HashMap; 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, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; use crate::plonk::permutation_argument::ForestNode; use crate::timed; use crate::util::timing::TimingTree; pub struct Yo( pub Vec>, pub Box usize>, ); impl Yo { 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 { targets.iter().map(|&t| self.get_target(t)).collect() } pub fn get_extension_target(&self, et: ExtensionTarget) -> F::Extension where F: Extendable, { F::Extension::from_basefield_array( self.get_targets(&et.to_target_array()).try_into().unwrap(), ) } pub fn get_extension_targets( &self, ets: &[ExtensionTarget], ) -> Vec where F: Extendable, { 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 { HashOut { elements: self.get_targets(&ht.elements).try_into().unwrap(), } } pub fn try_get_target(&self, target: Target) -> Option { 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 { 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) { 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) { for (ht, h) in ct.0.iter().zip(&value.0) { self.set_hash_target(*ht, *h); } } pub fn set_extension_target( &mut self, et: ExtensionTarget, value: F::Extension, ) where F: Extendable, { let limbs = value.to_basefield_array(); (0..D).for_each(|i| { self.set_target(et.0[i], limbs[i]); }); } pub fn set_extension_targets( &mut self, ets: &[ExtensionTarget], values: &[F::Extension], ) where F: Extendable, { 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(&mut self, wires: W, values: &[F]) where W: IntoIterator, { // 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(&mut self, wires: W, value: F::Extension) where F: Extendable, W: IntoIterator, { self.set_wires(wires, &value.to_basefield_array()); } pub fn extend>(&mut self, pairs: I) { for (t, v) in pairs { self.set_target(t, v); } } pub fn full_witness(self, degree: usize, num_wires: usize) -> MatrixWitness { 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); } } MatrixWitness { 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( witness: &mut Yo, generators: &[Box>], num_wires: usize, degree: usize, max_virtual_target: usize, timing: &mut TimingTree, ) { // let target_index = |t: Target| -> usize { // match t { // Target::Wire(Wire { gate, input }) => gate * num_wires + input, // Target::VirtualTarget { index } => degree * num_wires + index, // } // }; let max_target_index = 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[witness.1(watch)].push(i); } } }); // Build a list of "pending" generators which are queued to be run. Initially, all generators // are queued. let mut pending_generator_indices: Vec<_> = (0..generators.len()).collect(); // We also track a list of "expired" generators which have already returned false. let mut generator_is_expired = vec![false; generators.len()]; let mut buffer = GeneratedValues::empty(); let mut count = 0; // Keep running generators until no generators are queued. // while !pending_generator_indices.is_empty() { while !generator_is_expired.iter().all(|&x| x) { let mut next_pending_generator_indices = Vec::new(); for &generator_idx in &pending_generator_indices { if generator_is_expired[generator_idx] { continue; } let finished = generators[generator_idx].run(&witness, &mut buffer); // dbg!(&generators[generator_idx], &buffer); if finished { generator_is_expired[generator_idx] = true; } else { count += 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[witness.1(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; pending_generator_indices = if next_pending_generator_indices.is_empty() { (0..generators.len()).collect() } else { next_pending_generator_indices }; } dbg!(count); // for i in 0..generator_is_expired.len() { // if !generator_is_expired[i] { // println!("{}: {:?}", i, generators[i]); // for a in generators[i].watch_list() { // println!("{:?} {}", a, witness.contains(a)); // } // } // } assert!( generator_is_expired.into_iter().all(identity), "Some generators weren't run." ); } /// A generator participates in the generation of the witness. pub trait WitnessGenerator: 'static + Send + Sync + 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; /// 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: &Yo, out_buffer: &mut GeneratedValues) -> bool; } /// Values generated by a generator invocation. #[derive(Debug)] pub struct GeneratedValues { pub(crate) target_values: Vec<(Target, F)>, } impl From> for GeneratedValues { fn from(target_values: Vec<(Target, F)>) -> Self { Self { target_values } } } impl GeneratedValues { pub fn with_capacity(capacity: usize) -> Self { Vec::with_capacity(capacity).into() } pub fn empty() -> Self { Vec::new().into() } pub fn singleton_wire(wire: Wire, value: F) -> Self { Self::singleton_target(Target::Wire(wire), value) } pub fn singleton_target(target: Target, value: F) -> Self { vec![(target, value)].into() } pub fn clear(&mut self) { self.target_values.clear(); } pub fn singleton_extension_target( et: ExtensionTarget, value: F::Extension, ) -> Self where F: Extendable, { let mut witness = Self::with_capacity(D); witness.set_extension_target(et, value); witness } pub fn set_target(&mut self, target: Target, value: F) { self.target_values.push((target, value)) } pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { ht.elements .iter() .zip(value.elements) .for_each(|(&t, x)| self.set_target(t, x)); } pub fn set_extension_target( &mut self, et: ExtensionTarget, value: F::Extension, ) where F: Extendable, { let limbs = value.to_basefield_array(); (0..D).for_each(|i| { self.set_target(et.0[i], limbs[i]); }); } pub fn set_wire(&mut self, wire: Wire, value: F) { self.set_target(Target::Wire(wire), value) } pub fn set_wires(&mut self, wires: W, values: &[F]) where W: IntoIterator, { // 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(&mut self, wires: W, value: F::Extension) where F: Extendable, W: IntoIterator, { self.set_wires(wires, &value.to_basefield_array()); } } /// A generator which runs once after a list of dependencies is present in the witness. pub trait SimpleGenerator: 'static + Send + Sync + Debug { fn dependencies(&self) -> Vec; fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues); } impl> WitnessGenerator for SG { fn watch_list(&self) -> Vec { self.dependencies() } fn run(&self, witness: &Yo, out_buffer: &mut GeneratedValues) -> bool { if witness.contains_all(&self.dependencies()) { self.run_once(witness, out_buffer); true } else { false } } } /// A generator which copies one wire to another. #[derive(Debug)] pub(crate) struct CopyGenerator { pub(crate) src: Target, pub(crate) dst: Target, } impl SimpleGenerator for CopyGenerator { fn dependencies(&self) -> Vec { vec![self.src] } fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let value = witness.get_target(self.src); out_buffer.set_target(self.dst, value); } } /// A generator for including a random value #[derive(Debug)] pub(crate) struct RandomValueGenerator { pub(crate) target: Target, } impl SimpleGenerator for RandomValueGenerator { fn dependencies(&self) -> Vec { Vec::new() } fn run_once(&self, _witness: &Yo, out_buffer: &mut GeneratedValues) { let random_value = F::rand(); out_buffer.set_target(self.target, random_value); } } /// A generator for testing if a value equals zero #[derive(Debug)] pub(crate) struct NonzeroTestGenerator { pub(crate) to_test: Target, pub(crate) dummy: Target, } impl SimpleGenerator for NonzeroTestGenerator { fn dependencies(&self) -> Vec { vec![self.to_test] } fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let to_test_value = witness.get_target(self.to_test); let dummy_value = if to_test_value == F::ZERO { F::ONE } else { to_test_value.inverse() }; out_buffer.set_target(self.dummy, dummy_value); } }