Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions plonk-napi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ arkworks.workspace = true
mina-curves = { path = "../curves" }
mina-poseidon = { path = "../poseidon" }
o1-utils = { path = "../utils" }
poly-commitment = { path = "../poly-commitment" }

getrandom.workspace = true
libc.workspace = true
Expand Down
9 changes: 8 additions & 1 deletion plonk-napi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
mod poseidon;
pub(crate) mod poseidon;
pub(crate) mod wrappers;
pub(crate) mod wasm_vector;
pub(crate) mod poly_comm;

pub use poseidon::{
caml_pasta_fp_poseidon_block_cipher,
caml_pasta_fq_poseidon_block_cipher,
};

pub use wrappers::group::{WasmGPallas, WasmGVesta};
pub use wasm_vector::{fp::WasmVecVecFp, fq::WasmVecVecFq};
pub use poly_comm::{pallas::WasmFqPolyComm, vesta::WasmFpPolyComm};
115 changes: 115 additions & 0 deletions plonk-napi/src/poly_comm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use crate::{
wrappers::group::{WasmGPallas, WasmGVesta},
wasm_vector::WasmVector,
};
use napi_derive::napi;
use paste::paste;
use poly_commitment::commitment::PolyComm;

macro_rules! impl_poly_comm {
(
$wasm_g:ty,
$g:ty,
$field_name:ident
) => {
paste! {
#[napi]
#[derive(Clone)]
pub struct [<Wasm $field_name:camel PolyComm>] {
#[napi(skip)]
pub unshifted: WasmVector<$wasm_g>,
pub shifted: Option<$wasm_g>,
}

#[napi]
impl [<Wasm $field_name:camel PolyComm>] {
#[napi(constructor)]
pub fn new(unshifted: WasmVector<$wasm_g>, shifted: Option<$wasm_g>) -> Self {
assert!(
shifted.is_none(),
"mina#14628: Shifted commitments are deprecated and must not be used",
);
Self { unshifted, shifted }
}

#[napi(getter)]
pub fn unshifted(&self) -> WasmVector<$wasm_g> {
self.unshifted.clone()
}

#[napi(setter)]
pub fn set_unshifted(&mut self, value: WasmVector<$wasm_g>) {
self.unshifted = value;
}
}

impl From<PolyComm<$g>> for [<Wasm $field_name:camel PolyComm>] {
fn from(value: PolyComm<$g>) -> Self {
let PolyComm { chunks } = value;
let unshifted: Vec<$wasm_g> = chunks.into_iter().map(Into::into).collect();
Self {
unshifted: unshifted.into(),
shifted: None,
}
}
}

impl From<&PolyComm<$g>> for [<Wasm $field_name:camel PolyComm>] {
fn from(value: &PolyComm<$g>) -> Self {
let unshifted: Vec<$wasm_g> = value.chunks.iter().map(|chunk| (*chunk).into()).collect();
Self {
unshifted: unshifted.into(),
shifted: None,
}
}
}

impl From<[<Wasm $field_name:camel PolyComm>]> for PolyComm<$g> {
fn from(value: [<Wasm $field_name:camel PolyComm>]) -> Self {
let [<Wasm $field_name:camel PolyComm>] { unshifted, shifted } = value;
assert!(
shifted.is_none(),
"mina#14628: Shifted commitments are deprecated and must not be used",
);
PolyComm {
chunks: Vec::<$wasm_g>::from(unshifted)
.into_iter()
.map(Into::into)
.collect(),
}
}
}

impl From<&[<Wasm $field_name:camel PolyComm>]> for PolyComm<$g> {
fn from(value: &[<Wasm $field_name:camel PolyComm>]) -> Self {
assert!(
value.shifted.is_none(),
"mina#14628: Shifted commitments are deprecated and must not be used",
);
PolyComm {
chunks: value
.unshifted
.iter()
.cloned()
.map(Into::into)
.collect(),
}
}
}
}
};
}

pub mod pallas {
use super::*;
use mina_curves::pasta::Pallas as GAffine;

impl_poly_comm!(WasmGPallas, GAffine, Fq);
}

pub mod vesta {
use super::*;
use mina_curves::pasta::Vesta as GAffine;

impl_poly_comm!(WasmGVesta, GAffine, Fp);
}
2 changes: 1 addition & 1 deletion plonk-napi/src/poseidon.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use arkworks::{WasmPastaFp, WasmPastaFq};
use crate::wrappers::field::{WasmPastaFp, WasmPastaFq};
use mina_curves::pasta::{Fp, Fq};
use mina_poseidon::{constants::PlonkSpongeConstantsKimchi, permutation::poseidon_block_cipher};
use napi::bindgen_prelude::*;
Expand Down
199 changes: 199 additions & 0 deletions plonk-napi/src/wasm_vector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
use std::{iter::FromIterator, ops::Deref};

use napi::{bindgen_prelude::*, sys};
use wasm_types::{FlatVector, FlatVectorElem};

#[derive(Clone, Debug, Default)]
pub struct WasmVector<T>(pub Vec<T>);

impl<T> WasmVector<T> {
pub fn into_inner(self) -> Vec<T> {
self.0
}
}

impl<T> Deref for WasmVector<T> {
type Target = Vec<T>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<T> From<Vec<T>> for WasmVector<T> {
fn from(value: Vec<T>) -> Self {
WasmVector(value)
}
}

impl<T> From<WasmVector<T>> for Vec<T> {
fn from(value: WasmVector<T>) -> Self {
value.0
}
}

impl<'a, T> From<&'a WasmVector<T>> for &'a Vec<T> {
fn from(value: &'a WasmVector<T>) -> Self {
&value.0
}
}

impl<T> IntoIterator for WasmVector<T> {
type Item = T;
type IntoIter = <Vec<T> as IntoIterator>::IntoIter;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

impl<'a, T> IntoIterator for &'a WasmVector<T> {
type Item = &'a T;
type IntoIter = <&'a Vec<T> as IntoIterator>::IntoIter;

fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}

impl<T> FromIterator<T> for WasmVector<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
WasmVector(Vec::from_iter(iter))
}
}

impl<T> Extend<T> for WasmVector<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.0.extend(iter);
}
}

impl<T> TypeName for WasmVector<T>
where
Vec<T>: TypeName,
{
fn type_name() -> &'static str {
<Vec<T> as TypeName>::type_name()
}

fn value_type() -> ValueType {
<Vec<T> as TypeName>::value_type()
}
}

impl<T> ValidateNapiValue for WasmVector<T>
where
Vec<T>: ValidateNapiValue,
T: FromNapiValue,
{
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
<Vec<T> as ValidateNapiValue>::validate(env, napi_val)
}
}

impl<T> FromNapiValue for WasmVector<T>
where
Vec<T>: FromNapiValue,
{
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
Ok(WasmVector(<Vec<T> as FromNapiValue>::from_napi_value(
env, napi_val,
)?))
}
}

impl<T> ToNapiValue for WasmVector<T>
where
Vec<T>: ToNapiValue,
{
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
<Vec<T> as ToNapiValue>::to_napi_value(env, val.0)
}
}

macro_rules! impl_vec_vec_fp {
($name:ident, $field:ty, $wasm_field:ty) => {
#[napi]
#[derive(Clone, Debug, Default)]
pub struct $name(#[napi(skip)] pub Vec<Vec<$field>>);

#[napi]
impl $name {
#[napi(constructor)]
pub fn create(capacity: i32) -> Self {
Self(Vec::with_capacity(capacity as usize))
}

#[napi]
pub fn push(&mut self, vector: Uint8Array) -> Result<()> {
let flattened = vector.as_ref().to_vec();
let values = FlatVector::<$wasm_field>::from_bytes(flattened)
.into_iter()
.map(Into::into)
.collect();
self.0.push(values);
Ok(())
}

#[napi]
pub fn get(&self, index: i32) -> Result<Uint8Array> {
let slice = self.0.get(index as usize).ok_or_else(|| {
Error::new(Status::InvalidArg, "index out of bounds".to_string())
})?;

let bytes = slice
.iter()
.cloned()
.map(<$wasm_field>::from)
.flat_map(FlatVectorElem::flatten)
.collect::<Vec<u8>>();

Ok(Uint8Array::from(bytes))
}

#[napi]
pub fn set(&mut self, index: i32, vector: Uint8Array) -> Result<()> {
let entry = self.0.get_mut(index as usize).ok_or_else(|| {
Error::new(Status::InvalidArg, "index out of bounds".to_string())
})?;

let flattened = vector.as_ref().to_vec();
*entry = FlatVector::<$wasm_field>::from_bytes(flattened)
.into_iter()
.map(Into::into)
.collect();
Ok(())
}
}

impl From<Vec<Vec<$field>>> for $name {
fn from(value: Vec<Vec<$field>>) -> Self {
Self(value)
}
}

impl From<$name> for Vec<Vec<$field>> {
fn from(value: $name) -> Self {
value.0
}
}
};
}

pub mod fp {
use super::*;
use crate::wrappers::field::WasmPastaFp;
use mina_curves::pasta::Fp;
use napi_derive::napi;

impl_vec_vec_fp!(WasmVecVecFp, Fp, WasmPastaFp);
}

pub mod fq {
use super::*;
use crate::wrappers::field::WasmPastaFq;
use mina_curves::pasta::Fq;
use napi_derive::napi;

impl_vec_vec_fp!(WasmVecVecFq, Fq, WasmPastaFq);
}
Loading
Loading