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;