kimchi/circuits/witness/
variables.rs

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