← Back to demo

How it works

Three steps. No identity data touches the blockchain at any point.

The flow

  1. 1Publish a compliance policy. Commit each holder's opaque ID and policy attributes into a Merkle tree, then publish only the 32 byte root on chain. The blockchain never sees holder identities or the holder count.
  2. 2Verify a holder's eligibility. Generate a zero knowledge proof that a holder exists in the tree without revealing which one. The proof is 256 bytes.
  3. 3Check the proof on chain. The smart contract verifies the proof using a single BN254 pairing operation. A nullifier prevents the same check from being replayed. The contract returns a pass/fail code. No identity data is involved.

What the verifier sees vs. what stays private


Integrate

Two calls. One to verify eligibility, one to check the proof on chain.

API
POST /api/generate-proof
{ "holder_id": "acc20240891", "policy_id": "reg-d-506c" }

POST /api/submit-verify
{ "proof": "...", "nullifier": "0x...", "policy_version": 3 }
Solidity (Base)
require(
  verifier.verifyMatch(anchor, epoch, pA, pB, pC, nullifier) == 0,
  "not eligible"
);
Soroban / Rust (Stellar)
let code: u32 = client.verify_match(&anchor, &epoch, &proof, &nullifier);
assert!(code == 0, "not eligible");

Threat model


Stack