This guide walks through integrating Noir zero knowledge circuits with smart contracts on Stellar. You will:
- Build a Noir circuit
- Generate UltraHonk proofs in Node on a backend
- Generate proofs directly in the browser with React
- Verify proofs inside a Stellar smart contract
All code is open-source: https://github.com/jamesbachini/Noirlang-Experiments/
The integration follows a clean separation of responsibilities.
Noir defines the constraint system – the private logic you want to prove. Barretenberg (bb.js) generates a verification key and proofs from that circuit.
A Stellar smart contract verifies those proofs on chain. Optionally, a React frontend can generate proofs client side using WebAssembly and submit them to the contract.
In practical terms, the flow looks like this:
Noir circuit > BB.js > Stellar verifier contract
Setup
You’ll need Rust, Docker, Stellar-cli all installed, ideally on a unix based console.
On-chain verification of Ultrahonk proofs is computationally expensive and even simple circuits are right on the borderline of CPU instruction limits for on-chain transactions currently.
This is being worked on and an update is expected in Protocol 26. Until then I would recommend deploying to a local network environment using stellar/quickstart with the flag –limits unlimited. So let’s go ahead and set that up.
sudo dockerd &
git clone https://github.com/jamesbachini/Noirlang-Experiments
cd Noirlang-Experiments
docker run -d -p 8000:8000 stellar/quickstart \
--local \
--limits unlimited \
--enable core,rpc,lab,horizon,friendbot
stellar network add local \
--rpc-url http://localhost:8000/soroban/rpc \
--network-passphrase "Standalone Network ; February 2017"
stellar network use local
stellar keys generate --global alice
stellar keys fund alice --network local
This command sequence starts the Docker daemon, clones the Noir Stellar integration repository, launches a local stellar/quickstart node with unlimited execution limits (required for CPU intensive UltraHonk verification), configures the Stellar CLI to use the local Soroban RPC endpoint, generates a test keypair, and funds it via the built in friendbot.
The result is a fully configured local development environment ready for deploying and testing Noir generated zero knowledge proofs against a Stellar verifier contract without hitting network budget constraints.
Noir Circuit
The example circuit lives in private_limit_orders/src/main.nr. It models a simple but useful pattern: a private limit order.
fn main(my_limit_price: u64, market_price: pub u64) {
assert(my_limit_price > market_price);
}
The circuit takes a private input (my_limit_price) and a public input (market_price) and enforces the constraint that the private value is greater than the public one. In other words, the prover demonstrates that their hidden limit price satisfies the trade condition without revealing it.
This minimal constraint illustrates how Noir can encode financial logic while preserving confidentiality. The same pattern can be extended to hidden game moves, sealed bids, eligibility checks, or confidential scoring systems.
Backend Proof Generation
The repository includes a script that orchestrates the entire proving and verification lifecycle:
./test-local.sh
The script compiles and executes the Noir circuit using nargo, producing the witness data required for proof generation.
Then it invokes @aztec/bb.js to generate an UltraHonk verification key and a proof bundle containing both proof data and public inputs. The script splits this bundle into raw byte files suitable for contract submission.
It builds the Stellar UltraHonk verifier contract and deploys it to the local network. During deployment, the verification key bytes are passed to initialise the contract. Finally, the script calls the verify_proof function, first in simulation mode and then on chain, confirming that the proof verifies successfully.
If all steps complete without error, you will see the deployed contract ID and confirmation that verification succeeded on chain.

If you encounter funding errors during deployment or invocation, open http://localhost:8000/lab, paste your account address into the account funding interface, and retry the script.
The script passes raw binary proof files directly to the Stellar CLI using file path flags. If you prefer to test manually in a contract explorer such as SoroPG on a local network, you’ll need to convert those byte files to hex.
From the private_limit_orders/target directory:
xxd -p -c 999999 public_inputs | tr -d '\n' > public_inputs.hex
xxd -p -c 999999 proof | tr -d '\n' > proof.hex
These hex strings can be pasted into the verify_proof contract call on the SoroPG contract explorer. A valid proof returns OK; modifying inputs to violate the constraint will result in a contract error.

Frontend Proof Generator
The repository also includes a React based prover UI in private_limit_orders/prover ui. This demonstrates client side proof generation using WebAssembly.
Start the UI with:
cd private_limit_orders/prover-ui
npm install
npm run dev
Open the development server in your browser. The interface allows you to enter a limit price and market price, generate a proof entirely in the browser, and copy hex encoded proof data suitable for submission to the Stellar verifier.

This UI uses the same bb.js library that we were using in the node.js backend.
This workflow demonstrates a complete zero knowledge pipeline on Stellar: private logic expressed in Noir, UltraHonk proof generation via bb.js, and on chain verification inside a Stellar contract.
With this foundation, developers can build privacy preserving financial tools, competitive games with hidden state, sealed bid auctions, and many other applications that require verifiable computation without revealing sensitive data.
The combination of Noir’s expressive constraint language and Stellar’s programmable smart contracts opens the door to practical zero-knowledge applications on Stellar.


