Skip to main content

kimchi/circuits/witness/
variables.rs

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