Poseidon and domains
Poseidon over BN254 is used for field-friendly owner, note, nullifier and Merkle hashing with distinct protocol domains.
The protocol uses Poseidon with BN254 field elements for hashes that are computed both in circuits and by the Solana program. This keeps the hash relation expressed in the same field used by Groth16; a conventional byte-oriented hash would be substantially less suitable for these in-circuit relations.
Domain-separated constructions
| Purpose | Domain constant | Construction |
|---|---|---|
| Note/protocol commitment | 0x5a4b43504d4d0003 | Start with domain field; Poseidon2-fold pool limbs, asset limbs, amount, owner commitment and randomness limbs. |
| Owner commitment | 0x5a4b43504d4f0003 | Poseidon3(domain, spend_secret_hi, spend_secret_lo). |
| Nullifier | 0x5a4b43504d4e0003 | Poseidon9(domain, pool limbs, asset limbs, spend-secret limbs, randomness limbs). |
| Merkle parent | No extra protocol prefix | Poseidon2(left, right), with ordering selected from the leaf index bit. |
The circuit, SDK and on-chain program share the domain and limb conventions. The note's protocol version is 2; the encrypted outer note payload version is 1. These versions are distinct from the numeric domain values.
Field encoding
32-byte public keys, random values and commitments are divided into high and low 16-byte big-endian limbs where required. Amounts and counters are encoded as field representations of unsigned integers. The program rejects noncanonical field values at proof boundaries.
Domain separation makes the construction's semantic role explicit. A value intended as an owner commitment cannot be silently substituted for a nullifier input simply because both are 32-byte field encodings.
The exact numeric constants are listed in Reference: constants & domains.