Merkle tree membership proof circuit in Noir. Proves that a value exists in a Poseidon2-based Merkle tree (depth 3, 8 leaves) without revealing the value or its position.
Equivalent to the circom version in ../circom/, but using Noir's Poseidon2 hash and the UltraHonk proving system (via Barretenberg).
nargo checknargo test --show-outputRuns test_membership (verifies proof logic) and test_print_tree_data (prints all tree node hashes).
nargo executeReads inputs from Prover.toml, compiles the circuit, and generates the witness at target/merkle.gz.
bb prove -b ./target/merkle.json -w ./target/merkle.gz --write_vk -o ./targetGenerates target/proof, target/vk (verification key), and target/public_inputs.
bb verify -p ./target/proof -k ./target/vkExpected output: Proof verified successfully
node scripts/visualize_tree.js [leafIndex]Prints an ASCII tree with color-coded proof path (green), sibling witnesses (yellow), and other nodes (dim). Default leaf index is 3 (value 42). Pass a different index (0–7) to prove a different leaf.
This script calls nargo test internally to compute the Poseidon2 hashes.
| Signal | Visibility | Description |
|---|---|---|
leaf |
private | The leaf value to prove membership of |
index |
private | Leaf position in the tree (bit-decomposed for path selection) |
siblings[3] |
private | Sibling hashes along the authentication path |
root |
public | Expected Merkle root |
The circuit walks up the tree from the leaf using Poseidon2::hash([left, right], 2) at each level, selecting left/right based on the index bits, and asserts the computed root equals the provided root.
| Circom | Noir | |
|---|---|---|
| Hash function | Poseidon | Poseidon2 |
| Proving system | Groth16 (snarkjs) | UltraHonk (Barretenberg) |
| Leaf handling | Hashes value with Poseidon(1) before tree insertion |
Uses raw values directly as leaves |
| Setup | Requires trusted setup ceremony (Powers of Tau + phase 2) | No trusted setup required |
| Proof size | ~256 bytes | Larger (UltraHonk) |