The first developer SDK and reference verifier contract for zero-knowledge proofs on Stellar, built on Protocol 25's native BN254 and Poseidon host functions.
Testnet registry contract (targeted by demo/):
CDTPNARKKZCZ36PL4BNKBXZTT2BLVR373S2K5NCFAOKCPPY62ESRHSXH
Follow the step-by-step tutorial: docs/tutorial-first-proof.md
It covers prerequisites, Testnet account funding, exact commands, expected output, and a troubleshooting section.
- Install prerequisites: Node.js 22+, Rust, Stellar CLI,
make, andcircom. - Install the workspace dependencies from the repository root:
make install - Build the verifier contract and SDK:
make build - Run the full local check suite:
make test - Run the end-to-end demo:
make demo
The demo verifies against contracts/registry via a read-only simulation
call — no funded Testnet account or secret key needed. Accept the
interactive prompts' defaults to run against the deployed registry
directly.
Useful maintenance commands:
make lint: run Rust formatting, clippy, and TypeScript checks.make circuits: compile and verify the reference Poseidon preimage circuit.make clean: remove generated Rust, SDK, demo, and circuit build artifacts.
Expected result:
✓ Proof verified on-chain: true
contracts/verifier/: a Soroban verifier contract for a Groth16 proof over BN254, gated by caller auth, per-caller rate limiting, and proof expiry.contracts/registry/: a multi-circuit verifying-key registry, deployed to Testnet — see docs/architecture.md.sdk/: a TypeScript SDK for Poseidon hashing, snarkjs proof formatting, and on-chain verification.circuits/: the reference Poseidon preimage circuit (wired to both contracts above) plus three additional circuits —merkle_inclusion,range_proof,threshold_2of3— registered withcontracts/registryand tested there, but not yet on the live Testnet deployment (see docs/multi-circuit.md).demo/: an end-to-end script that generates a fresh secret, proves knowledge of its Poseidon commitment, and verifies it on Stellar Testnet.docs/: architecture notes, ZK primer, proof format specification, security audit checklist, and Poseidon parameter notes.
User secret
|
v
Poseidon(secret) -> commitment
|
v
circom + snarkjs
generate Groth16 proof
|
v
SDK formatProof()
encodes proofA / proofB / proofC / publicInputs
|
v
SDK verifyOnChain()
submits Soroban transaction
|
v
Verifier contract
reconstructs vk_x and runs BN254 pairing check
|
v
bool result on-chain
The reference circuit exposes one public input, commitment, and one private input, secret. The prover shows that Poseidon(secret) == commitment without revealing secret. The contract keeps state to a minimum — an admin address and per-caller rate-limit counters, nothing proof- or nullifier-related — and returns a boolean, which keeps the MVP easy to audit and inexpensive to call. See docs/security.md for exactly what this contract does and does not guarantee.
- Phase 0: foundation complete
- Phase 1: verifier contract deployed and resource-gated
- Phase 2: SDK complete with Testnet integration tests
- Phase 3: reference circuit, setup artifacts, and demo complete
- Phase 4: documentation and submission polish complete
Known gaps, tracked as open issues rather than left implicit:
- No replay protection — the same valid proof can be verified more than once (#11).
merkle_inclusion,range_proof, andthreshold_2of3circuits are registered withcontracts/registryin a local test environment, but not yet on the live Testnet deployment — that needs the registry's admin key (#183).
contracts/registrycontract address (deployed, targeted bydemo/,poseidon_preimageregistered under circuit ID1):CDTPNARKKZCZ36PL4BNKBXZTT2BLVR373S2K5NCFAOKCPPY62ESRHSXH- Verified directly against the live deployment via
demo/: a correct proof returnstrue, and a proof paired with the wrong public input returnsfalse. contracts/verifier(the original single-circuit contract) is still live atCBL6MAWJALQP25LYKUUOC34K464XPSF6BLKUW6MXZDEXEDXMQUSP7HNN, but predates rate-limiting, caller auth, and expiry, and is no longer whatdemo/targets.
- The setup artifacts in
circuits/poseidon_preimage/setup/are testnet-only and non-production. contracts/verifierstill hardcodes one circuit's verifying key;contracts/registrysupports multiple, and is deployed, but onlyposeidon_preimageis registered under it so far.- This contract provides no replay protection — see docs/security.md for what it does and does not guarantee.
Building an application on top of zksoroban? Read
docs/security-model.md first — it covers the
full stack's guarantees, trust assumptions, and threat model, including
what this stack explicitly does not protect against.
See docs/zk-primer.md and docs/proof-format.md for the detailed background and byte-level interoperability spec.