feat: unify RLN types, refactor public APIs, add full (de)serialization, align FFI/WASM/APIs, simplify errors, update docs/examples, and clean up zerokit (#355)

# Changes

- Unified the `RLN` struct and core protocol types across public, FFI,
and WASM so everything works consistently.
- Fully refactored `protocol.rs` and `public.rs` to clean up the API
surface and make the flow easier to work with.
- Added (de)serialization for `RLN_Proof` and `RLN_ProofValues`, and
matched all C, Nim, WASM, and Node.js examples.
- Aligned FFI and WASM behavior, added missing APIs, and standardized
how witness are created and passed around.
- Reworked the error types, added clearer verification messages, and
simplified the overall error structure.
- Updated variable names, README, Rust docs, and examples across the
repo, updated outdated RLN RFC link.
- Refactored `rln-cli` to use the new public API, removed
serialize-based cli example, and dropped the `eyre` crate.
- Bumped dependencies, fixed CI, fixed `+atomic` flags for latest
nightly Rust and added `Clippy.toml` for better fmt.
- Added a `prelude.rs` file for easier use, cleaned up public access for
types and types import across zerokit modules.
- Separated keygen, proof handling, slashing logic, and witness into
protocol folder.
This commit is contained in:
Vinh Trịnh
2025-12-09 19:03:04 +07:00
committed by GitHub
parent 5c73af1130
commit 77a8d28965
82 changed files with 4714 additions and 6591 deletions

173
rln-wasm/Cargo.lock generated
View File

@@ -69,7 +69,7 @@ checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -122,7 +122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60"
dependencies = [
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -135,7 +135,7 @@ dependencies = [
"num-traits",
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -221,7 +221,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -253,6 +253,17 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "async-trait"
version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.111",
]
[[package]]
name = "autocfg"
version = "1.5.0"
@@ -303,15 +314,21 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.10.1"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.44"
version = "1.2.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -393,9 +410,9 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
@@ -432,7 +449,7 @@ dependencies = [
"enum-ordinalize",
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -458,7 +475,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -520,9 +537,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "find-msvc-tools"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
[[package]]
name = "fnv"
@@ -551,9 +568,9 @@ dependencies = [
[[package]]
name = "generic-array"
version = "0.14.9"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
@@ -595,24 +612,18 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.16.0"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "indexmap"
version = "2.12.0"
version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f"
checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
dependencies = [
"equivalent",
"hashbrown 0.16.0",
"hashbrown 0.16.1",
]
[[package]]
@@ -650,9 +661,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "js-sys"
version = "0.3.82"
version = "0.3.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65"
checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -744,6 +755,15 @@ dependencies = [
"walkdir",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
@@ -779,6 +799,12 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "oorandom"
version = "11.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
[[package]]
name = "parking_lot"
version = "0.11.2"
@@ -887,14 +913,14 @@ dependencies = [
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
name = "quote"
version = "1.0.41"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
dependencies = [
"proc-macro2",
]
@@ -1202,7 +1228,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -1317,9 +1343,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.108"
version = "2.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
dependencies = [
"proc-macro2",
"quote",
@@ -1356,7 +1382,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -1400,9 +1426,9 @@ dependencies = [
[[package]]
name = "tracing"
version = "0.1.41"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
dependencies = [
"pin-project-lite",
"tracing-attributes",
@@ -1411,20 +1437,20 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.30"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
name = "tracing-core"
version = "0.1.34"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
dependencies = [
"once_cell",
"valuable",
@@ -1511,9 +1537,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.105"
version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60"
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
dependencies = [
"cfg-if",
"once_cell",
@@ -1524,9 +1550,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.55"
version = "0.4.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0"
checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c"
dependencies = [
"cfg-if",
"js-sys",
@@ -1537,9 +1563,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.105"
version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2"
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1547,14 +1573,14 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.105"
version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc"
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
"wasm-bindgen-shared",
]
@@ -1572,21 +1598,29 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.105"
version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76"
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
dependencies = [
"unicode-ident",
]
[[package]]
name = "wasm-bindgen-test"
version = "0.3.55"
version = "0.3.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfc379bfb624eb59050b509c13e77b4eb53150c350db69628141abce842f2373"
checksum = "25e90e66d265d3a1efc0e72a54809ab90b9c0c515915c67cdf658689d2c22c6c"
dependencies = [
"async-trait",
"cast",
"js-sys",
"libm",
"minicov",
"nu-ansi-term",
"num-traits",
"oorandom",
"serde",
"serde_json",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
@@ -1594,13 +1628,13 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.55"
version = "0.3.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "085b2df989e1e6f9620c1311df6c996e83fe16f57792b272ce1e024ac16a90f1"
checksum = "7150335716dce6028bead2b848e72f47b45e7b9422f64cccdc23bedca89affc1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -1616,9 +1650,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.82"
version = "0.3.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1"
checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -1672,9 +1706,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.7.13"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
dependencies = [
"memchr",
]
@@ -1707,22 +1741,22 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.8.27"
version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.27"
version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -1742,7 +1776,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.108",
"syn 2.0.111",
]
[[package]]
@@ -1750,7 +1784,6 @@ name = "zerokit_utils"
version = "0.7.0"
dependencies = [
"ark-ff",
"hex",
"num-bigint",
"rayon",
"serde_json",

View File

@@ -13,10 +13,10 @@ rln = { path = "../rln", version = "0.9.0", default-features = false, features =
] }
zerokit_utils = { path = "../utils", version = "0.7.0", default-features = false }
num-bigint = { version = "0.4.6", default-features = false }
js-sys = "0.3.77"
wasm-bindgen = "0.2.100"
js-sys = "0.3.83"
wasm-bindgen = "0.2.106"
serde-wasm-bindgen = "0.6.5"
serde = "1.0"
serde = "1.0.228"
wasm-bindgen-rayon = { version = "1.3.0", features = [
"no-bundler",
], optional = true }
@@ -34,13 +34,13 @@ console_error_panic_hook = { version = "0.1.7", optional = true }
getrandom = { version = "0.2.16", features = ["js"] }
[dev-dependencies]
serde_json = "1.0.141"
wasm-bindgen-test = "0.3.50"
wasm-bindgen-futures = "0.4.50"
serde_json = "1.0.145"
wasm-bindgen-test = "0.3.56"
wasm-bindgen-futures = "0.4.56"
ark-std = { version = "0.5.0", default-features = false }
[dev-dependencies.web-sys]
version = "0.3.77"
version = "0.3.83"
features = ["Window", "Navigator"]
[features]

View File

@@ -17,10 +17,10 @@ args = ["build", "--release", "--target", "web", "--scope", "waku"]
[tasks.pack_build_parallel]
command = "env"
args = [
"RUSTFLAGS=-C target-feature=+atomics,+bulk-memory,+mutable-globals",
"CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS=-C target-feature=+atomics,+bulk-memory,+mutable-globals -C link-arg=--shared-memory -C link-arg=--max-memory=1073741824 -C link-arg=--import-memory -C link-arg=--export=__wasm_init_tls -C link-arg=--export=__tls_size -C link-arg=--export=__tls_align -C link-arg=--export=__tls_base",
"rustup",
"run",
"nightly-2025-09-24",
"nightly",
"wasm-pack",
"build",
"--release",
@@ -85,10 +85,10 @@ dependencies = ["build"]
[tasks.test_parallel]
command = "env"
args = [
"RUSTFLAGS=-C target-feature=+atomics,+bulk-memory,+mutable-globals",
"CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS=-C target-feature=+atomics,+bulk-memory,+mutable-globals -C link-arg=--shared-memory -C link-arg=--max-memory=1073741824 -C link-arg=--import-memory -C link-arg=--export=__wasm_init_tls -C link-arg=--export=__tls_size -C link-arg=--export=__tls_align -C link-arg=--export=__tls_base",
"rustup",
"run",
"nightly-2025-09-24",
"nightly",
"wasm-pack",
"test",
"--release",

View File

@@ -5,7 +5,7 @@
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
The Zerokit RLN WASM Module provides WebAssembly bindings for working with
Rate-Limiting Nullifier [RLN](https://rfc.vac.dev/spec/32/) zkSNARK proofs and primitives.
Rate-Limiting Nullifier [RLN](https://rfc.vac.dev/vac/raw/rln-v2) zkSNARK proofs and primitives.
This module is used by [waku-org/js-rln](https://github.com/waku-org/js-rln/) to enable
RLN functionality in JavaScript/TypeScript applications.
@@ -116,7 +116,7 @@ enabling multi-threaded execution in the browser.
#### Install `nightly` Rust
```bash
rustup install nightly-2025-09-24
rustup install nightly
```
### Build Commands

View File

@@ -5,6 +5,12 @@ import { dirname, join } from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
function debugUint8Array(uint8Array) {
return Array.from(uint8Array, (byte) =>
byte.toString(16).padStart(2, "0")
).join(", ");
}
async function calculateWitness(circomPath, inputs, witnessCalculatorFile) {
const wasmFile = readFileSync(circomPath);
const wasmFileBuffer = wasmFile.slice(
@@ -67,7 +73,11 @@ async function main() {
console.log("\nWasmFr serialization: WasmFr <-> bytes");
const serRateCommitment = rateCommitment.toBytesLE();
console.log(" - serialized rate_commitment =", serRateCommitment);
console.log(
" - serialized rate_commitment = [" +
debugUint8Array(serRateCommitment) +
"]"
);
const deserRateCommitment = rlnWasm.WasmFr.fromBytesLE(serRateCommitment);
console.log(
@@ -96,14 +106,18 @@ async function main() {
console.log("\nVecWasmFr serialization: VecWasmFr <-> bytes");
const serPathElements = pathElements.toBytesLE();
console.log(" - serialized path_elements = ", serPathElements);
console.log(
" - serialized path_elements = [" + debugUint8Array(serPathElements) + "]"
);
const deserPathElements = rlnWasm.VecWasmFr.fromBytesLE(serPathElements);
console.log(" - deserialized path_elements = ", deserPathElements.debug());
console.log("\nUint8Array serialization: Uint8Array <-> bytes");
const serPathIndex = rlnWasm.Uint8ArrayUtils.toBytesLE(identityPathIndex);
console.log(" - serialized path_index =", serPathIndex);
console.log(
" - serialized path_index = [" + debugUint8Array(serPathIndex) + "]"
);
const deserPathIndex = rlnWasm.Uint8ArrayUtils.fromBytesLE(serPathIndex);
console.log(" - deserialized path_index =", deserPathIndex);
@@ -156,7 +170,7 @@ async function main() {
const messageId = rlnWasm.WasmFr.fromUint(0);
console.log(" - message_id = " + messageId.debug());
console.log("\nGenerating RLN Proof");
console.log("\nCreating RLN Witness");
const witness = new rlnWasm.WasmRLNWitnessInput(
identitySecret,
userMessageLimit,
@@ -166,22 +180,59 @@ async function main() {
x,
externalNullifier
);
console.log("RLN Witness created successfully");
console.log("\nCalculating witness");
const witnessJson = witness.toBigIntJson();
const calculatedWitness = await calculateWitness(
circomPath,
witnessJson,
witnessCalculatorFile
);
const proof = rlnInstance.generateProofWithWitness(
console.log("Witness calculated successfully");
console.log("\nGenerating RLN Proof");
const rln_proof = rlnInstance.generateRLNProofWithWitness(
calculatedWitness,
witness
);
console.log("Proof generated successfully");
console.log("\nGetting proof values");
const proofValues = rln_proof.getValues();
console.log(" - y = " + proofValues.y.debug());
console.log(" - nullifier = " + proofValues.nullifier.debug());
console.log(" - root = " + proofValues.root.debug());
console.log(" - x = " + proofValues.x.debug());
console.log(
" - external_nullifier = " + proofValues.externalNullifier.debug()
);
console.log("\nRLNProof serialization: RLNProof <-> bytes");
const serProof = rln_proof.toBytesLE();
console.log(" - serialized proof = [" + debugUint8Array(serProof) + " ]");
const deserProof = rlnWasm.WasmRLNProof.fromBytesLE(serProof);
console.log(" - proof deserialized successfully");
console.log("\nRLNProofValues serialization: RLNProofValues <-> bytes");
const serProofValues = proofValues.toBytesLE();
console.log(
" - serialized proof_values = [" + debugUint8Array(serProofValues) + " ]"
);
const deserProofValues2 =
rlnWasm.WasmRLNProofValues.fromBytesLE(serProofValues);
console.log(" - proof_values deserialized successfully");
console.log(
" - deserialized external_nullifier = " +
deserProofValues2.externalNullifier.debug()
);
console.log("\nVerifying Proof");
const roots = new rlnWasm.VecWasmFr();
roots.push(computedRoot);
const isValid = rlnInstance.verifyWithRoots(proof, roots, x);
const isValid = rlnInstance.verifyWithRoots(rln_proof, roots, x);
if (isValid) {
console.log("Proof verified successfully");
} else {
@@ -205,7 +256,7 @@ async function main() {
const messageId2 = rlnWasm.WasmFr.fromUint(0);
console.log(" - message_id2 = " + messageId2.debug());
console.log("\nGenerating second RLN Proof");
console.log("\nCreating second RLN Witness");
const witness2 = new rlnWasm.WasmRLNWitnessInput(
identitySecret,
userMessageLimit,
@@ -215,25 +266,36 @@ async function main() {
x2,
externalNullifier
);
console.log("Second RLN Witness created successfully");
console.log("\nCalculating second witness");
const witnessJson2 = witness2.toBigIntJson();
const calculatedWitness2 = await calculateWitness(
circomPath,
witnessJson2,
witnessCalculatorFile
);
const proof2 = rlnInstance.generateProofWithWitness(
console.log("Second witness calculated successfully");
console.log("\nGenerating second RLN Proof");
const rln_proof2 = rlnInstance.generateRLNProofWithWitness(
calculatedWitness2,
witness2
);
console.log("Second proof generated successfully");
console.log("\nVerifying second proof");
const isValid2 = rlnInstance.verifyWithRoots(proof2, roots, x2);
const isValid2 = rlnInstance.verifyWithRoots(rln_proof2, roots, x2);
if (isValid2) {
console.log("Second proof verified successfully");
console.log("\nRecovering identity secret");
const recoveredSecret = rlnWasm.WasmRLNProof.recoverIdSecret(proof, proof2);
const proofValues1 = rln_proof.getValues();
const proofValues2 = rln_proof2.getValues();
const recoveredSecret = rlnWasm.WasmRLNProofValues.recoverIdSecret(
proofValues1,
proofValues2
);
console.log(" - recovered_secret = " + recoveredSecret.debug());
console.log(" - original_secret = " + identitySecret.debug());
console.log("Slashing successful: Identity is recovered!");

View File

@@ -3,13 +3,11 @@
mod wasm_rln;
mod wasm_utils;
#[cfg(not(feature = "utils"))]
pub use wasm_rln::{WasmRLN, WasmRLNProof, WasmRLNWitnessInput};
pub use wasm_utils::{ExtendedIdentity, Hasher, Identity, VecWasmFr, WasmFr};
#[cfg(all(feature = "parallel", not(feature = "utils")))]
pub use wasm_bindgen_rayon::init_thread_pool;
#[cfg(not(feature = "utils"))]
pub use wasm_rln::{WasmRLN, WasmRLNProof, WasmRLNProofValues, WasmRLNWitnessInput};
pub use wasm_utils::{ExtendedIdentity, Hasher, Identity, VecWasmFr, WasmFr};
#[cfg(feature = "panic_hook")]
#[wasm_bindgen(js_name = initPanicHook)]

View File

@@ -1,42 +1,31 @@
#![cfg(target_arch = "wasm32")]
#![cfg(not(feature = "utils"))]
use crate::wasm_utils::{VecWasmFr, WasmFr};
use js_sys::{BigInt as JsBigInt, Object, Uint8Array};
use num_bigint::BigInt;
use rln::{
circuit::{zkey_from_raw, Fr, Proof},
protocol::{
compute_id_secret, generate_proof_with_witness, proof_values_from_witness,
rln_witness_to_bigint_json, verify_proof, RLNProofValues, RLNWitnessInput, RLN,
},
utils::IdSecret,
};
use rln::prelude::*;
use serde::Serialize;
use wasm_bindgen::prelude::*;
use crate::wasm_utils::{VecWasmFr, WasmFr};
#[wasm_bindgen]
pub struct WasmRLN(RLN);
#[wasm_bindgen]
impl WasmRLN {
#[wasm_bindgen(constructor)]
pub fn new(zkey_buffer: &Uint8Array) -> Result<WasmRLN, String> {
let zkey = zkey_from_raw(&zkey_buffer.to_vec()).map_err(|err| err.to_string())?;
let rln = RLN { zkey };
pub fn new(zkey_data: &Uint8Array) -> Result<WasmRLN, String> {
let rln = RLN::new_with_params(zkey_data.to_vec()).map_err(|err| err.to_string())?;
Ok(WasmRLN(rln))
}
#[wasm_bindgen(js_name = generateProofWithWitness)]
pub fn generate_proof_with_witness(
#[wasm_bindgen(js_name = generateRLNProofWithWitness)]
pub fn generate_rln_proof_with_witness(
&self,
calculated_witness: Vec<JsBigInt>,
rln_witness: &WasmRLNWitnessInput,
witness: &WasmRLNWitnessInput,
) -> Result<WasmRLNProof, String> {
let proof_values =
proof_values_from_witness(&rln_witness.0).map_err(|err| err.to_string())?;
let calculated_witness_bigint: Vec<BigInt> = calculated_witness
.iter()
.map(|js_bigint| {
@@ -45,95 +34,137 @@ impl WasmRLN {
})
.collect();
let proof = generate_proof_with_witness(calculated_witness_bigint, &self.0.zkey)
let (proof, proof_values) = self
.0
.generate_rln_proof_with_witness(calculated_witness_bigint, &witness.0)
.map_err(|err| err.to_string())?;
Ok(WasmRLNProof {
let rln_proof = RLNProof {
proof_values,
proof,
})
};
Ok(WasmRLNProof(rln_proof))
}
#[wasm_bindgen(js_name = verifyWithRoots)]
pub fn verify_with_roots(
&self,
proof: &WasmRLNProof,
rln_proof: &WasmRLNProof,
roots: &VecWasmFr,
x: &WasmFr,
) -> Result<bool, String> {
let proof_verified = verify_proof(&self.0.zkey.0.vk, &proof.proof, &proof.proof_values)
.map_err(|err| err.to_string())?;
let roots_fr: Vec<Fr> = (0..roots.length())
.filter_map(|i| roots.get(i))
.map(|root| *root)
.collect();
if !proof_verified {
return Ok(false);
}
let roots_verified = if roots.length() == 0 {
true
} else {
(0..roots.length())
.filter_map(|i| roots.get(i))
.any(|root| *root == proof.proof_values.root)
};
let signal_verified = **x == proof.proof_values.x;
Ok(proof_verified && roots_verified && signal_verified)
self.0
.verify_with_roots(&rln_proof.0.proof, &rln_proof.0.proof_values, x, &roots_fr)
.map_err(|err| err.to_string())
}
}
#[wasm_bindgen]
pub struct WasmRLNProof {
proof: Proof,
proof_values: RLNProofValues,
}
pub struct WasmRLNProof(RLNProof);
#[wasm_bindgen]
impl WasmRLNProof {
#[wasm_bindgen(js_name = getValues)]
pub fn get_values(&self) -> WasmRLNProofValues {
WasmRLNProofValues(self.0.proof_values)
}
#[wasm_bindgen(js_name = toBytesLE)]
pub fn to_bytes_le(&self) -> Uint8Array {
Uint8Array::from(&rln_proof_to_bytes_le(&self.0)[..])
}
#[wasm_bindgen(js_name = toBytesBE)]
pub fn to_bytes_be(&self) -> Uint8Array {
Uint8Array::from(&rln_proof_to_bytes_be(&self.0)[..])
}
#[wasm_bindgen(js_name = fromBytesLE)]
pub fn from_bytes_le(bytes: &Uint8Array) -> Result<WasmRLNProof, String> {
let bytes_vec = bytes.to_vec();
let (proof, _) = bytes_le_to_rln_proof(&bytes_vec).map_err(|e| e.to_string())?;
Ok(WasmRLNProof(proof))
}
#[wasm_bindgen(js_name = fromBytesBE)]
pub fn from_bytes_be(bytes: &Uint8Array) -> Result<WasmRLNProof, String> {
let bytes_vec = bytes.to_vec();
let (proof, _) = bytes_be_to_rln_proof(&bytes_vec).map_err(|e| e.to_string())?;
Ok(WasmRLNProof(proof))
}
}
#[wasm_bindgen]
pub struct WasmRLNProofValues(RLNProofValues);
#[wasm_bindgen]
impl WasmRLNProofValues {
#[wasm_bindgen(getter)]
pub fn y(&self) -> WasmFr {
WasmFr::from(self.proof_values.y)
WasmFr::from(self.0.y)
}
#[wasm_bindgen(getter)]
pub fn nullifier(&self) -> WasmFr {
WasmFr::from(self.proof_values.nullifier)
WasmFr::from(self.0.nullifier)
}
#[wasm_bindgen(getter)]
pub fn root(&self) -> WasmFr {
WasmFr::from(self.proof_values.root)
WasmFr::from(self.0.root)
}
#[wasm_bindgen(getter)]
pub fn x(&self) -> WasmFr {
WasmFr::from(self.proof_values.x)
WasmFr::from(self.0.x)
}
#[wasm_bindgen(getter, js_name = externalNullifier)]
pub fn external_nullifier(&self) -> WasmFr {
WasmFr::from(self.proof_values.external_nullifier)
WasmFr::from(self.0.external_nullifier)
}
#[wasm_bindgen(js_name = toBytesLE)]
pub fn to_bytes_le(&self) -> Uint8Array {
Uint8Array::from(&rln_proof_values_to_bytes_le(&self.0)[..])
}
#[wasm_bindgen(js_name = toBytesBE)]
pub fn to_bytes_be(&self) -> Uint8Array {
Uint8Array::from(&rln_proof_values_to_bytes_be(&self.0)[..])
}
#[wasm_bindgen(js_name = fromBytesLE)]
pub fn from_bytes_le(bytes: &Uint8Array) -> Result<WasmRLNProofValues, String> {
let bytes_vec = bytes.to_vec();
let (proof_values, _) =
bytes_le_to_rln_proof_values(&bytes_vec).map_err(|e| e.to_string())?;
Ok(WasmRLNProofValues(proof_values))
}
#[wasm_bindgen(js_name = fromBytesBE)]
pub fn from_bytes_be(bytes: &Uint8Array) -> Result<WasmRLNProofValues, String> {
let bytes_vec = bytes.to_vec();
let (proof_values, _) =
bytes_be_to_rln_proof_values(&bytes_vec).map_err(|e| e.to_string())?;
Ok(WasmRLNProofValues(proof_values))
}
#[wasm_bindgen(js_name = recoverIdSecret)]
pub fn recover_id_secret(
proof_1: &WasmRLNProof,
proof_2: &WasmRLNProof,
proof_values_1: &WasmRLNProofValues,
proof_values_2: &WasmRLNProofValues,
) -> Result<WasmFr, String> {
let external_nullifier_1 = proof_1.proof_values.external_nullifier;
let external_nullifier_2 = proof_2.proof_values.external_nullifier;
let recovered_identity_secret = recover_id_secret(&proof_values_1.0, &proof_values_2.0)
.map_err(|err| err.to_string())?;
if external_nullifier_1 != external_nullifier_2 {
return Err("External nullifiers do not match".to_string());
}
let share1 = (proof_1.proof_values.x, proof_1.proof_values.y);
let share2 = (proof_2.proof_values.x, proof_2.proof_values.y);
let recovered_identity_secret_hash =
compute_id_secret(share1, share2).map_err(|err| err.to_string())?;
Ok(WasmFr::from(*recovered_identity_secret_hash))
Ok(WasmFr::from(*recovered_identity_secret))
}
}
@@ -156,7 +187,7 @@ impl WasmRLNWitnessInput {
let path_elements: Vec<Fr> = path_elements.inner();
let identity_path_index: Vec<u8> = identity_path_index.to_vec();
let rln_witness = RLNWitnessInput::new(
let witness = RLNWitnessInput::new(
IdSecret::from(&mut identity_secret_fr),
user_message_limit.inner(),
message_id.inner(),
@@ -167,15 +198,15 @@ impl WasmRLNWitnessInput {
)
.map_err(|err| err.to_string())?;
Ok(WasmRLNWitnessInput(rln_witness))
Ok(WasmRLNWitnessInput(witness))
}
#[wasm_bindgen(js_name = toBigIntJson)]
pub fn to_bigint_json(&self) -> Result<Object, String> {
let inputs = rln_witness_to_bigint_json(&self.0).map_err(|err| err.to_string())?;
let bigint_json = rln_witness_to_bigint_json(&self.0).map_err(|err| err.to_string())?;
let serializer = serde_wasm_bindgen::Serializer::json_compatible();
let js_value = inputs
let js_value = bigint_json
.serialize(&serializer)
.map_err(|err| err.to_string())?;
@@ -183,4 +214,30 @@ impl WasmRLNWitnessInput {
.dyn_into::<Object>()
.map_err(|err| format!("{:#?}", err))
}
#[wasm_bindgen(js_name = toBytesLE)]
pub fn to_bytes_le(&self) -> Result<Uint8Array, String> {
let bytes = rln_witness_to_bytes_le(&self.0).map_err(|err| err.to_string())?;
Ok(Uint8Array::from(&bytes[..]))
}
#[wasm_bindgen(js_name = toBytesBE)]
pub fn to_bytes_be(&self) -> Result<Uint8Array, String> {
let bytes = rln_witness_to_bytes_be(&self.0).map_err(|err| err.to_string())?;
Ok(Uint8Array::from(&bytes[..]))
}
#[wasm_bindgen(js_name = fromBytesLE)]
pub fn from_bytes_le(bytes: &Uint8Array) -> Result<WasmRLNWitnessInput, String> {
let bytes_vec = bytes.to_vec();
let (witness, _) = bytes_le_to_rln_witness(&bytes_vec).map_err(|err| err.to_string())?;
Ok(WasmRLNWitnessInput(witness))
}
#[wasm_bindgen(js_name = fromBytesBE)]
pub fn from_bytes_be(bytes: &Uint8Array) -> Result<WasmRLNWitnessInput, String> {
let bytes_vec = bytes.to_vec();
let (witness, _) = bytes_be_to_rln_witness(&bytes_vec).map_err(|err| err.to_string())?;
Ok(WasmRLNWitnessInput(witness))
}
}

View File

@@ -1,17 +1,9 @@
#![cfg(target_arch = "wasm32")]
use js_sys::Uint8Array;
use rln::{
circuit::Fr,
hashers::{hash_to_field_be, hash_to_field_le, poseidon_hash},
protocol::{extended_keygen, extended_seeded_keygen, keygen, seeded_keygen},
utils::{
bytes_be_to_fr, bytes_be_to_vec_fr, bytes_be_to_vec_u8, bytes_le_to_fr, bytes_le_to_vec_fr,
bytes_le_to_vec_u8, fr_to_bytes_be, fr_to_bytes_le, vec_fr_to_bytes_be, vec_fr_to_bytes_le,
vec_u8_to_bytes_be, vec_u8_to_bytes_le,
},
};
use std::ops::Deref;
use js_sys::Uint8Array;
use rln::prelude::*;
use wasm_bindgen::prelude::*;
// WasmFr
@@ -51,17 +43,17 @@ impl WasmFr {
}
#[wasm_bindgen(js_name = fromBytesLE)]
pub fn from_bytes_le(bytes: &Uint8Array) -> Self {
pub fn from_bytes_le(bytes: &Uint8Array) -> Result<Self, String> {
let bytes_vec = bytes.to_vec();
let (fr, _) = bytes_le_to_fr(&bytes_vec);
Self(fr)
let (fr, _) = bytes_le_to_fr(&bytes_vec).map_err(|e| e.to_string())?;
Ok(Self(fr))
}
#[wasm_bindgen(js_name = fromBytesBE)]
pub fn from_bytes_be(bytes: &Uint8Array) -> Self {
pub fn from_bytes_be(bytes: &Uint8Array) -> Result<Self, String> {
let bytes_vec = bytes.to_vec();
let (fr, _) = bytes_be_to_fr(&bytes_vec);
Self(fr)
let (fr, _) = bytes_be_to_fr(&bytes_vec).map_err(|e| e.to_string())?;
Ok(Self(fr))
}
#[wasm_bindgen(js_name = toBytesLE)]
@@ -219,7 +211,7 @@ impl Hasher {
#[wasm_bindgen]
pub struct Identity {
identity_secret_hash: Fr,
identity_secret: Fr,
id_commitment: Fr,
}
@@ -227,9 +219,9 @@ pub struct Identity {
impl Identity {
#[wasm_bindgen(js_name = generate)]
pub fn generate() -> Identity {
let (identity_secret_hash, id_commitment) = keygen();
let (identity_secret, id_commitment) = keygen();
Identity {
identity_secret_hash: *identity_secret_hash,
identity_secret: *identity_secret,
id_commitment,
}
}
@@ -237,16 +229,16 @@ impl Identity {
#[wasm_bindgen(js_name = generateSeeded)]
pub fn generate_seeded(seed: &Uint8Array) -> Identity {
let seed_vec = seed.to_vec();
let (identity_secret_hash, id_commitment) = seeded_keygen(&seed_vec);
let (identity_secret, id_commitment) = seeded_keygen(&seed_vec);
Identity {
identity_secret_hash,
identity_secret,
id_commitment,
}
}
#[wasm_bindgen(js_name = getSecretHash)]
pub fn get_secret_hash(&self) -> WasmFr {
WasmFr(self.identity_secret_hash)
WasmFr(self.identity_secret)
}
#[wasm_bindgen(js_name = getCommitment)]
@@ -256,7 +248,7 @@ impl Identity {
#[wasm_bindgen(js_name = toArray)]
pub fn to_array(&self) -> VecWasmFr {
VecWasmFr(vec![self.identity_secret_hash, self.id_commitment])
VecWasmFr(vec![self.identity_secret, self.id_commitment])
}
}
@@ -264,7 +256,7 @@ impl Identity {
pub struct ExtendedIdentity {
identity_trapdoor: Fr,
identity_nullifier: Fr,
identity_secret_hash: Fr,
identity_secret: Fr,
id_commitment: Fr,
}
@@ -272,12 +264,12 @@ pub struct ExtendedIdentity {
impl ExtendedIdentity {
#[wasm_bindgen(js_name = generate)]
pub fn generate() -> ExtendedIdentity {
let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) =
let (identity_trapdoor, identity_nullifier, identity_secret, id_commitment) =
extended_keygen();
ExtendedIdentity {
identity_trapdoor,
identity_nullifier,
identity_secret_hash,
identity_secret,
id_commitment,
}
}
@@ -285,12 +277,12 @@ impl ExtendedIdentity {
#[wasm_bindgen(js_name = generateSeeded)]
pub fn generate_seeded(seed: &Uint8Array) -> ExtendedIdentity {
let seed_vec = seed.to_vec();
let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) =
let (identity_trapdoor, identity_nullifier, identity_secret, id_commitment) =
extended_seeded_keygen(&seed_vec);
ExtendedIdentity {
identity_trapdoor,
identity_nullifier,
identity_secret_hash,
identity_secret,
id_commitment,
}
}
@@ -307,7 +299,7 @@ impl ExtendedIdentity {
#[wasm_bindgen(js_name = getSecretHash)]
pub fn get_secret_hash(&self) -> WasmFr {
WasmFr(self.identity_secret_hash)
WasmFr(self.identity_secret)
}
#[wasm_bindgen(js_name = getCommitment)]
@@ -320,7 +312,7 @@ impl ExtendedIdentity {
VecWasmFr(vec![
self.identity_trapdoor,
self.identity_nullifier,
self.identity_secret_hash,
self.identity_secret,
self.id_commitment,
])
}

View File

@@ -4,8 +4,7 @@
#[cfg(test)]
mod test {
use js_sys::{BigInt as JsBigInt, Date, Object, Uint8Array};
use rln::circuit::TEST_TREE_DEPTH;
use rln::hashers::PoseidonHash;
use rln::prelude::*;
use rln_wasm::{
Hasher, Identity, VecWasmFr, WasmFr, WasmRLN, WasmRLNProof, WasmRLNWitnessInput,
};
@@ -14,7 +13,6 @@ mod test {
use zerokit_utils::{
OptimalMerkleProof, OptimalMerkleTree, ZerokitMerkleProof, ZerokitMerkleTree,
};
#[cfg(feature = "parallel")]
use {rln_wasm::init_thread_pool, wasm_bindgen_futures::JsFuture, web_sys::window};
@@ -114,7 +112,7 @@ mod test {
// Create RLN instance for other benchmarks
let rln_instance = WasmRLN::new(&zkey).expect("Failed to create RLN instance");
let mut tree: OptimalMerkleTree<PoseidonHash> =
OptimalMerkleTree::default(TEST_TREE_DEPTH).expect("Failed to create tree");
OptimalMerkleTree::default(DEFAULT_TREE_DEPTH).expect("Failed to create tree");
// Benchmark generate identity
let start_identity_gen = Date::now();
@@ -125,7 +123,7 @@ mod test {
// Generate identity for other benchmarks
let identity_pair = Identity::generate();
let identity_secret_hash = identity_pair.get_secret_hash();
let identity_secret = identity_pair.get_secret_hash();
let id_commitment = identity_pair.get_commitment();
let epoch = Hasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8]));
@@ -155,8 +153,8 @@ mod test {
}
let path_index = Uint8Array::from(&merkle_proof.get_path_index()[..]);
let rln_witness_input = WasmRLNWitnessInput::new(
&identity_secret_hash,
let witness = WasmRLNWitnessInput::new(
&identity_secret,
&user_message_limit,
&message_id,
&path_elements,
@@ -166,26 +164,25 @@ mod test {
)
.expect("Failed to create WasmRLNWitnessInput");
let rln_witness_input_bigint_json = rln_witness_input
let bigint_json = witness
.to_bigint_json()
.expect("Failed to convert witness to BigInt JSON");
// Benchmark witness calculation
let start_calculate_witness = Date::now();
for _ in 0..iterations {
let _ = calculateWitness(CIRCOM_BYTES, rln_witness_input_bigint_json.clone())
let _ = calculateWitness(CIRCOM_BYTES, bigint_json.clone())
.await
.expect("Failed to calculate witness");
}
let calculate_witness_result = Date::now() - start_calculate_witness;
// Calculate witness for other benchmarks
let calculated_witness_str =
calculateWitness(CIRCOM_BYTES, rln_witness_input_bigint_json.clone())
.await
.expect("Failed to calculate witness")
.as_string()
.expect("Failed to convert calculated witness to string");
let calculated_witness_str = calculateWitness(CIRCOM_BYTES, bigint_json.clone())
.await
.expect("Failed to calculate witness")
.as_string()
.expect("Failed to convert calculated witness to string");
let calculated_witness_vec_str: Vec<String> =
serde_json::from_str(&calculated_witness_str).expect("Failed to parse JSON");
let calculated_witness: Vec<JsBigInt> = calculated_witness_vec_str
@@ -194,17 +191,18 @@ mod test {
.collect();
// Benchmark proof generation with witness
let start_generate_proof_with_witness = Date::now();
let start_generate_rln_proof_with_witness = Date::now();
for _ in 0..iterations {
let _ = rln_instance
.generate_proof_with_witness(calculated_witness.clone(), &rln_witness_input)
.generate_rln_proof_with_witness(calculated_witness.clone(), &witness)
.expect("Failed to generate proof");
}
let generate_proof_with_witness_result = Date::now() - start_generate_proof_with_witness;
let generate_rln_proof_with_witness_result =
Date::now() - start_generate_rln_proof_with_witness;
// Generate proof with witness for other benchmarks
let proof: WasmRLNProof = rln_instance
.generate_proof_with_witness(calculated_witness, &rln_witness_input)
.generate_rln_proof_with_witness(calculated_witness, &witness)
.expect("Failed to generate proof");
let root = WasmFr::from(tree.root());
@@ -250,7 +248,7 @@ mod test {
));
results.push_str(&format!(
"Proof generation with witness: {}\n",
format_duration(generate_proof_with_witness_result)
format_duration(generate_rln_proof_with_witness_result)
));
results.push_str(&format!(
"Proof verification with roots: {}\n",

View File

@@ -4,8 +4,7 @@
#[cfg(test)]
mod test {
use js_sys::{BigInt as JsBigInt, Date, Object, Uint8Array};
use rln::circuit::TEST_TREE_DEPTH;
use rln::hashers::PoseidonHash;
use rln::prelude::*;
use rln_wasm::{
Hasher, Identity, VecWasmFr, WasmFr, WasmRLN, WasmRLNProof, WasmRLNWitnessInput,
};
@@ -94,7 +93,7 @@ mod test {
// Create RLN instance for other benchmarks
let rln_instance = WasmRLN::new(&zkey).expect("Failed to create RLN instance");
let mut tree: OptimalMerkleTree<PoseidonHash> =
OptimalMerkleTree::default(TEST_TREE_DEPTH).expect("Failed to create tree");
OptimalMerkleTree::default(DEFAULT_TREE_DEPTH).expect("Failed to create tree");
// Benchmark generate identity
let start_identity_gen = Date::now();
@@ -105,7 +104,7 @@ mod test {
// Generate identity for other benchmarks
let identity_pair = Identity::generate();
let identity_secret_hash = identity_pair.get_secret_hash();
let identity_secret = identity_pair.get_secret_hash();
let id_commitment = identity_pair.get_commitment();
let epoch = Hasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8]));
@@ -135,8 +134,8 @@ mod test {
}
let path_index = Uint8Array::from(&merkle_proof.get_path_index()[..]);
let rln_witness_input = WasmRLNWitnessInput::new(
&identity_secret_hash,
let witness = WasmRLNWitnessInput::new(
&identity_secret,
&user_message_limit,
&message_id,
&path_elements,
@@ -146,26 +145,25 @@ mod test {
)
.expect("Failed to create WasmRLNWitnessInput");
let rln_witness_input_bigint_json = rln_witness_input
let bigint_json = witness
.to_bigint_json()
.expect("Failed to convert witness to BigInt JSON");
// Benchmark witness calculation
let start_calculate_witness = Date::now();
for _ in 0..iterations {
let _ = calculateWitness(CIRCOM_PATH, rln_witness_input_bigint_json.clone())
let _ = calculateWitness(CIRCOM_PATH, bigint_json.clone())
.await
.expect("Failed to calculate witness");
}
let calculate_witness_result = Date::now() - start_calculate_witness;
// Calculate witness for other benchmarks
let calculated_witness_str =
calculateWitness(CIRCOM_PATH, rln_witness_input_bigint_json.clone())
.await
.expect("Failed to calculate witness")
.as_string()
.expect("Failed to convert calculated witness to string");
let calculated_witness_str = calculateWitness(CIRCOM_PATH, bigint_json.clone())
.await
.expect("Failed to calculate witness")
.as_string()
.expect("Failed to convert calculated witness to string");
let calculated_witness_vec_str: Vec<String> =
serde_json::from_str(&calculated_witness_str).expect("Failed to parse JSON");
let calculated_witness: Vec<JsBigInt> = calculated_witness_vec_str
@@ -174,17 +172,18 @@ mod test {
.collect();
// Benchmark proof generation with witness
let start_generate_proof_with_witness = Date::now();
let start_generate_rln_proof_with_witness = Date::now();
for _ in 0..iterations {
let _ = rln_instance
.generate_proof_with_witness(calculated_witness.clone(), &rln_witness_input)
.generate_rln_proof_with_witness(calculated_witness.clone(), &witness)
.expect("Failed to generate proof");
}
let generate_proof_with_witness_result = Date::now() - start_generate_proof_with_witness;
let generate_rln_proof_with_witness_result =
Date::now() - start_generate_rln_proof_with_witness;
// Generate proof with witness for other benchmarks
let proof: WasmRLNProof = rln_instance
.generate_proof_with_witness(calculated_witness, &rln_witness_input)
.generate_rln_proof_with_witness(calculated_witness, &witness)
.expect("Failed to generate proof");
let root = WasmFr::from(tree.root());
@@ -230,7 +229,7 @@ mod test {
));
results.push_str(&format!(
"Proof generation with witness: {}\n",
format_duration(generate_proof_with_witness_result)
format_duration(generate_rln_proof_with_witness_result)
));
results.push_str(&format!(
"Proof verification with roots: {}\n",

View File

@@ -2,28 +2,27 @@
#[cfg(test)]
mod test {
use std::assert_eq;
use ark_std::rand::thread_rng;
use js_sys::Uint8Array;
use rand::Rng;
use rln::circuit::Fr;
use rln::hashers::poseidon_hash;
use rln::utils::{fr_to_bytes_be, fr_to_bytes_le, str_to_fr, IdSecret};
use rln::prelude::*;
use rln_wasm::{ExtendedIdentity, Hasher, Identity, VecWasmFr, WasmFr};
use std::assert_eq;
use wasm_bindgen_test::wasm_bindgen_test;
#[wasm_bindgen_test]
fn test_keygen_wasm() {
let identity = Identity::generate();
let identity_secret_hash = *identity.get_secret_hash();
let identity_secret = *identity.get_secret_hash();
let id_commitment = *identity.get_commitment();
assert_ne!(identity_secret_hash, Fr::from(0u8));
assert_ne!(identity_secret, Fr::from(0u8));
assert_ne!(id_commitment, Fr::from(0u8));
let arr = identity.to_array();
assert_eq!(arr.length(), 2);
assert_eq!(*arr.get(0).unwrap(), identity_secret_hash);
assert_eq!(*arr.get(0).unwrap(), identity_secret);
assert_eq!(*arr.get(1).unwrap(), id_commitment);
}
@@ -33,19 +32,19 @@ mod test {
let identity_trapdoor = *identity.get_trapdoor();
let identity_nullifier = *identity.get_nullifier();
let identity_secret_hash = *identity.get_secret_hash();
let identity_secret = *identity.get_secret_hash();
let id_commitment = *identity.get_commitment();
assert_ne!(identity_trapdoor, Fr::from(0u8));
assert_ne!(identity_nullifier, Fr::from(0u8));
assert_ne!(identity_secret_hash, Fr::from(0u8));
assert_ne!(identity_secret, Fr::from(0u8));
assert_ne!(id_commitment, Fr::from(0u8));
let arr = identity.to_array();
assert_eq!(arr.length(), 4);
assert_eq!(*arr.get(0).unwrap(), identity_trapdoor);
assert_eq!(*arr.get(1).unwrap(), identity_nullifier);
assert_eq!(*arr.get(2).unwrap(), identity_secret_hash);
assert_eq!(*arr.get(2).unwrap(), identity_secret);
assert_eq!(*arr.get(3).unwrap(), id_commitment);
}
@@ -55,10 +54,10 @@ mod test {
let seed = Uint8Array::from(&seed_bytes[..]);
let identity = Identity::generate_seeded(&seed);
let identity_secret_hash = *identity.get_secret_hash();
let identity_secret = *identity.get_secret_hash();
let id_commitment = *identity.get_commitment();
let expected_identity_secret_hash_seed_bytes = str_to_fr(
let expected_identity_secret_seed_bytes = str_to_fr(
"0x766ce6c7e7a01bdf5b3f257616f603918c30946fa23480f2859c597817e6716",
16,
)
@@ -69,10 +68,7 @@ mod test {
)
.unwrap();
assert_eq!(
identity_secret_hash,
expected_identity_secret_hash_seed_bytes
);
assert_eq!(identity_secret, expected_identity_secret_seed_bytes);
assert_eq!(id_commitment, expected_id_commitment_seed_bytes);
}
@@ -85,7 +81,7 @@ mod test {
let identity_trapdoor = *identity.get_trapdoor();
let identity_nullifier = *identity.get_nullifier();
let identity_secret_hash = *identity.get_secret_hash();
let identity_secret = *identity.get_secret_hash();
let id_commitment = *identity.get_commitment();
let expected_identity_trapdoor_seed_bytes = str_to_fr(
@@ -98,7 +94,7 @@ mod test {
16,
)
.unwrap();
let expected_identity_secret_hash_seed_bytes = str_to_fr(
let expected_identity_secret_seed_bytes = str_to_fr(
"0x2aca62aaa7abaf3686fff2caf00f55ab9462dc12db5b5d4bcf3994e671f8e521",
16,
)
@@ -111,10 +107,7 @@ mod test {
assert_eq!(identity_trapdoor, expected_identity_trapdoor_seed_bytes);
assert_eq!(identity_nullifier, expected_identity_nullifier_seed_bytes);
assert_eq!(
identity_secret_hash,
expected_identity_secret_hash_seed_bytes
);
assert_eq!(identity_secret, expected_identity_secret_seed_bytes);
assert_eq!(id_commitment, expected_id_commitment_seed_bytes);
}