#[cfg(not(feature = "std"))]
use alloc::{
boxed::Box,
string::{String, ToString},
vec,
vec::Vec,
};
use core::fmt::Debug;
use core::marker::PhantomData;
use anyhow::{anyhow, Result};
use crate::field::extension::Extendable;
use crate::field::types::Field;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartialWitness, PartitionWitness, Witness, WitnessWrite};
use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
use crate::plonk::config::GenericConfig;
use crate::util::serialization::{Buffer, IoResult, Read, Write};
pub fn generate_partial_witness<
'a,
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
const D: usize,
>(
inputs: PartialWitness<F>,
prover_data: &'a ProverOnlyCircuitData<F, C, D>,
common_data: &'a CommonCircuitData<F, D>,
) -> Result<PartitionWitness<'a, F>> {
let config = &common_data.config;
let generators = &prover_data.generators;
let generator_indices_by_watches = &prover_data.generator_indices_by_watches;
let mut witness = PartitionWitness::new(
config.num_wires,
common_data.degree(),
&prover_data.representative_map,
);
for (t, v) in inputs.target_values.into_iter() {
witness.set_target(t, v)?;
}
let mut pending_generator_indices: Vec<_> = (0..generators.len()).collect();
let mut generator_is_expired = vec![false; generators.len()];
let mut remaining_generators = generators.len();
let mut buffer = GeneratedValues::empty();
while !pending_generator_indices.is_empty() {
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].0.run(&witness, &mut buffer);
if finished {
generator_is_expired[generator_idx] = true;
remaining_generators -= 1;
}
let mut new_target_reps = Vec::with_capacity(buffer.target_values.len());
for (t, v) in buffer.target_values.drain(..) {
let reps = witness.set_target_returning_rep(t, v)?;
new_target_reps.extend(reps);
}
for watch in new_target_reps {
let opt_watchers = generator_indices_by_watches.get(&watch);
if let Some(watchers) = opt_watchers {
for &watching_generator_idx in watchers {
if !generator_is_expired[watching_generator_idx] {
next_pending_generator_indices.push(watching_generator_idx);
}
}
}
}
}
pending_generator_indices = next_pending_generator_indices;
}
if remaining_generators != 0 {
return Err(anyhow!("{} generators weren't run", remaining_generators));
}
Ok(witness)
}
pub trait WitnessGenerator<F: RichField + Extendable<D>, const D: usize>:
'static + Send + Sync + Debug
{
fn id(&self) -> String;
fn watch_list(&self) -> Vec<Target>;
fn run(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) -> bool;
fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()>;
fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self>
where
Self: Sized;
}
pub struct WitnessGeneratorRef<F: RichField + Extendable<D>, const D: usize>(
pub Box<dyn WitnessGenerator<F, D>>,
);
impl<F: RichField + Extendable<D>, const D: usize> WitnessGeneratorRef<F, D> {
pub fn new<G: WitnessGenerator<F, D>>(generator: G) -> WitnessGeneratorRef<F, D> {
WitnessGeneratorRef(Box::new(generator))
}
}
impl<F: RichField + Extendable<D>, const D: usize> PartialEq for WitnessGeneratorRef<F, D> {
fn eq(&self, other: &Self) -> bool {
self.0.id() == other.0.id()
}
}
impl<F: RichField + Extendable<D>, const D: usize> Eq for WitnessGeneratorRef<F, D> {}
impl<F: RichField + Extendable<D>, const D: usize> Debug for WitnessGeneratorRef<F, D> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0.id())
}
}
#[derive(Debug)]
pub struct GeneratedValues<F: Field> {
pub target_values: Vec<(Target, F)>,
}
impl<F: Field> From<Vec<(Target, F)>> for GeneratedValues<F> {
fn from(target_values: Vec<(Target, F)>) -> Self {
Self { target_values }
}
}
impl<F: Field> WitnessWrite<F> for GeneratedValues<F> {
fn set_target(&mut self, target: Target, value: F) -> Result<()> {
self.target_values.push((target, value));
Ok(())
}
}
impl<F: Field> GeneratedValues<F> {
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 singleton_extension_target<const D: usize>(
et: ExtensionTarget<D>,
value: F::Extension,
) -> Result<Self>
where
F: RichField + Extendable<D>,
{
let mut witness = Self::with_capacity(D);
witness.set_extension_target(et, value)?;
Ok(witness)
}
}
pub trait SimpleGenerator<F: RichField + Extendable<D>, const D: usize>:
'static + Send + Sync + Debug
{
fn id(&self) -> String;
fn dependencies(&self) -> Vec<Target>;
fn run_once(
&self,
witness: &PartitionWitness<F>,
out_buffer: &mut GeneratedValues<F>,
) -> Result<()>;
fn adapter(self) -> SimpleGeneratorAdapter<F, Self, D>
where
Self: Sized,
{
SimpleGeneratorAdapter {
inner: self,
_phantom: PhantomData,
}
}
fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()>;
fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self>
where
Self: Sized;
}
#[derive(Debug)]
pub struct SimpleGeneratorAdapter<
F: RichField + Extendable<D>,
SG: SimpleGenerator<F, D> + ?Sized,
const D: usize,
> {
_phantom: PhantomData<F>,
inner: SG,
}
impl<F: RichField + Extendable<D>, SG: SimpleGenerator<F, D>, const D: usize> WitnessGenerator<F, D>
for SimpleGeneratorAdapter<F, SG, D>
{
fn id(&self) -> String {
self.inner.id()
}
fn watch_list(&self) -> Vec<Target> {
self.inner.dependencies()
}
fn run(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) -> bool {
if witness.contains_all(&self.inner.dependencies()) {
self.inner.run_once(witness, out_buffer).is_ok()
} else {
false
}
}
fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
self.inner.serialize(dst, common_data)
}
fn deserialize(src: &mut Buffer, common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
Ok(Self {
inner: SG::deserialize(src, common_data)?,
_phantom: PhantomData,
})
}
}
#[derive(Debug, Default)]
pub struct CopyGenerator {
pub(crate) src: Target,
pub(crate) dst: Target,
}
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for CopyGenerator {
fn id(&self) -> String {
"CopyGenerator".to_string()
}
fn dependencies(&self) -> Vec<Target> {
vec![self.src]
}
fn run_once(
&self,
witness: &PartitionWitness<F>,
out_buffer: &mut GeneratedValues<F>,
) -> Result<()> {
let value = witness.get_target(self.src);
out_buffer.set_target(self.dst, value)
}
fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.src)?;
dst.write_target(self.dst)
}
fn deserialize(source: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let src = source.read_target()?;
let dst = source.read_target()?;
Ok(Self { src, dst })
}
}
#[derive(Debug, Default)]
#[cfg(feature = "rand")]
pub struct RandomValueGenerator {
pub(crate) target: Target,
}
#[cfg(feature = "rand")]
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for RandomValueGenerator {
fn id(&self) -> String {
"RandomValueGenerator".to_string()
}
fn dependencies(&self) -> Vec<Target> {
Vec::new()
}
fn run_once(
&self,
_witness: &PartitionWitness<F>,
out_buffer: &mut GeneratedValues<F>,
) -> Result<()> {
let random_value = F::rand();
out_buffer.set_target(self.target, random_value)
}
fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.target)
}
fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let target = src.read_target()?;
Ok(Self { target })
}
}
#[derive(Debug, Default)]
pub struct NonzeroTestGenerator {
pub(crate) to_test: Target,
pub(crate) dummy: Target,
}
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for NonzeroTestGenerator {
fn id(&self) -> String {
"NonzeroTestGenerator".to_string()
}
fn dependencies(&self) -> Vec<Target> {
vec![self.to_test]
}
fn run_once(
&self,
witness: &PartitionWitness<F>,
out_buffer: &mut GeneratedValues<F>,
) -> Result<()> {
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)
}
fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target(self.to_test)?;
dst.write_target(self.dummy)
}
fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let to_test = src.read_target()?;
let dummy = src.read_target()?;
Ok(Self { to_test, dummy })
}
}
#[derive(Debug, Clone, Default)]
pub struct ConstantGenerator<F: Field> {
pub row: usize,
pub constant_index: usize,
pub wire_index: usize,
pub constant: F,
}
impl<F: Field> ConstantGenerator<F> {
pub fn set_constant(&mut self, c: F) {
self.constant = c;
}
}
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for ConstantGenerator<F> {
fn id(&self) -> String {
"ConstantGenerator".to_string()
}
fn dependencies(&self) -> Vec<Target> {
vec![]
}
fn run_once(
&self,
_witness: &PartitionWitness<F>,
out_buffer: &mut GeneratedValues<F>,
) -> Result<()> {
out_buffer.set_target(Target::wire(self.row, self.wire_index), self.constant)
}
fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.row)?;
dst.write_usize(self.constant_index)?;
dst.write_usize(self.wire_index)?;
dst.write_field(self.constant)
}
fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let row = src.read_usize()?;
let constant_index = src.read_usize()?;
let wire_index = src.read_usize()?;
let constant = src.read_field()?;
Ok(Self {
row,
constant_index,
wire_index,
constant,
})
}
}