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;