1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
/// Layout variable handling
///
/// First, you use "anchor" names for the variables when specifying
/// the witness layout.
///
/// Ex.
///```ignore
/// let layout = [
/// [
/// &CopyShiftCell::create(0, 2, 8),
/// &VariableCell::create("sum_of_products"),
/// ...
/// &VariableCell::create("final_value"),
/// ]
/// ;
///```
///
/// Second, you use variables with the same names when performing the
/// witness computation.
///
/// Ex.
///```ignore
///
/// let sum_of_products = carry1 * limb1 + pow1 * limb2;
/// ...
/// let final_value = middle_bits.pow(&[2u8]) * carry_flag
///```
///
/// Third, when you're ready to generate the witness, you pass those
/// variables to the witness creation functions using variables!(foo, bar)
/// or variable_map!("foo" => 12, "bar" => blah).
///```ignore
/// Ex.
///
/// init_witness(
/// &mut witness2,
/// &layout,
/// &variables!(sum_of_products, something_else, final_value),
/// );
///```
///
use std::{
collections::HashMap,
ops::{Index, IndexMut},
};
/// Layout variables mapping - these values are substituted
/// into the witness layout when creating the witness instance.
///
/// Map of witness values (used by VariableCells)
/// name (String) -> value (F)
pub struct Variables<'a, T>(HashMap<&'a str, T>);
impl<'a, T> Variables<'a, T> {
/// Create a layout variable map
pub fn create() -> Variables<'a, T> {
Variables(HashMap::new())
}
/// Insert a variable and corresponding value into the variable map
pub fn insert(&mut self, name: &'a str, value: T) {
self.0.insert(name, value);
}
}
impl<'a, T> Index<&'a str> for Variables<'a, T> {
type Output = T;
fn index(&self, name: &'a str) -> &Self::Output {
&self.0[name]
}
}
impl<'a, T> IndexMut<&'a str> for Variables<'a, T> {
fn index_mut(&mut self, name: &'a str) -> &mut Self::Output {
self.0.get_mut(name).expect("failed to get witness value")
}
}
/// Macro to simplify mapping of layout variable
#[macro_export]
macro_rules! variables {
() => {
Variables::create()
};
($( $var: ident ),*) => {{
let mut vars = Variables::create();
$( vars.insert(stringify!{$var}, $var); )*
vars
}}
}
/// Macro to simplify creation of layout map
#[macro_export]
macro_rules! variable_map {
[$( $name: expr => $value: expr ),*] => {{
let mut vars = Variables::create();
$( vars.insert($name, $value); )*
vars
}}
}
pub use variable_map;
pub use variables;