plonk_wasm/
gate_vector.rs

1//! A GateVector: this is used to represent a list of gates.
2
3use kimchi::circuits::{
4    gate::{Circuit, CircuitGate, GateType},
5    wires::Wire,
6};
7use o1_utils::hasher::CryptoDigest;
8use paste::paste;
9use wasm_bindgen::prelude::*;
10use wasm_types::FlatVector as WasmFlatVector;
11
12#[wasm_bindgen]
13#[derive(Clone, Copy, Debug)]
14pub struct WasmGateWires(
15    pub Wire,
16    pub Wire,
17    pub Wire,
18    pub Wire,
19    pub Wire,
20    pub Wire,
21    pub Wire,
22);
23
24#[wasm_bindgen]
25impl WasmGateWires {
26    #[wasm_bindgen(constructor)]
27    pub fn new(w0: Wire, w1: Wire, w2: Wire, w3: Wire, w4: Wire, w5: Wire, w6: Wire) -> Self {
28        WasmGateWires(w0, w1, w2, w3, w4, w5, w6)
29    }
30}
31
32macro_rules! impl_gate_vector {
33    ($name: ident,
34     $WasmF: ty,
35     $F: ty,
36     $field_name: ident) => {
37        paste! {
38            #[wasm_bindgen]
39            pub struct [<Wasm $field_name:camel GateVector>](
40                #[wasm_bindgen(skip)] pub Vec<CircuitGate<$F>>);
41            pub type WasmGateVector = [<Wasm $field_name:camel GateVector>];
42
43            #[wasm_bindgen]
44            pub struct [<Wasm $field_name:camel Gate>] {
45                pub typ: GateType, // type of the gate
46                pub wires: WasmGateWires,  // gate wires
47                #[wasm_bindgen(skip)] pub coeffs: Vec<$WasmF>,  // constraints vector
48            }
49
50            #[wasm_bindgen]
51            impl [<Wasm $field_name:camel Gate>] {
52                #[wasm_bindgen(constructor)]
53                pub fn new(
54                    typ: GateType,
55                    wires: WasmGateWires,
56                    coeffs: WasmFlatVector<$WasmF>) -> Self {
57                    Self {
58                        typ,
59                        wires,
60                        coeffs: coeffs.into(),
61                    }
62                }
63            }
64
65            impl From<CircuitGate<$F>> for [<Wasm $field_name:camel Gate>]
66            {
67                fn from(cg: CircuitGate<$F>) -> Self {
68                    Self {
69                        typ: cg.typ,
70                        wires: WasmGateWires(
71                            cg.wires[0],
72                            cg.wires[1],
73                            cg.wires[2],
74                            cg.wires[3],
75                            cg.wires[4],
76                            cg.wires[5],
77                            cg.wires[6]),
78                        coeffs: cg.coeffs.into_iter().map(Into::into).collect(),
79                    }
80                }
81            }
82
83            impl From<&CircuitGate<$F>> for [<Wasm $field_name:camel Gate>]
84            {
85                fn from(cg: &CircuitGate<$F>) -> Self {
86                    Self {
87                        typ: cg.typ,
88                        wires: WasmGateWires(
89                            cg.wires[0],
90                            cg.wires[1],
91                            cg.wires[2],
92                            cg.wires[3],
93                            cg.wires[4],
94                            cg.wires[5],
95                            cg.wires[6]),
96                        coeffs: cg.coeffs.clone().into_iter().map(Into::into).collect(),
97                    }
98                }
99            }
100
101            impl From<[<Wasm $field_name:camel Gate>]> for CircuitGate<$F>
102            {
103                fn from(ccg: [<Wasm $field_name:camel Gate>]) -> Self {
104                    Self {
105                        typ: ccg.typ,
106                        wires: [
107                            ccg.wires.0,
108                            ccg.wires.1,
109                            ccg.wires.2,
110                            ccg.wires.3,
111                            ccg.wires.4,
112                            ccg.wires.5,
113                            ccg.wires.6
114                        ],
115                        coeffs: ccg.coeffs.into_iter().map(Into::into).collect(),
116                    }
117                }
118            }
119
120            #[wasm_bindgen]
121            pub fn [<caml_pasta_ $name:snake _plonk_gate_vector_create>]() -> WasmGateVector {
122                [<Wasm $field_name:camel GateVector>](Vec::new())
123            }
124
125            #[wasm_bindgen]
126            pub fn [<caml_pasta_ $name:snake _plonk_gate_vector_add>](
127                v: &mut WasmGateVector,
128                gate: [<Wasm $field_name:camel Gate>],
129            ) {
130                let gate: CircuitGate<$F> = gate.into();
131                v.0.push(gate);
132            }
133
134            #[wasm_bindgen]
135            pub fn [<caml_pasta_ $name:snake _plonk_gate_vector_get>](
136                v: &WasmGateVector,
137                i: i32,
138            ) -> [<Wasm $field_name:camel Gate>] {
139                (&(v.0)[i as usize]).into()
140            }
141
142            #[wasm_bindgen]
143            pub fn [<caml_pasta_ $name:snake _plonk_gate_vector_len>](
144                v: &WasmGateVector,
145            ) -> usize {
146                v.0.len()
147            }
148
149            #[wasm_bindgen]
150            pub fn [<caml_pasta_ $name:snake _plonk_gate_vector_wrap>](
151                v: &mut WasmGateVector,
152                t: Wire,
153                h: Wire,
154            ) {
155                (v.0)[t.row as usize].wires[t.col as usize] = h.into();
156            }
157
158            #[wasm_bindgen]
159            pub fn [<caml_pasta_ $name:snake _plonk_gate_vector_digest>](
160                public_input_size: usize,
161                v: &WasmGateVector
162            ) -> Box<[u8]> {
163                Circuit::new(public_input_size, &(v.0)).digest().to_vec().into_boxed_slice()
164            }
165
166            #[wasm_bindgen]
167            pub fn [<caml_pasta_ $name:snake _plonk_circuit_serialize>](
168                public_input_size: usize,
169                v: &WasmGateVector
170            ) -> String {
171                let circuit = Circuit::new(public_input_size, &v.0);
172                serde_json::to_string(&circuit).expect("couldn't serialize constraints")
173            }
174        }
175    };
176}
177
178pub mod fp {
179    use super::*;
180    use arkworks::WasmPastaFp as WasmF;
181    use mina_curves::pasta::Fp as F;
182
183    impl_gate_vector!(fp, WasmF, F, Fp);
184}
185
186//
187// Fq
188//
189
190pub mod fq {
191    use super::*;
192    use arkworks::WasmPastaFq as WasmF;
193    use mina_curves::pasta::Fq as F;
194
195    impl_gate_vector!(fq, WasmF, F, Fq);
196}