diff --git a/libzkbob-rs-node/Cargo.toml b/libzkbob-rs-node/Cargo.toml index ddf6f52..7a3396b 100644 --- a/libzkbob-rs-node/Cargo.toml +++ b/libzkbob-rs-node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libzkbob-rs-node" -version = "1.0.0" +version = "1.1.0" authors = ["Dmitry Vdovin "] repository = "https://github.com/zkBob/libzkbob-rs/" license = "MIT OR Apache-2.0" @@ -11,7 +11,7 @@ exclude = ["index.node"] crate-type = ["cdylib"] [dependencies] -libzkbob-rs = { version = "1.0.0", features = ["native"] } +libzkbob-rs = { version = "1.4.0", features = ["native"] } #libzkbob-rs = { path = "../libzkbob-rs", features = ["native"] } neon = { version = "0.10.0", default-features = false, features = ["channel-api", "napi-6", "promise-api", "task-api"] } # FIXME: Using a random fork for now @@ -23,5 +23,5 @@ hex = "0.4.3" git = "https://github.com/zkbob/fawkes-crypto" branch = "master" package = "fawkes-crypto-zkbob" -version = "4.5.0" +version = "4.6.0" features = ["multicore"] \ No newline at end of file diff --git a/libzkbob-rs-node/index.d.ts b/libzkbob-rs-node/index.d.ts index b8f3781..17217f9 100644 --- a/libzkbob-rs-node/index.d.ts +++ b/libzkbob-rs-node/index.d.ts @@ -109,8 +109,8 @@ export interface VK { } declare class Params { - static fromBinary(data: Buffer): Params; - static fromFile(path: string): Params; + static fromBinary(data: Buffer, precompute: boolean): Params; + static fromFile(path: string, precompute: boolean): Params; } declare class Proof { diff --git a/libzkbob-rs-node/package.json b/libzkbob-rs-node/package.json index d3a3f1c..258ef71 100644 --- a/libzkbob-rs-node/package.json +++ b/libzkbob-rs-node/package.json @@ -1,6 +1,6 @@ { "name": "libzkbob-rs-node", - "version": "1.0.0", + "version": "1.1.0", "description": "Neon version of libzkbob-rs", "main": "index.js", "types": "index.d.ts", diff --git a/libzkbob-rs-node/src/params.rs b/libzkbob-rs-node/src/params.rs index ace68df..40f8a95 100644 --- a/libzkbob-rs-node/src/params.rs +++ b/libzkbob-rs-node/src/params.rs @@ -1,14 +1,15 @@ use std::path::PathBuf; use std::sync::Arc; -use libzkbob_rs::libzeropool::fawkes_crypto::backend::bellman_groth16::Parameters; +use libzkbob_rs::libzeropool::fawkes_crypto::backend::bellman_groth16::{Parameters, PrecomputedData}; use neon::{prelude::*, types::buffer::TypedArray}; -use crate::Engine; +use crate::{Engine, Fr}; pub type BoxedParams = JsBox>; pub struct Params { pub inner: Parameters, + pub precomputed: Option>, } pub fn from_binary(mut cx: FunctionContext) -> JsResult { @@ -16,8 +17,9 @@ pub fn from_binary(mut cx: FunctionContext) -> JsResult { let mut data = input.as_slice(&cx); let inner = Parameters::read(&mut data, true, true).unwrap(); - - Ok(cx.boxed(Arc::new(Params { inner }))) + let precompute = cx.argument::(1)?.value(&mut cx); + let precomputed = precompute.then(|| inner.precompute()); + Ok(cx.boxed(Arc::new(Params { inner, precomputed }))) } pub fn from_file(mut cx: FunctionContext) -> JsResult { @@ -28,8 +30,9 @@ pub fn from_file(mut cx: FunctionContext) -> JsResult { let data = std::fs::read(path).unwrap(); let inner = Parameters::read(&mut data.as_slice(), true, true).unwrap(); - - Ok(cx.boxed(Arc::new(Params { inner }))) + let precompute = cx.argument::(1)?.value(&mut cx); + let precomputed = precompute.then(|| inner.precompute()); + Ok(cx.boxed(Arc::new(Params { inner, precomputed }))) } impl Finalize for Params {} diff --git a/libzkbob-rs-node/src/proof.rs b/libzkbob-rs-node/src/proof.rs index 4e3e916..4b7d599 100644 --- a/libzkbob-rs-node/src/proof.rs +++ b/libzkbob-rs-node/src/proof.rs @@ -5,7 +5,8 @@ use libzkbob_rs::libzeropool::fawkes_crypto::backend::bellman_groth16::verifier: use libzkbob_rs::libzeropool::fawkes_crypto::ff_uint::Num; use libzkbob_rs::libzeropool::POOL_PARAMS; use libzkbob_rs::proof::{ - prove_delegated_deposit as prove_delegated_deposit_native, prove_tree as prove_tree_native, + prove_delegated_deposit as prove_delegated_deposit_native, + prove_tree as prove_tree_native, prove_tx as prove_tx_native, }; use neon::prelude::*; @@ -31,7 +32,13 @@ pub fn prove_tx_async(mut cx: FunctionContext) -> JsResult { let promise = cx .task(move || { - let (inputs, proof) = prove_tx_native(¶ms.inner, &*POOL_PARAMS, tr_pub, tr_sec); + let (inputs, proof) = prove_tx_native( + ¶ms.inner, + &*POOL_PARAMS, + tr_pub, + tr_sec, + ¶ms.precomputed, + ); SnarkProof { inputs, proof } }) .promise(move |mut cx, proof| { @@ -50,7 +57,13 @@ pub fn prove_tree_async(mut cx: FunctionContext) -> JsResult { let promise = cx .task(move || { - let (inputs, proof) = prove_tree_native(¶ms.inner, &*POOL_PARAMS, tr_pub, tr_sec); + let (inputs, proof) = prove_tree_native( + ¶ms.inner, + &*POOL_PARAMS, + tr_pub, + tr_sec, + ¶ms.precomputed, + ); SnarkProof { inputs, proof } }) .promise(move |mut cx, proof| { @@ -69,8 +82,13 @@ pub fn prove_delegated_deposit_async(mut cx: FunctionContext) -> JsResult JsResult { let tr_pub = neon_serde::from_value(&mut cx, tr_pub_js).unwrap(); let tr_sec = neon_serde::from_value(&mut cx, tr_sec_js).unwrap(); - let pair = prove_tx_native(¶ms.inner, &*POOL_PARAMS, tr_pub, tr_sec); + let pair = prove_tx_native( + ¶ms.inner, + &*POOL_PARAMS, + tr_pub, + tr_sec, + ¶ms.precomputed, + ); let proof = SnarkProof { inputs: pair.0, @@ -108,7 +132,13 @@ pub fn prove_tree(mut cx: FunctionContext) -> JsResult { let tr_pub = neon_serde::from_value(&mut cx, tr_pub_js).unwrap(); let tr_sec = neon_serde::from_value(&mut cx, tr_sec_js).unwrap(); - let pair = prove_tree_native(¶ms.inner, &*POOL_PARAMS, tr_pub, tr_sec); + let pair = prove_tree_native( + ¶ms.inner, + &*POOL_PARAMS, + tr_pub, + tr_sec, + ¶ms.precomputed, + ); let proof = SnarkProof { inputs: pair.0, @@ -128,8 +158,13 @@ pub fn prove_delegated_deposit(mut cx: FunctionContext) -> JsResult { let d_pub = neon_serde::from_value(&mut cx, d_pub_js).unwrap(); let d_sec = neon_serde::from_value(&mut cx, d_sec_js).unwrap(); - let (inputs, proof) = - prove_delegated_deposit_native(¶ms.inner, &*POOL_PARAMS, d_pub, d_sec); + let (inputs, proof) = prove_delegated_deposit_native( + ¶ms.inner, + &*POOL_PARAMS, + d_pub, + d_sec, + ¶ms.precomputed, + ); let proof = SnarkProof { inputs, proof }; diff --git a/libzkbob-rs-wasm/Cargo.toml b/libzkbob-rs-wasm/Cargo.toml index d9d6c91..9705c21 100644 --- a/libzkbob-rs-wasm/Cargo.toml +++ b/libzkbob-rs-wasm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libzkbob-rs-wasm" description = "A higher level zkBob API for Wasm" -version = "1.3.0" +version = "1.4.0" authors = ["Dmitry Vdovin "] repository = "https://github.com/zkBob/libzkbob-rs/" license = "MIT OR Apache-2.0" @@ -57,7 +57,7 @@ web-sys = "0.3.61" git = "https://github.com/zkBob/fawkes-crypto" branch = "master" package = "fawkes-crypto-zkbob" -version = "4.5.0" +version = "4.6.0" features = ["wasm", "serde_support"] diff --git a/libzkbob-rs-wasm/src/params.rs b/libzkbob-rs-wasm/src/params.rs index e42317f..dfa7a54 100644 --- a/libzkbob-rs-wasm/src/params.rs +++ b/libzkbob-rs-wasm/src/params.rs @@ -1,17 +1,20 @@ +use fawkes_crypto::backend::bellman_groth16::PrecomputedData; use libzkbob_rs::libzeropool::fawkes_crypto::backend::bellman_groth16::Parameters; use wasm_bindgen::prelude::*; -use crate::Engine; +use crate::{Engine, Fr}; #[wasm_bindgen] pub struct Params { #[wasm_bindgen(skip)] pub inner: Parameters, + #[wasm_bindgen(skip)] + pub precomputed: Option> } impl From> for Params { fn from(params: Parameters) -> Self { - Params { inner: params } + Params { inner: params, precomputed: None } } } @@ -25,14 +28,29 @@ impl From for Parameters { impl Params { #[wasm_bindgen(js_name = "fromBinary")] pub fn from_binary(input: &[u8]) -> Result { - Self::from_binary_ext(input, true, true) + Self::from_binary_ext(input, true, true, false) } #[wasm_bindgen(js_name = "fromBinaryExtended")] - pub fn from_binary_ext(input: &[u8], disallow_points_at_infinity: bool, checked: bool) -> Result { + pub fn from_binary_ext(input: &[u8], disallow_points_at_infinity: bool, checked: bool, precompute: bool) -> Result { let mut input = input; let inner = Parameters::read(&mut input, disallow_points_at_infinity, checked).map_err(|err| js_err!("{}", err))?; + let mut precomputed = None; + + if precompute { + if let Ok(precompute_memory_size) = inner.precompute_memory_size() { + { + // WebAssembly.Memory.grow(..) is extremely slow on iOS + // so it's much better to allocate necessary memory with one call + // than to do it multiple times in precompute. + let mut v: Vec = Vec::new(); + v.reserve(precompute_memory_size); + v.shrink_to_fit() + } + precomputed = Some(inner.precompute()); + } + } - Ok(Params { inner }) + Ok(Params { inner, precomputed }) } } diff --git a/libzkbob-rs-wasm/src/proof.rs b/libzkbob-rs-wasm/src/proof.rs index ed9d26f..c20df8c 100644 --- a/libzkbob-rs-wasm/src/proof.rs +++ b/libzkbob-rs-wasm/src/proof.rs @@ -1,3 +1,4 @@ +use fawkes_crypto::backend::bellman_groth16::prover::prove_precomputed; use libzkbob_rs::libzeropool::{ circuit::tree::tree_update, circuit::tx::c_transfer, @@ -45,6 +46,7 @@ impl Proof { transfer_pub: ts_types::TransferPub, transfer_sec: ts_types::TransferSec, ) -> Result { + let precomputed = ¶ms.precomputed; let params = ¶ms.inner; let public: NativeTransferPub<_> = @@ -56,7 +58,10 @@ impl Proof { c_transfer(&public, &secret, &*POOL_PARAMS); }; - let (inputs, snark_proof) = prove(params, &public, &secret, circuit); + let (inputs, snark_proof) = match precomputed { + Some(precomputed) => prove_precomputed(params, &public, &secret, circuit, precomputed), + None => prove(params, &public, &secret, circuit) + }; let proof = Proof { inputs, diff --git a/libzkbob-rs/Cargo.toml b/libzkbob-rs/Cargo.toml index deec3a4..af85336 100644 --- a/libzkbob-rs/Cargo.toml +++ b/libzkbob-rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libzkbob-rs" description = "A higher level zkBob API" -version = "1.3.0" +version = "1.4.0" authors = ["Dmitry Vdovin "] repository = "https://github.com/zkBob/libzkbob-rs/" license = "MIT OR Apache-2.0" @@ -26,7 +26,7 @@ hex = { version = "0.4.3", features = ["serde"] } git = "https://github.com/zkbob/libzeropool-zkbob" branch = "master" package = "libzeropool-zkbob" -version = "1.2.0" +version = "1.3.0" default-features = false features = ["in3out127"] diff --git a/libzkbob-rs/src/proof.rs b/libzkbob-rs/src/proof.rs index adc2774..e4c9e23 100644 --- a/libzkbob-rs/src/proof.rs +++ b/libzkbob-rs/src/proof.rs @@ -4,8 +4,8 @@ use libzeropool::{ }, fawkes_crypto::{ backend::bellman_groth16::engines::Engine, - backend::bellman_groth16::prover::{prove, Proof}, - backend::bellman_groth16::Parameters, + backend::bellman_groth16::{prover::{prove, Proof}, PrecomputedData}, + backend::bellman_groth16::{Parameters, prover::prove_precomputed}, ff_uint::Num, }, native::{ @@ -21,6 +21,7 @@ pub fn prove_tx( pool_params: &P, transfer_pub: TransferPub, transfer_sec: TransferSec, + precomputed: &Option>, ) -> (Vec>, Proof) where P: PoolParams, @@ -30,7 +31,12 @@ where c_transfer(&public, &secret, pool_params); }; - prove(params, &transfer_pub, &transfer_sec, circuit) + match precomputed { + Some(precomputed) => { + prove_precomputed(params, &transfer_pub, &transfer_sec, circuit, precomputed) + }, + None => prove(params, &transfer_pub, &transfer_sec, circuit) + } } pub fn prove_tree( @@ -38,6 +44,7 @@ pub fn prove_tree( pool_params: &P, tree_pub: TreePub, tree_sec: TreeSec, + precomputed: &Option>, ) -> (Vec>, Proof) where P: PoolParams, @@ -47,7 +54,12 @@ where tree_update(&public, &secret, pool_params); }; - prove(params, &tree_pub, &tree_sec, circuit) + match precomputed { + Some(precomputed) => { + prove_precomputed(params, &tree_pub, &tree_sec, circuit, precomputed) + }, + None => prove(params, &tree_pub, &tree_sec, circuit) + } } pub fn prove_delegated_deposit( @@ -55,6 +67,7 @@ pub fn prove_delegated_deposit( pool_params: &P, d_pub: DelegatedDepositBatchPub, d_sec: DelegatedDepositBatchSec, + precomputed: &Option>, ) -> (Vec>, Proof) where P: PoolParams, @@ -64,6 +77,10 @@ where check_delegated_deposit_batch(&public, &secret, pool_params); }; - prove(params, &d_pub, &d_sec, circuit) -} - + match precomputed { + Some(precomputed) => { + prove_precomputed(params, &d_pub, &d_sec, circuit, precomputed) + }, + None => prove(params, &d_pub, &d_sec, circuit) + } +} \ No newline at end of file