mirror of
https://github.com/vacp2p/zerokit.git
synced 2026-01-08 21:28:11 -05:00
release v0.8.0 (#315)
This commit is contained in:
committed by
GitHub
parent
36013bf4ba
commit
dc0b31752c
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -1627,7 +1627,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rln"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"ark-bn254",
|
||||
"ark-ec",
|
||||
@@ -1670,7 +1670,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rln-wasm"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"getrandom 0.2.16",
|
||||
@@ -2471,7 +2471,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerokit_utils"
|
||||
version = "0.5.2"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"ark-bn254",
|
||||
"ark-ff 0.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rln-wasm"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
license = "MIT or Apache2"
|
||||
|
||||
@@ -9,7 +9,9 @@ crate-type = ["cdylib", "rlib"]
|
||||
required-features = ["stateless"]
|
||||
|
||||
[dependencies]
|
||||
rln = { path = "../rln", default-features = false }
|
||||
rln = { path = "../rln", version = "0.8.0", default-features = false }
|
||||
zerokit_utils = { path = "../utils", version = "0.6.0" }
|
||||
|
||||
num-bigint = { version = "0.4.6", default-features = false }
|
||||
js-sys = "0.3.77"
|
||||
wasm-bindgen = "0.2.100"
|
||||
@@ -21,7 +23,6 @@ wasm-bindgen-rayon = { version = "1.2.0", optional = true }
|
||||
# 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 }
|
||||
zerokit_utils = { path = "../utils" }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
getrandom = { version = "0.2.16", features = ["js"] }
|
||||
@@ -40,3 +41,6 @@ default = ["console_error_panic_hook"]
|
||||
stateless = ["rln/stateless"]
|
||||
arkzkey = ["rln/arkzkey"]
|
||||
multithread = ["wasm-bindgen-rayon"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
@@ -1,15 +1,22 @@
|
||||
# RLN for WASM
|
||||
|
||||
This library is used in [waku-org/js-rln](https://github.com/waku-org/js-rln/)
|
||||
[](https://badge.fury.io/js/@waku%2Fzerokit-rln-wasm)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
The Zerokit RLN WASM Module provides WebAssembly bindings for working with
|
||||
Rate-Limiting Nullifier [RLN](https://rfc.vac.dev/spec/32/) zkSNARK proofs and primitives.
|
||||
This module is used by [waku-org/js-rln](https://github.com/waku-org/js-rln/) to enable
|
||||
RLN functionality in JavaScript/TypeScript applications.
|
||||
|
||||
## 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)
|
||||
> - `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.
|
||||
|
||||
@@ -29,7 +36,8 @@ 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).
|
||||
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`:
|
||||
|
||||
@@ -39,7 +47,8 @@ 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.
|
||||
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
|
||||
|
||||
@@ -90,7 +99,8 @@ cargo make test_browser_arkzkey
|
||||
|
||||
## Parallel computation
|
||||
|
||||
The library supports parallel computation using the `wasm-bindgen-rayon` crate, enabling multi-threaded execution in the browser.
|
||||
The library supports parallel computation using the `wasm-bindgen-rayon` crate,
|
||||
enabling multi-threaded execution in the browser.
|
||||
|
||||
> [!NOTE]
|
||||
> Parallel support is not enabled by default due to WebAssembly and browser limitations. \
|
||||
@@ -126,7 +136,8 @@ cargo make build_multithread_arkzkey
|
||||
|
||||
### WebAssembly Threading Support
|
||||
|
||||
Most modern browsers support WebAssembly threads, but they require the following headers to enable `SharedArrayBuffer`, which is necessary for multithreading:
|
||||
Most modern browsers support WebAssembly threads,
|
||||
but they require the following headers to enable `SharedArrayBuffer`, which is necessary for multithreading:
|
||||
|
||||
- Cross-Origin-Opener-Policy: same-origin
|
||||
- Cross-Origin-Embedder-Policy: require-corp
|
||||
@@ -135,9 +146,12 @@ 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 - and use feature detection to choose the right one on the JavaScript side.
|
||||
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 -
|
||||
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. For example, your code might look like this:
|
||||
You can use [wasm-feature-detect](https://github.com/GoogleChromeLabs/wasm-feature-detect)library for this purpose.
|
||||
For example, your code might look like this:
|
||||
|
||||
```js
|
||||
import { threads } from 'wasm-feature-detect';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rln"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "APIs to manage, compute and verify zkSNARK proofs and RLN primitives"
|
||||
@@ -53,7 +53,7 @@ rand = "0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
ruint = { version = "1.15.0", features = ["rand", "serde", "ark-ff-04"] }
|
||||
tiny-keccak = { version = "2.0.2", features = ["keccak"] }
|
||||
utils = { package = "zerokit_utils", version = "0.5.2", path = "../utils", default-features = false }
|
||||
utils = { package = "zerokit_utils", version = "0.6.0", path = "../utils", default-features = false }
|
||||
|
||||
# serialization
|
||||
prost = "0.13.5"
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
# Zerokit RLN Module
|
||||
|
||||
[](https://crates.io/crates/rln)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
The Zerokit RLN Module provides a Rust implementation for working with Rate-Limiting Nullifier [RLN](https://rfc.vac.dev/spec/32/) zkSNARK proofs and primitives. This module allows you to:
|
||||
The Zerokit RLN Module provides a Rust implementation for working with
|
||||
Rate-Limiting Nullifier [RLN](https://rfc.vac.dev/spec/32/) zkSNARK proofs and primitives.
|
||||
This module allows you to:
|
||||
|
||||
- Generate and verify RLN proofs
|
||||
- Work with Merkle trees for commitment storage
|
||||
@@ -11,7 +15,8 @@ The Zerokit RLN Module provides a Rust implementation for working with Rate-Limi
|
||||
## Quick Start
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Version 0.6.1 is required for WASM support or x32 architecture. Current version doesn't support these platforms due to dependency issues. WASM support will return in a future release.
|
||||
> Version 0.7.0 is the only version that does not support WASM and x32 architecture.
|
||||
> WASM support is available in version 0.8.0 and above.
|
||||
|
||||
### Add RLN as dependency
|
||||
|
||||
@@ -24,9 +29,16 @@ rln = { git = "https://github.com/vacp2p/zerokit" }
|
||||
|
||||
## Basic Usage Example
|
||||
|
||||
Note that we need to pass to RLN object constructor the path where the graph file (`graph.bin`, built for the input tree size), the corresponding proving key (`rln_final.zkey`) or (`rln_final_uncompr.arkzkey`) and verification key (`verification_key.arkvkey`, optional) are found.
|
||||
The RLN object constructor requires the following files:
|
||||
|
||||
In the following we will use [cursors](https://doc.rust-lang.org/std/io/struct.Cursor.html) as readers/writers for interfacing with RLN public APIs.
|
||||
- `graph.bin`: The graph file built for the input tree size
|
||||
- `rln_final.zkey` or `rln_final_uncompr.arkzkey`: The proving key
|
||||
- `verification_key.arkvkey`: The verification key (optional)
|
||||
|
||||
Additionally, `rln.wasm` is used for testing in the rln-wasm module.
|
||||
|
||||
In the following we will use [cursors](https://doc.rust-lang.org/std/io/struct.Cursor.html)
|
||||
as readers/writers for interfacing with RLN public APIs.
|
||||
|
||||
```rust
|
||||
use std::io::Cursor;
|
||||
@@ -74,7 +86,8 @@ fn main() {
|
||||
let signal = b"RLN is awesome";
|
||||
|
||||
// 6. Prepare input for generate_rln_proof API
|
||||
// input_data is [ identity_secret<32> | id_index<8> | external_nullifier<32> | user_message_limit<32> | message_id<32> | signal_len<8> | signal<var> ]
|
||||
// input_data is [ identity_secret<32> | id_index<8> | external_nullifier<32>
|
||||
// | user_message_limit<32> | message_id<32> | signal_len<8> | signal<var> ]
|
||||
let prove_input = prepare_prove_input(
|
||||
identity_secret_hash,
|
||||
id_index,
|
||||
@@ -92,11 +105,13 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
// We get the public outputs returned by the circuit evaluation
|
||||
// The byte vector `proof_data` is serialized as `[ zk-proof | tree_root | external_nullifier | share_x | share_y | nullifier ]`.
|
||||
// The byte vector `proof_data` is serialized as
|
||||
// `[ zk-proof | tree_root | external_nullifier | share_x | share_y | nullifier ]`.
|
||||
let proof_data = output_buffer.into_inner();
|
||||
|
||||
// 8. Verify a RLN proof
|
||||
// Input buffer is serialized as `[proof_data | signal_len | signal ]`, where `proof_data` is (computed as) the output obtained by `generate_rln_proof`.
|
||||
// Input buffer is serialized as `[proof_data | signal_len | signal ]`,
|
||||
// where `proof_data` is (computed as) the output obtained by `generate_rln_proof`.
|
||||
let verify_data = prepare_verify_input(proof_data, signal);
|
||||
|
||||
// We verify the zk-proof against the provided proof values
|
||||
@@ -113,16 +128,22 @@ fn main() {
|
||||
The `external nullifier` includes two parameters.
|
||||
|
||||
The first one is `epoch` and it's used to identify messages received in a certain time frame.
|
||||
It usually corresponds to the current UNIX time but can also be set to a random value or generated by a seed, provided that it corresponds to a field element.
|
||||
It usually corresponds to the current UNIX time but can also be set to a random value or generated by a seed,
|
||||
provided that it corresponds to a field element.
|
||||
|
||||
The second one is `rln_identifier` and it's used to prevent a RLN ZK proof generated for one application to be re-used in another one.
|
||||
The second one is `rln_identifier` and it's used to prevent a RLN ZK proof generated
|
||||
for one application to be re-used in another one.
|
||||
|
||||
### Features
|
||||
|
||||
- **Multiple Backend Support**: Choose between different zkey formats with feature flags
|
||||
- `arkzkey`: Use the optimized Arkworks-compatible zkey format (faster loading)
|
||||
- `stateless`: For stateless proof verification
|
||||
- **Pre-compiled Circuits**: Ready-to-use circuits with Merkle tree height of 20
|
||||
- **Pre-compiled Circuits**: Ready-to-use circuits with Merkle tree depth of 20
|
||||
- **Wasm Support**: WebAssembly bindings via rln-wasm crate with features like:
|
||||
- Browser and Node.js compatibility
|
||||
- Optional multi-threading support using wasm-bindgen-rayon
|
||||
- Headless browser testing capabilities
|
||||
|
||||
## Building and Testing
|
||||
|
||||
@@ -150,13 +171,16 @@ cargo make test_stateless # For stateless feature
|
||||
|
||||
## Advanced: Custom Circuit Compilation
|
||||
|
||||
The `rln` (<https://github.com/rate-limiting-nullifier/circom-rln>) repository, which contains the RLN circuit implementation is using for pre-compiled RLN circuit for zerokit RLN.
|
||||
The `rln` (<https://github.com/rate-limiting-nullifier/circom-rln>) repository,
|
||||
which contains the RLN circuit implementation is using for pre-compiled RLN circuit for zerokit RLN.
|
||||
If you want to compile your own RLN circuit, you can follow the instructions below.
|
||||
|
||||
### 1. Compile ZK Circuits for getting the zkey and verification key files
|
||||
|
||||
This script actually generates not only the zkey and verification key files for the RLN circuit, but also the execution wasm file used for witness calculation.
|
||||
However, the wasm file is not needed for the `rln` module, because current implementation uses the iden3 graph file for witness calculation.
|
||||
This script actually generates not only the zkey and verification key files for the RLN circuit,
|
||||
but also the execution wasm file used for witness calculation.
|
||||
However, the wasm file is not needed for the `rln` module,
|
||||
because current implementation uses the iden3 graph file for witness calculation.
|
||||
This graph file is generated by the `circom-witnesscalc` tool in [step 2](#2-generate-witness-calculation-graph).
|
||||
|
||||
To customize the circuit parameters, modify `circom-rln/circuits/rln.circom`:
|
||||
@@ -169,19 +193,27 @@ component main { public [x, externalNullifier] } = RLN(N, M);
|
||||
|
||||
Where:
|
||||
|
||||
- `N`: Merkle tree height, determining the maximum membership capacity (2^N members).
|
||||
- `N`: Merkle tree depth, determining the maximum membership capacity (2^N members).
|
||||
|
||||
- `M`: Bit size for range checks, setting an upper bound for the number of messages per epoch (2^M messages).
|
||||
|
||||
> [!NOTE]
|
||||
> However, if `N` is too big, this might require a larger Powers of Tau ceremony than the one hardcoded in `./scripts/build-circuits.sh`, which is `2^14`. \
|
||||
> In such case, we refer to the official [Circom documentation](https://docs.circom.io/getting-started/proving-circuits/#powers-of-tau) for instructions on how to run an appropriate Powers of Tau ceremony and Phase 2 in order to compile the desired circuit. \
|
||||
> Additionally, while `M` sets an upper bound on the number of messages per epoch (`2^M`), you can configure lower message limit for your use case, as long as it satisfies `user_message_limit ≤ 2^M`. \
|
||||
> Currently, the `rln` module comes with a [pre-compiled](https://github.com/vacp2p/zerokit/tree/master/rln/resources) RLN circuit with a Merkle tree of height `20` and a bit size of `16`, allowing up to `2^20` registered members and a `2^16` message limit per epoch.
|
||||
> However, if `N` is too big, this might require a larger Powers of Tau ceremony
|
||||
> than the one hardcoded in `./scripts/build-circuits.sh`, which is `2^14`.
|
||||
> In such case, we refer to the official
|
||||
> [Circom documentation](https://docs.circom.io/getting-started/proving-circuits/#powers-of-tau)
|
||||
> for instructions on how to run an appropriate Powers of Tau ceremony and Phase 2 in order to compile the desired circuit. \
|
||||
> Additionally, while `M` sets an upper bound on the number of messages per epoch (`2^M`),
|
||||
> you can configure lower message limit for your use case, as long as it satisfies `user_message_limit ≤ 2^M`. \
|
||||
> Currently, the `rln` module comes with a [pre-compiled](https://github.com/vacp2p/zerokit/tree/master/rln/resources)
|
||||
> RLN circuit with a Merkle tree of depth `20` and a bit size of `16`,
|
||||
> allowing up to `2^20` registered members and a `2^16` message limit per epoch.
|
||||
|
||||
#### Install circom compiler
|
||||
|
||||
You can follow the instructions below or refer to the [installing Circom](https://docs.circom.io/getting-started/installation/#installing-circom) guide for more details, but make sure to use the specific version `v2.1.0`.
|
||||
You can follow the instructions below or refer to the
|
||||
[installing Circom](https://docs.circom.io/getting-started/installation/#installing-circom) guide for more details,
|
||||
but make sure to use the specific version `v2.1.0`.
|
||||
|
||||
```sh
|
||||
# Clone the circom repository
|
||||
@@ -218,7 +250,8 @@ cp zkeyFiles/rln/final.zkey <path_to_rln_final.zkey>
|
||||
|
||||
### 2. Generate Witness Calculation Graph
|
||||
|
||||
The execution graph file used for witness calculation can be compiled following instructions in the [circom-witnesscalc](https://github.com/iden3/circom-witnesscalc) repository.
|
||||
The execution graph file used for witness calculation can be compiled following instructions
|
||||
in the [circom-witnesscalc](https://github.com/iden3/circom-witnesscalc) repository.
|
||||
As mentioned in step 1, we should use `rln.circom` file from `circom-rln` repository.
|
||||
|
||||
```sh
|
||||
@@ -235,11 +268,14 @@ cargo build
|
||||
cargo run --package circom_witnesscalc --bin build-circuit ../circom-rln/circuits/rln.circom <path_to_graph.bin>
|
||||
```
|
||||
|
||||
The `rln` module comes with [pre-compiled](https://github.com/vacp2p/zerokit/tree/master/rln/resources) execution graph files for the RLN circuit.
|
||||
The `rln` module comes with [pre-compiled](https://github.com/vacp2p/zerokit/tree/master/rln/resources)
|
||||
execution graph files for the RLN circuit.
|
||||
|
||||
### 3. Generate Arkzkey Representation for zkey and verification key files
|
||||
|
||||
For faster loading, compile the zkey file into the arkzkey format using [ark-zkey](https://github.com/seemenkina/ark-zkey). This is fork of the [original](https://github.com/zkmopro/ark-zkey) repository with the uncompressed zkey support.
|
||||
For faster loading, compile the zkey file into the arkzkey format using
|
||||
[ark-zkey](https://github.com/seemenkina/ark-zkey).
|
||||
This is fork of the [original](https://github.com/zkmopro/ark-zkey) repository with the uncompressed zkey support.
|
||||
|
||||
```sh
|
||||
# Clone the ark-zkey repository
|
||||
@@ -252,7 +288,8 @@ cd ark-zkey && cargo build
|
||||
cargo run --bin arkzkey-util <path_to_rln_final.zkey>
|
||||
```
|
||||
|
||||
Currently, the `rln` module comes with [pre-compiled](https://github.com/vacp2p/zerokit/tree/master/rln/resources) arkzkey keys for the RLN circuit.
|
||||
Currently, the `rln` module comes with
|
||||
[pre-compiled](https://github.com/vacp2p/zerokit/tree/master/rln/resources) arkzkey keys for the RLN circuit.
|
||||
|
||||
## Get involved
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ pub fn deserialize_identity_tuple(serialized: Vec<u8>) -> (Fr, Fr, Fr, Fr) {
|
||||
/// # Errors
|
||||
///
|
||||
/// 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> ]
|
||||
/// 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<Vec<u8>, ProtocolError> {
|
||||
// Check if message_id is within user_message_limit
|
||||
message_id_range_check(&rln_witness.message_id, &rln_witness.user_message_limit)?;
|
||||
|
||||
@@ -117,7 +117,6 @@ impl RLN {
|
||||
/// // We create a new RLN instance
|
||||
/// let mut rln = RLN::new();
|
||||
/// ```
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "stateless")))]
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "stateless"))]
|
||||
pub fn new() -> Result<RLN, RLNError> {
|
||||
let proving_key = zkey_from_folder().to_owned();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "zerokit_utils"
|
||||
version = "0.5.2"
|
||||
version = "0.6.0"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Various utilities for Zerokit"
|
||||
@@ -42,3 +42,6 @@ harness = false
|
||||
[[bench]]
|
||||
name = "poseidon_benchmark"
|
||||
harness = false
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
@@ -1,42 +1,45 @@
|
||||
# Zerokit Utils Crate
|
||||
|
||||
[](https://crates.io/crates/zerokit_utils)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
Cryptographic primitives for zero-knowledge applications, featuring efficient Merkle tree implementations and a Poseidon hash function.
|
||||
**Zerokit Utils** provides essential cryptographic primitives optimized for zero-knowledge applications.
|
||||
This crate features efficient Merkle tree implementations and a Poseidon hash function,
|
||||
designed to be robust and performant.
|
||||
|
||||
## Overview
|
||||
|
||||
This crate provides core cryptographic components optimized for zero-knowledge proof systems:
|
||||
|
||||
1. Multiple Merkle tree implementations with different space/time tradeoffs
|
||||
2. A Poseidon hash implementation
|
||||
- **Multiple Merkle Trees**: Various implementations optimised for the trade-off between space and time.
|
||||
- **Poseidon Hash Function**: An efficient hashing algorithm suitable for ZK contexts, with customizable parameters.
|
||||
- **Parallel Performance**: Leverages Rayon for significant speed-ups in Merkle tree computations.
|
||||
- **Arkworks Compatibility**: Poseidon hash implementation is designed to work seamlessly
|
||||
with Arkworks field traits and data structures.
|
||||
|
||||
## Merkle Tree Implementations
|
||||
|
||||
The crate supports two interchangeable Merkle tree implementations:
|
||||
Merkle trees are fundamental data structures for verifying data integrity and set membership.
|
||||
Zerokit Utils offers two interchangeable implementations:
|
||||
|
||||
- **FullMerkleTree**
|
||||
- Stores each tree node in memory
|
||||
- **OptimalMerkleTree**
|
||||
- Only stores nodes used to prove accumulation of set leaves
|
||||
### Understanding Merkle Tree Terminology
|
||||
|
||||
Both OptimalMerkleTree and FullMerkleTree use [Rayon](https://crates.io/crates/rayon) internally to speed up computation through data parallelism. This provides significant performance improvements, especially during large Merkle tree updates.
|
||||
To better understand the structure and parameters of our Merkle trees, here's a quick glossary:
|
||||
|
||||
### Implementation notes
|
||||
- **Depth (`depth`)**: level of leaves if we count from root.
|
||||
If the root is at level 0, leaves are at level `depth`.
|
||||
- **Number of Levels**: `depth + 1`.
|
||||
- **Capacity (Number of Leaves)**: $2^{\text{depth}}$. This is the maximum number of leaves the tree can hold.
|
||||
- **Total Number of Nodes**: $2^{(\text{depth} + 1)} - 1$ for a full binary tree.
|
||||
|
||||
Glossary:
|
||||
**Example for a tree with `depth: 3`**:
|
||||
|
||||
- depth: level of leaves if we count from levels from 0
|
||||
- number of levels: depth + 1
|
||||
- capacity (number of leaves): 1 << depth
|
||||
- total number of nodes: 1 << (depth + 1) - 1
|
||||
- Number of Levels: 4 (levels 0, 1, 2, 3)
|
||||
- Capacity (Number of Leaves): $2^3 = 8$
|
||||
- Total Number of Nodes: $2^{(3+1)} - 1 = 15$
|
||||
|
||||
So for instance:
|
||||
|
||||
- depth: 3
|
||||
- number of levels: 4
|
||||
- capacity (number of leaves): 8
|
||||
- total number of nodes: 15
|
||||
Visual representation of a Merkle tree with `depth: 3`:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
@@ -56,38 +59,55 @@ flowchart TD
|
||||
N6 -->|Leaf| L8
|
||||
```
|
||||
|
||||
### Available Implementations
|
||||
|
||||
- **FullMerkleTree**
|
||||
- Stores all tree nodes in memory.
|
||||
- Use Case: Use when memory is abundant and operation speed is critical.
|
||||
|
||||
- **OptimalMerkleTree**
|
||||
- Stores only the nodes required to prove the accumulation of set leaves (i.e., authentication paths).
|
||||
- Use Case: Suited for environments where memory efficiency is a higher priority than raw speed.
|
||||
|
||||
#### Parallel Processing with Rayon
|
||||
|
||||
Both `OptimalMerkleTree` and `FullMerkleTree` internally utilize the Rayon crate
|
||||
to accelerate computations through data parallelism.
|
||||
This can lead to significant performance improvements, particularly during updates to large Merkle trees.
|
||||
|
||||
## Poseidon Hash Implementation
|
||||
|
||||
This crate provides an implementation to compute the Poseidon hash round constants and MDS matrices:
|
||||
This crate provides an implementation for computing Poseidon hash round constants and MDS matrices.
|
||||
Key characteristics include:
|
||||
|
||||
- **Customizable parameters**: Supports different security levels and input sizes
|
||||
- **Arkworks-friendly**: Adapted to work over arkworks field traits and custom data structures
|
||||
- **Customizable parameters**: Supports various security levels and input sizes,
|
||||
allowing you to tailor the hash function to your specific needs.
|
||||
- **Arkworks-friendly**: Adapted to integrate smoothly with Arkworks field traits and custom data structures.
|
||||
|
||||
### Security Note
|
||||
### ⚠️ Security Note
|
||||
|
||||
The MDS matrices are generated iteratively using the Grain LFSR until certain criteria are met.
|
||||
According to the paper, such matrices must respect specific conditions which are checked by 3 different algorithms in the reference implementation.
|
||||
The MDS matrices used in the Poseidon hash function are generated iteratively
|
||||
using the Grain LFSR (Linear Feedback Shift Register) algorithm until specific cryptographic criteria are met.
|
||||
|
||||
These validation algorithms are not currently implemented in this crate.
|
||||
For the hardcoded parameters, the first random matrix generated satisfies these conditions.
|
||||
If using different parameters, you should check against the reference implementation how many matrices are generated before outputting the correct one,
|
||||
and pass this number to the `skip_matrices` parameter of the `find_poseidon_ark_and_mds` function.
|
||||
- The reference Poseidon implementation includes validation algorithms to ensure these criteria are satisfied.
|
||||
These validation algorithms are not currently implemented in this crate.
|
||||
- For the hardcoded parameters provided within this crate,
|
||||
the initially generated random matrix has been verified to meet these conditions.
|
||||
- If you intend to use custom parameters, it is crucial to verify your generated MDS matrix.
|
||||
You should consult the Poseidon reference implementation to determine
|
||||
how many matrices are typically skipped before a valid one is found.
|
||||
This count should then be passed as the `skip_matrices parameter` to the `find_poseidon_ark_and_mds`
|
||||
function in this crate.
|
||||
|
||||
## Installation
|
||||
|
||||
Add Zerokit Utils to your Rust project:
|
||||
Add zerokit-utils as a dependency to your Cargo.toml file:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
zerokit-utils = "0.5.1"
|
||||
zerokit-utils = "0.6.0"
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- **FullMerkleTree**: Use when memory is abundant and operation speed is critical
|
||||
- **OptimalMerkleTree**: Use when memory efficiency is more important than raw speed
|
||||
- **Poseidon**: Offers a good balance between security and performance for ZK applications
|
||||
|
||||
## Building and Testing
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user