plonky2/src/iop/witness.rs

212 lines
6.0 KiB
Rust
Raw Normal View History

2021-02-09 21:25:21 -08:00
use std::collections::HashMap;
2021-06-23 14:22:42 +02:00
use std::convert::TryInto;
2021-02-09 21:25:21 -08:00
use anyhow::{ensure, Result};
2021-06-07 11:19:54 +02:00
use crate::field::extension_field::target::ExtensionTarget;
2021-05-19 15:57:28 -07:00
use crate::field::extension_field::{Extendable, FieldExtension};
use crate::field::field_types::Field;
use crate::gates::gate::GateInstance;
use crate::hash::hash_types::HashOut;
use crate::hash::hash_types::HashOutTarget;
use crate::iop::generator::GeneratedValues;
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::plonk::copy_constraint::CopyConstraint;
2021-02-09 21:25:21 -08:00
#[derive(Clone, Debug)]
pub struct Witness<F: Field> {
pub(crate) wire_values: Vec<Vec<F>>,
}
impl<F: Field> Witness<F> {
pub fn get_wire(&self, gate: usize, input: usize) -> F {
self.wire_values[input][gate]
}
}
2021-02-09 21:25:21 -08:00
2021-03-01 13:40:05 -08:00
#[derive(Clone, Debug)]
2021-02-24 12:25:13 -08:00
pub struct PartialWitness<F: Field> {
2021-03-01 13:40:05 -08:00
pub(crate) target_values: HashMap<Target, F>,
2021-02-09 21:25:21 -08:00
}
2021-02-24 12:25:13 -08:00
impl<F: Field> PartialWitness<F> {
2021-02-09 21:25:21 -08:00
pub fn new() -> Self {
2021-02-24 12:25:13 -08:00
PartialWitness {
2021-02-09 21:25:21 -08:00
target_values: HashMap::new(),
}
}
pub fn is_empty(&self) -> bool {
self.target_values.is_empty()
}
2021-02-26 13:18:41 -08:00
pub fn get_target(&self, target: Target) -> F {
2021-02-09 21:25:21 -08:00
self.target_values[&target]
2021-04-21 22:31:45 +02:00
}
2021-04-02 14:00:26 -07:00
pub fn get_targets(&self, targets: &[Target]) -> Vec<F> {
2021-04-21 22:31:45 +02:00
targets.iter().map(|&t| self.get_target(t)).collect()
2021-02-09 21:25:21 -08:00
}
2021-06-07 11:19:54 +02:00
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_hash_target(&self, ht: HashOutTarget) -> HashOut<F> {
HashOut {
2021-07-15 09:52:42 +02:00
elements: self.get_targets(&ht.elements).try_into().unwrap(),
}
}
2021-02-26 13:18:41 -08:00
pub fn try_get_target(&self, target: Target) -> Option<F> {
2021-02-09 21:25:21 -08:00
self.target_values.get(&target).cloned()
}
pub fn get_wire(&self, wire: Wire) -> F {
2021-02-26 13:18:41 -08:00
self.get_target(Target::Wire(wire))
2021-02-09 21:25:21 -08:00
}
2021-03-21 19:50:05 -07:00
pub fn try_get_wire(&self, wire: Wire) -> Option<F> {
self.try_get_target(Target::Wire(wire))
}
2021-02-26 13:18:41 -08:00
pub fn contains(&self, target: Target) -> bool {
2021-02-09 21:25:21 -08:00
self.target_values.contains_key(&target)
}
2021-02-26 13:18:41 -08:00
pub fn contains_all(&self, targets: &[Target]) -> bool {
2021-02-09 21:25:21 -08:00
targets.iter().all(|&t| self.contains(t))
}
2021-02-26 13:18:41 -08:00
pub fn set_target(&mut self, target: Target, value: F) {
2021-03-18 12:44:45 -07:00
let opt_old_value = self.target_values.insert(target, value);
if let Some(old_value) = opt_old_value {
2021-04-21 22:31:45 +02:00
assert_eq!(
old_value, value,
"Target was set twice with different values: {:?}",
target
);
2021-03-18 12:44:45 -07:00
}
2021-02-09 21:25:21 -08:00
}
pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut<F>) {
2021-07-08 17:16:26 +02:00
ht.elements
2021-07-15 10:39:57 +02:00
.iter()
2021-07-08 17:16:26 +02:00
.zip(value.elements)
.for_each(|(&t, x)| self.set_target(t, x));
}
2021-06-07 17:55:27 +02:00
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();
2021-06-15 08:35:06 +02:00
(0..D).for_each(|i| {
self.set_target(et.0[i], limbs[i]);
});
2021-06-07 17:55:27 +02:00
}
2021-08-02 14:17:42 +02:00
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));
}
2021-02-09 21:25:21 -08:00
pub fn set_wire(&mut self, wire: Wire, value: F) {
2021-02-26 13:18:41 -08:00
self.set_target(Target::Wire(wire), value)
2021-02-09 21:25:21 -08:00
}
2021-03-01 13:40:05 -08:00
2021-05-19 15:57:28 -07:00
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) {
2021-05-19 15:13:33 -07:00
self.set_wire(wire, value);
}
}
2021-05-19 15:57:28 -07:00
pub fn set_ext_wires<W, const D: usize>(&mut self, wires: W, value: F::Extension)
where
F: Extendable<D>,
W: IntoIterator<Item = Wire>,
{
2021-05-19 15:13:33 -07:00
self.set_wires(wires, &value.to_basefield_array());
}
pub fn extend(&mut self, other: GeneratedValues<F>) {
2021-03-01 13:40:05 -08:00
for (target, value) in other.target_values {
self.set_target(target, value);
}
}
pub fn full_witness(self, degree: usize, num_wires: usize) -> Witness<F> {
let mut wire_values = vec![vec![F::ZERO; degree]; num_wires];
self.target_values.into_iter().for_each(|(t, v)| {
if let Target::Wire(Wire { gate, input }) = t {
wire_values[input][gate] = v;
}
});
Witness { wire_values }
}
/// Checks that the copy constraints are satisfied in the witness.
pub fn check_copy_constraints<const D: usize>(
&self,
2021-07-14 20:54:30 +02:00
copy_constraints: &[CopyConstraint],
gate_instances: &[GateInstance<F, D>],
) -> Result<()>
where
F: Extendable<D>,
{
2021-07-14 20:54:30 +02:00
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,
2021-07-14 20:54:30 +02:00
"Copy constraint '{}' between {} and {} is not satisfied. \
Got values of {} and {} respectively.",
2021-07-14 20:54:30 +02:00
name,
desc(a),
desc(b),
va,
vb
);
}
Ok(())
}
2021-02-09 21:25:21 -08:00
}
2021-04-23 12:35:19 -07:00
impl<F: Field> Default for PartialWitness<F> {
fn default() -> Self {
Self::new()
}
}