Skip to content

Commit 8d12caf

Browse files
committed
napi: ffi and types for srs
1 parent 0912380 commit 8d12caf

File tree

2 files changed

+289
-6
lines changed

2 files changed

+289
-6
lines changed

plonk-napi/src/lib.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
pub(crate) mod gate_vector;
22
pub(crate) mod poly_comm;
33
pub(crate) mod poseidon;
4+
//pub(crate) mod srs;
45
pub(crate) mod wasm_vector;
56
pub(crate) mod wrappers;
67

7-
pub use poseidon::{
8-
caml_pasta_fp_poseidon_block_cipher,
9-
caml_pasta_fq_poseidon_block_cipher,
10-
};
8+
pub use poseidon::{caml_pasta_fp_poseidon_block_cipher, caml_pasta_fq_poseidon_block_cipher};
119

12-
pub use wrappers::group::{WasmGPallas, WasmGVesta};
13-
pub use wasm_vector::{fp::WasmVecVecFp, fq::WasmVecVecFq};
1410
pub use poly_comm::{pallas::WasmFqPolyComm, vesta::WasmFpPolyComm};
11+
//pub use srs::{fp::WasmFpSrs, fq::WasmFqSrs};
12+
pub use wasm_vector::{fp::WasmVecVecFp, fq::WasmVecVecFq};
13+
pub use wrappers::group::{WasmGPallas, WasmGVesta};

plonk-napi/src/srs.rs

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
use std::{
2+
fs::{File, OpenOptions},
3+
io::{BufReader, BufWriter, Seek, SeekFrom},
4+
sync::Arc,
5+
};
6+
7+
use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, EvaluationDomain, Evaluations};
8+
use napi::bindgen_prelude::*;
9+
use napi_derive::napi;
10+
use paste::paste;
11+
use poly_commitment::{commitment::b_poly_coefficients, hash_map_cache::HashMapCache, ipa::SRS};
12+
use wasm_types::FlatVector as WasmFlatVector;
13+
14+
use crate::{
15+
poly_comm::{pallas::WasmFqPolyComm, vesta::WasmFpPolyComm},
16+
wasm_vector::WasmVector,
17+
wrappers::field::{WasmPastaFp, WasmPastaFq},
18+
wrappers::group::{WasmGPallas, WasmGVesta},
19+
};
20+
21+
macro_rules! impl_srs_module {
22+
(
23+
$mod_name:ident,
24+
$field_ty:ty,
25+
$wasm_field:ty,
26+
$group_ty:ty,
27+
$group_wrapper:ty,
28+
$poly_comm_wrapper:ty,
29+
$struct_ident:ident
30+
) => {
31+
pub mod $mod_name {
32+
use super::*;
33+
34+
#[napi]
35+
#[derive(Clone)]
36+
pub struct $struct_ident {
37+
#[napi(skip)]
38+
pub inner: Arc<SRS<$group_ty>>,
39+
}
40+
41+
impl $struct_ident {
42+
fn new(inner: SRS<$group_ty>) -> Self {
43+
Self {
44+
inner: Arc::new(inner),
45+
}
46+
}
47+
48+
fn from_arc(inner: Arc<SRS<$group_ty>>) -> Self {
49+
Self { inner }
50+
}
51+
}
52+
53+
fn invalid_domain_error() -> Error {
54+
Error::new(Status::InvalidArg, "invalid domain size")
55+
}
56+
57+
fn map_error(context: &str, err: impl std::fmt::Display) -> Error {
58+
Error::new(Status::GenericFailure, format!("{}: {}", context, err))
59+
}
60+
61+
#[napi]
62+
impl $struct_ident {
63+
#[napi(factory)]
64+
pub fn create(depth: i32) -> Result<Self> {
65+
Ok(Self::from_arc(Arc::new(SRS::<$group_ty>::create(depth as usize))))
66+
}
67+
68+
#[napi(factory)]
69+
pub fn create_parallel(depth: i32) -> Result<Self> {
70+
Ok(Self::from_arc(Arc::new(SRS::<$group_ty>::create_parallel(
71+
depth as usize,
72+
))))
73+
}
74+
75+
#[napi]
76+
pub fn add_lagrange_basis(&self, log2_size: i32) -> Result<()> {
77+
let size = 1usize << (log2_size as usize);
78+
let domain = EvaluationDomain::<$field_ty>::new(size).ok_or_else(invalid_domain_error)?;
79+
self.inner.get_lagrange_basis(domain);
80+
Ok(())
81+
}
82+
83+
#[napi]
84+
pub fn write(&self, append: Option<bool>, path: String) -> Result<()> {
85+
let file = OpenOptions::new()
86+
.write(true)
87+
.create(true)
88+
.append(append.unwrap_or(true))
89+
.open(&path)
90+
.map_err(|err| map_error("srs_write", err))?;
91+
let mut writer = BufWriter::new(file);
92+
self.inner
93+
.serialize(&mut rmp_serde::Serializer::new(&mut writer))
94+
.map_err(|err| map_error("srs_write", err))
95+
}
96+
97+
#[napi]
98+
pub fn read(offset: Option<i32>, path: String) -> Result<Option<Self>> {
99+
let file = match File::open(&path) {
100+
Ok(file) => file,
101+
Err(err) => return Err(map_error("srs_read", err)),
102+
};
103+
let mut reader = BufReader::new(file);
104+
105+
if let Some(off) = offset {
106+
reader
107+
.seek(SeekFrom::Start(off as u64))
108+
.map_err(|err| map_error("srs_read", err))?;
109+
}
110+
111+
match SRS::<$group_ty>::deserialize(&mut rmp_serde::Deserializer::new(reader)) {
112+
Ok(srs) => Ok(Some(Self::from_arc(Arc::new(srs)))),
113+
Err(_) => Ok(None),
114+
}
115+
}
116+
117+
#[napi]
118+
pub fn get(&self) -> WasmVector<$group_wrapper> {
119+
let mut points: Vec<$group_wrapper> = vec![self.inner.h.into()];
120+
points.extend(self.inner.g.iter().cloned().map(Into::into));
121+
points.into()
122+
}
123+
124+
#[napi]
125+
pub fn set(points: WasmVector<$group_wrapper>) -> Result<Self> {
126+
let mut pts: Vec<$group_ty> = points.into_iter().map(Into::into).collect();
127+
if pts.is_empty() {
128+
return Err(Error::new(
129+
Status::InvalidArg,
130+
"expected at least one element for SRS",
131+
));
132+
}
133+
let h = pts.remove(0);
134+
let g = pts;
135+
Ok(Self::from_arc(Arc::new(SRS::<$group_ty> {
136+
h,
137+
g,
138+
lagrange_bases: HashMapCache::new(),
139+
})))
140+
}
141+
142+
#[napi]
143+
pub fn maybe_lagrange_commitment(
144+
&self,
145+
domain_size: i32,
146+
index: i32,
147+
) -> Option<$poly_comm_wrapper> {
148+
if !self
149+
.inner
150+
.lagrange_bases
151+
.contains_key(&(domain_size as usize))
152+
{
153+
return None;
154+
}
155+
let basis = self
156+
.inner
157+
.get_lagrange_basis_from_domain_size(domain_size as usize);
158+
basis.get(index as usize).cloned().map(Into::into)
159+
}
160+
161+
#[napi]
162+
pub fn set_lagrange_basis(
163+
&self,
164+
domain_size: i32,
165+
bases: WasmVector<$poly_comm_wrapper>,
166+
) {
167+
let domain = domain_size as usize;
168+
let commitments: Vec<_> = bases.into_iter().map(Into::into).collect();
169+
self.inner
170+
.lagrange_bases
171+
.get_or_generate(domain, || commitments.clone());
172+
}
173+
174+
#[napi]
175+
pub fn get_lagrange_basis(
176+
&self,
177+
domain_size: i32,
178+
) -> Result<WasmVector<$poly_comm_wrapper>> {
179+
let domain = EvaluationDomain::<$field_ty>::new(domain_size as usize)
180+
.ok_or_else(invalid_domain_error)?;
181+
let basis = self.inner.get_lagrange_basis(domain);
182+
Ok(basis.iter().cloned().map(Into::into).collect())
183+
}
184+
185+
#[napi]
186+
pub fn commit_evaluations(
187+
&self,
188+
domain_size: i32,
189+
evaluations: Uint8Array,
190+
) -> Result<$poly_comm_wrapper> {
191+
let elems: Vec<$field_ty> = WasmFlatVector::<$wasm_field>::from_bytes(
192+
evaluations.as_ref().to_vec(),
193+
)
194+
.into_iter()
195+
.map(Into::into)
196+
.collect();
197+
let domain = EvaluationDomain::<$field_ty>::new(domain_size as usize)
198+
.ok_or_else(invalid_domain_error)?;
199+
let evals = Evaluations::from_vec_and_domain(elems, domain);
200+
let poly = evals.interpolate();
201+
Ok(self.inner.commit(&poly, None).into())
202+
}
203+
204+
#[napi]
205+
pub fn b_poly_commitment(&self, chals: Uint8Array) -> Result<$poly_comm_wrapper> {
206+
let elements: Vec<$field_ty> = WasmFlatVector::<$wasm_field>::from_bytes(
207+
chals.as_ref().to_vec(),
208+
)
209+
.into_iter()
210+
.map(Into::into)
211+
.collect();
212+
let coeffs = b_poly_coefficients(&elements);
213+
let poly = DensePolynomial::<$field_ty>::from_coefficients_vec(coeffs);
214+
Ok(self.inner.commit_non_hiding(&poly, 1).into())
215+
}
216+
217+
#[napi]
218+
pub fn batch_accumulator_check(
219+
&self,
220+
commitments: WasmVector<$group_wrapper>,
221+
chals: Uint8Array,
222+
) -> Result<bool> {
223+
let comms: Vec<$group_ty> = commitments.into_iter().map(Into::into).collect();
224+
let chals: Vec<$field_ty> = WasmFlatVector::<$wasm_field>::from_bytes(
225+
chals.as_ref().to_vec(),
226+
)
227+
.into_iter()
228+
.map(Into::into)
229+
.collect();
230+
Ok(poly_commitment::utils::batch_dlog_accumulator_check(
231+
&self.inner,
232+
&comms,
233+
&chals,
234+
))
235+
}
236+
237+
#[napi]
238+
pub fn batch_accumulator_generate(
239+
&self,
240+
count: i32,
241+
chals: Uint8Array,
242+
) -> Result<WasmVector<$group_wrapper>> {
243+
let chals: Vec<$field_ty> = WasmFlatVector::<$wasm_field>::from_bytes(
244+
chals.as_ref().to_vec(),
245+
)
246+
.into_iter()
247+
.map(Into::into)
248+
.collect();
249+
let points = poly_commitment::utils::batch_dlog_accumulator_generate::<$group_ty>(
250+
&self.inner,
251+
count as usize,
252+
&chals,
253+
);
254+
Ok(points.into_iter().map(Into::into).collect())
255+
}
256+
257+
#[napi]
258+
pub fn h(&self) -> $group_wrapper {
259+
self.inner.h.into()
260+
}
261+
}
262+
}
263+
};
264+
}
265+
266+
impl_srs_module!(
267+
fp,
268+
mina_curves::pasta::Fp,
269+
WasmPastaFp,
270+
mina_curves::pasta::Vesta,
271+
WasmGVesta,
272+
WasmFpPolyComm,
273+
WasmFpSrs
274+
);
275+
276+
impl_srs_module!(
277+
fq,
278+
mina_curves::pasta::Fq,
279+
WasmPastaFq,
280+
mina_curves::pasta::Pallas,
281+
WasmGPallas,
282+
WasmFqPolyComm,
283+
WasmFqSrs
284+
);

0 commit comments

Comments
 (0)