Skip to main content

Keystore tree

The keystore tree is a Merkle tree (depth 18) of registered accounts. Registering puts your account in the tree and publishes your viewing public key on-chain, which is what lets senders encrypt notes addressed to you in discoverable mode.

Properties​

  • Depth 18: the tree is 18 levels deep, supporting up to 2^18 (262,144) registered accounts. That sizing targets the early stage, and the depth is a circuit parameter (see Transact circuit).
  • Public by design: registration is a deliberate opt-in that says "I want to receive discoverable notes," and anyone can read the tree to find someone's viewing key.

The account leaf​

Each registered account contributes one leaf, Poseidon(ownerAddress, privateNullifyingKeyHash, authDigest). The three committed values play distinct roles:

  • Owner address: ties the leaf to your wallet.
  • Nullifying key hash: the on-chain commitment to your private nullifying key, set once at registration and proved by every spend. This is how a transfer, withdrawal, or ragequit shows that the note's owner is registered without revealing which leaf is yours.
  • authDigest: commits to your current revocable-key authorization, and can be rotated in place at any time, not only after a compromise.

Your viewing public key is deliberately not in the leaf. It lives in a separate on-chain mapping (Keystore.viewingKeys(address)) that senders read to encrypt discoverable notes to you, so publishing it for discovery never exposes your spend authority.

What registration enables​

Once you are registered, a sender can use the canonical recipientDiscoveryData: { evmAddress } variant: the SDK resolves your viewing public key from the keystore and encrypts to it. On your side, discoverNotes() then finds discoverable-mode notes automatically, with no out-of-band hand-off per payment.

What it doesn't do​

Registration does not gate receiving. Anyone can still send you a note out-of-band, and registering just adds the more convenient path. It also does not publish your nullifying or revocable keys, because only the viewing public key goes on-chain.

Cost​

Registration takes two on-chain transactions (setAuthPolicy and setViewingKey), a one-time cost whose gas varies with network conditions.

See register your viewing key for the operational flow.