The tree is the commitment layer for private exits. When a transfer is recorded, its leaf
commits to (recipient, per-recipient count, asset, quantized amount) โ no sender, no secrets. Later,
the recipient proves in zero knowledge: "some leaf in this tree paid me, and I know the secret that lets
me spend it". The wormhole pallet checks that proof with verify_private_batch /
verify_public_batch (pallet 20) and enforces one-spend-per-leaf with nullifiers.
record_transfer โ leaf appendedon_finalize folds the block's leaves; root โ block headerZkTreeApi_get_merkle_proof, builds a ZK proof off-chainThe depth-16 circuit ceiling
The chain lets the tree grow to depth 32, but the deployed ZK circuits only accept proofs up
to depth 16 โ every leaf proof pays a full 16-level path, so the cap keeps proving fast.
416 โ 4.29 billion leaves. If the tree ever outgrows it, proof generation halts until
a circuit update + runtime upgrade raises the ceiling โ a deliberate "fix it when we get close" trade-off,
documented in pallets/zk-tree/src/lib.rs. LeafCount is public storage, so exhaustion
is visible years in advance.
Chain facts this story stands on Quantus-Network/chain @ 482c5b9
- 4-ary tree, Poseidon2-Goldilocks,
MAX_TREE_DEPTH = 32,CIRCUIT_MAX_TREE_DEPTH = 16โpallets/zk-tree/src/lib.rs - Leaf =
(to, transfer_count, asset_id, amount);AMOUNT_SCALE_DOWN_FACTOR = 1010โpallets/zk-tree/src/tree.rs - Root published in the block header via
frame_system::set_zk_tree_rootinon_finalize - Leaf sources: mining rewards every block (
pallets/mining-rewards/src/lib.rs:247), SafeSend (pallets/reversible-transfers/src/lib.rs:833), vesting (pallets/vesting/src/lib.rs:643) - Per-recipient
transfer_countkeyed on the canonical recipient; nullifier binds(secret, transfer_count)โpallets/wormhole/src/lib.rs - Wormhole dispatchables:
verify_private_batch,verify_public_batch(pallet 20)