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
|
|
|
|
2021-06-23 14:16:05 +02: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};
|
2021-07-29 22:00:29 -07:00
|
|
|
use crate::field::field_types::Field;
|
2021-06-23 14:16:05 +02:00
|
|
|
use crate::gates::gate::GateInstance;
|
2021-07-29 22:00:29 -07:00
|
|
|
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
|
|
|
|
2021-06-17 15:49:21 +02: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(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-29 22:00:29 -07:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2021-07-29 22:00:29 -07: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());
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-21 08:26:34 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-23 14:16:05 +02:00
|
|
|
|
2021-06-17 15:49:21 +02:00
|
|
|
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;
|
2021-06-23 14:16:05 +02:00
|
|
|
}
|
2021-06-17 15:49:21 +02:00
|
|
|
});
|
|
|
|
|
Witness { wire_values }
|
2021-06-23 14:16:05 +02:00
|
|
|
}
|
2021-07-14 18:44:58 +02:00
|
|
|
|
|
|
|
|
/// 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],
|
2021-07-14 18:44:58 +02:00
|
|
|
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 {
|
2021-07-14 18:44:58 +02:00
|
|
|
match t {
|
|
|
|
|
Target::Wire(Wire { gate, input }) => format!(
|
|
|
|
|
"wire {} of gate #{} (`{}`)",
|
|
|
|
|
input,
|
|
|
|
|
gate,
|
2021-07-22 23:48:03 -07:00
|
|
|
gate_instances[*gate].gate_ref.0.id()
|
2021-07-14 18:44:58 +02:00
|
|
|
),
|
|
|
|
|
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. \
|
2021-07-14 18:44:58 +02:00
|
|
|
Got values of {} and {} respectively.",
|
2021-07-14 20:54:30 +02:00
|
|
|
name,
|
2021-07-14 18:44:58 +02:00
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
}
|