Skip to main content

kimchi_napi/wrappers/
lookups.rs

1use crate::{
2    vector::{fp::NapiVecVecFp, fq::NapiVecVecFq, NapiFlatVector},
3    wrappers::field::{NapiPastaFp, NapiPastaFq},
4};
5use kimchi::circuits::lookup::{
6    lookups::{LookupFeatures, LookupInfo, LookupPatterns},
7    runtime_tables::{RuntimeTable, RuntimeTableCfg},
8    tables::LookupTable,
9};
10use mina_curves::pasta::{Fp, Fq};
11use napi::bindgen_prelude::*;
12use napi_derive::napi;
13use paste::paste;
14use serde::{Deserialize, Serialize};
15use wasm_types::{FlatVector, FlatVectorElem};
16
17// -----------------
18// Lookup pattern and info wrappers
19// -----------------
20
21#[napi(object, js_name = "WasmLookupPatterns")]
22#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default)]
23pub struct NapiLookupPatterns {
24    pub xor: bool,
25    pub lookup: bool,
26    #[napi(js_name = "range_check")]
27    pub range_check: bool,
28    #[napi(js_name = "foreign_field_mul")]
29    pub foreign_field_mul: bool,
30}
31
32impl From<LookupPatterns> for NapiLookupPatterns {
33    fn from(value: LookupPatterns) -> Self {
34        Self {
35            xor: value.xor,
36            lookup: value.lookup,
37            range_check: value.range_check,
38            foreign_field_mul: value.foreign_field_mul,
39        }
40    }
41}
42
43impl From<NapiLookupPatterns> for LookupPatterns {
44    fn from(value: NapiLookupPatterns) -> Self {
45        LookupPatterns {
46            xor: value.xor,
47            lookup: value.lookup,
48            range_check: value.range_check,
49            foreign_field_mul: value.foreign_field_mul,
50        }
51    }
52}
53
54#[napi(object, js_name = "WasmLookupFeatures")]
55#[derive(Clone, Debug, Default, Serialize, Deserialize)]
56pub struct NapiLookupFeatures {
57    pub patterns: NapiLookupPatterns,
58    #[napi(js_name = "joint_lookup_used")]
59    pub joint_lookup_used: bool,
60    #[napi(js_name = "uses_runtime_tables")]
61    pub uses_runtime_tables: bool,
62}
63
64impl From<LookupFeatures> for NapiLookupFeatures {
65    fn from(value: LookupFeatures) -> Self {
66        Self {
67            patterns: value.patterns.into(),
68            joint_lookup_used: value.joint_lookup_used,
69            uses_runtime_tables: value.uses_runtime_tables,
70        }
71    }
72}
73
74impl From<NapiLookupFeatures> for LookupFeatures {
75    fn from(value: NapiLookupFeatures) -> Self {
76        LookupFeatures {
77            patterns: value.patterns.into(),
78            joint_lookup_used: value.joint_lookup_used,
79            uses_runtime_tables: value.uses_runtime_tables,
80        }
81    }
82}
83
84#[napi(object, js_name = "WasmLookupInfo")]
85#[derive(Clone, Debug, Default, Serialize, Deserialize)]
86pub struct NapiLookupInfo {
87    #[napi(js_name = "max_per_row")]
88    pub max_per_row: i32,
89    #[napi(js_name = "max_joint_size")]
90    pub max_joint_size: i32,
91    pub features: NapiLookupFeatures,
92}
93
94impl From<LookupInfo> for NapiLookupInfo {
95    fn from(value: LookupInfo) -> Self {
96        Self {
97            max_per_row: value.max_per_row as i32,
98            max_joint_size: value.max_joint_size as i32,
99            features: value.features.into(),
100        }
101    }
102}
103
104impl From<NapiLookupInfo> for LookupInfo {
105    fn from(value: NapiLookupInfo) -> Self {
106        LookupInfo {
107            max_per_row: value.max_per_row as usize,
108            max_joint_size: value.max_joint_size as u32,
109            features: value.features.into(),
110        }
111    }
112}
113
114// -----------------
115// Lookup tables & runtime tables
116// -----------------
117
118macro_rules! impl_lookup_wrappers {
119    ($field_name:ident, $field:ty, $NapiF:ty, $vec_vec:ty) => {
120        paste! {
121            #[napi(js_name = [<"WasmPasta" $field_name:camel "LookupTable">])]
122            #[derive(Clone)]
123            pub struct [<NapiPasta $field_name:camel LookupTable>] {
124                id: i32,
125                data: $vec_vec,
126            }
127
128            #[napi]
129            impl [<NapiPasta $field_name:camel LookupTable>] {
130                #[napi(constructor)]
131                pub fn new(id: i32, data: $vec_vec) -> Self {
132                    Self {
133                        id,
134                        data: data.clone(),
135                    }
136                }
137
138                #[napi(getter)]
139                pub fn id(&self) -> i32 {
140                    self.id
141                }
142
143                #[napi(setter)]
144                pub fn set_id(&mut self, id: i32) {
145                    self.id = id;
146                }
147
148                #[napi(getter)]
149                pub fn data(&self) -> $vec_vec {
150                    self.data.clone()
151                }
152
153                #[napi(setter)]
154                pub fn set_data(&mut self, data: $vec_vec) {
155                    self.data = data.clone();
156                }
157            }
158
159            impl From<LookupTable<$field>> for [<NapiPasta $field_name:camel LookupTable>] {
160                fn from(value: LookupTable<$field>) -> Self {
161                    Self {
162                        id: value.id,
163                        data: value.data.into(),
164                    }
165                }
166            }
167
168            impl From<[<NapiPasta $field_name:camel LookupTable>]> for LookupTable<$field> {
169                fn from(value: [<NapiPasta $field_name:camel LookupTable>]) -> Self {
170                    Self {
171                        id: value.id,
172                        data: value.data.into(),
173                    }
174                }
175            }
176
177            #[napi(js_name = [<"WasmPasta"  $field_name:camel "RuntimeTableCfg">])]
178            #[derive(Clone)]
179            pub struct [<NapiPasta $field_name:camel RuntimeTableCfg>] {
180                id: i32,
181                first_column: Vec<$field>,
182            }
183
184            #[napi]
185            impl [<NapiPasta $field_name:camel RuntimeTableCfg>] {
186                #[napi(constructor)]
187                pub fn new(id: i32, first_column: Uint8Array) -> Result<Self> {
188                    let bytes = first_column.as_ref().to_vec();
189                    let elements: Vec<$field> = FlatVector::<$NapiF>::from_bytes(bytes)
190                        .into_iter()
191                        .map(Into::into)
192                        .collect();
193                    Ok(Self { id, first_column: elements })
194                }
195
196                #[napi(getter)]
197                pub fn id(&self) -> i32 {
198                    self.id
199                }
200
201                #[napi(setter)]
202                pub fn set_id(&mut self, id: i32) {
203                    self.id = id;
204                }
205
206                #[napi(getter, js_name = "first_column")]
207                pub fn first_column(&self) -> Result<Uint8Array> {
208                    let mut bytes = Vec::with_capacity(self.first_column.len() * <$NapiF>::FLATTENED_SIZE);
209                    for value in &self.first_column {
210                        let element = <$NapiF>::from(*value);
211                        bytes.extend(element.flatten());
212                    }
213                    Ok(Uint8Array::from(bytes))
214                }
215            }
216
217            impl From<RuntimeTableCfg<$field>> for [<NapiPasta $field_name:camel RuntimeTableCfg>] {
218                fn from(value: RuntimeTableCfg<$field>) -> Self {
219                    Self {
220                        id: value.id,
221                        first_column: value.first_column,
222                    }
223                }
224            }
225
226            impl From<[<NapiPasta $field_name:camel RuntimeTableCfg>]> for RuntimeTableCfg<$field> {
227                fn from(value: [<NapiPasta $field_name:camel RuntimeTableCfg>]) -> Self {
228                    Self {
229                        id: value.id,
230                        first_column: value.first_column,
231                    }
232                }
233            }
234
235            #[napi(object, js_name = [<"Wasm" $field_name:camel "RuntimeTable">])]
236            #[derive(Clone)]
237            pub struct [<Napi $field_name:camel RuntimeTable>] {
238                pub id: i32,
239                pub data: NapiFlatVector<$NapiF>,
240            }
241
242            impl From<RuntimeTable<$field>> for [<Napi $field_name:camel RuntimeTable>] {
243                fn from(value: RuntimeTable<$field>) -> Self {
244                    Self {
245                        id: value.id,
246                        data: value.data.into_iter().map(Into::into).collect(),
247                    }
248                }
249            }
250
251            impl From<[<Napi $field_name:camel RuntimeTable>]> for RuntimeTable<$field> {
252                fn from(value: [<Napi $field_name:camel RuntimeTable>]) -> Self {
253                    Self {
254                        id: value.id,
255                        data: value.data.into_iter().map(Into::into).collect(),
256                    }
257                }
258            }
259        }
260    };
261}
262
263impl_lookup_wrappers!(Fp, Fp, NapiPastaFp, NapiVecVecFp);
264impl_lookup_wrappers!(Fq, Fq, NapiPastaFq, NapiVecVecFq);