diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba66d76..164f149 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,6 @@ on: - "!rln/src/**" - "!rln/resources/**" - "!utils/src/**" - - "!rln-wasm-utils/**" pull_request: types: [opened, synchronize, reopened, ready_for_review] paths-ignore: @@ -19,7 +18,6 @@ on: - "!rln/src/**" - "!rln/resources/**" - "!utils/src/**" - - "!rln-wasm-utils/**" name: CI @@ -136,36 +134,14 @@ jobs: run: cargo make test_parallel --release working-directory: ${{ matrix.crate }} - rln-wasm-utils-test: - # skip tests on draft PRs - if: github.event_name == 'push' || (github.event_name == 'pull_request' && !github.event.pull_request.draft) - strategy: - matrix: - platform: [ubuntu-latest, macos-latest] - crate: [rln-wasm-utils] - runs-on: ${{ matrix.platform }} - timeout-minutes: 60 - - name: Test - ${{ matrix.crate }} - ${{ matrix.platform }} - steps: - - uses: actions/checkout@v4 - - name: Install stable toolchain - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - - name: Install dependencies - run: make installdeps - - name: Test rln-wasm-utils - run: cargo make test --release - working-directory: ${{ matrix.crate }} - lint: # run on both ready and draft PRs if: github.event_name == 'push' || (github.event_name == 'pull_request' && !github.event.pull_request.draft) strategy: matrix: - # we run lint tests only on ubuntu + # run lint tests only on ubuntu platform: [ubuntu-latest] - crate: [rln, rln-wasm, rln-wasm-utils, utils] + crate: [rln, rln-wasm, utils] runs-on: ${{ matrix.platform }} timeout-minutes: 60 @@ -177,6 +153,9 @@ jobs: uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy + - name: Install wasm32 target + if: matrix.crate == 'rln-wasm' + run: rustup target add wasm32-unknown-unknown - uses: Swatinem/rust-cache@v2 - name: Install dependencies run: make installdeps @@ -184,18 +163,23 @@ jobs: if: success() || failure() run: cargo fmt -- --check working-directory: ${{ matrix.crate }} - - name: Check clippy - if: success() || failure() + - name: Check clippy (wasm) + if: (success() || failure()) && (matrix.crate == 'rln-wasm') run: | - cargo clippy --all-targets --release -- -D warnings + cargo clippy --target wasm32-unknown-unknown --tests --release -- -D warnings + working-directory: ${{ matrix.crate }} + - name: Check clippy (native) + if: (success() || failure()) && (matrix.crate != 'rln-wasm') + run: | + cargo clippy --all-targets --tests --release -- -D warnings working-directory: ${{ matrix.crate }} benchmark-utils: - # run only on ready pull requests + # run only on ready PRs if: github.event_name == 'pull_request' && !github.event.pull_request.draft strategy: matrix: - # we run benchmark tests only on ubuntu + # run benchmark tests only on ubuntu platform: [ubuntu-latest] crate: [utils] runs-on: ${{ matrix.platform }} @@ -212,11 +196,11 @@ jobs: cwd: ${{ matrix.crate }} benchmark-rln: - # run only on ready pull requests + # run only on ready PRs if: github.event_name == 'pull_request' && !github.event.pull_request.draft strategy: matrix: - # we run benchmark tests only on ubuntu + # run benchmark tests only on ubuntu platform: [ubuntu-latest] crate: [rln] feature: ["default"] diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml index cbab208..2c09daa 100644 --- a/.github/workflows/nightly-release.yml +++ b/.github/workflows/nightly-release.yml @@ -97,6 +97,7 @@ jobs: feature: - "default" - "parallel" + - "utils" steps: - name: Checkout sources uses: actions/checkout@v4 @@ -123,10 +124,11 @@ jobs: wasm-pack build --release --target web --scope waku fi - sed -i.bak 's/rln-wasm/zerokit-rln-wasm/g' pkg/package.json && rm pkg/package.json.bak - - wasm-opt pkg/rln_wasm_bg.wasm -Oz --strip-debug --strip-dwarf \ - --remove-unused-module-elements --vacuum -o pkg/rln_wasm_bg.wasm + if [[ ${{ matrix.feature }} == "utils" ]]; then + sed -i.bak 's/rln-wasm/zerokit-rln-wasm-utils/g' pkg/package.json && rm pkg/package.json.bak + else + sed -i.bak 's/rln-wasm/zerokit-rln-wasm/g' pkg/package.json && rm pkg/package.json.bak + fi mkdir release cp -r pkg/* release/ @@ -139,42 +141,9 @@ jobs: path: rln-wasm/rln-wasm-${{ matrix.feature }}.tar.gz retention-days: 2 - rln-wasm-utils: - name: Build rln-wasm-utils - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - name: Install stable toolchain - uses: dtolnay/rust-toolchain@stable - with: - targets: wasm32-unknown-unknown - - uses: Swatinem/rust-cache@v2 - - name: Install dependencies - run: make installdeps - - name: Build rln-wasm-utils package - run: | - wasm-pack build --release --target web --scope waku - - sed -i.bak 's/rln-wasm-utils/zerokit-rln-wasm-utils/g' pkg/package.json && rm pkg/package.json.bak - - wasm-opt pkg/rln_wasm_utils_bg.wasm -Oz --strip-debug --strip-dwarf \ - --remove-unused-module-elements --vacuum -o pkg/rln_wasm_utils_bg.wasm - - mkdir release - cp -r pkg/* release/ - tar -czvf rln-wasm-utils.tar.gz release/ - working-directory: rln-wasm-utils - - name: Upload archive artifact - uses: actions/upload-artifact@v4 - with: - name: rln-wasm-utils-archive - path: rln-wasm-utils/rln-wasm-utils.tar.gz - retention-days: 2 - prepare-prerelease: name: Prepare pre-release - needs: [linux, macos, rln-wasm, rln-wasm-utils] + needs: [linux, macos, rln-wasm] runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/.gitignore b/.gitignore index 49ca3ef..b226ba3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,6 @@ tmp/ # Generated by Cargo will have compiled files and executables /target -# Generated by rln-cli -rln-cli/database - # Generated by Nix result @@ -27,3 +24,6 @@ rln/ffi_c_examples/database # FFI Nim examples rln/ffi_nim_examples/main rln/ffi_nim_examples/database + +# Vscode +.vscode diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6dc2f87..0630f36 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,13 +47,6 @@ cd rln-wasm && cargo make test_browser # Test in browser headless mode cd rln-wasm && cargo make test_parallel # Test parallel features ``` -Choose the appropriate test commands based on your changes: - -- Core RLN changes: `make test` -- Stateless features: `cargo make test_stateless` -- WASM/browser features: `cargo make test_browser` -- Parallel computation: `cargo make test_parallel` - ### Tools We recommend using the [markdownlint extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) @@ -107,7 +100,6 @@ Use scopes to improve the Changelog: - `rln` - Core RLN implementation - `rln-cli` - Command-line interface - `rln-wasm` - WebAssembly bindings -- `rln-wasm-utils` - WebAssembly utilities - `utils` - Cryptographic utilities (Merkle trees, Poseidon hash) - `ci` - Continuous integration diff --git a/Cargo.lock b/Cargo.lock index 5db4c2c..7c8f391 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -777,12 +777,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.177" @@ -1189,7 +1183,6 @@ dependencies = [ "cfg-if", "criterion", "document-features", - "lazy_static", "num-bigint", "num-traits", "once_cell", @@ -1846,7 +1839,6 @@ dependencies = [ "criterion", "hex", "hex-literal", - "lazy_static", "num-bigint", "num-traits", "rayon", diff --git a/Cargo.toml b/Cargo.toml index ae7b1d3..2b7a831 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = ["rln", "utils"] -exclude = ["rln-cli", "rln-wasm", "rln-wasm-utils"] +exclude = ["rln-cli", "rln-wasm"] resolver = "2" # Compilation profile for any non-workspace member. diff --git a/Makefile b/Makefile index ad91710..c69ceb1 100644 --- a/Makefile +++ b/Makefile @@ -13,12 +13,13 @@ endif installdeps: .pre-build ifeq ($(shell uname),Darwin) - @brew install ninja binaryen + @brew install ninja else ifeq ($(shell uname),Linux) @if [ -f /etc/os-release ] && grep -q "ID=nixos" /etc/os-release; then \ - echo "Detected NixOS, skipping apt-get installation."; \ + echo "Detected NixOS, skipping apt installation."; \ else \ - sudo apt-get install -y cmake ninja-build binaryen; \ + sudo apt update; \ + sudo apt install -y cmake ninja-build; \ fi endif @which wasm-pack > /dev/null && wasm-pack --version | grep -q "0.13.1" || cargo install wasm-pack --version=0.13.1 diff --git a/rln-wasm-utils/.gitignore b/rln-cli/.gitignore similarity index 88% rename from rln-wasm-utils/.gitignore rename to rln-cli/.gitignore index 3068f54..d381780 100644 --- a/rln-wasm-utils/.gitignore +++ b/rln-cli/.gitignore @@ -6,10 +6,9 @@ tmp/ # Generated by Cargo will have compiled files and executables /target -Cargo.lock -# Generated by rln-wasm -pkg/ +# Generated by rln-cli +/database # Generated by Nix result diff --git a/rln-cli/Cargo.lock b/rln-cli/Cargo.lock new file mode 100644 index 0000000..2f46a48 --- /dev/null +++ b/rln-cli/Cargo.lock @@ -0,0 +1,1883 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-r1cs-std", + "ark-std", +] + +[[package]] +name = "ark-crypto-primitives" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0c292754729c8a190e50414fd1a37093c786c709899f29c9f7daccecfa855e" +dependencies = [ + "ahash", + "ark-crypto-primitives-macros", + "ark-ec", + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-snark", + "ark-std", + "blake2", + "derivative", + "digest", + "fnv", + "merlin", + "rayon", + "sha2", +] + +[[package]] +name = "ark-crypto-primitives-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "arrayvec", + "digest", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.108", +] + +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "ark-groth16" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f1d0f3a534bb54188b8dcc104307db6c56cdae574ddc3212aec0625740fc7e" +dependencies = [ + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-std", + "rayon", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", + "rayon", +] + +[[package]] +name = "ark-r1cs-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-relations", + "ark-std", + "educe", + "num-bigint", + "num-integer", + "num-traits", + "tracing", +] + +[[package]] +name = "ark-relations" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" +dependencies = [ + "ark-ff", + "ark-std", + "tracing", + "tracing-subscriber 0.2.25", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "arrayvec", + "digest", + "num-bigint", + "rayon", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "ark-snark" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d368e2848c2d4c129ce7679a7d0d2d612b6a274d3ea6a13bad4445d61b381b88" +dependencies = [ + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", + "rayon", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clap" +version = "4.5.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "color-eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "ext-trait" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5" +dependencies = [ + "ext-trait-proc_macros", +] + +[[package]] +name = "ext-trait-proc_macros" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "extension-traits" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537" +dependencies = [ + "ext-trait", +] + +[[package]] +name = "extern-c" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320bea982e85d42441eb25c49b41218e7eaa2657e8f90bc4eca7437376751e23" + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "macro_rules_attribute" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf0c9b980bf4f3a37fd7b1c066941dd1b1d0152ce6ee6e8fe8c49b9f6810d862" +dependencies = [ + "macro_rules_attribute-proc_macro", + "paste", +] + +[[package]] +name = "macro_rules_attribute-proc_macro" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58093314a45e00c77d5c508f76e77c3396afbbc0d01506e7fae47b018bac2b1d" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "owo-colors" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +dependencies = [ + "bitflags 2.10.0", + "num-traits", + "rand 0.9.2", + "rand_chacha 0.9.0", + "rand_xorshift", + "unarray", +] + +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "rln" +version = "0.9.0" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-groth16", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-std", + "byteorder", + "cfg-if", + "num-bigint", + "num-traits", + "once_cell", + "prost", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon", + "ruint", + "safer-ffi", + "serde", + "serde_json", + "tempfile", + "thiserror", + "tiny-keccak", + "zeroize", + "zerokit_utils", +] + +[[package]] +name = "rln-cli" +version = "0.5.0" +dependencies = [ + "clap", + "color-eyre", + "rln", + "serde", + "serde_json", + "zerokit_utils", +] + +[[package]] +name = "ruint" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" +dependencies = [ + "ark-ff", + "proptest", + "rand 0.8.5", + "rand 0.9.2", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "safer-ffi" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435fdd58b61a6f1d8545274c1dfa458e905ff68c166e65e294a0130ef5e675bd" +dependencies = [ + "extern-c", + "libc", + "macro_rules_attribute", + "paste", + "safer_ffi-proc_macros", + "scopeguard", + "stabby", + "uninit", + "unwind_safe", + "with_builtin_macros", +] + +[[package]] +name = "safer_ffi-proc_macros" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f25be5ba5f319542edb31925517e0380245ae37df50a9752cdbc05ef948156" +dependencies = [ + "macro_rules_attribute", + "prettyplease", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2-const-stable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9" + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stabby" +version = "36.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b7e94eaf470c2e76b5f15fb2fb49714471a36cc512df5ee231e62e82ec79f8" +dependencies = [ + "rustversion", + "stabby-abi", +] + +[[package]] +name = "stabby-abi" +version = "36.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc7a63b8276b54e51bfffe3d85da56e7906b2dcfcb29018a8ab666c06734c1a" +dependencies = [ + "rustc_version", + "rustversion", + "sha2-const-stable", + "stabby-macros", +] + +[[package]] +name = "stabby-macros" +version = "36.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eecb7ec5611ec93ec79d120fbe55f31bea234dc1bed1001d4a071bb688651615" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "rand 0.8.5", + "syn 1.0.109", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +dependencies = [ + "tracing", + "tracing-subscriber 0.3.20", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "uninit" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e130f2ed46ca5d8ec13c7ff95836827f92f5f5f37fd2b2bf16f33c408d98bb6" +dependencies = [ + "extension-traits", +] + +[[package]] +name = "unwind_safe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vacp2p_pmtree" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47145034d8885c2f7ff7562c504ee8be6e78b564a60cc26fc174f861c61bdec2" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "with_builtin_macros" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a59d55032495429b87f9d69954c6c8602e4d3f3e0a747a12dea6b0b23de685da" +dependencies = [ + "with_builtin_macros-proc_macros", +] + +[[package]] +name = "with_builtin_macros-proc_macros" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bd7679c15e22924f53aee34d4e448c45b674feb6129689af88593e129f8f42" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zerokit_utils" +version = "0.7.0" +dependencies = [ + "ark-ff", + "hex", + "num-bigint", + "rayon", + "serde_json", + "sled", + "thiserror", + "vacp2p_pmtree", +] diff --git a/rln-cli/Cargo.toml b/rln-cli/Cargo.toml index 90068a2..61b0fa6 100644 --- a/rln-cli/Cargo.toml +++ b/rln-cli/Cargo.toml @@ -23,3 +23,6 @@ serde = { version = "1.0", features = ["derive"] } [features] default = ["rln/pmtree-ft", "rln/parallel"] stateless = ["rln/stateless", "rln/parallel"] + +[package.metadata.docs.rs] +all-features = true diff --git a/rln-cli/src/examples/stateless.rs b/rln-cli/src/examples/stateless.rs index aebcea3..0458b09 100644 --- a/rln-cli/src/examples/stateless.rs +++ b/rln-cli/src/examples/stateless.rs @@ -10,7 +10,7 @@ use color_eyre::{eyre::eyre, Result}; use rln::{ circuit::{Fr, TEST_TREE_DEPTH}, hashers::{hash_to_field_le, poseidon_hash, PoseidonHash}, - protocol::{keygen, prepare_verify_input, rln_witness_from_values, serialize_witness}, + protocol::{keygen, prepare_verify_input, serialize_witness}, public::RLN, utils::{fr_to_bytes_le, IdSecret}, }; @@ -130,15 +130,16 @@ impl RLNSystem { let merkle_proof = self.tree.proof(user_index)?; let x = hash_to_field_le(signal.as_bytes()); - let rln_witness = rln_witness_from_values( + let rln_witness = RLNWitnessInput::new( identity.identity_secret_hash.clone(), + Fr::from(MESSAGE_LIMIT), + Fr::from(message_id), merkle_proof.get_path_elements(), merkle_proof.get_path_index(), x, external_nullifier, - Fr::from(MESSAGE_LIMIT), - Fr::from(message_id), - )?; + ) + .unwrap(); let serialized = serialize_witness(&rln_witness)?; let mut input_buffer = Cursor::new(serialized); diff --git a/rln-wasm-utils/Cargo.toml b/rln-wasm-utils/Cargo.toml deleted file mode 100644 index a14d23c..0000000 --- a/rln-wasm-utils/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "rln-wasm-utils" -version = "0.1.0" -edition = "2024" - - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -# TODO: remove this once we have a proper release -rln = { path = "../rln", version = "0.9.0", default-features = false, features = ["stateless"] } -js-sys = "0.3.77" -wasm-bindgen = "0.2.100" -rand = "0.8.5" - -# The `console_error_panic_xhook` crate provides better debugging of panics by -# logging them with `console.error`. This is great for development, but requires -# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for -# code size when deploying. -console_error_panic_hook = { version = "0.1.7", optional = true } - -[target.'cfg(target_arch = "wasm32")'.dependencies] -getrandom = { version = "0.2.16", features = ["js"] } - -[dev-dependencies] -wasm-bindgen-test = "0.3.50" -web-sys = { version = "0.3.77", features = ["console"] } -ark-std = { version = "0.5.0", default-features = false } - -[features] -default = ["console_error_panic_hook"] - -[package.metadata.docs.rs] -all-features = true diff --git a/rln-wasm-utils/Makefile.toml b/rln-wasm-utils/Makefile.toml deleted file mode 100644 index 511b77d..0000000 --- a/rln-wasm-utils/Makefile.toml +++ /dev/null @@ -1,36 +0,0 @@ -[tasks.build] -clear = true -dependencies = ["pack_build", "pack_rename", "pack_resize"] - -[tasks.pack_build] -command = "wasm-pack" -args = ["build", "--release", "--target", "web", "--scope", "waku"] - -[tasks.pack_rename] -script = "sed -i.bak 's/rln-wasm-utils/zerokit-rln-wasm-utils/g' pkg/package.json && rm pkg/package.json.bak" - -[tasks.pack_resize] -command = "wasm-opt" -args = [ - "pkg/rln_wasm_utils_bg.wasm", - "-Oz", - "--strip-debug", - "--strip-dwarf", - "--remove-unused-module-elements", - "--vacuum", - "-o", - "pkg/rln_wasm_utils_bg.wasm", -] - -[tasks.test] -command = "wasm-pack" -args = [ - "test", - "--release", - "--node", - "--target", - "wasm32-unknown-unknown", - "--", - "--nocapture", -] -dependencies = ["build"] diff --git a/rln-wasm-utils/README.md b/rln-wasm-utils/README.md deleted file mode 100644 index 50c9b86..0000000 --- a/rln-wasm-utils/README.md +++ /dev/null @@ -1,206 +0,0 @@ -# RLN WASM Utils - -[![npm version](https://badge.fury.io/js/@waku%2Fzerokit-rln-wasm.svg)](https://badge.fury.io/js/@waku%2Fzerokit-rln-wasm-utils) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) -[![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 Utils Module provides WebAssembly bindings for Rate-Limiting Nullifier [RLN](https://rfc.vac.dev/spec/32/) cryptographic primitives. -This module offers comprehensive functionality for identity generation and hashing needed for RLN applications. - -## Features - -### Identity Generation - -- **Random Identity Generation**: Generate cryptographically secure random identities -- **Seeded Identity Generation**: Generate deterministic identities from seeds -- **Extended Identity Generation**: Generate extended identities with additional parameters -- **Seeded Extended Identity Generation**: Generate deterministic extended identities from seeds -- **Endianness Support**: Both little-endian and big-endian serialization support - -### Hashing - -- **Standard Hashing**: Hash arbitrary data to field elements -- **Poseidon Hashing**: Advanced cryptographic hashing using Poseidon hash function -- **Endianness Support**: Both little-endian and big-endian serialization support - -## API Reference - -### Identity Generation Functions - -#### `generateMembershipKey(isLittleEndian: boolean): Uint8Array` - -Generates a random membership key pair (identity secret and commitment). - -**Inputs:** - -- `isLittleEndian`: Boolean indicating endianness for serialization - -**Outputs:** Serialized identity pair as `Uint8Array` in corresponding endianness - -#### `generateExtendedMembershipKey(isLittleEndian: boolean): Uint8Array` - -Generates an extended membership key with additional parameters. - -**Inputs:** - -- `isLittleEndian`: Boolean indicating endianness for serialization - -**Outputs:** Serialized extended identity tuple as `Uint8Array` in corresponding endianness - -#### `generateSeededMembershipKey(seed: Uint8Array, isLittleEndian: boolean): Uint8Array` - -Generates a deterministic membership key from a seed. - -**Inputs:** - -- `seed`: Seed data as `Uint8Array` -- `isLittleEndian`: Boolean indicating endianness for serialization - -**Outputs:** Serialized identity pair as `Uint8Array` in corresponding endianness - -#### `generateSeededExtendedMembershipKey(seed: Uint8Array, isLittleEndian: boolean): Uint8Array` - -Generates a deterministic extended membership key from a seed. - -**Inputs:** - -- `seed`: Seed data as `Uint8Array` -- `isLittleEndian`: Boolean indicating endianness for serialization - -**Outputs:** Serialized extended identity tuple as `Uint8Array` in corresponding endianness - -### Hashing Functions - -#### `hash(input: Uint8Array, isLittleEndian: boolean): Uint8Array` - -Hashes input data to a field element. - -**Inputs:** - -- `input`: Input data as `Uint8Array` -- `isLittleEndian`: Boolean indicating endianness for serialization - -**Outputs:** Serialized hash result as `Uint8Array` in corresponding endianness - -#### `poseidonHash(input: Uint8Array, isLittleEndian: boolean): Uint8Array` - -Computes Poseidon hash of input field elements. - -**Inputs:** - -- `input`: Serialized field elements as `Uint8Array` (format: length + field elements) -- `isLittleEndian`: Boolean indicating endianness for serialization - -**Outputs:** Serialized hash result as `Uint8Array` in corresponding endianness - -## Usage Examples - -### JavaScript/TypeScript - -```javascript -import init, { - generateMembershipKey, - generateSeededMembershipKey, - hash, - poseidonHash -} from '@waku/zerokit-rln-wasm-utils'; - -// Initialize the WASM module -await init(); - -// Generate a random membership key -const membershipKey = generateMembershipKey(true); // little-endian -console.log('Membership key:', membershipKey); - -// Generate a deterministic membership key from seed -const seed = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); -const seededKey = generateSeededMembershipKey(seed, true); -console.log('Seeded key:', seededKey); - -// Hash some data -const input = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); -const hashResult = hash(input, true); -console.log('Hash result:', hashResult); - -// Poseidon hash with field elements -const fieldElements = new Uint8Array([ - // Length (8 bytes) + field elements (32 bytes each) - 1, 0, 0, 0, 0, 0, 0, 0, // length = 1 - // field element data... -]); -const poseidonResult = poseidonHash(fieldElements, true); -console.log('Poseidon hash:', poseidonResult); -``` - -## Install Dependencies - -> [!NOTE] -> This project requires the following tools: -> -> - `wasm-pack` - for compiling Rust to WebAssembly -> - `cargo-make` - for running build commands -> - `nvm` - to install and manage Node.js -> -> Ensure all dependencies are installed before proceeding. - -### Manually - -#### Install `wasm-pack` - -```bash -cargo install wasm-pack --version=0.13.1 -``` - -#### Install `cargo-make` - -```bash -cargo install cargo-make -``` - -#### Install `Node.js` - -If you don't have `nvm` (Node Version Manager), install it by following -the [installation instructions](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). - -After installing `nvm`, install and use Node.js `v22.14.0`: - -```bash -nvm install 22.14.0 -nvm use 22.14.0 -nvm alias default 22.14.0 -``` - -If you already have Node.js installed, -check your version with `node -v` command — the version must be strictly greater than 22. - -### Or install everything - -You can run the following command from the root of the repository to install all required dependencies for `zerokit` - -```bash -make installdeps -``` - -## Building the library - -First, navigate to the rln-wasm-utils directory: - -```bash -cd rln-wasm-utils -``` - -Compile rln-wasm-utils for `wasm32-unknown-unknown`: - -```bash -cargo make build -``` - -## Running tests - -```bash -cargo make test -``` - -## License - -This project is licensed under both MIT and Apache 2.0 licenses. See the LICENSE files for details. diff --git a/rln-wasm-utils/src/lib.rs b/rln-wasm-utils/src/lib.rs deleted file mode 100644 index f523fa4..0000000 --- a/rln-wasm-utils/src/lib.rs +++ /dev/null @@ -1,112 +0,0 @@ -#![cfg(target_arch = "wasm32")] - -use js_sys::Uint8Array; -use rln::public::{ - extended_key_gen, hash, key_gen, poseidon_hash, seeded_extended_key_gen, seeded_key_gen, -}; -use std::vec::Vec; -use wasm_bindgen::prelude::*; - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = generateMembershipKey)] -pub fn wasm_key_gen(is_little_endian: bool) -> Result { - let mut output_data: Vec = Vec::new(); - if let Err(err) = key_gen(&mut output_data, is_little_endian) { - std::mem::forget(output_data); - Err(format!( - "Msg: could not generate membership keys, Error: {:#?}", - err - )) - } else { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = generateExtendedMembershipKey)] -pub fn wasm_extended_key_gen(is_little_endian: bool) -> Result { - let mut output_data: Vec = Vec::new(); - if let Err(err) = extended_key_gen(&mut output_data, is_little_endian) { - std::mem::forget(output_data); - Err(format!( - "Msg: could not generate membership keys, Error: {:#?}", - err - )) - } else { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = generateSeededMembershipKey)] -pub fn wasm_seeded_key_gen(seed: Uint8Array, is_little_endian: bool) -> Result { - let mut output_data: Vec = Vec::new(); - let input_data = &seed.to_vec()[..]; - if let Err(err) = seeded_key_gen(input_data, &mut output_data, is_little_endian) { - std::mem::forget(output_data); - Err(format!( - "Msg: could not generate membership key, Error: {:#?}", - err - )) - } else { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = generateSeededExtendedMembershipKey)] -pub fn wasm_seeded_extended_key_gen( - seed: Uint8Array, - is_little_endian: bool, -) -> Result { - let mut output_data: Vec = Vec::new(); - let input_data = &seed.to_vec()[..]; - if let Err(err) = seeded_extended_key_gen(input_data, &mut output_data, is_little_endian) { - std::mem::forget(output_data); - Err(format!( - "Msg: could not generate membership key, Error: {:#?}", - err - )) - } else { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } -} - -#[wasm_bindgen(js_name = hash)] -pub fn wasm_hash(input: Uint8Array, is_little_endian: bool) -> Result { - let mut output_data: Vec = Vec::new(); - let input_data = &input.to_vec()[..]; - if let Err(err) = hash(input_data, &mut output_data, is_little_endian) { - std::mem::forget(output_data); - Err(format!("Msg: could not generate hash, Error: {:#?}", err)) - } else { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } -} - -#[wasm_bindgen(js_name = poseidonHash)] -pub fn wasm_poseidon_hash(input: Uint8Array, is_little_endian: bool) -> Result { - let mut output_data: Vec = Vec::new(); - let input_data = &input.to_vec()[..]; - if let Err(err) = poseidon_hash(input_data, &mut output_data, is_little_endian) { - std::mem::forget(output_data); - Err(format!( - "Msg: could not generate poseidon hash, Error: {:#?}", - err - )) - } else { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } -} diff --git a/rln-wasm-utils/tests/wasm_utils_test.rs b/rln-wasm-utils/tests/wasm_utils_test.rs deleted file mode 100644 index c11f9a3..0000000 --- a/rln-wasm-utils/tests/wasm_utils_test.rs +++ /dev/null @@ -1,114 +0,0 @@ -#![cfg(target_arch = "wasm32")] - -#[cfg(test)] -mod test { - use ark_std::{UniformRand, rand::thread_rng}; - use rand::Rng; - use rln::circuit::Fr; - use rln::hashers::{ROUND_PARAMS, hash_to_field_le, poseidon_hash}; - use rln::protocol::{ - deserialize_identity_pair_be, deserialize_identity_pair_le, deserialize_identity_tuple_be, - deserialize_identity_tuple_le, - }; - use rln::utils::{bytes_le_to_fr, vec_fr_to_bytes_le}; - use rln_wasm_utils::{ - wasm_extended_key_gen, wasm_hash, wasm_key_gen, wasm_poseidon_hash, - wasm_seeded_extended_key_gen, wasm_seeded_key_gen, - }; - use wasm_bindgen_test::*; - - #[wasm_bindgen_test] - fn test_wasm_key_gen() { - let result_le = wasm_key_gen(true); - assert!(result_le.is_ok()); - deserialize_identity_pair_le(result_le.unwrap().to_vec()); - - let result_be = wasm_key_gen(false); - assert!(result_be.is_ok()); - deserialize_identity_pair_be(result_be.unwrap().to_vec()); - } - - #[wasm_bindgen_test] - fn test_wasm_extended_key_gen() { - let result_le = wasm_extended_key_gen(true); - assert!(result_le.is_ok()); - deserialize_identity_tuple_le(result_le.unwrap().to_vec()); - - let result_be = wasm_extended_key_gen(false); - assert!(result_be.is_ok()); - deserialize_identity_tuple_be(result_be.unwrap().to_vec()); - } - - #[wasm_bindgen_test] - fn test_wasm_seeded_key_gen() { - // Create a test seed - let seed_data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let seed = js_sys::Uint8Array::from(&seed_data[..]); - - let result_le = wasm_seeded_key_gen(seed.clone(), true); - assert!(result_le.is_ok()); - let fr_le = deserialize_identity_pair_le(result_le.unwrap().to_vec()); - - let result_be = wasm_seeded_key_gen(seed, false); - assert!(result_be.is_ok()); - let fr_be = deserialize_identity_pair_be(result_be.unwrap().to_vec()); - - assert_eq!(fr_le, fr_be); - } - - #[wasm_bindgen_test] - fn test_wasm_seeded_extended_key_gen() { - // Create a test seed - let seed_data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let seed = js_sys::Uint8Array::from(&seed_data[..]); - - let result_le = wasm_seeded_extended_key_gen(seed.clone(), true); - assert!(result_le.is_ok()); - let fr_le = deserialize_identity_tuple_le(result_le.unwrap().to_vec()); - - let result_be = wasm_seeded_extended_key_gen(seed, false); - assert!(result_be.is_ok()); - let fr_be = deserialize_identity_tuple_be(result_be.unwrap().to_vec()); - - assert_eq!(fr_le, fr_be); - } - - #[wasm_bindgen_test] - fn test_wasm_hash() { - // Create test input data - let signal: [u8; 32] = [0; 32]; - let input = js_sys::Uint8Array::from(&signal[..]); - - let result_le = wasm_hash(input.clone(), true); - assert!(result_le.is_ok()); - - let serialized_hash = result_le.unwrap().to_vec(); - let (hash1, _) = bytes_le_to_fr(&serialized_hash); - - let hash2 = hash_to_field_le(&signal); - - assert_eq!(hash1, hash2); - } - - #[wasm_bindgen_test] - fn test_wasm_poseidon_hash() { - let mut rng = thread_rng(); - let number_of_inputs = rng.gen_range(1..ROUND_PARAMS.len()); - let mut inputs = Vec::with_capacity(number_of_inputs); - for _ in 0..number_of_inputs { - inputs.push(Fr::rand(&mut rng)); - } - let inputs_ser = vec_fr_to_bytes_le(&inputs); - let input = js_sys::Uint8Array::from(&inputs_ser[..]); - - let expected_hash = poseidon_hash(inputs.as_ref()); - - let result_le = wasm_poseidon_hash(input.clone(), true); - assert!(result_le.is_ok()); - - let serialized_hash = result_le.unwrap().to_vec(); - let (received_hash, _) = bytes_le_to_fr(&serialized_hash); - - assert_eq!(received_hash, expected_hash); - } -} diff --git a/rln-wasm/.gitignore b/rln-wasm/.gitignore index 3068f54..363fc4a 100644 --- a/rln-wasm/.gitignore +++ b/rln-wasm/.gitignore @@ -6,10 +6,11 @@ tmp/ # Generated by Cargo will have compiled files and executables /target -Cargo.lock # Generated by rln-wasm -pkg/ +/pkg +/examples/node_modules +/examples/package-lock.json # Generated by Nix result diff --git a/rln-wasm/Cargo.lock b/rln-wasm/Cargo.lock new file mode 100644 index 0000000..d292653 --- /dev/null +++ b/rln-wasm/Cargo.lock @@ -0,0 +1,1759 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-r1cs-std", + "ark-std", +] + +[[package]] +name = "ark-crypto-primitives" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0c292754729c8a190e50414fd1a37093c786c709899f29c9f7daccecfa855e" +dependencies = [ + "ahash", + "ark-crypto-primitives-macros", + "ark-ec", + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-snark", + "ark-std", + "blake2", + "derivative", + "digest", + "fnv", + "merlin", + "rayon", + "sha2", +] + +[[package]] +name = "ark-crypto-primitives-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "arrayvec", + "digest", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.108", +] + +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "ark-groth16" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f1d0f3a534bb54188b8dcc104307db6c56cdae574ddc3212aec0625740fc7e" +dependencies = [ + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-std", + "rayon", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", + "rayon", +] + +[[package]] +name = "ark-r1cs-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-relations", + "ark-std", + "educe", + "num-bigint", + "num-integer", + "num-traits", + "tracing", +] + +[[package]] +name = "ark-relations" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" +dependencies = [ + "ark-ff", + "ark-std", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "arrayvec", + "digest", + "num-bigint", + "rayon", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "ark-snark" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d368e2848c2d4c129ce7679a7d0d2d612b6a274d3ea6a13bad4445d61b381b88" +dependencies = [ + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", + "rayon", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "ext-trait" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5" +dependencies = [ + "ext-trait-proc_macros", +] + +[[package]] +name = "ext-trait-proc_macros" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "extension-traits" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537" +dependencies = [ + "ext-trait", +] + +[[package]] +name = "extern-c" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320bea982e85d42441eb25c49b41218e7eaa2657e8f90bc4eca7437376751e23" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +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" + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "macro_rules_attribute" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf0c9b980bf4f3a37fd7b1c066941dd1b1d0152ce6ee6e8fe8c49b9f6810d862" +dependencies = [ + "macro_rules_attribute-proc_macro", + "paste", +] + +[[package]] +name = "macro_rules_attribute-proc_macro" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58093314a45e00c77d5c508f76e77c3396afbbc0d01506e7fae47b018bac2b1d" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +dependencies = [ + "bitflags 2.10.0", + "num-traits", + "rand 0.9.2", + "rand_chacha 0.9.0", + "rand_xorshift", + "unarray", +] + +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", + "wasm_sync", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", + "wasm_sync", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "rln" +version = "0.9.0" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-groth16", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-std", + "byteorder", + "cfg-if", + "num-bigint", + "num-traits", + "once_cell", + "prost", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rayon", + "ruint", + "safer-ffi", + "serde", + "serde_json", + "tempfile", + "thiserror", + "tiny-keccak", + "zeroize", + "zerokit_utils", +] + +[[package]] +name = "rln-wasm" +version = "0.3.0" +dependencies = [ + "ark-groth16", + "ark-relations", + "ark-std", + "console_error_panic_hook", + "getrandom 0.2.16", + "js-sys", + "num-bigint", + "rand 0.8.5", + "rln", + "serde", + "serde-wasm-bindgen", + "serde_json", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-rayon", + "wasm-bindgen-test", + "web-sys", + "zerokit_utils", +] + +[[package]] +name = "ruint" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" +dependencies = [ + "ark-ff", + "proptest", + "rand 0.8.5", + "rand 0.9.2", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "safer-ffi" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435fdd58b61a6f1d8545274c1dfa458e905ff68c166e65e294a0130ef5e675bd" +dependencies = [ + "extern-c", + "libc", + "macro_rules_attribute", + "paste", + "safer_ffi-proc_macros", + "scopeguard", + "stabby", + "uninit", + "unwind_safe", + "with_builtin_macros", +] + +[[package]] +name = "safer_ffi-proc_macros" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f25be5ba5f319542edb31925517e0380245ae37df50a9752cdbc05ef948156" +dependencies = [ + "macro_rules_attribute", + "prettyplease", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2-const-stable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stabby" +version = "36.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b7e94eaf470c2e76b5f15fb2fb49714471a36cc512df5ee231e62e82ec79f8" +dependencies = [ + "rustversion", + "stabby-abi", +] + +[[package]] +name = "stabby-abi" +version = "36.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc7a63b8276b54e51bfffe3d85da56e7906b2dcfcb29018a8ab666c06734c1a" +dependencies = [ + "rustc_version", + "rustversion", + "sha2-const-stable", + "stabby-macros", +] + +[[package]] +name = "stabby-macros" +version = "36.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eecb7ec5611ec93ec79d120fbe55f31bea234dc1bed1001d4a071bb688651615" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "rand 0.8.5", + "syn 1.0.109", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "tracing-core", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "uninit" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e130f2ed46ca5d8ec13c7ff95836827f92f5f5f37fd2b2bf16f33c408d98bb6" +dependencies = [ + "extension-traits", +] + +[[package]] +name = "unwind_safe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.108", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-rayon" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a16c60a56c81e4dc3b9c43d76ba5633e1c0278211d59a9cb07d61b6cd1c6583" +dependencies = [ + "crossbeam-channel", + "js-sys", + "rayon", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfc379bfb624eb59050b509c13e77b4eb53150c350db69628141abce842f2373" +dependencies = [ + "js-sys", + "minicov", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "085b2df989e1e6f9620c1311df6c996e83fe16f57792b272ce1e024ac16a90f1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "wasm_sync" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff360cade7fec41ff0e9d2cda57fe58258c5f16def0e21302394659e6bbb0ea" +dependencies = [ + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "with_builtin_macros" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a59d55032495429b87f9d69954c6c8602e4d3f3e0a747a12dea6b0b23de685da" +dependencies = [ + "with_builtin_macros-proc_macros", +] + +[[package]] +name = "with_builtin_macros-proc_macros" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bd7679c15e22924f53aee34d4e448c45b674feb6129689af88593e129f8f42" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zerokit_utils" +version = "0.7.0" +dependencies = [ + "ark-ff", + "hex", + "num-bigint", + "rayon", + "serde_json", + "sled", + "thiserror", +] diff --git a/rln-wasm/Cargo.toml b/rln-wasm/Cargo.toml index 4391d73..737ce42 100644 --- a/rln-wasm/Cargo.toml +++ b/rln-wasm/Cargo.toml @@ -2,7 +2,7 @@ name = "rln-wasm" version = "0.3.0" edition = "2021" -license = "MIT or Apache2" +license = "MIT OR Apache-2.0" [lib] crate-type = ["cdylib", "rlib"] @@ -11,17 +11,20 @@ crate-type = ["cdylib", "rlib"] rln = { path = "../rln", version = "0.9.0", default-features = false, features = [ "stateless", ] } -rln-wasm-utils = { path = "../rln-wasm-utils", version = "0.1.0", default-features = false } 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" serde-wasm-bindgen = "0.6.5" +serde = "1.0" wasm-bindgen-rayon = { version = "1.3.0", features = [ "no-bundler", ], optional = true } +ark-relations = { version = "0.5.1", features = ["std"] } +ark-groth16 = { version = "0.5.0", default-features = false } +rand = "0.8.5" -# The `console_error_panic_xhook` crate provides better debugging of panics by +# The `console_error_panic_hook` crate provides better debugging of panics by # logging them with `console.error`. This is great for development, but requires # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for # code size when deploying. @@ -34,14 +37,17 @@ getrandom = { version = "0.2.16", features = ["js"] } serde_json = "1.0.141" wasm-bindgen-test = "0.3.50" wasm-bindgen-futures = "0.4.50" +ark-std = { version = "0.5.0", default-features = false } [dev-dependencies.web-sys] version = "0.3.77" features = ["Window", "Navigator"] [features] -default = ["console_error_panic_hook"] -parallel = ["rln/parallel", "wasm-bindgen-rayon"] +default = [] +utils = [] +panic_hook = ["console_error_panic_hook"] +parallel = ["rln/parallel", "wasm-bindgen-rayon", "ark-groth16/parallel"] [package.metadata.docs.rs] all-features = true diff --git a/rln-wasm/Makefile.toml b/rln-wasm/Makefile.toml index 738e4f1..1406d66 100644 --- a/rln-wasm/Makefile.toml +++ b/rln-wasm/Makefile.toml @@ -1,10 +1,14 @@ [tasks.build] clear = true -dependencies = ["pack_build", "pack_rename", "pack_resize"] +dependencies = ["pack_build", "pack_rename"] [tasks.build_parallel] clear = true -dependencies = ["pack_build_parallel", "pack_rename", "pack_resize"] +dependencies = ["pack_build_parallel", "pack_rename"] + +[tasks.build_utils] +clear = true +dependencies = ["pack_build_utils", "pack_rename_utils"] [tasks.pack_build] command = "wasm-pack" @@ -29,22 +33,28 @@ args = [ "-Z", "build-std=panic_abort,std", ] + [tasks.pack_rename] script = "sed -i.bak 's/rln-wasm/zerokit-rln-wasm/g' pkg/package.json && rm pkg/package.json.bak" -[tasks.pack_resize] -command = "wasm-opt" +[tasks.pack_build_utils] +command = "wasm-pack" args = [ - "pkg/rln_wasm_bg.wasm", - "-Oz", - "--strip-debug", - "--strip-dwarf", - "--remove-unused-module-elements", - "--vacuum", - "-o", - "pkg/rln_wasm_bg.wasm", + "build", + "--release", + "--target", + "web", + "--scope", + "waku", + "--no-default-features", + "--features", + "utils", ] +[tasks.pack_rename_utils] +script = "sed -i.bak 's/rln-wasm/zerokit-rln-wasm-utils/g' pkg/package.json && rm pkg/package.json.bak" + + [tasks.test] command = "wasm-pack" args = [ @@ -95,5 +105,21 @@ args = [ ] dependencies = ["build_parallel"] +[tasks.test_utils] +command = "wasm-pack" +args = [ + "test", + "--release", + "--node", + "--target", + "wasm32-unknown-unknown", + "--no-default-features", + "--features", + "utils", + "--", + "--nocapture", +] +dependencies = ["build_utils"] + [tasks.bench] disabled = true diff --git a/rln-wasm/README.md b/rln-wasm/README.md index 7a1fb29..3990117 100644 --- a/rln-wasm/README.md +++ b/rln-wasm/README.md @@ -72,6 +72,12 @@ Compile zerokit for `wasm32-unknown-unknown`: cargo make build ``` +Or you can build the utility functions only without RLN proof generation and verification: + +```bash +cargo make build_utils +``` + ## Running tests and benchmarks ```bash @@ -84,6 +90,18 @@ If you want to run the tests in browser headless mode, you can use the following cargo make test_browser ``` +If you want to test only the utility functions after running `cargo make build_utils`, you can use the following command: + +```bash +cargo make test_utils +``` + +## Examples + +Working examples demonstrating proof generation, proof verification and slashing: + +- [Node example](./examples/index.js) and [README](./examples/Readme.md) + ## Parallel computation The library supports parallel computation using the `wasm-bindgen-rayon` crate, @@ -109,7 +127,15 @@ To enable parallel computation for WebAssembly threads, you can use the followin cargo make build_parallel ``` -### WebAssembly Threading Support +### Running parallel tests and benchmarks + +If you want to run the parallel tests in browser headless mode, you can use the following command: + +```bash +cargo make test_parallel +``` + +### WebAssembly Threads Support Most modern browsers support WebAssembly threads, but they require the following headers to enable `SharedArrayBuffer`, which is necessary for multithreading: @@ -122,7 +148,7 @@ Without these, the application will fall back to single-threaded mode. ## Feature detection If you're targeting [older browser versions that didn't support WebAssembly threads yet](https://webassembly.org/roadmap/), -you'll likely want to create two builds - one with thread support and one without - +you'll likely want to create two builds - one with threads support and one without - and use feature detection to choose the right one on the JavaScript side. You can use [wasm-feature-detect](https://github.com/GoogleChromeLabs/wasm-feature-detect) library for this purpose. diff --git a/rln-wasm/examples/README.md b/rln-wasm/examples/README.md new file mode 100644 index 0000000..fc62425 --- /dev/null +++ b/rln-wasm/examples/README.md @@ -0,0 +1,20 @@ +# Compile and Run + +## Build the rln-wasm package at the root of rln-wasm + +```bash +cargo make build +``` + +## Move into this directory and install dependencies + +```bash +cd examples +npm install +``` + +## Run + +```bash +npm start +``` diff --git a/rln-wasm/examples/index.js b/rln-wasm/examples/index.js new file mode 100644 index 0000000..e8464c7 --- /dev/null +++ b/rln-wasm/examples/index.js @@ -0,0 +1,245 @@ +import { readFileSync } from "fs"; +import { fileURLToPath } from "url"; +import { dirname, join } from "path"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +async function calculateWitness(circomPath, inputs, witnessCalculatorFile) { + const wasmFile = readFileSync(circomPath); + const wasmFileBuffer = wasmFile.slice( + wasmFile.byteOffset, + wasmFile.byteOffset + wasmFile.byteLength + ); + const witnessCalculator = await witnessCalculatorFile(wasmFileBuffer); + const calculatedWitness = await witnessCalculator.calculateWitness( + inputs, + false + ); + return calculatedWitness; +} + +async function main() { + const rlnWasm = await import("../pkg/rln_wasm.js"); + const wasmPath = join(__dirname, "../pkg/rln_wasm_bg.wasm"); + const wasmBytes = readFileSync(wasmPath); + rlnWasm.initSync({ module: wasmBytes }); + + const zkeyPath = join( + __dirname, + "../../rln/resources/tree_depth_20/rln_final.arkzkey" + ); + const circomPath = join( + __dirname, + "../../rln/resources/tree_depth_20/rln.wasm" + ); + const witnessCalculatorPath = join( + __dirname, + "../resources/witness_calculator.js" + ); + const { builder: witnessCalculatorFile } = await import( + witnessCalculatorPath + ); + + console.log("Creating RLN instance"); + const zkeyData = readFileSync(zkeyPath); + const rlnInstance = new rlnWasm.WasmRLN(new Uint8Array(zkeyData)); + console.log("RLN instance created successfully"); + + console.log("\nGenerating identity keys"); + const identity = rlnWasm.Identity.generate(); + const identitySecret = identity.getSecretHash(); + const idCommitment = identity.getCommitment(); + console.log("Identity generated"); + console.log(" - identity_secret = " + identitySecret.debug()); + console.log(" - id_commitment = " + idCommitment.debug()); + + console.log("\nCreating message limit"); + const userMessageLimit = rlnWasm.WasmFr.fromUint(1); + console.log(" - user_message_limit = " + userMessageLimit.debug()); + + console.log("\nComputing rate commitment"); + const rateCommitment = rlnWasm.Hasher.poseidonHashPair( + idCommitment, + userMessageLimit + ); + console.log(" - rate_commitment = " + rateCommitment.debug()); + + console.log("\nWasmFr serialization: WasmFr <-> bytes"); + const serRateCommitment = rateCommitment.toBytesLE(); + console.log(" - serialized rate_commitment =", serRateCommitment); + + const deserRateCommitment = rlnWasm.WasmFr.fromBytesLE(serRateCommitment); + console.log( + " - deserialized rate_commitment = " + deserRateCommitment.debug() + ); + + console.log("\nBuilding Merkle path for stateless mode"); + const treeDepth = 20; + const defaultLeaf = rlnWasm.WasmFr.zero(); + + const defaultHashes = []; + defaultHashes[0] = rlnWasm.Hasher.poseidonHashPair(defaultLeaf, defaultLeaf); + for (let i = 1; i < treeDepth - 1; i++) { + defaultHashes[i] = rlnWasm.Hasher.poseidonHashPair( + defaultHashes[i - 1], + defaultHashes[i - 1] + ); + } + + const pathElements = new rlnWasm.VecWasmFr(); + pathElements.push(defaultLeaf); + for (let i = 1; i < treeDepth; i++) { + pathElements.push(defaultHashes[i - 1]); + } + const identityPathIndex = new Uint8Array(treeDepth); + + console.log("\nVecWasmFr serialization: VecWasmFr <-> bytes"); + const serPathElements = pathElements.toBytesLE(); + console.log(" - serialized path_elements = ", 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); + + const deserPathIndex = rlnWasm.Uint8ArrayUtils.fromBytesLE(serPathIndex); + console.log(" - deserialized path_index =", deserPathIndex); + + console.log("\nComputing Merkle root for stateless mode"); + console.log(" - computing root for index 0 with rate_commitment"); + + let computedRoot = rlnWasm.Hasher.poseidonHashPair( + rateCommitment, + defaultLeaf + ); + for (let i = 1; i < treeDepth; i++) { + computedRoot = rlnWasm.Hasher.poseidonHashPair( + computedRoot, + defaultHashes[i - 1] + ); + } + console.log(" - computed_root = " + computedRoot.debug()); + + console.log("\nHashing signal"); + const signal = new Uint8Array([ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ]); + const x = rlnWasm.Hasher.hashToFieldLE(signal); + console.log(" - x = " + x.debug()); + + console.log("\nHashing epoch"); + const epochStr = "test-epoch"; + const epoch = rlnWasm.Hasher.hashToFieldLE( + new TextEncoder().encode(epochStr) + ); + console.log(" - epoch = " + epoch.debug()); + + console.log("\nHashing RLN identifier"); + const rlnIdStr = "test-rln-identifier"; + const rlnIdentifier = rlnWasm.Hasher.hashToFieldLE( + new TextEncoder().encode(rlnIdStr) + ); + console.log(" - rln_identifier = " + rlnIdentifier.debug()); + + console.log("\nComputing Poseidon hash for external nullifier"); + const externalNullifier = rlnWasm.Hasher.poseidonHashPair( + epoch, + rlnIdentifier + ); + console.log(" - external_nullifier = " + externalNullifier.debug()); + + console.log("\nCreating message_id"); + const messageId = rlnWasm.WasmFr.fromUint(0); + console.log(" - message_id = " + messageId.debug()); + + console.log("\nGenerating RLN Proof"); + const witness = new rlnWasm.WasmRLNWitnessInput( + identitySecret, + userMessageLimit, + messageId, + pathElements, + identityPathIndex, + x, + externalNullifier + ); + const witnessJson = witness.toBigIntJson(); + const calculatedWitness = await calculateWitness( + circomPath, + witnessJson, + witnessCalculatorFile + ); + const proof = rlnInstance.generateProofWithWitness( + calculatedWitness, + witness + ); + console.log("Proof generated successfully"); + + console.log("\nVerifying Proof"); + const roots = new rlnWasm.VecWasmFr(); + roots.push(computedRoot); + const isValid = rlnInstance.verifyWithRoots(proof, roots, x); + if (isValid) { + console.log("Proof verified successfully"); + } else { + console.log("Proof verification failed"); + return; + } + + console.log( + "\nSimulating double-signaling attack (same epoch, different message)" + ); + + console.log("\nHashing second signal"); + const signal2 = new Uint8Array([ + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]); + const x2 = rlnWasm.Hasher.hashToFieldLE(signal2); + console.log(" - x2 = " + x2.debug()); + + console.log("\nCreating second message with the same id"); + const messageId2 = rlnWasm.WasmFr.fromUint(0); + console.log(" - message_id2 = " + messageId2.debug()); + + console.log("\nGenerating second RLN Proof"); + const witness2 = new rlnWasm.WasmRLNWitnessInput( + identitySecret, + userMessageLimit, + messageId2, + pathElements, + identityPathIndex, + x2, + externalNullifier + ); + const witnessJson2 = witness2.toBigIntJson(); + const calculatedWitness2 = await calculateWitness( + circomPath, + witnessJson2, + witnessCalculatorFile + ); + const proof2 = rlnInstance.generateProofWithWitness( + calculatedWitness2, + witness2 + ); + console.log("Second proof generated successfully"); + + console.log("\nVerifying second proof"); + const isValid2 = rlnInstance.verifyWithRoots(proof2, roots, x2); + if (isValid2) { + console.log("Second proof verified successfully"); + + console.log("\nRecovering identity secret"); + const recoveredSecret = rlnWasm.WasmRLNProof.recoverIdSecret(proof, proof2); + console.log(" - recovered_secret = " + recoveredSecret.debug()); + console.log(" - original_secret = " + identitySecret.debug()); + console.log("Slashing successful: Identity is recovered!"); + } else { + console.log("Second proof verification failed"); + } +} + +main().catch(console.error); diff --git a/rln-wasm/examples/package.json b/rln-wasm/examples/package.json new file mode 100644 index 0000000..d5016f2 --- /dev/null +++ b/rln-wasm/examples/package.json @@ -0,0 +1,13 @@ +{ + "name": "rln-wasm-node-example", + "version": "1.0.0", + "description": "Node.js example for RLN WASM", + "type": "module", + "main": "index.js", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "@waku/zerokit-rln-wasm": "file:../../pkg" + } +} diff --git a/rln-wasm/src/lib.rs b/rln-wasm/src/lib.rs index 4cb47d1..f1e0b62 100644 --- a/rln-wasm/src/lib.rs +++ b/rln-wasm/src/lib.rs @@ -1,212 +1,18 @@ #![cfg(target_arch = "wasm32")] -use js_sys::{BigInt as JsBigInt, Object, Uint8Array}; -use num_bigint::BigInt; -use rln::public::RLN; -use std::vec::Vec; -use wasm_bindgen::prelude::*; +mod wasm_rln; +mod wasm_utils; -#[cfg(feature = "parallel")] +#[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(feature = "panic_hook")] #[wasm_bindgen(js_name = initPanicHook)] pub fn init_panic_hook() { console_error_panic_hook::set_once(); } - -#[wasm_bindgen(js_name = RLN)] -pub struct RLNWrapper { - // The purpose of this wrapper is to hold a RLN instance with the 'static lifetime - // because wasm_bindgen does not allow returning elements with lifetimes - instance: RLN, -} - -// Macro to call methods with arbitrary amount of arguments, -// which have the last argument is output buffer pointer -// First argument to the macro is context, -// second is the actual method on `RLN` -// third is the aforementioned output buffer argument -// rest are all other arguments to the method -macro_rules! call_with_output_and_error_msg { - // this variant is needed for the case when - // there are zero other arguments - ($instance:expr, $method:ident, $error_msg:expr) => { - { - let mut output_data: Vec = Vec::new(); - let new_instance = $instance.process(); - if let Err(err) = new_instance.instance.$method(&mut output_data) { - std::mem::forget(output_data); - Err(format!("Msg: {:#?}, Error: {:#?}", $error_msg, err)) - } else { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } - } - }; - ($instance:expr, $method:ident, $error_msg:expr, $( $arg:expr ),* ) => { - { - let mut output_data: Vec = Vec::new(); - let new_instance = $instance.process(); - if let Err(err) = new_instance.instance.$method($($arg.process()),*, &mut output_data) { - std::mem::forget(output_data); - Err(format!("Msg: {:#?}, Error: {:#?}", $error_msg, err)) - } else { - let result = Uint8Array::from(&output_data[..]); - std::mem::forget(output_data); - Ok(result) - } - } - }; -} - -macro_rules! call { - ($instance:expr, $method:ident $(, $arg:expr)*) => { - { - let new_instance: &mut RLNWrapper = $instance.process(); - new_instance.instance.$method($($arg.process()),*) - } - } -} - -macro_rules! call_bool_method_with_error_msg { - ($instance:expr, $method:ident, $error_msg:expr $(, $arg:expr)*) => { - { - let new_instance: &RLNWrapper = $instance.process(); - new_instance.instance.$method($($arg.process()),*).map_err(|err| format!("Msg: {:#?}, Error: {:#?}", $error_msg, err)) - } - } -} - -trait ProcessArg { - type ReturnType; - fn process(self) -> Self::ReturnType; -} - -impl ProcessArg for usize { - type ReturnType = usize; - fn process(self) -> Self::ReturnType { - self - } -} - -impl ProcessArg for Vec { - type ReturnType = Vec; - fn process(self) -> Self::ReturnType { - self - } -} - -impl ProcessArg for *const RLN { - type ReturnType = &'static RLN; - fn process(self) -> Self::ReturnType { - unsafe { &*self } - } -} - -impl ProcessArg for *const RLNWrapper { - type ReturnType = &'static RLNWrapper; - fn process(self) -> Self::ReturnType { - unsafe { &*self } - } -} - -impl ProcessArg for *mut RLNWrapper { - type ReturnType = &'static mut RLNWrapper; - fn process(self) -> Self::ReturnType { - unsafe { &mut *self } - } -} - -impl<'a> ProcessArg for &'a [u8] { - type ReturnType = &'a [u8]; - - fn process(self) -> Self::ReturnType { - self - } -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = newRLN)] -pub fn wasm_new(zkey: Uint8Array) -> Result<*mut RLNWrapper, String> { - let instance = RLN::new_with_params(zkey.to_vec()).map_err(|err| format!("{:#?}", err))?; - let wrapper = RLNWrapper { instance }; - Ok(Box::into_raw(Box::new(wrapper))) -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = rlnWitnessToJson)] -pub fn wasm_rln_witness_to_json( - ctx: *mut RLNWrapper, - serialized_witness: Uint8Array, -) -> Result { - let inputs = call!( - ctx, - get_rln_witness_bigint_json, - &serialized_witness.to_vec()[..] - ) - .map_err(|err| err.to_string())?; - let js_value = serde_wasm_bindgen::to_value(&inputs).map_err(|err| err.to_string())?; - Object::from_entries(&js_value).map_err(|err| format!("{:#?}", err)) -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = generateRLNProofWithWitness)] -pub fn wasm_generate_rln_proof_with_witness( - ctx: *mut RLNWrapper, - calculated_witness: Vec, - serialized_witness: Uint8Array, -) -> Result { - let mut witness_vec: Vec = vec![]; - - for v in calculated_witness { - witness_vec.push( - v.to_string(10) - .map_err(|err| format!("{:#?}", err))? - .as_string() - .ok_or("not a string error")? - .parse::() - .map_err(|err| format!("{:#?}", err))?, - ); - } - - call_with_output_and_error_msg!( - ctx, - generate_rln_proof_with_witness, - "could not generate proof", - witness_vec, - serialized_witness.to_vec() - ) -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = recovedIDSecret)] -pub fn wasm_recover_id_secret( - ctx: *const RLNWrapper, - input_proof_data_1: Uint8Array, - input_proof_data_2: Uint8Array, -) -> Result { - call_with_output_and_error_msg!( - ctx, - recover_id_secret, - "could not recover id secret", - &input_proof_data_1.to_vec()[..], - &input_proof_data_2.to_vec()[..] - ) -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[wasm_bindgen(js_name = verifyWithRoots)] -pub fn wasm_verify_with_roots( - ctx: *const RLNWrapper, - proof: Uint8Array, - roots: Uint8Array, -) -> Result { - call_bool_method_with_error_msg!( - ctx, - verify_with_roots, - "error while verifying proof with roots".to_string(), - &proof.to_vec()[..], - &roots.to_vec()[..] - ) -} diff --git a/rln-wasm/src/wasm_rln.rs b/rln-wasm/src/wasm_rln.rs new file mode 100644 index 0000000..d98a532 --- /dev/null +++ b/rln-wasm/src/wasm_rln.rs @@ -0,0 +1,186 @@ +#![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 serde::Serialize; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub struct WasmRLN(RLN); + +#[wasm_bindgen] +impl WasmRLN { + #[wasm_bindgen(constructor)] + pub fn new(zkey_buffer: &Uint8Array) -> Result { + let zkey = zkey_from_raw(&zkey_buffer.to_vec()).map_err(|err| err.to_string())?; + let rln = RLN { zkey }; + + Ok(WasmRLN(rln)) + } + + #[wasm_bindgen(js_name = generateProofWithWitness)] + pub fn generate_proof_with_witness( + &self, + calculated_witness: Vec, + rln_witness: &WasmRLNWitnessInput, + ) -> Result { + let proof_values = + proof_values_from_witness(&rln_witness.0).map_err(|err| err.to_string())?; + + let calculated_witness_bigint: Vec = calculated_witness + .iter() + .map(|js_bigint| { + let str_val = js_bigint.to_string(10).unwrap().as_string().unwrap(); + str_val.parse::().unwrap() + }) + .collect(); + + let proof = generate_proof_with_witness(calculated_witness_bigint, &self.0.zkey) + .map_err(|err| err.to_string())?; + + Ok(WasmRLNProof { + proof_values, + proof, + }) + } + + #[wasm_bindgen(js_name = verifyWithRoots)] + pub fn verify_with_roots( + &self, + proof: &WasmRLNProof, + roots: &VecWasmFr, + x: &WasmFr, + ) -> Result { + let proof_verified = verify_proof(&self.0.zkey.0.vk, &proof.proof, &proof.proof_values) + .map_err(|err| err.to_string())?; + + 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) + } +} + +#[wasm_bindgen] +pub struct WasmRLNProof { + proof: Proof, + proof_values: RLNProofValues, +} + +#[wasm_bindgen] +impl WasmRLNProof { + #[wasm_bindgen(getter)] + pub fn y(&self) -> WasmFr { + WasmFr::from(self.proof_values.y) + } + + #[wasm_bindgen(getter)] + pub fn nullifier(&self) -> WasmFr { + WasmFr::from(self.proof_values.nullifier) + } + + #[wasm_bindgen(getter)] + pub fn root(&self) -> WasmFr { + WasmFr::from(self.proof_values.root) + } + + #[wasm_bindgen(getter)] + pub fn x(&self) -> WasmFr { + WasmFr::from(self.proof_values.x) + } + + #[wasm_bindgen(getter, js_name = externalNullifier)] + pub fn external_nullifier(&self) -> WasmFr { + WasmFr::from(self.proof_values.external_nullifier) + } + + #[wasm_bindgen(js_name = recoverIdSecret)] + pub fn recover_id_secret( + proof_1: &WasmRLNProof, + proof_2: &WasmRLNProof, + ) -> Result { + let external_nullifier_1 = proof_1.proof_values.external_nullifier; + let external_nullifier_2 = proof_2.proof_values.external_nullifier; + + 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)) + } +} + +#[wasm_bindgen] +pub struct WasmRLNWitnessInput(RLNWitnessInput); + +#[wasm_bindgen] +impl WasmRLNWitnessInput { + #[wasm_bindgen(constructor)] + pub fn new( + identity_secret: &WasmFr, + user_message_limit: &WasmFr, + message_id: &WasmFr, + path_elements: &VecWasmFr, + identity_path_index: &Uint8Array, + x: &WasmFr, + external_nullifier: &WasmFr, + ) -> Result { + let mut identity_secret_fr = identity_secret.inner(); + let path_elements: Vec = path_elements.inner(); + let identity_path_index: Vec = identity_path_index.to_vec(); + + let rln_witness = RLNWitnessInput::new( + IdSecret::from(&mut identity_secret_fr), + user_message_limit.inner(), + message_id.inner(), + path_elements, + identity_path_index, + x.inner(), + external_nullifier.inner(), + ) + .map_err(|err| err.to_string())?; + + Ok(WasmRLNWitnessInput(rln_witness)) + } + + #[wasm_bindgen(js_name = toBigIntJson)] + pub fn to_bigint_json(&self) -> Result { + let inputs = 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 + .serialize(&serializer) + .map_err(|err| err.to_string())?; + + js_value + .dyn_into::() + .map_err(|err| format!("{:#?}", err)) + } +} diff --git a/rln-wasm/src/wasm_utils.rs b/rln-wasm/src/wasm_utils.rs new file mode 100644 index 0000000..ab6d837 --- /dev/null +++ b/rln-wasm/src/wasm_utils.rs @@ -0,0 +1,327 @@ +#![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 wasm_bindgen::prelude::*; + +// WasmFr + +#[wasm_bindgen] +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct WasmFr(Fr); + +impl From for WasmFr { + fn from(fr: Fr) -> Self { + Self(fr) + } +} + +impl Deref for WasmFr { + type Target = Fr; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[wasm_bindgen] +impl WasmFr { + #[wasm_bindgen(js_name = zero)] + pub fn zero() -> Self { + Self(Fr::from(0u32)) + } + + #[wasm_bindgen(js_name = one)] + pub fn one() -> Self { + Self(Fr::from(1u32)) + } + + #[wasm_bindgen(js_name = fromUint)] + pub fn from_uint(value: u32) -> Self { + Self(Fr::from(value)) + } + + #[wasm_bindgen(js_name = fromBytesLE)] + pub fn from_bytes_le(bytes: &Uint8Array) -> Self { + let bytes_vec = bytes.to_vec(); + let (fr, _) = bytes_le_to_fr(&bytes_vec); + Self(fr) + } + + #[wasm_bindgen(js_name = fromBytesBE)] + pub fn from_bytes_be(bytes: &Uint8Array) -> Self { + let bytes_vec = bytes.to_vec(); + let (fr, _) = bytes_be_to_fr(&bytes_vec); + Self(fr) + } + + #[wasm_bindgen(js_name = toBytesLE)] + pub fn to_bytes_le(&self) -> Uint8Array { + let bytes = fr_to_bytes_le(&self.0); + Uint8Array::from(&bytes[..]) + } + + #[wasm_bindgen(js_name = toBytesBE)] + pub fn to_bytes_be(&self) -> Uint8Array { + let bytes = fr_to_bytes_be(&self.0); + Uint8Array::from(&bytes[..]) + } + + #[wasm_bindgen(js_name = debug)] + pub fn debug(&self) -> String { + format!("{:?}", self.0) + } +} + +impl WasmFr { + pub fn inner(&self) -> Fr { + self.0 + } +} + +// VecWasmFr + +#[wasm_bindgen] +#[derive(Debug, Clone, PartialEq, Default)] +pub struct VecWasmFr(Vec); + +#[wasm_bindgen] +impl VecWasmFr { + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + Self(Vec::new()) + } + + #[wasm_bindgen(js_name = fromBytesLE)] + pub fn from_bytes_le(bytes: &Uint8Array) -> Result { + let bytes_vec = bytes.to_vec(); + bytes_le_to_vec_fr(&bytes_vec) + .map(|(vec_fr, _)| VecWasmFr(vec_fr)) + .map_err(|err| err.to_string()) + } + + #[wasm_bindgen(js_name = fromBytesBE)] + pub fn from_bytes_be(bytes: &Uint8Array) -> Result { + let bytes_vec = bytes.to_vec(); + bytes_be_to_vec_fr(&bytes_vec) + .map(|(vec_fr, _)| VecWasmFr(vec_fr)) + .map_err(|err| err.to_string()) + } + + #[wasm_bindgen(js_name = toBytesLE)] + pub fn to_bytes_le(&self) -> Uint8Array { + let bytes = vec_fr_to_bytes_le(&self.0); + Uint8Array::from(&bytes[..]) + } + + #[wasm_bindgen(js_name = toBytesBE)] + pub fn to_bytes_be(&self) -> Uint8Array { + let bytes = vec_fr_to_bytes_be(&self.0); + Uint8Array::from(&bytes[..]) + } + + #[wasm_bindgen(js_name = get)] + pub fn get(&self, index: usize) -> Option { + self.0.get(index).map(|&fr| WasmFr(fr)) + } + + #[wasm_bindgen(js_name = length)] + pub fn length(&self) -> usize { + self.0.len() + } + + #[wasm_bindgen(js_name = push)] + pub fn push(&mut self, element: &WasmFr) { + self.0.push(element.0); + } + + #[wasm_bindgen(js_name = debug)] + pub fn debug(&self) -> String { + format!("{:?}", self.0) + } +} + +impl VecWasmFr { + pub fn inner(&self) -> Vec { + self.0.clone() + } +} + +// Uint8Array + +#[wasm_bindgen] +pub struct Uint8ArrayUtils; + +#[wasm_bindgen] +impl Uint8ArrayUtils { + #[wasm_bindgen(js_name = toBytesLE)] + pub fn to_bytes_le(input: &Uint8Array) -> Uint8Array { + let input_vec = input.to_vec(); + let bytes = vec_u8_to_bytes_le(&input_vec); + Uint8Array::from(&bytes[..]) + } + + #[wasm_bindgen(js_name = toBytesBE)] + pub fn to_bytes_be(input: &Uint8Array) -> Uint8Array { + let input_vec = input.to_vec(); + let bytes = vec_u8_to_bytes_be(&input_vec); + Uint8Array::from(&bytes[..]) + } + + #[wasm_bindgen(js_name = fromBytesLE)] + pub fn from_bytes_le(bytes: &Uint8Array) -> Result { + let bytes_vec = bytes.to_vec(); + bytes_le_to_vec_u8(&bytes_vec) + .map(|(vec_u8, _)| Uint8Array::from(&vec_u8[..])) + .map_err(|err| err.to_string()) + } + + #[wasm_bindgen(js_name = fromBytesBE)] + pub fn from_bytes_be(bytes: &Uint8Array) -> Result { + let bytes_vec = bytes.to_vec(); + bytes_be_to_vec_u8(&bytes_vec) + .map(|(vec_u8, _)| Uint8Array::from(&vec_u8[..])) + .map_err(|err| err.to_string()) + } +} + +// Utility APIs + +#[wasm_bindgen] +pub struct Hasher; + +#[wasm_bindgen] +impl Hasher { + #[wasm_bindgen(js_name = hashToFieldLE)] + pub fn hash_to_field_le(input: &Uint8Array) -> WasmFr { + WasmFr(hash_to_field_le(&input.to_vec())) + } + + #[wasm_bindgen(js_name = hashToFieldBE)] + pub fn hash_to_field_be(input: &Uint8Array) -> WasmFr { + WasmFr(hash_to_field_be(&input.to_vec())) + } + + #[wasm_bindgen(js_name = poseidonHashPair)] + pub fn poseidon_hash_pair(a: &WasmFr, b: &WasmFr) -> WasmFr { + WasmFr(poseidon_hash(&[a.0, b.0])) + } +} + +#[wasm_bindgen] +pub struct Identity { + identity_secret_hash: Fr, + id_commitment: Fr, +} + +#[wasm_bindgen] +impl Identity { + #[wasm_bindgen(js_name = generate)] + pub fn generate() -> Identity { + let (identity_secret_hash, id_commitment) = keygen(); + Identity { + identity_secret_hash: *identity_secret_hash, + id_commitment, + } + } + + #[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); + Identity { + identity_secret_hash, + id_commitment, + } + } + + #[wasm_bindgen(js_name = getSecretHash)] + pub fn get_secret_hash(&self) -> WasmFr { + WasmFr(self.identity_secret_hash) + } + + #[wasm_bindgen(js_name = getCommitment)] + pub fn get_commitment(&self) -> WasmFr { + WasmFr(self.id_commitment) + } + + #[wasm_bindgen(js_name = toArray)] + pub fn to_array(&self) -> VecWasmFr { + VecWasmFr(vec![self.identity_secret_hash, self.id_commitment]) + } +} + +#[wasm_bindgen] +pub struct ExtendedIdentity { + identity_trapdoor: Fr, + identity_nullifier: Fr, + identity_secret_hash: Fr, + id_commitment: Fr, +} + +#[wasm_bindgen] +impl ExtendedIdentity { + #[wasm_bindgen(js_name = generate)] + pub fn generate() -> ExtendedIdentity { + let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) = + extended_keygen(); + ExtendedIdentity { + identity_trapdoor, + identity_nullifier, + identity_secret_hash, + id_commitment, + } + } + + #[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) = + extended_seeded_keygen(&seed_vec); + ExtendedIdentity { + identity_trapdoor, + identity_nullifier, + identity_secret_hash, + id_commitment, + } + } + + #[wasm_bindgen(js_name = getTrapdoor)] + pub fn get_trapdoor(&self) -> WasmFr { + WasmFr(self.identity_trapdoor) + } + + #[wasm_bindgen(js_name = getNullifier)] + pub fn get_nullifier(&self) -> WasmFr { + WasmFr(self.identity_nullifier) + } + + #[wasm_bindgen(js_name = getSecretHash)] + pub fn get_secret_hash(&self) -> WasmFr { + WasmFr(self.identity_secret_hash) + } + + #[wasm_bindgen(js_name = getCommitment)] + pub fn get_commitment(&self) -> WasmFr { + WasmFr(self.id_commitment) + } + + #[wasm_bindgen(js_name = toArray)] + pub fn to_array(&self) -> VecWasmFr { + VecWasmFr(vec![ + self.identity_trapdoor, + self.identity_nullifier, + self.identity_secret_hash, + self.id_commitment, + ]) + } +} diff --git a/rln-wasm/tests/browser.rs b/rln-wasm/tests/browser.rs index 52fd3aa..0f4e154 100644 --- a/rln-wasm/tests/browser.rs +++ b/rln-wasm/tests/browser.rs @@ -1,17 +1,14 @@ #![cfg(target_arch = "wasm32")] +#![cfg(not(feature = "utils"))] #[cfg(test)] mod test { use js_sys::{BigInt as JsBigInt, Date, Object, Uint8Array}; - use rln::circuit::{Fr, TEST_TREE_DEPTH}; - use rln::hashers::{hash_to_field_le, poseidon_hash, PoseidonHash}; - use rln::protocol::{prepare_verify_input, rln_witness_from_values, serialize_witness}; - use rln::utils::{bytes_le_to_fr, fr_to_bytes_le, IdSecret}; + use rln::circuit::TEST_TREE_DEPTH; + use rln::hashers::PoseidonHash; use rln_wasm::{ - wasm_generate_rln_proof_with_witness, wasm_new, wasm_rln_witness_to_json, - wasm_verify_with_roots, + Hasher, Identity, VecWasmFr, WasmFr, WasmRLN, WasmRLNProof, WasmRLNWitnessInput, }; - use rln_wasm_utils::wasm_key_gen; use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; use wasm_bindgen_test::{console_log, wasm_bindgen_test, wasm_bindgen_test_configure}; use zerokit_utils::{ @@ -105,134 +102,131 @@ mod test { let mut results = String::from("\nbenchmarks:\n"); let iterations = 10; - let zkey = readFile(&ARKZKEY_BYTES).expect("Failed to read zkey file"); + let zkey = readFile(ARKZKEY_BYTES).expect("Failed to read zkey file"); - // Benchmark wasm_new - let start_wasm_new = Date::now(); + // Benchmark RLN instance creation + let start_rln_new = Date::now(); for _ in 0..iterations { - let _ = wasm_new(zkey.clone()).expect("Failed to create RLN instance"); + let _ = WasmRLN::new(&zkey).expect("Failed to create RLN instance"); } - let wasm_new_result = Date::now() - start_wasm_new; + let rln_new_result = Date::now() - start_rln_new; // Create RLN instance for other benchmarks - let rln_instance = wasm_new(zkey).expect("Failed to create RLN instance"); + let rln_instance = WasmRLN::new(&zkey).expect("Failed to create RLN instance"); let mut tree: OptimalMerkleTree = OptimalMerkleTree::default(TEST_TREE_DEPTH).expect("Failed to create tree"); - // Benchmark wasm_key_gen - let start_wasm_key_gen = Date::now(); + // Benchmark generate identity + let start_identity_gen = Date::now(); for _ in 0..iterations { - let _ = wasm_key_gen(true).expect("Failed to generate keys"); + let _ = Identity::generate(); } - let wasm_key_gen_result = Date::now() - start_wasm_key_gen; + let identity_gen_result = Date::now() - start_identity_gen; - // Generate identity pair for other benchmarks - let mem_keys = wasm_key_gen(true).expect("Failed to generate keys"); - let id_key = mem_keys.subarray(0, 32); - let (identity_secret_hash, _) = IdSecret::from_bytes_le(&id_key.to_vec()); - let (id_commitment, _) = bytes_le_to_fr(&mem_keys.subarray(32, 64).to_vec()); + // Generate identity for other benchmarks + let identity_pair = Identity::generate(); + let identity_secret_hash = identity_pair.get_secret_hash(); + let id_commitment = identity_pair.get_commitment(); - let epoch = hash_to_field_le(b"test-epoch"); - let rln_identifier = hash_to_field_le(b"test-rln-identifier"); - let external_nullifier = poseidon_hash(&[epoch, rln_identifier]); + let epoch = Hasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8])); + let rln_identifier = + Hasher::hash_to_field_le(&Uint8Array::from(b"test-rln-identifier" as &[u8])); + let external_nullifier = Hasher::poseidon_hash_pair(&epoch, &rln_identifier); let identity_index = tree.leaves_set(); - let user_message_limit = Fr::from(100); + let user_message_limit = WasmFr::from_uint(100); - let rate_commitment = poseidon_hash(&[id_commitment, user_message_limit]); - tree.update_next(rate_commitment) + let rate_commitment = Hasher::poseidon_hash_pair(&id_commitment, &user_message_limit); + tree.update_next(*rate_commitment) .expect("Failed to update tree"); - let message_id = Fr::from(0); + let message_id = WasmFr::from_uint(0); let signal: [u8; 32] = [0; 32]; - let x = hash_to_field_le(&signal); + let x = Hasher::hash_to_field_le(&Uint8Array::from(&signal[..])); let merkle_proof: OptimalMerkleProof = tree .proof(identity_index) .expect("Failed to generate merkle proof"); - let rln_witness = rln_witness_from_values( - identity_secret_hash, - merkle_proof.get_path_elements(), - merkle_proof.get_path_index(), - x, - external_nullifier, - user_message_limit, - message_id, + let mut path_elements = VecWasmFr::new(); + for path_element in merkle_proof.get_path_elements() { + path_elements.push(&WasmFr::from(path_element)); + } + let path_index = Uint8Array::from(&merkle_proof.get_path_index()[..]); + + let rln_witness_input = WasmRLNWitnessInput::new( + &identity_secret_hash, + &user_message_limit, + &message_id, + &path_elements, + &path_index, + &x, + &external_nullifier, ) - .expect("Failed to create RLN witness"); + .expect("Failed to create WasmRLNWitnessInput"); - let serialized_witness = - serialize_witness(&rln_witness).expect("Failed to serialize witness"); - let witness_buffer = Uint8Array::from(&serialized_witness[..]); + let rln_witness_input_bigint_json = rln_witness_input + .to_bigint_json() + .expect("Failed to convert witness to BigInt JSON"); - let json_inputs = wasm_rln_witness_to_json(rln_instance, witness_buffer.clone()) - .expect("Failed to convert witness to JSON"); - - // Benchmark calculateWitness + // Benchmark witness calculation let start_calculate_witness = Date::now(); for _ in 0..iterations { - let _ = calculateWitness(&CIRCOM_BYTES, json_inputs.clone()) + let _ = calculateWitness(CIRCOM_BYTES, rln_witness_input_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_json = calculateWitness(&CIRCOM_BYTES, json_inputs) - .await - .expect("Failed to calculate witness") - .as_string() - .expect("Failed to convert calculated witness to string"); + 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_vec_str: Vec = - serde_json::from_str(&calculated_witness_json).expect("Failed to parse JSON"); + serde_json::from_str(&calculated_witness_str).expect("Failed to parse JSON"); let calculated_witness: Vec = calculated_witness_vec_str .iter() .map(|x| JsBigInt::new(&x.into()).expect("Failed to create JsBigInt")) .collect(); - // Benchmark wasm_generate_rln_proof_with_witness - let start_wasm_generate_rln_proof_with_witness = Date::now(); + // Benchmark proof generation with witness + let start_generate_proof_with_witness = Date::now(); for _ in 0..iterations { - let _ = wasm_generate_rln_proof_with_witness( - rln_instance, - calculated_witness.clone(), - witness_buffer.clone(), - ) - .expect("Failed to generate proof"); - } - let wasm_generate_rln_proof_with_witness_result = - Date::now() - start_wasm_generate_rln_proof_with_witness; - - // Generate a proof for other benchmarks - let proof = - wasm_generate_rln_proof_with_witness(rln_instance, calculated_witness, witness_buffer) + let _ = rln_instance + .generate_proof_with_witness(calculated_witness.clone(), &rln_witness_input) .expect("Failed to generate proof"); - - let proof_data = proof.to_vec(); - let verify_input = prepare_verify_input(proof_data, &signal); - let input_buffer = Uint8Array::from(&verify_input[..]); - - let root = tree.root(); - let roots_serialized = fr_to_bytes_le(&root); - let roots_buffer = Uint8Array::from(&roots_serialized[..]); - - // Benchmark wasm_verify_with_roots - let start_wasm_verify_with_roots = Date::now(); - for _ in 0..iterations { - let _ = - wasm_verify_with_roots(rln_instance, input_buffer.clone(), roots_buffer.clone()) - .expect("Failed to verify proof"); } - let wasm_verify_with_roots_result = Date::now() - start_wasm_verify_with_roots; + let generate_proof_with_witness_result = Date::now() - start_generate_proof_with_witness; - // Verify the proof with the root - let is_proof_valid = wasm_verify_with_roots(rln_instance, input_buffer, roots_buffer) + // Generate proof with witness for other benchmarks + let proof: WasmRLNProof = rln_instance + .generate_proof_with_witness(calculated_witness, &rln_witness_input) + .expect("Failed to generate proof"); + + let root = WasmFr::from(tree.root()); + let mut roots = VecWasmFr::new(); + roots.push(&root); + + // Benchmark proof verification with the root + let start_verify_with_roots = Date::now(); + for _ in 0..iterations { + let _ = rln_instance + .verify_with_roots(&proof, &roots, &x) + .expect("Failed to verify proof"); + } + let verify_with_roots_result = Date::now() - start_verify_with_roots; + + // Verify proof with the root for other benchmarks + let is_proof_valid = rln_instance + .verify_with_roots(&proof, &roots, &x) .expect("Failed to verify proof"); assert!(is_proof_valid, "verification failed"); - // Format and display results + // Format and display the benchmark results let format_duration = |duration_ms: f64| -> String { let avg_ms = duration_ms / (iterations as f64); if avg_ms >= 1000.0 { @@ -242,22 +236,25 @@ mod test { } }; - results.push_str(&format!("wasm_new: {}\n", format_duration(wasm_new_result))); results.push_str(&format!( - "wasm_key_gen: {}\n", - format_duration(wasm_key_gen_result) + "RLN instance creation: {}\n", + format_duration(rln_new_result) )); results.push_str(&format!( - "calculateWitness: {}\n", + "Identity generation: {}\n", + format_duration(identity_gen_result) + )); + results.push_str(&format!( + "Witness calculation: {}\n", format_duration(calculate_witness_result) )); results.push_str(&format!( - "wasm_generate_rln_proof_with_witness: {}\n", - format_duration(wasm_generate_rln_proof_with_witness_result) + "Proof generation with witness: {}\n", + format_duration(generate_proof_with_witness_result) )); results.push_str(&format!( - "wasm_verify_with_roots: {}\n", - format_duration(wasm_verify_with_roots_result) + "Proof verification with roots: {}\n", + format_duration(verify_with_roots_result) )); // Log the results diff --git a/rln-wasm/tests/node.rs b/rln-wasm/tests/node.rs index 9e7ff71..01319c8 100644 --- a/rln-wasm/tests/node.rs +++ b/rln-wasm/tests/node.rs @@ -1,26 +1,20 @@ -#![cfg(not(feature = "parallel"))] #![cfg(target_arch = "wasm32")] +#![cfg(not(feature = "utils"))] #[cfg(test)] mod test { use js_sys::{BigInt as JsBigInt, Date, Object, Uint8Array}; - use rln::circuit::{Fr, TEST_TREE_DEPTH}; - use rln::hashers::{hash_to_field_le, poseidon_hash, PoseidonHash}; - use rln::protocol::{prepare_verify_input, rln_witness_from_values, serialize_witness}; - use rln::utils::{bytes_le_to_fr, fr_to_bytes_le, IdSecret}; + use rln::circuit::TEST_TREE_DEPTH; + use rln::hashers::PoseidonHash; use rln_wasm::{ - wasm_generate_rln_proof_with_witness, wasm_new, wasm_rln_witness_to_json, - wasm_verify_with_roots, + Hasher, Identity, VecWasmFr, WasmFr, WasmRLN, WasmRLNProof, WasmRLNWitnessInput, }; - use rln_wasm_utils::wasm_key_gen; use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; use wasm_bindgen_test::{console_log, wasm_bindgen_test}; use zerokit_utils::{ OptimalMerkleProof, OptimalMerkleTree, ZerokitMerkleProof, ZerokitMerkleTree, }; - const WITNESS_CALCULATOR_JS: &str = include_str!("../resources/witness_calculator.js"); - #[wasm_bindgen(inline_js = r#" const fs = require("fs"); @@ -73,6 +67,8 @@ mod test { async fn calculateWitness(circom_path: &str, input: Object) -> Result; } + const WITNESS_CALCULATOR_JS: &str = include_str!("../resources/witness_calculator.js"); + const ARKZKEY_PATH: &str = "../rln/resources/tree_depth_20/rln_final.arkzkey"; const CIRCOM_PATH: &str = "../rln/resources/tree_depth_20/rln.wasm"; @@ -86,134 +82,131 @@ mod test { let mut results = String::from("\nbenchmarks:\n"); let iterations = 10; - let zkey = readFile(&ARKZKEY_PATH).expect("Failed to read zkey file"); + let zkey = readFile(ARKZKEY_PATH).expect("Failed to read zkey file"); - // Benchmark wasm_new - let start_wasm_new = Date::now(); + // Benchmark RLN instance creation + let start_rln_new = Date::now(); for _ in 0..iterations { - let _ = wasm_new(zkey.clone()).expect("Failed to create RLN instance"); + let _ = WasmRLN::new(&zkey).expect("Failed to create RLN instance"); } - let wasm_new_result = Date::now() - start_wasm_new; + let rln_new_result = Date::now() - start_rln_new; // Create RLN instance for other benchmarks - let rln_instance = wasm_new(zkey).expect("Failed to create RLN instance"); + let rln_instance = WasmRLN::new(&zkey).expect("Failed to create RLN instance"); let mut tree: OptimalMerkleTree = OptimalMerkleTree::default(TEST_TREE_DEPTH).expect("Failed to create tree"); - // Benchmark wasm_key_gen - let start_wasm_key_gen = Date::now(); + // Benchmark generate identity + let start_identity_gen = Date::now(); for _ in 0..iterations { - let _ = wasm_key_gen(true).expect("Failed to generate keys"); + let _ = Identity::generate(); } - let wasm_key_gen_result = Date::now() - start_wasm_key_gen; + let identity_gen_result = Date::now() - start_identity_gen; - // Generate identity pair for other benchmarks - let mem_keys = wasm_key_gen(true).expect("Failed to generate keys"); - let id_key = mem_keys.subarray(0, 32); - let (identity_secret_hash, _) = IdSecret::from_bytes_le(&id_key.to_vec()); - let (id_commitment, _) = bytes_le_to_fr(&mem_keys.subarray(32, 64).to_vec()); + // Generate identity for other benchmarks + let identity_pair = Identity::generate(); + let identity_secret_hash = identity_pair.get_secret_hash(); + let id_commitment = identity_pair.get_commitment(); - let epoch = hash_to_field_le(b"test-epoch"); - let rln_identifier = hash_to_field_le(b"test-rln-identifier"); - let external_nullifier = poseidon_hash(&[epoch, rln_identifier]); + let epoch = Hasher::hash_to_field_le(&Uint8Array::from(b"test-epoch" as &[u8])); + let rln_identifier = + Hasher::hash_to_field_le(&Uint8Array::from(b"test-rln-identifier" as &[u8])); + let external_nullifier = Hasher::poseidon_hash_pair(&epoch, &rln_identifier); let identity_index = tree.leaves_set(); - let user_message_limit = Fr::from(100); + let user_message_limit = WasmFr::from_uint(100); - let rate_commitment = poseidon_hash(&[id_commitment, user_message_limit]); - tree.update_next(rate_commitment) + let rate_commitment = Hasher::poseidon_hash_pair(&id_commitment, &user_message_limit); + tree.update_next(*rate_commitment) .expect("Failed to update tree"); - let message_id = Fr::from(0); + let message_id = WasmFr::from_uint(0); let signal: [u8; 32] = [0; 32]; - let x = hash_to_field_le(&signal); + let x = Hasher::hash_to_field_le(&Uint8Array::from(&signal[..])); let merkle_proof: OptimalMerkleProof = tree .proof(identity_index) .expect("Failed to generate merkle proof"); - let rln_witness = rln_witness_from_values( - identity_secret_hash, - merkle_proof.get_path_elements(), - merkle_proof.get_path_index(), - x, - external_nullifier, - user_message_limit, - message_id, + let mut path_elements = VecWasmFr::new(); + for path_element in merkle_proof.get_path_elements() { + path_elements.push(&WasmFr::from(path_element)); + } + let path_index = Uint8Array::from(&merkle_proof.get_path_index()[..]); + + let rln_witness_input = WasmRLNWitnessInput::new( + &identity_secret_hash, + &user_message_limit, + &message_id, + &path_elements, + &path_index, + &x, + &external_nullifier, ) - .expect("Failed to create RLN witness"); + .expect("Failed to create WasmRLNWitnessInput"); - let serialized_witness = - serialize_witness(&rln_witness).expect("Failed to serialize witness"); - let witness_buffer = Uint8Array::from(&serialized_witness[..]); + let rln_witness_input_bigint_json = rln_witness_input + .to_bigint_json() + .expect("Failed to convert witness to BigInt JSON"); - let json_inputs = wasm_rln_witness_to_json(rln_instance, witness_buffer.clone()) - .expect("Failed to convert witness to JSON"); - - // Benchmark calculateWitness + // Benchmark witness calculation let start_calculate_witness = Date::now(); for _ in 0..iterations { - let _ = calculateWitness(&CIRCOM_PATH, json_inputs.clone()) + let _ = calculateWitness(CIRCOM_PATH, rln_witness_input_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_json = calculateWitness(&CIRCOM_PATH, json_inputs) - .await - .expect("Failed to calculate witness") - .as_string() - .expect("Failed to convert calculated witness to string"); + 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_vec_str: Vec = - serde_json::from_str(&calculated_witness_json).expect("Failed to parse JSON"); + serde_json::from_str(&calculated_witness_str).expect("Failed to parse JSON"); let calculated_witness: Vec = calculated_witness_vec_str .iter() .map(|x| JsBigInt::new(&x.into()).expect("Failed to create JsBigInt")) .collect(); - // Benchmark wasm_generate_rln_proof_with_witness - let start_wasm_generate_rln_proof_with_witness = Date::now(); + // Benchmark proof generation with witness + let start_generate_proof_with_witness = Date::now(); for _ in 0..iterations { - let _ = wasm_generate_rln_proof_with_witness( - rln_instance, - calculated_witness.clone(), - witness_buffer.clone(), - ) - .expect("Failed to generate proof"); - } - let wasm_generate_rln_proof_with_witness_result = - Date::now() - start_wasm_generate_rln_proof_with_witness; - - // Generate a proof for other benchmarks - let proof = - wasm_generate_rln_proof_with_witness(rln_instance, calculated_witness, witness_buffer) + let _ = rln_instance + .generate_proof_with_witness(calculated_witness.clone(), &rln_witness_input) .expect("Failed to generate proof"); - - let proof_data = proof.to_vec(); - let verify_input = prepare_verify_input(proof_data, &signal); - let input_buffer = Uint8Array::from(&verify_input[..]); - - let root = tree.root(); - let roots_serialized = fr_to_bytes_le(&root); - let roots_buffer = Uint8Array::from(&roots_serialized[..]); - - // Benchmark wasm_verify_with_roots - let start_wasm_verify_with_roots = Date::now(); - for _ in 0..iterations { - let _ = - wasm_verify_with_roots(rln_instance, input_buffer.clone(), roots_buffer.clone()) - .expect("Failed to verify proof"); } - let wasm_verify_with_roots_result = Date::now() - start_wasm_verify_with_roots; + let generate_proof_with_witness_result = Date::now() - start_generate_proof_with_witness; - // Verify the proof with the root - let is_proof_valid = wasm_verify_with_roots(rln_instance, input_buffer, roots_buffer) + // Generate proof with witness for other benchmarks + let proof: WasmRLNProof = rln_instance + .generate_proof_with_witness(calculated_witness, &rln_witness_input) + .expect("Failed to generate proof"); + + let root = WasmFr::from(tree.root()); + let mut roots = VecWasmFr::new(); + roots.push(&root); + + // Benchmark proof verification with the root + let start_verify_with_roots = Date::now(); + for _ in 0..iterations { + let _ = rln_instance + .verify_with_roots(&proof, &roots, &x) + .expect("Failed to verify proof"); + } + let verify_with_roots_result = Date::now() - start_verify_with_roots; + + // Verify proof with the root for other benchmarks + let is_proof_valid = rln_instance + .verify_with_roots(&proof, &roots, &x) .expect("Failed to verify proof"); assert!(is_proof_valid, "verification failed"); - // Format and display results + // Format and display the benchmark results let format_duration = |duration_ms: f64| -> String { let avg_ms = duration_ms / (iterations as f64); if avg_ms >= 1000.0 { @@ -223,22 +216,25 @@ mod test { } }; - results.push_str(&format!("wasm_new: {}\n", format_duration(wasm_new_result))); results.push_str(&format!( - "wasm_key_gen: {}\n", - format_duration(wasm_key_gen_result) + "RLN instance creation: {}\n", + format_duration(rln_new_result) )); results.push_str(&format!( - "calculate_witness: {}\n", + "Identity generation: {}\n", + format_duration(identity_gen_result) + )); + results.push_str(&format!( + "Witness calculation: {}\n", format_duration(calculate_witness_result) )); results.push_str(&format!( - "wasm_generate_rln_proof_with_witness: {}\n", - format_duration(wasm_generate_rln_proof_with_witness_result) + "Proof generation with witness: {}\n", + format_duration(generate_proof_with_witness_result) )); results.push_str(&format!( - "wasm_verify_with_roots: {}\n", - format_duration(wasm_verify_with_roots_result) + "Proof verification with roots: {}\n", + format_duration(verify_with_roots_result) )); // Log the results diff --git a/rln-wasm/tests/utils.rs b/rln-wasm/tests/utils.rs new file mode 100644 index 0000000..7c1b978 --- /dev/null +++ b/rln-wasm/tests/utils.rs @@ -0,0 +1,229 @@ +#![cfg(target_arch = "wasm32")] + +#[cfg(test)] +mod test { + 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_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 id_commitment = *identity.get_commitment(); + + assert_ne!(identity_secret_hash, 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(1).unwrap(), id_commitment); + } + + #[wasm_bindgen_test] + fn test_extended_keygen_wasm() { + let identity = ExtendedIdentity::generate(); + + let identity_trapdoor = *identity.get_trapdoor(); + let identity_nullifier = *identity.get_nullifier(); + let identity_secret_hash = *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!(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(3).unwrap(), id_commitment); + } + + #[wasm_bindgen_test] + fn test_seeded_keygen_wasm() { + let seed_bytes: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let seed = Uint8Array::from(&seed_bytes[..]); + + let identity = Identity::generate_seeded(&seed); + let identity_secret_hash = *identity.get_secret_hash(); + let id_commitment = *identity.get_commitment(); + + let expected_identity_secret_hash_seed_bytes = str_to_fr( + "0x766ce6c7e7a01bdf5b3f257616f603918c30946fa23480f2859c597817e6716", + 16, + ) + .unwrap(); + let expected_id_commitment_seed_bytes = str_to_fr( + "0xbf16d2b5c0d6f9d9d561e05bfca16a81b4b873bb063508fae360d8c74cef51f", + 16, + ) + .unwrap(); + + assert_eq!( + identity_secret_hash, + expected_identity_secret_hash_seed_bytes + ); + assert_eq!(id_commitment, expected_id_commitment_seed_bytes); + } + + #[wasm_bindgen_test] + fn test_seeded_extended_keygen_wasm() { + let seed_bytes: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let seed = Uint8Array::from(&seed_bytes[..]); + + let identity = ExtendedIdentity::generate_seeded(&seed); + + let identity_trapdoor = *identity.get_trapdoor(); + let identity_nullifier = *identity.get_nullifier(); + let identity_secret_hash = *identity.get_secret_hash(); + let id_commitment = *identity.get_commitment(); + + let expected_identity_trapdoor_seed_bytes = str_to_fr( + "0x766ce6c7e7a01bdf5b3f257616f603918c30946fa23480f2859c597817e6716", + 16, + ) + .unwrap(); + let expected_identity_nullifier_seed_bytes = str_to_fr( + "0x1f18714c7bc83b5bca9e89d404cf6f2f585bc4c0f7ed8b53742b7e2b298f50b4", + 16, + ) + .unwrap(); + let expected_identity_secret_hash_seed_bytes = str_to_fr( + "0x2aca62aaa7abaf3686fff2caf00f55ab9462dc12db5b5d4bcf3994e671f8e521", + 16, + ) + .unwrap(); + let expected_id_commitment_seed_bytes = str_to_fr( + "0x68b66aa0a8320d2e56842581553285393188714c48f9b17acd198b4f1734c5c", + 16, + ) + .unwrap(); + + 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!(id_commitment, expected_id_commitment_seed_bytes); + } + + #[wasm_bindgen_test] + fn test_wasmfr() { + let wasmfr_zero = WasmFr::zero(); + let fr_zero = Fr::from(0u8); + assert_eq!(*wasmfr_zero, fr_zero); + + let wasmfr_one = WasmFr::one(); + let fr_one = Fr::from(1u8); + assert_eq!(*wasmfr_one, fr_one); + + let wasmfr_int = WasmFr::from_uint(42); + let fr_int = Fr::from(42u8); + assert_eq!(*wasmfr_int, fr_int); + + let wasmfr_debug_str = wasmfr_int.debug(); + assert_eq!(wasmfr_debug_str.to_string(), "42"); + + let identity = Identity::generate(); + let mut id_secret_fr = *identity.get_secret_hash(); + let id_secret_hash = IdSecret::from(&mut id_secret_fr); + let id_commitment = *identity.get_commitment(); + let wasmfr_id_secret_hash = *identity.get_secret_hash(); + assert_eq!(wasmfr_id_secret_hash, *id_secret_hash); + let wasmfr_id_commitment = *identity.get_commitment(); + assert_eq!(wasmfr_id_commitment, id_commitment); + } + + #[wasm_bindgen_test] + fn test_vec_wasmfr() { + let vec_fr = vec![Fr::from(1u8), Fr::from(2u8), Fr::from(3u8), Fr::from(4u8)]; + let mut vec_wasmfr = VecWasmFr::new(); + for fr in &vec_fr { + vec_wasmfr.push(&WasmFr::from(*fr)); + } + + let bytes_le = vec_wasmfr.to_bytes_le(); + let expected_le = rln::utils::vec_fr_to_bytes_le(&vec_fr); + assert_eq!(bytes_le.to_vec(), expected_le); + + let bytes_be = vec_wasmfr.to_bytes_be(); + let expected_be = rln::utils::vec_fr_to_bytes_be(&vec_fr); + assert_eq!(bytes_be.to_vec(), expected_be); + + let vec_wasmfr_from_le = match VecWasmFr::from_bytes_le(&bytes_le) { + Ok(v) => v, + Err(err) => panic!("VecWasmFr::from_bytes_le call failed: {}", err), + }; + assert_eq!(vec_wasmfr_from_le.length(), vec_wasmfr.length()); + for i in 0..vec_wasmfr.length() { + assert_eq!( + *vec_wasmfr_from_le.get(i).unwrap(), + *vec_wasmfr.get(i).unwrap() + ); + } + + let vec_wasmfr_from_be = match VecWasmFr::from_bytes_be(&bytes_be) { + Ok(v) => v, + Err(err) => panic!("VecWasmFr::from_bytes_be call failed: {}", err), + }; + for i in 0..vec_wasmfr.length() { + assert_eq!( + *vec_wasmfr_from_be.get(i).unwrap(), + *vec_wasmfr.get(i).unwrap() + ); + } + } + + #[wasm_bindgen_test] + fn test_hash_to_field_wasm() { + let mut rng = thread_rng(); + let signal_gen: [u8; 32] = rng.gen(); + let signal = Uint8Array::from(&signal_gen[..]); + + let wasmfr_le_1 = Hasher::hash_to_field_le(&signal); + let fr_le_2 = rln::hashers::hash_to_field_le(&signal_gen); + assert_eq!(*wasmfr_le_1, fr_le_2); + + let wasmfr_be_1 = Hasher::hash_to_field_be(&signal); + let fr_be_2 = rln::hashers::hash_to_field_be(&signal_gen); + assert_eq!(*wasmfr_be_1, fr_be_2); + + assert_eq!(*wasmfr_le_1, *wasmfr_be_1); + assert_eq!(fr_le_2, fr_be_2); + + let hash_wasmfr_le_1 = wasmfr_le_1.to_bytes_le(); + let hash_fr_le_2 = fr_to_bytes_le(&fr_le_2); + assert_eq!(hash_wasmfr_le_1.to_vec(), hash_fr_le_2); + + let hash_wasmfr_be_1 = wasmfr_be_1.to_bytes_be(); + let hash_fr_be_2 = fr_to_bytes_be(&fr_be_2); + assert_eq!(hash_wasmfr_be_1.to_vec(), hash_fr_be_2); + + assert_ne!(hash_wasmfr_le_1.to_vec(), hash_wasmfr_be_1.to_vec()); + assert_ne!(hash_fr_le_2, hash_fr_be_2); + } + + #[wasm_bindgen_test] + fn test_poseidon_hash_pair_wasm() { + let input_1 = Fr::from(42u8); + let input_2 = Fr::from(99u8); + + let expected_hash = poseidon_hash(&[input_1, input_2]); + let wasmfr_1 = WasmFr::from_uint(42); + let wasmfr_2 = WasmFr::from_uint(99); + let received_hash = Hasher::poseidon_hash_pair(&wasmfr_1, &wasmfr_2); + + assert_eq!(*received_hash, expected_hash); + } +} diff --git a/rln/Cargo.toml b/rln/Cargo.toml index ca9ab3f..5032b46 100644 --- a/rln/Cargo.toml +++ b/rln/Cargo.toml @@ -36,7 +36,6 @@ cfg-if = "1.0" num-bigint = { version = "0.4.6", default-features = false, features = ["std"] } num-traits = "0.2.19" once_cell = "1.21.3" -lazy_static = "1.5.0" rand = "0.8.5" rand_chacha = "0.3.1" ruint = { version = "1.17.0", default-features = false, features = [ diff --git a/rln/src/circuit/iden3calc.rs b/rln/src/circuit/iden3calc.rs index 70b2113..22335c7 100644 --- a/rln/src/circuit/iden3calc.rs +++ b/rln/src/circuit/iden3calc.rs @@ -17,7 +17,7 @@ use graph::Node; pub type InputSignalsInfo = HashMap; -pub fn calc_witness)>>( +pub(crate) fn calc_witness)>>( inputs: I, graph_data: &[u8], ) -> Vec { diff --git a/rln/src/circuit/iden3calc/storage.rs b/rln/src/circuit/iden3calc/storage.rs index f0bed5f..7c23fcc 100644 --- a/rln/src/circuit/iden3calc/storage.rs +++ b/rln/src/circuit/iden3calc/storage.rs @@ -1,16 +1,18 @@ // This file is based on the code by iden3. Its preimage can be found here: // https://github.com/iden3/circom-witnesscalc/blob/5cb365b6e4d9052ecc69d4567fcf5bc061c20e94/src/storage.rs -use ark_bn254::Fr; use ark_ff::PrimeField; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use prost::Message; use std::io::{Read, Write}; -use crate::circuit::iden3calc::{ - graph, - graph::{Operation, TresOperation, UnoOperation}, - proto, InputSignalsInfo, +use crate::circuit::{ + iden3calc::{ + graph, + graph::{Operation, TresOperation, UnoOperation}, + proto, InputSignalsInfo, + }, + Fr, }; // format of the wtns.graph file: diff --git a/rln/src/circuit/mod.rs b/rln/src/circuit/mod.rs index 0121f59..e7f5be4 100644 --- a/rln/src/circuit/mod.rs +++ b/rln/src/circuit/mod.rs @@ -4,30 +4,32 @@ pub mod error; pub mod iden3calc; pub mod qap; -use ::lazy_static::lazy_static; use ark_bn254::{ Bn254, Fq as ArkFq, Fq2 as ArkFq2, Fr as ArkFr, G1Affine as ArkG1Affine, G1Projective as ArkG1Projective, G2Affine as ArkG2Affine, G2Projective as ArkG2Projective, }; -use ark_groth16::ProvingKey; +use ark_groth16::{ + Proof as ArkProof, ProvingKey as ArkProvingKey, VerifyingKey as ArkVerifyingKey, +}; use ark_relations::r1cs::ConstraintMatrices; use crate::circuit::error::ZKeyReadError; -use crate::circuit::iden3calc::calc_witness; use {ark_ff::Field, ark_serialize::CanonicalDeserialize, ark_serialize::CanonicalSerialize}; -use crate::utils::FrOrSecret; - -pub const ARKZKEY_BYTES: &[u8] = include_bytes!("../../resources/tree_depth_20/rln_final.arkzkey"); +#[cfg(not(target_arch = "wasm32"))] +use std::sync::LazyLock; #[cfg(not(target_arch = "wasm32"))] const GRAPH_BYTES: &[u8] = include_bytes!("../../resources/tree_depth_20/graph.bin"); -lazy_static! { - static ref ARKZKEY: (ProvingKey, ConstraintMatrices) = - read_arkzkey_from_bytes_uncompressed(ARKZKEY_BYTES).expect("Failed to read arkzkey"); -} +#[cfg(not(target_arch = "wasm32"))] +const ARKZKEY_BYTES: &[u8] = include_bytes!("../../resources/tree_depth_20/rln_final.arkzkey"); + +#[cfg(not(target_arch = "wasm32"))] +static ARKZKEY: LazyLock = LazyLock::new(|| { + read_arkzkey_from_bytes_uncompressed(ARKZKEY_BYTES).expect("Failed to read arkzkey") +}); pub const TEST_TREE_DEPTH: usize = 20; @@ -42,10 +44,13 @@ pub type G1Projective = ArkG1Projective; pub type G2Affine = ArkG2Affine; pub type G2Projective = ArkG2Projective; -// Loads the proving key using a bytes vector -pub fn zkey_from_raw( - zkey_data: &[u8], -) -> Result<(ProvingKey, ConstraintMatrices), ZKeyReadError> { +pub type Proof = ArkProof; +pub type ProvingKey = ArkProvingKey; +pub type Zkey = (ArkProvingKey, ConstraintMatrices); +pub type VerifyingKey = ArkVerifyingKey; + +// Loads the zkey using a bytes vector +pub fn zkey_from_raw(zkey_data: &[u8]) -> Result { if zkey_data.is_empty() { return Err(ZKeyReadError::EmptyBytes); } @@ -57,17 +62,11 @@ pub fn zkey_from_raw( // Loads the proving key #[cfg(not(target_arch = "wasm32"))] -pub fn zkey_from_folder() -> &'static (ProvingKey, ConstraintMatrices) { +pub fn zkey_from_folder() -> &'static Zkey { &ARKZKEY } -pub fn calculate_rln_witness)>>( - inputs: I, - graph_data: &[u8], -) -> Vec { - calc_witness(inputs, graph_data) -} - +// Loads the graph data #[cfg(not(target_arch = "wasm32"))] pub fn graph_from_folder() -> &'static [u8] { GRAPH_BYTES @@ -75,33 +74,30 @@ pub fn graph_from_folder() -> &'static [u8] { //////////////////////////////////////////////////////// // Functions and structs from [arkz-key](https://github.com/zkmopro/ark-zkey/blob/main/src/lib.rs#L106) -// without print and allow to choose between compressed and uncompressed arkzkey //////////////////////////////////////////////////////// #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] -pub struct SerializableProvingKey(pub ProvingKey); +struct SerializableProvingKey(ArkProvingKey); #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] -pub struct SerializableConstraintMatrices { - pub num_instance_variables: usize, - pub num_witness_variables: usize, - pub num_constraints: usize, - pub a_num_non_zero: usize, - pub b_num_non_zero: usize, - pub c_num_non_zero: usize, - pub a: SerializableMatrix, - pub b: SerializableMatrix, - pub c: SerializableMatrix, +struct SerializableConstraintMatrices { + num_instance_variables: usize, + num_witness_variables: usize, + num_constraints: usize, + a_num_non_zero: usize, + b_num_non_zero: usize, + c_num_non_zero: usize, + a: SerializableMatrix, + b: SerializableMatrix, + c: SerializableMatrix, } #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] -pub struct SerializableMatrix { +struct SerializableMatrix { pub data: Vec>, } -pub fn read_arkzkey_from_bytes_uncompressed( - arkzkey_data: &[u8], -) -> Result<(ProvingKey, ConstraintMatrices), ZKeyReadError> { +fn read_arkzkey_from_bytes_uncompressed(arkzkey_data: &[u8]) -> Result { if arkzkey_data.is_empty() { return Err(ZKeyReadError::EmptyBytes); } @@ -115,8 +111,8 @@ pub fn read_arkzkey_from_bytes_uncompressed( SerializableConstraintMatrices::deserialize_uncompressed_unchecked(&mut cursor)?; // Get on right form for API - let proving_key: ProvingKey = serialized_proving_key.0; - let constraint_matrices: ConstraintMatrices = ConstraintMatrices { + let proving_key: ProvingKey = serialized_proving_key.0; + let constraint_matrices: ConstraintMatrices = ConstraintMatrices { num_instance_variables: serialized_constraint_matrices.num_instance_variables, num_witness_variables: serialized_constraint_matrices.num_witness_variables, num_constraints: serialized_constraint_matrices.num_constraints, @@ -127,6 +123,7 @@ pub fn read_arkzkey_from_bytes_uncompressed( b: serialized_constraint_matrices.b.data, c: serialized_constraint_matrices.c.data, }; + let zkey = (proving_key, constraint_matrices); - Ok((proving_key, constraint_matrices)) + Ok(zkey) } diff --git a/rln/src/circuit/qap.rs b/rln/src/circuit/qap.rs index 46952a4..499c531 100644 --- a/rln/src/circuit/qap.rs +++ b/rln/src/circuit/qap.rs @@ -18,7 +18,7 @@ use rayon::iter::{ /// coefficients domain. snarkjs instead precomputes the Lagrange form of the powers of tau bases /// in a domain twice as large and the witness map is computed as the odd coefficients of (AB-C) /// in that domain. This serves as HZ when computing the C proof element. -pub struct CircomReduction; +pub(crate) struct CircomReduction; impl R1CSToQAP for CircomReduction { #[allow(clippy::type_complexity)] diff --git a/rln/src/error.rs b/rln/src/error.rs index 7fe2748..cab12a2 100644 --- a/rln/src/error.rs +++ b/rln/src/error.rs @@ -1,5 +1,3 @@ -use crate::circuit::error::ZKeyReadError; -use ark_bn254::Fr; use ark_relations::r1cs::SynthesisError; use ark_serialize::SerializationError; use num_bigint::{BigInt, ParseBigIntError}; @@ -9,6 +7,8 @@ use std::string::FromUtf8Error; use thiserror::Error; use utils::error::{FromConfigError, ZerokitMerkleTreeError}; +use crate::circuit::{error::ZKeyReadError, Fr}; + #[derive(Debug, thiserror::Error)] pub enum ConversionError { #[error("Expected radix 10 or 16")] diff --git a/rln/src/ffi/ffi_rln.rs b/rln/src/ffi/ffi_rln.rs index 2fbeb18..0899527 100644 --- a/rln/src/ffi/ffi_rln.rs +++ b/rln/src/ffi/ffi_rln.rs @@ -2,16 +2,13 @@ use super::ffi_utils::{CBoolResult, CFr, CResult}; use crate::{ - circuit::{graph_from_folder, zkey_from_folder, zkey_from_raw, Curve}, + circuit::{graph_from_folder, zkey_from_folder, zkey_from_raw, Fr, Proof}, protocol::{ compute_id_secret, generate_proof, proof_values_from_witness, verify_proof, RLNProofValues, - RLNWitnessInput, + RLNWitnessInput, RLN, }, utils::IdSecret, }; -use ark_bn254::Fr; -use ark_groth16::{Proof as ArkProof, ProvingKey}; -use ark_relations::r1cs::ConstraintMatrices; use safer_ffi::{boxed::Box_, derive_ReprC, ffi_export, prelude::repr_c}; #[cfg(not(feature = "stateless"))] @@ -26,13 +23,7 @@ use { #[derive_ReprC] #[repr(opaque)] -pub struct FFI_RLN { - pub(crate) proving_key: (ProvingKey, ConstraintMatrices), - #[cfg(not(target_arch = "wasm32"))] - pub(crate) graph_data: Vec, - #[cfg(not(feature = "stateless"))] - pub(crate) tree: PoseidonTree, -} +pub struct FFI_RLN(pub(crate) RLN); // RLN initialization APIs @@ -61,7 +52,7 @@ pub fn ffi_rln_new( _ => ::Config::default(), }; - let proving_key = zkey_from_folder().to_owned(); + let zkey = zkey_from_folder().to_owned(); let graph_data = graph_from_folder().to_owned(); // We compute a default empty tree @@ -79,15 +70,15 @@ pub fn ffi_rln_new( } }; - let rln = FFI_RLN { - proving_key: proving_key.to_owned(), - graph_data: graph_data.to_vec(), + let rln = RLN { + zkey, + graph_data, #[cfg(not(feature = "stateless"))] tree, }; CResult { - ok: Some(Box_::new(rln)), + ok: Some(Box_::new(FFI_RLN(rln))), err: None, } } @@ -95,16 +86,13 @@ pub fn ffi_rln_new( #[cfg(feature = "stateless")] #[ffi_export] pub fn ffi_rln_new() -> CResult, repr_c::String> { - let proving_key = zkey_from_folder().to_owned(); + let zkey = zkey_from_folder().to_owned(); let graph_data = graph_from_folder().to_owned(); - let rln = FFI_RLN { - proving_key: proving_key.to_owned(), - graph_data: graph_data.to_vec(), - }; + let rln = RLN { zkey, graph_data }; CResult { - ok: Some(Box_::new(rln)), + ok: Some(Box_::new(FFI_RLN(rln))), err: None, } } @@ -136,7 +124,7 @@ pub fn ffi_rln_new_with_params( _ => ::Config::default(), }; - let proving_key = match zkey_from_raw(zkey_buffer) { + let zkey = match zkey_from_raw(zkey_buffer) { Ok(pk) => pk, Err(err) => { return CResult { @@ -145,6 +133,7 @@ pub fn ffi_rln_new_with_params( }; } }; + let graph_data = graph_data.to_vec(); // We compute a default empty tree let tree = match PoseidonTree::new( @@ -161,15 +150,15 @@ pub fn ffi_rln_new_with_params( } }; - let rln = FFI_RLN { - proving_key, - graph_data: graph_data.to_vec(), + let rln = RLN { + zkey, + graph_data, #[cfg(not(feature = "stateless"))] tree, }; CResult { - ok: Some(Box_::new(rln)), + ok: Some(Box_::new(FFI_RLN(rln))), err: None, } } @@ -180,7 +169,7 @@ pub fn ffi_new_with_params( zkey_buffer: &repr_c::Vec, graph_data: &repr_c::Vec, ) -> CResult, repr_c::String> { - let proving_key = match zkey_from_raw(zkey_buffer) { + let zkey = match zkey_from_raw(zkey_buffer) { Ok(pk) => pk, Err(err) => { return CResult { @@ -189,14 +178,12 @@ pub fn ffi_new_with_params( }; } }; + let graph_data = graph_data.to_vec(); - let rln = FFI_RLN { - proving_key, - graph_data: graph_data.to_vec(), - }; + let rln = RLN { zkey, graph_data }; CResult { - ok: Some(Box_::new(rln)), + ok: Some(Box_::new(FFI_RLN(rln))), err: None, } } @@ -211,8 +198,8 @@ pub fn ffi_rln_free(rln: repr_c::Box) { #[derive_ReprC] #[repr(opaque)] pub struct FFI_RLNProof { - pub(crate) proof: ArkProof, - pub(crate) proof_values: RLNProofValues, + pub proof: Proof, + pub proof_values: RLNProofValues, } #[ffi_export] @@ -233,7 +220,7 @@ pub fn ffi_generate_rln_proof( external_nullifier: &CFr, leaf_index: usize, ) -> CResult, repr_c::String> { - let proof = match rln.tree.proof(leaf_index) { + let proof = match rln.0.tree.proof(leaf_index) { Ok(proof) => proof, Err(err) => { return CResult { @@ -275,7 +262,7 @@ pub fn ffi_generate_rln_proof( } }; - let proof = match generate_proof(&rln.proving_key, &rln_witness, &rln.graph_data) { + let proof = match generate_proof(&rln.0.zkey, &rln_witness, &rln.0.graph_data) { Ok(proof) => proof, Err(err) => { return CResult { @@ -337,7 +324,7 @@ pub fn ffi_generate_rln_proof_stateless( } }; - let proof = match generate_proof(&rln.proving_key, &rln_witness, &rln.graph_data) { + let proof = match generate_proof(&rln.0.zkey, &rln_witness, &rln.0.graph_data) { Ok(proof) => proof, Err(err) => { return CResult { @@ -366,7 +353,7 @@ pub fn ffi_verify_rln_proof( x: &CFr, ) -> CBoolResult { // Verify the root - if rln.tree.root() != proof.proof_values.root { + if rln.0.tree.root() != proof.proof_values.root { return CBoolResult { ok: false, err: Some("Invalid root".to_string().into()), @@ -382,7 +369,7 @@ pub fn ffi_verify_rln_proof( } // Verify the proof - match verify_proof(&rln.proving_key.0.vk, &proof.proof, &proof.proof_values) { + match verify_proof(&rln.0.zkey.0.vk, &proof.proof, &proof.proof_values) { Ok(proof_verified) => { if !proof_verified { return CBoolResult { @@ -430,7 +417,7 @@ pub fn ffi_verify_with_roots( } // Verify the proof - match verify_proof(&rln.proving_key.0.vk, &proof.proof, &proof.proof_values) { + match verify_proof(&rln.0.zkey.0.vk, &proof.proof, &proof.proof_values) { Ok(proof_verified) => { if !proof_verified { return CBoolResult { diff --git a/rln/src/ffi/ffi_tree.rs b/rln/src/ffi/ffi_tree.rs index 2dc81ae..3cb84d0 100644 --- a/rln/src/ffi/ffi_tree.rs +++ b/rln/src/ffi/ffi_tree.rs @@ -30,7 +30,7 @@ pub fn ffi_set_tree(rln: &mut repr_c::Box, tree_depth: usize) -> CBoolR // We compute a default empty tree of desired depth match PoseidonTree::default(tree_depth) { Ok(tree) => { - rln.tree = tree; + rln.0.tree = tree; CBoolResult { ok: true, err: None, @@ -47,7 +47,7 @@ pub fn ffi_set_tree(rln: &mut repr_c::Box, tree_depth: usize) -> CBoolR #[ffi_export] pub fn ffi_delete_leaf(rln: &mut repr_c::Box, index: usize) -> CBoolResult { - match rln.tree.delete(index) { + match rln.0.tree.delete(index) { Ok(_) => CBoolResult { ok: true, err: None, @@ -65,7 +65,7 @@ pub fn ffi_set_leaf( index: usize, leaf: &repr_c::Box, ) -> CBoolResult { - match rln.tree.set(index, leaf.0) { + match rln.0.tree.set(index, leaf.0) { Ok(_) => CBoolResult { ok: true, err: None, @@ -82,7 +82,7 @@ pub fn ffi_get_leaf( rln: &repr_c::Box, index: usize, ) -> CResult, repr_c::String> { - match rln.tree.get(index) { + match rln.0.tree.get(index) { Ok(leaf) => CResult { ok: Some(CFr::from(leaf).into()), err: None, @@ -96,12 +96,12 @@ pub fn ffi_get_leaf( #[ffi_export] pub fn ffi_leaves_set(rln: &repr_c::Box) -> usize { - rln.tree.leaves_set() + rln.0.tree.leaves_set() } #[ffi_export] pub fn ffi_set_next_leaf(rln: &mut repr_c::Box, leaf: &repr_c::Box) -> CBoolResult { - match rln.tree.update_next(leaf.0) { + match rln.0.tree.update_next(leaf.0) { Ok(_) => CBoolResult { ok: true, err: None, @@ -120,6 +120,7 @@ pub fn ffi_set_leaves_from( leaves: &repr_c::Vec, ) -> CBoolResult { match rln + .0 .tree .override_range(index, leaves.iter().map(|cfr| cfr.0), [].into_iter()) { @@ -140,7 +141,7 @@ pub fn ffi_init_tree_with_leaves( leaves: &repr_c::Vec, ) -> CBoolResult { // Reset tree to default - let tree_depth = rln.tree.depth(); + let tree_depth = rln.0.tree.depth(); if let Err(err) = PoseidonTree::default(tree_depth) { return CBoolResult { ok: false, @@ -149,6 +150,7 @@ pub fn ffi_init_tree_with_leaves( }; match rln + .0 .tree .override_range(0, leaves.iter().map(|cfr| cfr.0), [].into_iter()) { @@ -172,7 +174,7 @@ pub fn ffi_atomic_operation( leaves: &repr_c::Vec, indices: &repr_c::Vec, ) -> CBoolResult { - match rln.tree.override_range( + match rln.0.tree.override_range( index, leaves.iter().map(|cfr| cfr.0), indices.iter().copied(), @@ -194,8 +196,8 @@ pub fn ffi_seq_atomic_operation( leaves: &repr_c::Vec, indices: &repr_c::Vec, ) -> CBoolResult { - let index = rln.tree.leaves_set(); - match rln.tree.override_range( + let index = rln.0.tree.leaves_set(); + match rln.0.tree.override_range( index, leaves.iter().map(|cfr| cfr.0), indices.iter().map(|x| *x as usize), @@ -215,7 +217,7 @@ pub fn ffi_seq_atomic_operation( #[ffi_export] pub fn ffi_get_root(rln: &repr_c::Box) -> repr_c::Box { - CFr::from(rln.tree.root()).into() + CFr::from(rln.0.tree.root()).into() } #[ffi_export] @@ -223,7 +225,7 @@ pub fn ffi_get_proof( rln: &repr_c::Box, index: usize, ) -> CResult, repr_c::String> { - match rln.tree.proof(index) { + match rln.0.tree.proof(index) { Ok(proof) => { let path_elements: repr_c::Vec = proof .get_path_elements() @@ -255,7 +257,7 @@ pub fn ffi_get_proof( #[ffi_export] pub fn ffi_set_metadata(rln: &mut repr_c::Box, metadata: &repr_c::Vec) -> CBoolResult { - match rln.tree.set_metadata(metadata) { + match rln.0.tree.set_metadata(metadata) { Ok(_) => CBoolResult { ok: true, err: None, @@ -269,7 +271,7 @@ pub fn ffi_set_metadata(rln: &mut repr_c::Box, metadata: &repr_c::Vec) -> CResult, repr_c::String> { - match rln.tree.metadata() { + match rln.0.tree.metadata() { Ok(metadata) => CResult { ok: Some(metadata.into()), err: None, @@ -283,7 +285,7 @@ pub fn ffi_get_metadata(rln: &repr_c::Box) -> CResult, #[ffi_export] pub fn ffi_flush(rln: &mut repr_c::Box) -> CBoolResult { - match rln.tree.close_db_connection() { + match rln.0.tree.close_db_connection() { Ok(_) => CBoolResult { ok: true, err: None, diff --git a/rln/src/ffi/ffi_utils.rs b/rln/src/ffi/ffi_utils.rs index 35d6727..54140cf 100644 --- a/rln/src/ffi/ffi_utils.rs +++ b/rln/src/ffi/ffi_utils.rs @@ -6,8 +6,8 @@ use crate::{ protocol::{extended_keygen, extended_seeded_keygen, keygen, seeded_keygen}, utils::{bytes_be_to_fr, bytes_le_to_fr, fr_to_bytes_be, fr_to_bytes_le}, }; -use safer_ffi::prelude::ReprC; -use safer_ffi::{boxed::Box_, derive_ReprC, ffi_export, prelude::repr_c}; +use safer_ffi::{boxed::Box_, prelude::ReprC}; +use safer_ffi::{derive_ReprC, ffi_export, prelude::repr_c}; use std::ops::Deref; // CResult @@ -56,7 +56,7 @@ impl From for repr_c::Box { impl From<&CFr> for repr_c::Box { fn from(cfr: &CFr) -> Self { - Box_::new(CFr(cfr.0)) + CFr(cfr.0).into() } } @@ -68,12 +68,12 @@ impl PartialEq for CFr { #[ffi_export] pub fn cfr_zero() -> repr_c::Box { - Box_::new(CFr::from(Fr::from(0))) + CFr::from(Fr::from(0)).into() } #[ffi_export] pub fn cfr_one() -> repr_c::Box { - Box_::new(CFr::from(Fr::from(1))) + CFr::from(Fr::from(1)).into() } #[ffi_export] @@ -89,18 +89,18 @@ pub fn cfr_to_bytes_be(cfr: &CFr) -> repr_c::Vec { #[ffi_export] pub fn bytes_le_to_cfr(bytes: &repr_c::Vec) -> repr_c::Box { let (cfr, _) = bytes_le_to_fr(bytes); - Box_::new(CFr(cfr)) + CFr(cfr).into() } #[ffi_export] pub fn bytes_be_to_cfr(bytes: &repr_c::Vec) -> repr_c::Box { let (cfr, _) = bytes_be_to_fr(bytes); - Box_::new(CFr(cfr)) + CFr(cfr).into() } #[ffi_export] pub fn uint_to_cfr(value: u32) -> repr_c::Box { - Box_::new(CFr::from(Fr::from(value))) + CFr::from(Fr::from(value)).into() } #[ffi_export] diff --git a/rln/src/hashers.rs b/rln/src/hashers.rs index 04923a3..3528c43 100644 --- a/rln/src/hashers.rs +++ b/rln/src/hashers.rs @@ -1,4 +1,5 @@ -/// This crate instantiates the Poseidon hash algorithm. +// This crate instantiates the Poseidon hash algorithm. + use crate::{ circuit::Fr, utils::{bytes_be_to_fr, bytes_le_to_fr}, diff --git a/rln/src/lib.rs b/rln/src/lib.rs index b7bfd39..f5efa0f 100644 --- a/rln/src/lib.rs +++ b/rln/src/lib.rs @@ -2,9 +2,7 @@ pub mod circuit; pub mod error; pub mod ffi; pub mod hashers; -#[cfg(feature = "pmtree-ft")] pub mod pm_tree_adapter; -#[cfg(not(feature = "stateless"))] pub mod poseidon_tree; pub mod protocol; pub mod public; diff --git a/rln/src/pm_tree_adapter.rs b/rln/src/pm_tree_adapter.rs index d3b6957..cbfe582 100644 --- a/rln/src/pm_tree_adapter.rs +++ b/rln/src/pm_tree_adapter.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "pmtree-ft")] + use serde_json::Value; use std::fmt::Debug; use std::path::PathBuf; diff --git a/rln/src/protocol.rs b/rln/src/protocol.rs index 724cf37..65a3667 100644 --- a/rln/src/protocol.rs +++ b/rln/src/protocol.rs @@ -7,29 +7,37 @@ use { utils::{ZerokitMerkleProof, ZerokitMerkleTree}, }; -use crate::circuit::{calculate_rln_witness, qap::CircomReduction, Curve}; +use crate::circuit::{ + iden3calc::calc_witness, qap::CircomReduction, Curve, Fr, Proof, VerifyingKey, Zkey, +}; use crate::error::{ComputeIdSecretError, ProofError, ProtocolError}; -use crate::hashers::{hash_to_field_le, poseidon_hash}; -use crate::public::RLN_IDENTIFIER; +use crate::hashers::poseidon_hash; use crate::utils::{ bytes_be_to_fr, bytes_le_to_fr, bytes_le_to_vec_fr, bytes_le_to_vec_u8, fr_byte_size, fr_to_bytes_le, normalize_usize_le, to_bigint, vec_fr_to_bytes_le, vec_u8_to_bytes_le, FrOrSecret, IdSecret, }; -use ark_bn254::{Fr, FrConfig}; -use ark_ff::{AdditiveGroup, Fp, MontBackend}; -use ark_groth16::{prepare_verifying_key, Groth16, Proof as ArkProof, ProvingKey, VerifyingKey}; -use ark_relations::r1cs::ConstraintMatrices; +use ark_ff::AdditiveGroup; +use ark_groth16::{prepare_verifying_key, Groth16}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::{rand::thread_rng, UniformRand}; use num_bigint::BigInt; -use rand::{Rng, SeedableRng}; +use rand::SeedableRng; use rand_chacha::ChaCha20Rng; use serde::{Deserialize, Serialize}; #[cfg(test)] use std::time::Instant; use tiny_keccak::{Hasher as _, Keccak}; use zeroize::Zeroize; + +pub struct RLN { + pub zkey: Zkey, + #[cfg(not(target_arch = "wasm32"))] + pub graph_data: Vec, + #[cfg(not(feature = "stateless"))] + pub tree: PoseidonTree, +} + /////////////////////////////////////////////////////// // RLN Witness data structure and utility functions /////////////////////////////////////////////////////// @@ -61,8 +69,23 @@ impl RLNWitnessInput { x: Fr, external_nullifier: Fr, ) -> Result { - merkle_proof_len_check(&path_elements, &identity_path_index)?; - message_id_range_check(&message_id, &user_message_limit)?; + // Message ID range check + if message_id > user_message_limit { + return Err(ProtocolError::InvalidMessageId( + message_id, + user_message_limit, + )); + } + + // Merkle proof length check + let path_elements_len = path_elements.len(); + let identity_path_index_len = identity_path_index.len(); + if path_elements_len != identity_path_index_len { + return Err(ProtocolError::InvalidMerkleProofLength( + path_elements_len, + identity_path_index_len, + )); + } Ok(Self { identity_secret, @@ -162,9 +185,6 @@ pub fn deserialize_identity_tuple_be(serialized: Vec) -> (Fr, Fr, Fr, Fr) { /// Returns an error if `rln_witness.message_id` is not within `rln_witness.user_message_limit`. /// input data is [ identity_secret<32> | user_message_limit<32> | message_id<32> | path_elements<32> | identity_path_index<8> | x<32> | external_nullifier<32> ] pub fn serialize_witness(rln_witness: &RLNWitnessInput) -> Result, ProtocolError> { - // Check if message_id is within user_message_limit - message_id_range_check(&rln_witness.message_id, &rln_witness.user_message_limit)?; - // Calculate capacity for Vec: // - 5 fixed field elements: identity_secret, user_message_limit, message_id, x, external_nullifier // - variable number of path elements @@ -201,8 +221,6 @@ pub fn deserialize_witness(serialized: &[u8]) -> Result<(RLNWitnessInput, usize) let (message_id, read) = bytes_le_to_fr(&serialized[all_read..]); all_read += read; - message_id_range_check(&message_id, &user_message_limit)?; - let (path_elements, read) = bytes_le_to_vec_fr(&serialized[all_read..])?; all_read += read; @@ -220,15 +238,15 @@ pub fn deserialize_witness(serialized: &[u8]) -> Result<(RLNWitnessInput, usize) } Ok(( - RLNWitnessInput { + RLNWitnessInput::new( identity_secret, + user_message_limit, + message_id, path_elements, identity_path_index, x, external_nullifier, - user_message_limit, - message_id, - }, + )?, all_read, )) } @@ -242,6 +260,8 @@ pub fn proof_inputs_to_rln_witness( tree: &mut PoseidonTree, serialized: &[u8], ) -> Result<(RLNWitnessInput, usize), ProtocolError> { + use crate::hashers::hash_to_field_le; + let mut all_read: usize = 0; let (identity_secret, read) = IdSecret::from_bytes_le(&serialized[all_read..]); @@ -281,81 +301,22 @@ pub fn proof_inputs_to_rln_witness( let x = hash_to_field_le(&signal); Ok(( - RLNWitnessInput { + RLNWitnessInput::new( identity_secret, - path_elements, - identity_path_index, user_message_limit, message_id, + path_elements, + identity_path_index, x, external_nullifier, - }, + )?, all_read, )) } -/// Creates [`RLNWitnessInput`] from it's fields. -/// -/// # Errors -/// -/// Returns an error if `message_id` is not within `user_message_limit`. -pub fn rln_witness_from_values( - identity_secret: IdSecret, - path_elements: Vec, 4>>, - identity_path_index: Vec, - x: Fr, - external_nullifier: Fr, - user_message_limit: Fr, - message_id: Fr, -) -> Result { - message_id_range_check(&message_id, &user_message_limit)?; - - Ok(RLNWitnessInput { - identity_secret, - path_elements, - identity_path_index, - x, - external_nullifier, - user_message_limit, - message_id, - }) -} - -pub fn random_rln_witness(tree_depth: usize) -> RLNWitnessInput { - let mut rng = thread_rng(); - - let identity_secret = IdSecret::rand(&mut rng); - let x = hash_to_field_le(&rng.gen::<[u8; 32]>()); - let epoch = hash_to_field_le(&rng.gen::<[u8; 32]>()); - let rln_identifier = hash_to_field_le(RLN_IDENTIFIER); - - let mut path_elements: Vec = Vec::new(); - let mut identity_path_index: Vec = Vec::new(); - - for _ in 0..tree_depth { - path_elements.push(hash_to_field_le(&rng.gen::<[u8; 32]>())); - identity_path_index.push(rng.gen_range(0..2) as u8); - } - - let user_message_limit = Fr::from(100); - let message_id = Fr::from(1); - - RLNWitnessInput { - identity_secret, - path_elements, - identity_path_index, - x, - external_nullifier: poseidon_hash(&[epoch, rln_identifier]), - user_message_limit, - message_id, - } -} - pub fn proof_values_from_witness( rln_witness: &RLNWitnessInput, ) -> Result { - message_id_range_check(&rln_witness.message_id, &rln_witness.user_message_limit)?; - // y share let a_0 = &rln_witness.identity_secret; let mut to_hash = [ @@ -638,14 +599,14 @@ fn calculate_witness_element( } pub fn generate_proof_with_witness( - witness: Vec, - proving_key: &(ProvingKey, ConstraintMatrices), -) -> Result, ProofError> { + calculated_witness: Vec, + zkey: &Zkey, +) -> Result { // If in debug mode, we measure and later print time take to compute witness #[cfg(test)] let now = Instant::now(); - let full_assignment = calculate_witness_element::(witness)?; + let full_assignment = calculate_witness_element::(calculated_witness)?; #[cfg(test)] println!("witness generation took: {:.2?}", now.elapsed()); @@ -660,12 +621,12 @@ pub fn generate_proof_with_witness( let now = Instant::now(); let proof = Groth16::<_, CircomReduction>::create_proof_with_reduction_and_matrices( - &proving_key.0, + &zkey.0, r, s, - &proving_key.1, - proving_key.1.num_instance_variables, - proving_key.1.num_constraints, + &zkey.1, + zkey.1.num_instance_variables, + zkey.1.num_constraints, full_assignment.as_slice(), )?; @@ -683,8 +644,6 @@ pub fn generate_proof_with_witness( pub fn inputs_for_witness_calculation( rln_witness: &RLNWitnessInput, ) -> Result<[(&str, Vec); 7], ProtocolError> { - message_id_range_check(&rln_witness.message_id, &rln_witness.user_message_limit)?; - let mut identity_path_index = Vec::with_capacity(rln_witness.identity_path_index.len()); rln_witness .identity_path_index @@ -728,10 +687,10 @@ pub fn inputs_for_witness_calculation( /// /// Returns a [`ProofError`] if proving fails. pub fn generate_proof( - proving_key: &(ProvingKey, ConstraintMatrices), + zkey: &Zkey, rln_witness: &RLNWitnessInput, graph_data: &[u8], -) -> Result, ProofError> { +) -> Result { let inputs = inputs_for_witness_calculation(rln_witness)? .into_iter() .map(|(name, values)| (name.to_string(), values)); @@ -739,7 +698,7 @@ pub fn generate_proof( // If in debug mode, we measure and later print time take to compute witness #[cfg(test)] let now = Instant::now(); - let full_assignment = calculate_rln_witness(inputs, graph_data); + let full_assignment = calc_witness(inputs, graph_data); #[cfg(test)] println!("witness generation took: {:.2?}", now.elapsed()); @@ -753,12 +712,12 @@ pub fn generate_proof( #[cfg(test)] let now = Instant::now(); let proof = Groth16::<_, CircomReduction>::create_proof_with_reduction_and_matrices( - &proving_key.0, + &zkey.0, r, s, - &proving_key.1, - proving_key.1.num_instance_variables, - proving_key.1.num_constraints, + &zkey.1, + zkey.1.num_instance_variables, + zkey.1.num_constraints, full_assignment.as_slice(), )?; @@ -775,8 +734,8 @@ pub fn generate_proof( /// Returns a [`ProofError`] if verifying fails. Verification failure does not /// necessarily mean the proof is incorrect. pub fn verify_proof( - verifying_key: &VerifyingKey, - proof: &ArkProof, + verifying_key: &VerifyingKey, + proof: &Proof, proof_values: &RLNProofValues, ) -> Result { // We re-arrange proof-values according to the circuit specification @@ -790,7 +749,6 @@ pub fn verify_proof( // Check that the proof is valid let pvk = prepare_verifying_key(verifying_key); - //let pr: ArkProof = (*proof).into(); // If in debug mode, we measure and later print time take to verify proof #[cfg(test)] @@ -833,10 +791,7 @@ where pub fn rln_witness_from_json( input_json: serde_json::Value, ) -> Result { - let rln_witness: RLNWitnessInput = serde_json::from_value(input_json).unwrap(); - message_id_range_check(&rln_witness.message_id, &rln_witness.user_message_limit)?; - - Ok(rln_witness) + Ok(serde_json::from_value(input_json)?) } /// Converts a [`RLNWitnessInput`] object to the corresponding JSON serialization. @@ -847,10 +802,7 @@ pub fn rln_witness_from_json( pub fn rln_witness_to_json( rln_witness: &RLNWitnessInput, ) -> Result { - message_id_range_check(&rln_witness.message_id, &rln_witness.user_message_limit)?; - - let rln_witness_json = serde_json::to_value(rln_witness)?; - Ok(rln_witness_json) + Ok(serde_json::to_value(rln_witness)?) } /// Converts a [`RLNWitnessInput`] object to the corresponding JSON serialization. @@ -862,8 +814,6 @@ pub fn rln_witness_to_json( pub fn rln_witness_to_bigint_json( rln_witness: &RLNWitnessInput, ) -> Result { - message_id_range_check(&rln_witness.message_id, &rln_witness.user_message_limit)?; - let mut path_elements = Vec::new(); for v in rln_witness.path_elements.iter() { @@ -888,28 +838,3 @@ pub fn rln_witness_to_bigint_json( Ok(inputs) } - -fn merkle_proof_len_check( - path_elements: &[Fr], - identity_path_index: &[u8], -) -> Result<(), ProtocolError> { - let path_elements_len = path_elements.len(); - let identity_path_index_len = identity_path_index.len(); - if path_elements_len != identity_path_index_len { - return Err(ProtocolError::InvalidMerkleProofLength( - path_elements_len, - identity_path_index_len, - )); - } - Ok(()) -} - -fn message_id_range_check(message_id: &Fr, user_message_limit: &Fr) -> Result<(), ProtocolError> { - if message_id > user_message_limit { - return Err(ProtocolError::InvalidMessageId( - *message_id, - *user_message_limit, - )); - } - Ok(()) -} diff --git a/rln/src/public.rs b/rln/src/public.rs index 51c1e39..dd0b37b 100644 --- a/rln/src/public.rs +++ b/rln/src/public.rs @@ -1,4 +1,4 @@ -use crate::circuit::{zkey_from_raw, Curve, Fr}; +use crate::circuit::{zkey_from_raw, Fr, Proof, VerifyingKey, Zkey}; use crate::hashers::{hash_to_field_be, hash_to_field_le, poseidon_hash as utils_poseidon_hash}; use crate::protocol::{ compute_id_secret, deserialize_proof_values, deserialize_witness, extended_keygen, @@ -35,8 +35,6 @@ use { }; use crate::error::{ConversionError, ProtocolError, RLNError}; -use ark_groth16::{Proof as ArkProof, ProvingKey, VerifyingKey}; -use ark_relations::r1cs::ConstraintMatrices; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, Write}; #[cfg(target_arch = "wasm32")] use num_bigint::BigInt; @@ -86,8 +84,8 @@ impl TreeConfigInput for ::Config { /// /// I/O is mostly done using writers and readers implementing `std::io::Write` and `std::io::Read`, respectively. pub struct RLN { - proving_key: (ProvingKey, ConstraintMatrices), - pub(crate) verification_key: VerifyingKey, + pub(crate) zkey: Zkey, + pub(crate) verifying_key: VerifyingKey, #[cfg(not(target_arch = "wasm32"))] pub(crate) graph_data: Vec, #[cfg(not(feature = "stateless"))] @@ -113,8 +111,8 @@ impl RLN { /// ``` #[cfg(all(not(target_arch = "wasm32"), not(feature = "stateless")))] pub fn new(tree_depth: usize, input_buffer: T) -> Result { - let proving_key = zkey_from_folder().to_owned(); - let verification_key = proving_key.0.vk.to_owned(); + let zkey = zkey_from_folder().to_owned(); + let verifying_key = zkey.0.vk.to_owned(); let graph_data = graph_from_folder().to_owned(); let tree_config = input_buffer.into_tree_config()?; @@ -126,8 +124,8 @@ impl RLN { )?; Ok(RLN { - proving_key, - verification_key, + zkey, + verifying_key, graph_data, #[cfg(not(feature = "stateless"))] tree, @@ -143,13 +141,13 @@ impl RLN { /// ``` #[cfg(all(not(target_arch = "wasm32"), feature = "stateless"))] pub fn new() -> Result { - let proving_key = zkey_from_folder().to_owned(); - let verification_key = proving_key.0.vk.to_owned(); + let zkey = zkey_from_folder().to_owned(); + let verifying_key = zkey.0.vk.to_owned(); let graph_data = graph_from_folder().to_owned(); Ok(RLN { - proving_key, - verification_key, + zkey, + verifying_key, graph_data, }) } @@ -197,8 +195,8 @@ impl RLN { graph_data: Vec, input_buffer: T, ) -> Result { - let proving_key = zkey_from_raw(&zkey_vec)?; - let verification_key = proving_key.0.vk.to_owned(); + let zkey = zkey_from_raw(&zkey_vec)?; + let verifying_key = zkey.0.vk.to_owned(); let tree_config = input_buffer.into_tree_config()?; // We compute a default empty tree @@ -209,8 +207,8 @@ impl RLN { )?; Ok(RLN { - proving_key, - verification_key, + zkey, + verifying_key, graph_data, #[cfg(not(feature = "stateless"))] tree, @@ -247,12 +245,12 @@ impl RLN { /// ``` #[cfg(all(not(target_arch = "wasm32"), feature = "stateless"))] pub fn new_with_params(zkey_vec: Vec, graph_data: Vec) -> Result { - let proving_key = zkey_from_raw(&zkey_vec)?; - let verification_key = proving_key.0.vk.to_owned(); + let zkey = zkey_from_raw(&zkey_vec)?; + let verifying_key = zkey.0.vk.to_owned(); Ok(RLN { - proving_key, - verification_key, + zkey, + verifying_key, graph_data, }) } @@ -278,12 +276,12 @@ impl RLN { /// ``` #[cfg(all(target_arch = "wasm32", feature = "stateless"))] pub fn new_with_params(zkey_vec: Vec) -> Result { - let proving_key = zkey_from_raw(&zkey_vec)?; - let verification_key = proving_key.0.vk.to_owned(); + let zkey = zkey_from_raw(&zkey_vec)?; + let verifying_key = zkey.0.vk.to_owned(); Ok(RLN { - proving_key, - verification_key, + zkey, + verifying_key, }) } @@ -777,7 +775,7 @@ impl RLN { input_data.read_to_end(&mut serialized_witness)?; let (rln_witness, _) = deserialize_witness(&serialized_witness)?; - let proof = generate_proof(&self.proving_key, &rln_witness, &self.graph_data)?; + let proof = generate_proof(&self.zkey, &rln_witness, &self.graph_data)?; // Note: we export a serialization of ark-groth16::Proof not semaphore::Proof proof.serialize_compressed(&mut output_data)?; @@ -827,11 +825,11 @@ impl RLN { // [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] let mut input_byte: Vec = Vec::new(); input_data.read_to_end(&mut input_byte)?; - let proof = ArkProof::deserialize_compressed(&mut Cursor::new(&input_byte[..128]))?; + let proof = Proof::deserialize_compressed(&mut Cursor::new(&input_byte[..128]))?; let (proof_values, _) = deserialize_proof_values(&input_byte[128..]); - let verified = verify_proof(&self.verification_key, &proof, &proof_values)?; + let verified = verify_proof(&self.verifying_key, &proof, &proof_values)?; Ok(verified) } @@ -899,7 +897,7 @@ impl RLN { let (rln_witness, _) = proof_inputs_to_rln_witness(&mut self.tree, &witness_byte)?; let proof_values = proof_values_from_witness(&rln_witness)?; - let proof = generate_proof(&self.proving_key, &rln_witness, &self.graph_data)?; + let proof = generate_proof(&self.zkey, &rln_witness, &self.graph_data)?; // Note: we export a serialization of ark-groth16::Proof not semaphore::Proof // This proof is compressed, i.e. 128 bytes long @@ -923,7 +921,7 @@ impl RLN { let (rln_witness, _) = deserialize_witness(&serialized_witness)?; let proof_values = proof_values_from_witness(&rln_witness)?; - let proof = generate_proof(&self.proving_key, &rln_witness, &self.graph_data)?; + let proof = generate_proof(&self.zkey, &rln_witness, &self.graph_data)?; // Note: we export a serialization of ark-groth16::Proof not semaphore::Proof // This proof is compressed, i.e. 128 bytes long @@ -945,7 +943,7 @@ impl RLN { let (rln_witness, _) = deserialize_witness(&serialized_witness[..])?; let proof_values = proof_values_from_witness(&rln_witness)?; - let proof = generate_proof_with_witness(calculated_witness, &self.proving_key).unwrap(); + let proof = generate_proof_with_witness(calculated_witness, &self.zkey).unwrap(); // Note: we export a serialization of ark-groth16::Proof not semaphore::Proof // This proof is compressed, i.e. 128 bytes long @@ -986,8 +984,7 @@ impl RLN { let mut serialized: Vec = Vec::new(); input_data.read_to_end(&mut serialized)?; let mut all_read = 0; - let proof = - ArkProof::deserialize_compressed(&mut Cursor::new(&serialized[..128].to_vec()))?; + let proof = Proof::deserialize_compressed(&mut Cursor::new(&serialized[..128].to_vec()))?; all_read += 128; let (proof_values, read) = deserialize_proof_values(&serialized[all_read..]); all_read += read; @@ -1002,7 +999,7 @@ impl RLN { let signal: Vec = serialized[all_read..all_read + signal_len].to_vec(); - let verified = verify_proof(&self.verification_key, &proof, &proof_values)?; + let verified = verify_proof(&self.verifying_key, &proof, &proof_values)?; let x = hash_to_field_le(&signal); // Consistency checks to counter proof tampering @@ -1068,8 +1065,7 @@ impl RLN { let mut serialized: Vec = Vec::new(); input_data.read_to_end(&mut serialized)?; let mut all_read = 0; - let proof = - ArkProof::deserialize_compressed(&mut Cursor::new(&serialized[..128].to_vec()))?; + let proof = Proof::deserialize_compressed(&mut Cursor::new(&serialized[..128].to_vec()))?; all_read += 128; let (proof_values, read) = deserialize_proof_values(&serialized[all_read..]); all_read += read; @@ -1084,7 +1080,7 @@ impl RLN { let signal: Vec = serialized[all_read..all_read + signal_len].to_vec(); - let verified = verify_proof(&self.verification_key, &proof, &proof_values)?; + let verified = verify_proof(&self.verifying_key, &proof, &proof_values)?; // First consistency checks to counter proof tampering let x = hash_to_field_le(&signal); diff --git a/rln/src/public_api_tests.rs b/rln/src/public_api_tests.rs index 8088f9c..624417b 100644 --- a/rln/src/public_api_tests.rs +++ b/rln/src/public_api_tests.rs @@ -1,12 +1,18 @@ -use crate::circuit::TEST_TREE_DEPTH; +use crate::circuit::{ + Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective, Proof, TEST_TREE_DEPTH, +}; +use crate::error::ProtocolError; +use crate::hashers::{hash_to_field_le, poseidon_hash}; use crate::protocol::{ - proof_values_from_witness, random_rln_witness, serialize_proof_values, serialize_witness, - verify_proof, RLNProofValues, + proof_values_from_witness, serialize_proof_values, serialize_witness, verify_proof, + RLNProofValues, RLNWitnessInput, }; use crate::public::RLN; -use crate::utils::str_to_fr; -use ark_groth16::Proof as ArkProof; +use crate::public::RLN_IDENTIFIER; +use crate::utils::{str_to_fr, IdSecret}; use ark_serialize::CanonicalDeserialize; +use rand::thread_rng; +use rand::Rng; use serde_json::{json, Value}; use std::io::Cursor; use std::str::FromStr; @@ -14,31 +20,31 @@ use std::str::FromStr; #[cfg(not(feature = "stateless"))] use crate::utils::generate_input_buffer; -fn fq_from_str(s: &str) -> ark_bn254::Fq { - ark_bn254::Fq::from_str(s).unwrap() +fn fq_from_str(s: &str) -> Fq { + Fq::from_str(s).unwrap() } -fn g1_from_str(g1: &[String]) -> ark_bn254::G1Affine { +fn g1_from_str(g1: &[String]) -> G1Affine { let x = fq_from_str(&g1[0]); let y = fq_from_str(&g1[1]); let z = fq_from_str(&g1[2]); - ark_bn254::G1Affine::from(ark_bn254::G1Projective::new(x, y, z)) + G1Affine::from(G1Projective::new(x, y, z)) } -fn g2_from_str(g2: &[Vec]) -> ark_bn254::G2Affine { +fn g2_from_str(g2: &[Vec]) -> G2Affine { let c0 = fq_from_str(&g2[0][0]); let c1 = fq_from_str(&g2[0][1]); - let x = ark_bn254::Fq2::new(c0, c1); + let x = Fq2::new(c0, c1); let c0 = fq_from_str(&g2[1][0]); let c1 = fq_from_str(&g2[1][1]); - let y = ark_bn254::Fq2::new(c0, c1); + let y = Fq2::new(c0, c1); let c0 = fq_from_str(&g2[2][0]); let c1 = fq_from_str(&g2[2][1]); - let z = ark_bn254::Fq2::new(c0, c1); + let z = Fq2::new(c0, c1); - ark_bn254::G2Affine::from(ark_bn254::G2Projective::new(x, y, z)) + G2Affine::from(G2Projective::new(x, y, z)) } fn value_to_string_vec(value: &Value) -> Vec { @@ -50,6 +56,37 @@ fn value_to_string_vec(value: &Value) -> Vec { .collect() } +fn random_rln_witness(tree_depth: usize) -> Result { + let mut rng = thread_rng(); + + let identity_secret = IdSecret::rand(&mut rng); + let x = hash_to_field_le(&rng.gen::<[u8; 32]>()); + let epoch = hash_to_field_le(&rng.gen::<[u8; 32]>()); + let rln_identifier = hash_to_field_le(RLN_IDENTIFIER); + + let mut path_elements: Vec = Vec::new(); + let mut identity_path_index: Vec = Vec::new(); + + for _ in 0..tree_depth { + path_elements.push(hash_to_field_le(&rng.gen::<[u8; 32]>())); + identity_path_index.push(rng.gen_range(0..2) as u8); + } + + let user_message_limit = Fr::from(100); + let message_id = Fr::from(1); + let external_nullifier = poseidon_hash(&[epoch, rln_identifier]); + + RLNWitnessInput::new( + identity_secret, + user_message_limit, + message_id, + path_elements, + identity_path_index, + x, + external_nullifier, + ) +} + #[test] fn test_groth16_proof_hardcoded() { #[cfg(not(feature = "stateless"))] @@ -85,7 +122,7 @@ fn test_groth16_proof_hardcoded() { "protocol": "groth16", "curve": "bn128" }); - let valid_ark_proof = ArkProof { + let valid_ark_proof = Proof { a: g1_from_str(&value_to_string_vec(&valid_snarkjs_proof["pi_a"])), b: g2_from_str( &valid_snarkjs_proof["pi_b"] @@ -126,7 +163,7 @@ fn test_groth16_proof_hardcoded() { .unwrap(), }; - let verified = verify_proof(&rln.verification_key, &valid_ark_proof, &valid_proof_values); + let verified = verify_proof(&rln.verifying_key, &valid_ark_proof, &valid_proof_values); assert!(verified.unwrap()); } @@ -141,7 +178,7 @@ fn test_groth16_proof() { let mut rln = RLN::new().unwrap(); // Note: we only test Groth16 proof generation, so we ignore setting the tree in the RLN object - let rln_witness = random_rln_witness(tree_depth); + let rln_witness = random_rln_witness(tree_depth).unwrap(); let proof_values = proof_values_from_witness(&rln_witness).unwrap(); // We compute a Groth16 proof @@ -151,8 +188,8 @@ fn test_groth16_proof() { let serialized_proof = output_buffer.into_inner(); // Before checking public verify API, we check that the (deserialized) proof generated by prove is actually valid - let proof = ArkProof::deserialize_compressed(&mut Cursor::new(&serialized_proof)).unwrap(); - let verified = verify_proof(&rln.verification_key, &proof, &proof_values); + let proof = Proof::deserialize_compressed(&mut Cursor::new(&serialized_proof)).unwrap(); + let verified = verify_proof(&rln.verifying_key, &proof, &proof_values); // dbg!(verified.unwrap()); assert!(verified.unwrap()); @@ -1082,15 +1119,16 @@ mod stateless_test { let x = hash_to_field_le(&signal); let merkle_proof = tree.proof(identity_index).expect("proof should exist"); + let message_id = Fr::from(1); - let rln_witness = rln_witness_from_values( + let rln_witness = RLNWitnessInput::new( identity_secret_hash, + user_message_limit, + message_id, merkle_proof.get_path_elements(), merkle_proof.get_path_index(), x, external_nullifier, - user_message_limit, - Fr::from(1), ) .unwrap(); @@ -1178,26 +1216,27 @@ mod stateless_test { let identity_index = tree.leaves_set(); let merkle_proof = tree.proof(identity_index).expect("proof should exist"); + let message_id = Fr::from(1); - let rln_witness1 = rln_witness_from_values( + let rln_witness1 = RLNWitnessInput::new( identity_secret_hash.clone(), + user_message_limit, + message_id, merkle_proof.get_path_elements(), merkle_proof.get_path_index(), x1, external_nullifier, - user_message_limit, - Fr::from(1), ) .unwrap(); - let rln_witness2 = rln_witness_from_values( + let rln_witness2 = RLNWitnessInput::new( identity_secret_hash.clone(), + user_message_limit, + message_id, merkle_proof.get_path_elements(), merkle_proof.get_path_index(), x2, external_nullifier, - user_message_limit, - Fr::from(1), ) .unwrap(); @@ -1247,14 +1286,14 @@ mod stateless_test { let identity_index_new = tree.leaves_set(); let merkle_proof_new = tree.proof(identity_index_new).expect("proof should exist"); - let rln_witness3 = rln_witness_from_values( + let rln_witness3 = RLNWitnessInput::new( identity_secret_hash_new.clone(), + user_message_limit, + message_id, merkle_proof_new.get_path_elements(), merkle_proof_new.get_path_index(), x3, external_nullifier, - user_message_limit, - Fr::from(1), ) .unwrap(); diff --git a/rln/src/utils.rs b/rln/src/utils.rs index 333be70..cc8e396 100644 --- a/rln/src/utils.rs +++ b/rln/src/utils.rs @@ -322,7 +322,8 @@ pub fn normalize_usize_le(input: usize) -> [u8; 8] { pub fn normalize_usize_be(input: usize) -> [u8; 8] { let mut bytes = [0u8; 8]; let input_bytes = input.to_be_bytes(); - bytes[..input_bytes.len()].copy_from_slice(&input_bytes); + let offset = 8 - input_bytes.len(); + bytes[offset..].copy_from_slice(&input_bytes); bytes } @@ -334,7 +335,7 @@ pub fn generate_input_buffer() -> Cursor { #[derive( Debug, Zeroize, ZeroizeOnDrop, Clone, PartialEq, CanonicalSerialize, CanonicalDeserialize, )] -pub struct IdSecret(ark_bn254::Fr); +pub struct IdSecret(Fr); impl IdSecret { pub fn rand(rng: &mut R) -> Self { diff --git a/rln/tests/ffi.rs b/rln/tests/ffi.rs index 8214345..f9c2713 100644 --- a/rln/tests/ffi.rs +++ b/rln/tests/ffi.rs @@ -8,7 +8,6 @@ mod test { use rln::hashers::{hash_to_field_le, poseidon_hash as utils_poseidon_hash}; use rln::protocol::*; use rln::utils::*; - use safer_ffi::boxed::Box_; use safer_ffi::prelude::repr_c; use serde_json::json; use std::fs::File; @@ -101,7 +100,7 @@ mod test { // We first add leaves one by one specifying the index for (i, leaf) in leaves.iter().enumerate() { // We prepare the rate_commitment and we set the leaf at provided index - let result = ffi_set_leaf(&mut ffi_rln_instance, i, &Box_::new(CFr::from(*leaf))); + let result = ffi_set_leaf(&mut ffi_rln_instance, i, &CFr::from(*leaf).into()); if !result.ok { panic!("set leaf call failed: {:?}", result.err); } @@ -118,7 +117,7 @@ mod test { // We add leaves one by one using the internal index (new leaves goes in next available position) for leaf in &leaves { - let result = ffi_set_next_leaf(&mut ffi_rln_instance, &Box_::new(CFr::from(*leaf))); + let result = ffi_set_next_leaf(&mut ffi_rln_instance, &CFr::from(*leaf).into()); if !result.ok { panic!("set next leaf call failed: {:?}", result.err); } @@ -224,7 +223,7 @@ mod test { // We add leaves one by one using the internal index (new leaves goes in next available position) for leaf in &leaves { - let result = ffi_set_next_leaf(&mut ffi_rln_instance, &Box_::new(CFr::from(*leaf))); + let result = ffi_set_next_leaf(&mut ffi_rln_instance, &CFr::from(*leaf).into()); if !result.ok { panic!("set next leaf call failed: {:?}", result.err); } @@ -319,7 +318,7 @@ mod test { let result = ffi_set_leaf( &mut ffi_rln_instance, leaf_index, - &Box_::new(CFr::from(rate_commitment)), + &CFr::from(rate_commitment).into(), ); if !result.ok { panic!("set leaf call failed: {:?}", result.err); @@ -487,10 +486,7 @@ mod test { let rate_commitment = utils_poseidon_hash(&[id_commitment, user_message_limit]); // We set as leaf rate_commitment, its index would be equal to no_of_leaves - let result = ffi_set_next_leaf( - &mut ffi_rln_instance, - &Box_::new(CFr::from(rate_commitment)), - ); + let result = ffi_set_next_leaf(&mut ffi_rln_instance, &CFr::from(rate_commitment).into()); if !result.ok { panic!("set next leaf call failed: {:?}", result.err); } @@ -557,10 +553,7 @@ mod test { let message_id = Fr::from(1); // We set as leaf rate_commitment, its index would be equal to no_of_leaves - let result = ffi_set_next_leaf( - &mut ffi_rln_instance, - &Box_::new(CFr::from(rate_commitment)), - ); + let result = ffi_set_next_leaf(&mut ffi_rln_instance, &CFr::from(rate_commitment).into()); if !result.ok { panic!("set next leaf call failed: {:?}", result.err); } @@ -657,10 +650,7 @@ mod test { let rate_commitment = utils_poseidon_hash(&[id_commitment, user_message_limit]); // We set as leaf rate_commitment, its index would be equal to 0 since tree is empty - let result = ffi_set_next_leaf( - &mut ffi_rln_instance, - &Box_::new(CFr::from(rate_commitment)), - ); + let result = ffi_set_next_leaf(&mut ffi_rln_instance, &CFr::from(rate_commitment).into()); if !result.ok { panic!("set next leaf call failed: {:?}", result.err); } @@ -750,7 +740,7 @@ mod test { // We set as leaf id_commitment, its index would be equal to 1 since at 0 there is id_commitment let result = ffi_set_next_leaf( &mut ffi_rln_instance, - &Box_::new(CFr::from(rate_commitment_new)), + &CFr::from(rate_commitment_new).into(), ); if !result.ok { panic!("set next leaf call failed: {:?}", result.err); @@ -833,7 +823,7 @@ mod test { let result = ffi_set_leaf( &mut ffi_rln_instance, index, - &Box_::new(CFr::from(id_commitment)), + &CFr::from(id_commitment).into(), ); if !result.ok { panic!("set leaf call failed: {:?}", result.err); diff --git a/rln/tests/protocol.rs b/rln/tests/protocol.rs index d8f2880..39aebbe 100644 --- a/rln/tests/protocol.rs +++ b/rln/tests/protocol.rs @@ -9,9 +9,8 @@ mod test { use rln::poseidon_tree::PoseidonTree; use rln::protocol::{ deserialize_proof_values, deserialize_witness, generate_proof, keygen, - proof_values_from_witness, rln_witness_from_json, rln_witness_from_values, - rln_witness_to_json, seeded_keygen, serialize_proof_values, serialize_witness, - verify_proof, RLNWitnessInput, + proof_values_from_witness, rln_witness_from_json, rln_witness_to_json, seeded_keygen, + serialize_proof_values, serialize_witness, verify_proof, RLNWitnessInput, }; use rln::utils::str_to_fr; use utils::{ZerokitMerkleProof, ZerokitMerkleTree}; @@ -119,14 +118,16 @@ mod test { let rln_identifier = hash_to_field_le(b"test-rln-identifier"); let external_nullifier = poseidon_hash(&[epoch, rln_identifier]); - rln_witness_from_values( + let message_id = Fr::from(1); + + RLNWitnessInput::new( identity_secret_hash, + user_message_limit, + message_id, merkle_proof.get_path_elements(), merkle_proof.get_path_index(), x, external_nullifier, - user_message_limit, - Fr::from(1), ) .unwrap() } @@ -136,7 +137,7 @@ mod test { fn test_witness_from_json() { // We generate all relevant keys let proving_key = zkey_from_folder(); - let verification_key = &proving_key.0.vk; + let verifying_key = &proving_key.0.vk; let graph_data = graph_from_folder(); // We compute witness from the json input let rln_witness = get_test_witness(); @@ -149,7 +150,7 @@ mod test { let proof_values = proof_values_from_witness(&rln_witness_deser).unwrap(); // Let's verify the proof - let verified = verify_proof(verification_key, &proof, &proof_values); + let verified = verify_proof(verifying_key, &proof, &proof_values); assert!(verified.unwrap()); } @@ -164,7 +165,7 @@ mod test { // We generate all relevant keys let proving_key = zkey_from_folder(); - let verification_key = &proving_key.0.vk; + let verifying_key = &proving_key.0.vk; let graph_data = graph_from_folder(); // Let's generate a zkSNARK proof @@ -173,7 +174,7 @@ mod test { let proof_values = proof_values_from_witness(&rln_witness_deser).unwrap(); // Let's verify the proof - let success = verify_proof(verification_key, &proof, &proof_values).unwrap(); + let success = verify_proof(verifying_key, &proof, &proof_values).unwrap(); assert!(success); } diff --git a/utils/Cargo.toml b/utils/Cargo.toml index cd51fb2..8d3f7e1 100644 --- a/utils/Cargo.toml +++ b/utils/Cargo.toml @@ -17,7 +17,6 @@ num-bigint = { version = "0.4.6", default-features = false } pmtree = { package = "vacp2p_pmtree", version = "2.0.3", optional = true } sled = "0.34.7" serde_json = "1.0.141" -lazy_static = "1.5.0" hex = "0.4.3" rayon = "1.10.0" thiserror = "2.0" diff --git a/utils/benches/merkle_tree_benchmark.rs b/utils/benches/merkle_tree_benchmark.rs index 2680f1d..a954a7b 100644 --- a/utils/benches/merkle_tree_benchmark.rs +++ b/utils/benches/merkle_tree_benchmark.rs @@ -1,7 +1,5 @@ -use std::{fmt::Display, str::FromStr}; - use criterion::{criterion_group, criterion_main, Criterion}; -use lazy_static::lazy_static; +use std::{fmt::Display, str::FromStr, sync::LazyLock}; use tiny_keccak::{Hasher as _, Keccak}; use zerokit_utils::{ FullMerkleConfig, FullMerkleTree, Hasher, OptimalMerkleConfig, OptimalMerkleTree, @@ -46,18 +44,17 @@ impl FromStr for TestFr { } } -lazy_static! { - static ref LEAVES: Vec = { - let mut leaves = Vec::with_capacity(1 << 20); - for i in 0..(1 << 20) { - let mut bytes = [0u8; 32]; - bytes[28..].copy_from_slice(&(i as u32).to_be_bytes()); - leaves.push(TestFr(bytes)); - } - leaves - }; - static ref INDICES: Vec = (0..(1 << 20)).collect(); -} +static LEAVES: LazyLock> = LazyLock::new(|| { + let mut leaves = Vec::with_capacity(1 << 20); + for i in 0..(1 << 20) { + let mut bytes = [0u8; 32]; + bytes[28..].copy_from_slice(&(i as u32).to_be_bytes()); + leaves.push(TestFr(bytes)); + } + leaves +}); + +static INDICES: LazyLock> = LazyLock::new(|| (0..(1 << 20)).collect()); const NOF_LEAVES: usize = 8192;