Merkle Tree

Position in the stack: Sits inside the Shielding Layer and interacts directly with the Smart Contract Infrastructure.

Purpose

  • Efficient membership proofs – Users prove a note exists in the shielded set without revealing which note it is.

  • Compact state – A single 32‑byte Merkle root represents millions of shielded notes, keeping onchain storage minimal.

  • Incremental privacy – Every new deposit grows the anonymity set, the Merkle root captures that growth in one hash.

How It Works in Veilon

  1. Deposit → Commitment

    • When you shield assets, Veilon creates a note commitment (a hash of value + owner + randomness).

  2. Commitment → Merkle Leaf

    • The commitment becomes a leaf in Veilon’s incremental Merkle tree stored onchain.

  3. Tree → Root

    • After the leaf is inserted, smart contracts update the Merkle root. This root is the only piece the zk‑SNARK circuit needs.

  4. Spend → zk Proof

    • To spend privately, you submit a zk proof that:

      • Knows a path from your leaf to the current root (membership).

      • Has a nullifier so the same note can’t be spent twice.

      • Reveals nothing about which leaf you used.

function verifyMerkleProof(
  bytes32 leaf,
  bytes32[] memory proof,
  uint256 index
) public view returns (bool) {
  bytes32 hash = leaf;
  for (uint256 i = 0; i < proof.length; i++) {
    if ((index >> i) & 1 == 1) {
      hash = keccak256(abi.encodePacked(proof[i], hash));
    } else {
      hash = keccak256(abi.encodePacked(hash, proof[i]));
    }
  }
  return hash == currentMerkleRoot;
}

Last updated