A Rust SDK for the DenseZK graph-native zero-knowledge virtual machine. Generates Groth16 proofs locally using the arkworks ecosystem. Ships with native Rust and React Native (WASM) targets.
DenseZK enables privacy-preserving decentralized social networking. A user's device generates a cryptographic witness locally, then produces a zk-SNARK proof -- all without exposing private graph data.
This SDK implements a local proving pipeline:
- Client -- computes a Poseidon commitment over a social graph edge, producing a lightweight witness
- Local Prover -- takes the witness and public inputs, runs Groth16 setup and proving in-process, and verifies the proof before returning it
+--------------------------------------------------+
| Application |
| |
| DenseClient LocalProver |
| +-------------+ +-------------------+ |
| | create_ | | setup() | |
| | witness() |----->| prove() | |
| | (Poseidon) | | verify() | |
| +-------------+ | serialize() | |
| +-------------------+ |
+--------------------------------------------------+
The SDK compiles to two targets:
| Target | Use case | Build command |
|---|---|---|
| Native (x86_64/aarch64) | Server-side, CLI tools, desktop apps | cargo build --release |
WASM (wasm32-unknown-unknown) |
React Native, web browsers | cargo build --target wasm32-unknown-unknown --release |
Add to your Cargo.toml:
[dependencies]
densezk-sdk = { path = "../denseZK" }Minimal example:
use densezk_sdk::execute_dense_zk_flow;
fn main() {
let result = execute_dense_zk_flow(
456, // sender_id
789, // receiver_id
1, // edge_weight
"0xabc123", // current graph root state
1, // threshold
);
match result {
Ok(proof) => println!("Proof generated, size: {} bytes", proof.proof_bytes.len()),
Err(e) => eprintln!("Error: {}", e),
}
}Install the WASM bindings:
npm install @densezk/react-nativeOr build from source:
cd react-native-sdk
npm install
npm run build:wasm
npm run buildUsage:
import { executeFlow, init, Client, Prover } from '@densezk/react-native';
await init();
// One-shot
const proof = await executeFlow(456, 789, 1, '0xabc123', 1);
console.log(`Proof size: ${proof.proof_bytes.length} bytes`);
// Or step-by-step
const client = new Client();
const witness = client.createWitness(456, 789, 1);
const prover = new Prover();
const proof = prover.prove(witness, { graph_root: '0xabc123', threshold: 1 });For fine-grained control, use the client and prover separately:
use densezk_sdk::{DenseClient, LocalProver, PublicInputs};
// Step 1: Generate witness on-device
let mut client = DenseClient::new();
let witness = client.create_witness(sender_id, receiver_id, weight)?;
// Step 2: Define public inputs
let public_inputs = PublicInputs {
graph_root: "0x...".to_string(),
threshold: 1,
};
// Step 3: Run local proving
let prover = LocalProver::setup()?;
let proof = prover.prove(witness, public_inputs)?;| Module | Purpose |
|---|---|
client |
On-device witness generation with Poseidon hashing |
prover |
Local Groth16 proving with arkworks |
crypto |
Poseidon hash over BN254 scalar field |
rel1cs |
Rel1CS data types (graph edges, public inputs) |
error |
Unified error type for all SDK operations |
wasm |
WASM bindings for React Native / web (wasm32 only) |
- ark-ff / ark-ec / ark-bn254 -- finite field and elliptic curve arithmetic
- ark-groth16 / ark-relations / ark-snark -- Groth16 zk-SNARK proving
- light-poseidon -- Poseidon hash implementation compatible with Circom
- serde / serde_json -- serialization for witness and proof payloads
- wasm-bindgen / serde-wasm-bindgen -- WASM bindings for JavaScript interop
- console_error_panic_hook -- Rust panic -> JS console error mapping
- thiserror -- ergonomic error definitions
cargo build
cargo build --releaseRunning the example binary:
cargo runExpected output:
[Client] Witness generated with Poseidon commitment: 3227429301273914876261610954147013817301286893576706611663322465376918135905
[Prover] Proof generated locally, size: 128 bytes
Proof generated locally, size: 128 bytes
rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --releasecargo install wasm-pack
wasm-pack build . --target bundler --release --out-dir react-native-sdk/pkgcargo run --bin stress --releaseThe ZKProof struct contains:
proof_bytes-- compressed Groth16 proof (128 bytes for BN254), serialized withCanonicalSerializeroot_commitment-- the graph root string passed as public input
The proof is verified internally before being returned. If verification fails, ConstraintViolation is returned.
- Curve: BN254 (Barreto-Naehrig)
- Proof system: Groth16 with circuit-specific trusted setup
- Hash: Poseidon with 3 inputs, x^5 S-box, BN254 scalar field, Circom-compatible parameters
- Serialization: Compressed canonical serialization via ark-serialize
See LICENSE file.