Soroban contract wrapper around the Noir(UltraHonk) verifier. The VK is set at deploy time; proofs are verified with public_inputs and proof.
Before you begin, ensure you have the following tools installed:
Install Rust using rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32v1-noneInstall the Soroban/Stellar CLI. We recommend using a recent version:
cargo install --locked stellar-cli@^3.2.0This project uses Noir 1.0.0-beta.9 and Barretenberg 0.87.0. Install them using their respective version managers:
# Install noirup and switch to Noir 1.0.0-beta.9
curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash
noirup -v 1.0.0-beta.9
# Install bbup and switch to Barretenberg 0.87.0
curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash
bbup -v 0.87.0For the helper scripts used to invoke verified transactions (scripts/invoke_ultrahonk), ensure you have Node.js and npm installed:
Docker is required to run the local Standalone Network container (stellar container start).
- Install Docker Desktop or Docker Engine depending on your system.
We use just as a convenient task runner for discoverability. Install it via cargo:
cargo install justOnce installed, run just --list to see all available commands.
Run just --list at any time to see available commands. The common workflow is:
Start a local Stellar network in a Docker container and configure your environment:
just startOptional: pass extra args to stellar container start, e.g. just start --limits unlimited
This will automatically fund your alice test account, compile the Noir circuits, build the Soroban contract, and deploy it to the localnet:
just deploy(The generated CONTRACT_ID is saved locally to .contract_id)
To simulate the verifier on-chain using the ZK proofs generated in the previous step:
just verifyThis automatically reads from .contract_id and executes verify_proof against your deployed contract. You can also pass a contract ID explicitly: just verify <CONTRACT_ID>
When you're done, tear down the container:
just stopTo run the full pipeline (start → fund → deploy → verify) in one command:
just e2e| Command | Description |
|---|---|
just setup |
Check dependencies, install Node packages, add Rust target |
just start |
Start the Stellar localnet container |
just stop |
Stop the Stellar localnet container |
just fund |
Generate and fund the alice test account |
just build-circuits |
Compile Noir circuits and generate proof, VK, and public inputs |
just build-contract |
Build the Soroban contract WASM |
just deploy |
Build circuits, build contract, and deploy to the network |
just verify [CONTRACT_ID] |
Verify proof on-chain (reads .contract_id if no arg given) |
just e2e |
Run the full localnet pipeline in one shot |
just testnet |
Run the full testnet pipeline (fund → deploy → verify) |
just clean |
Stop container and remove .contract_id |
The underlying shell scripts in scripts/ are still available if you prefer to use them directly.
All Noir circuits live under /circuits/. Each circuit keeps its source files and generated artifacts together, with build outputs under circuits/<name>/target/.
See circuits/README.md for the circuit layout, rebuild commands, and how to add a new circuit.
All Noir circuits live under /circuits/. Each circuit keeps its source files and generated artifacts together, with build outputs under circuits/<name>/target/.
See circuits/README.md for the circuit layout, rebuild commands, and how to add a new circuit.
The same flow runs against the Stellar public testnet — there is no Docker container to start or stop. Either run the orchestrator:
just testnetor invoke the steps individually after selecting the network:
export STELLAR_NETWORK_NAME=testnet
just fund # registers testnet profile + friendbot funds 'alice'
just deploy # builds + deploys to testnet (CONTRACT_ID saved to .contract_id)
just verify # invokes verify_proof on testnetNotes:
STELLAR_NETWORK_NAMEacceptslocal(default),testnet, ormainnet. RPC URL and network passphrase are auto-filled — override withSTELLAR_RPC_URL/STELLAR_NETWORK_PASSPHRASEif needed.- Cost measurement (the JS report) is skipped on testnet by default because it extracts the source-account secret. Re-enable with
MEASURE_COSTS=1 just verify. The default report is simulation-only; addMEASURE_SUBMIT=1to also submit a separate measurement transaction and print the actualfeeChargedfrom the ledger (real cost, costs ~0.014 XLM per run). mainnetis supported by config butjust fundwill refuse to call friendbot — fund the source account out-of-band before runningjust deploy.
All Noir circuits live under /circuits/. Each circuit keeps its source files and generated artifacts together, with build outputs under circuits/<name>/target/.
See circuits/README.md for the circuit layout, rebuild commands, and how to add a new circuit.
Expects a dataset folder with public_inputs, proof (the VK is already on-chain from deploy):
cd scripts/invoke_ultrahonk
npm install
npx ts-node invoke_ultrahonk.ts invoke \
--dataset ../../circuits/simple_circuit/target \
--contract-id $(cat ../../.contract_id) \
--network local \
--source-account alice \
--send yesThis contract does not enforce access control:
__constructorstores the VK once at deploy time (immutable after first set).verify_proofalways uses the stored VK set at deploy.
Note: Integration tests include circuit artifacts (VK, proof, public inputs) via
include_bytes!. You must build the circuits first before running tests:just build-circuits
Run all unit and integration tests across the Cargo workspace (including rs-soroban-ultrahonk and tornado_classic):
cargo test --workspace --all-features --release- Noir language: https://noir-lang.org/
- Barretenberg (bb): https://github.com/AztecProtocol/aztec-packages
- rs-soroban-ultrahonk: https://github.com/yugocabrio/rs-soroban-ultrahonk
- Soroban documentation: https://developers.stellar.org/docs/build/smart-contracts
- Soroban SDK (Rust): https://github.com/stellar/rs-soroban-sdk
This project has not been audited.
MIT