Skip to content

Commit e1da50c

Browse files
Trivo25querolita
authored andcommitted
merge
1 parent 3ac952e commit e1da50c

File tree

3 files changed

+240
-1
lines changed

3 files changed

+240
-1
lines changed

plonk-napi/src/gate_vector.rs

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
use kimchi::circuits::{
2+
gate::{Circuit, CircuitGate, GateType},
3+
wires::{GateWires, Wire as KimchiWire},
4+
};
5+
use mina_curves::pasta::{Fp, Fq};
6+
use napi::bindgen_prelude::*;
7+
use napi_derive::napi;
8+
use o1_utils::hasher::CryptoDigest;
9+
use paste::paste;
10+
use wasm_types::{FlatVector as WasmFlatVector, FlatVectorElem};
11+
12+
use crate::wrappers::{
13+
field::{WasmPastaFp, WasmPastaFq},
14+
wires::NapiWire,
15+
};
16+
17+
#[napi(object)]
18+
#[derive(Clone, Debug, Default)]
19+
pub struct NapiGateWires {
20+
pub w0: NapiWire,
21+
pub w1: NapiWire,
22+
pub w2: NapiWire,
23+
pub w3: NapiWire,
24+
pub w4: NapiWire,
25+
pub w5: NapiWire,
26+
pub w6: NapiWire,
27+
}
28+
29+
impl NapiGateWires {
30+
fn into_inner(self) -> GateWires {
31+
[
32+
KimchiWire::from(self.w0),
33+
KimchiWire::from(self.w1),
34+
KimchiWire::from(self.w2),
35+
KimchiWire::from(self.w3),
36+
KimchiWire::from(self.w4),
37+
KimchiWire::from(self.w5),
38+
KimchiWire::from(self.w6),
39+
]
40+
}
41+
}
42+
43+
impl From<&GateWires> for NapiGateWires {
44+
fn from(value: &GateWires) -> Self {
45+
Self {
46+
w0: value[0].into(),
47+
w1: value[1].into(),
48+
w2: value[2].into(),
49+
w3: value[3].into(),
50+
w4: value[4].into(),
51+
w5: value[5].into(),
52+
w6: value[6].into(),
53+
}
54+
}
55+
}
56+
57+
fn gate_type_from_i32(value: i32) -> Result<GateType> {
58+
// Ocaml/JS int are signed, so we use i32 here
59+
if value < 0 {
60+
return Err(Error::new(
61+
Status::InvalidArg,
62+
format!("invalid GateType discriminant: {}", value),
63+
));
64+
}
65+
66+
let variants: &[GateType] = &[
67+
GateType::Zero,
68+
GateType::Generic,
69+
GateType::Poseidon,
70+
GateType::CompleteAdd,
71+
GateType::VarBaseMul,
72+
GateType::EndoMul,
73+
GateType::EndoMulScalar,
74+
GateType::Lookup,
75+
GateType::CairoClaim,
76+
GateType::CairoInstruction,
77+
GateType::CairoFlags,
78+
GateType::CairoTransition,
79+
GateType::RangeCheck0,
80+
GateType::RangeCheck1,
81+
GateType::ForeignFieldAdd,
82+
GateType::ForeignFieldMul,
83+
GateType::Xor16,
84+
GateType::Rot64,
85+
];
86+
87+
let index = value as usize;
88+
variants.get(index).copied().ok_or_else(|| {
89+
Error::new(
90+
Status::InvalidArg,
91+
format!("invalid GateType discriminant: {}", value),
92+
)
93+
})
94+
}
95+
96+
// For convenience to not expose the GateType enum to JS
97+
fn gate_type_to_i32(value: GateType) -> i32 {
98+
value as i32
99+
}
100+
101+
macro_rules! impl_gate_support {
102+
($field_name:ident, $F:ty, $WasmF:ty) => {
103+
paste! {
104+
#[napi(object)]
105+
#[derive(Clone, Debug, Default)]
106+
pub struct [<Napi $field_name:camel Gate>] {
107+
pub typ: i32, // for convenience, we use i32 instead of GateType
108+
pub wires: NapiGateWires,
109+
pub coeffs: Vec<u8>, // for now, serializing fields as flat bytes, but subject to changes
110+
}
111+
112+
impl [<Napi $field_name:camel Gate>] {
113+
fn into_inner(self) -> Result<CircuitGate<$F>> {
114+
let coeffs = WasmFlatVector::<$WasmF>::from_bytes(self.coeffs)
115+
.into_iter()
116+
.map(Into::into)
117+
.collect();
118+
119+
Ok(CircuitGate {
120+
typ: gate_type_from_i32(self.typ)?,
121+
wires: self.wires.into_inner(),
122+
coeffs,
123+
})
124+
}
125+
126+
fn from_inner(value: &CircuitGate<$F>) -> Self {
127+
let coeffs = value
128+
.coeffs
129+
.iter()
130+
.cloned()
131+
.map($WasmF::from)
132+
.flat_map(|elem| elem.flatten())
133+
.collect();
134+
135+
Self {
136+
typ: gate_type_to_i32(value.typ),
137+
wires: (&value.wires).into(),
138+
coeffs,
139+
}
140+
}
141+
}
142+
143+
#[napi]
144+
#[derive(Clone, Default, Debug)]
145+
pub struct [<Napi $field_name:camel GateVector>](
146+
#[napi(skip)] pub Vec<CircuitGate<$F>>,
147+
);
148+
149+
#[napi]
150+
pub fn [<caml_pasta_ $field_name:snake _plonk_gate_vector_create>]() -> [<Napi $field_name:camel GateVector>] {
151+
println!("from native rust creating gate vector");
152+
[<Napi $field_name:camel GateVector>](Vec::new())
153+
}
154+
155+
#[napi]
156+
pub fn [<caml_pasta_ $field_name:snake _plonk_gate_vector_add>](
157+
vector: &mut [<Napi $field_name:camel GateVector>],
158+
gate: [<Napi $field_name:camel Gate>],
159+
) -> Result<()> {
160+
println!("from native rust adding gate to vector");
161+
vector.0.push(gate.into_inner()?);
162+
Ok(())
163+
}
164+
165+
#[napi]
166+
pub fn [<caml_pasta_ $field_name:snake _plonk_gate_vector_get>](
167+
vector: &[<Napi $field_name:camel GateVector>],
168+
index: i32,
169+
) -> [<Napi $field_name:camel Gate>] {
170+
println!("from native rust getting gate from vector");
171+
[<Napi $field_name:camel Gate>]::from_inner(&vector.0[index as usize])
172+
}
173+
174+
#[napi]
175+
pub fn [<caml_pasta_ $field_name:snake _plonk_gate_vector_len>](
176+
vector: &[<Napi $field_name:camel GateVector>],
177+
) -> i32 {
178+
println!("from native rust getting gate vector length");
179+
vector.0.len() as i32
180+
}
181+
182+
#[napi]
183+
pub fn [<caml_pasta_ $field_name:snake _plonk_gate_vector_wrap>](
184+
vector: &mut [<Napi $field_name:camel GateVector>],
185+
target: NapiWire,
186+
head: NapiWire,
187+
) {
188+
println!("from native rust wrapping wire in gate vector");
189+
vector.0[target.row as usize].wires[target.col as usize] = KimchiWire::from(head);
190+
}
191+
192+
#[napi]
193+
pub fn [<caml_pasta_ $field_name:snake _plonk_gate_vector_digest>](
194+
public_input_size: i32,
195+
vector: &[<Napi $field_name:camel GateVector>],
196+
) -> Uint8Array {
197+
println!("from native rust computing gate vector digest");
198+
let bytes = Circuit::new(public_input_size as usize, &vector.0)
199+
.digest()
200+
.to_vec();
201+
Uint8Array::from(bytes)
202+
}
203+
204+
#[napi]
205+
pub fn [<caml_pasta_ $field_name:snake _plonk_circuit_serialize>](
206+
public_input_size: i32,
207+
vector: &[<Napi $field_name:camel GateVector>],
208+
) -> Result<String> {
209+
println!("from native rust serializing gate vector to json");
210+
let circuit = Circuit::new(public_input_size as usize, &vector.0);
211+
serde_json::to_string(&circuit).map_err(|err| {
212+
Error::new(
213+
Status::GenericFailure,
214+
format!("couldn't serialize constraints: {}", err),
215+
)
216+
})
217+
}
218+
}
219+
};
220+
}
221+
222+
impl_gate_support!(fp, Fp, WasmPastaFp);
223+
impl_gate_support!(fq, Fq, WasmPastaFq);

plonk-napi/src/lib.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,19 @@ mod types;
99
mod wrappers;
1010
mod wasm_vector;
1111

12-
pub use circuit::prover_to_json;
12+
pub use poseidon::{caml_pasta_fp_poseidon_block_cipher, caml_pasta_fq_poseidon_block_cipher};
13+
14+
pub use gate_vector::{
15+
caml_pasta_fp_plonk_circuit_serialize, caml_pasta_fp_plonk_gate_vector_add,
16+
caml_pasta_fp_plonk_gate_vector_create, caml_pasta_fp_plonk_gate_vector_digest,
17+
caml_pasta_fp_plonk_gate_vector_get, caml_pasta_fp_plonk_gate_vector_len,
18+
caml_pasta_fp_plonk_gate_vector_wrap, caml_pasta_fq_plonk_circuit_serialize,
19+
caml_pasta_fq_plonk_gate_vector_add, caml_pasta_fq_plonk_gate_vector_create,
20+
caml_pasta_fq_plonk_gate_vector_digest, caml_pasta_fq_plonk_gate_vector_get,
21+
caml_pasta_fq_plonk_gate_vector_len, caml_pasta_fq_plonk_gate_vector_wrap,
22+
NapiFpGate as WasmFpGate, NapiFpGateVector as WasmFpGateVector, NapiFqGate as WasmFqGate,
23+
NapiFqGateVector as WasmFqGateVector,
24+
};
1325
pub use pasta_fp_plonk_index::{
1426
prover_index_fp_from_bytes, prover_index_fp_to_bytes, WasmPastaFpPlonkIndex,
1527
};

plonk-napi/src/poseidon.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use wasm_types::{FlatVector, FlatVectorElem};
99

1010
#[napi]
1111
pub fn caml_pasta_fp_poseidon_block_cipher(state: Uint8Array) -> Result<Uint8Array> {
12+
//println!("from native rust fp poseidon");
13+
1214
let mut state_vec: Vec<Fp> = FlatVector::<WasmPastaFp>::from_bytes(state.to_vec())
1315
.into_iter()
1416
.map(Into::into)
@@ -32,6 +34,8 @@ pub fn caml_pasta_fp_poseidon_block_cipher(state: Uint8Array) -> Result<Uint8Arr
3234

3335
#[napi]
3436
pub fn caml_pasta_fq_poseidon_block_cipher(state: Uint8Array) -> Result<Uint8Array> {
37+
//println!("from native rust fq poseidon");
38+
3539
let mut state_vec: Vec<Fq> = FlatVector::<WasmPastaFq>::from_bytes(state.to_vec())
3640
.into_iter()
3741
.map(Into::into)

0 commit comments

Comments
 (0)