Notes & Commitments
A note is the unit of value in the shielded pool — a private record of who owns how much of what. The chain never sees a note; it only sees its commitment cm, a short collision-resistant fingerprint that becomes a leaf in the Merkle tree.
Note fields
interface ActionNote {
d: Uint8Array; // diversifier (11 bytes) — selects which of the owner's addresses
gd: AffinePoint; // diversified base point = DiversifyHash(d)
pkd: AffinePoint; // diversified transmission key = [ivk] · gd
value: bigint; // 0 ≤ value < 2^128 (the in-circuit per-note range)
rho: bigint; // uniqueness tag (BN254 field element)
psi: bigint; // additional nullifier entropy
rcm: bigint; // commitment randomness (hiding blinding factor)
asset: Asset; // (encodedAssetAddress, encodedAssetId)
}
The commitment
| Property | Guarantee | Mechanism |
|---|---|---|
| Hiding | cm reveals nothing about v, pkd, d | Poseidon2 as a random oracle over BN254; fresh rcm |
| Binding | distinct notes ⇒ distinct cm | Poseidon2 collision resistance |
| Integrity | the circuit recomputes cm from witnesses | the Action circuit's commitment constraint |
Rho-chaining and the Faerie Gold defense
rho exists to stop the Faerie Gold attack: crafting two distinct commitments that collide to the same nullifier, letting an attacker deposit one and spend the other to mint value. Platus closes it with two coupled mechanisms.
1. The nullifier binds the commitment. nf = Poseidon2(NF_DOMAIN, nk, ρ, ψ, cm) — see Nullifiers. Because cm is an input, two notes differing in any committed field cannot share a nullifier.
2. Each output's rho is the paired input's nullifier (rho-chaining). In a 2-in/2-out Action:
Since nf_old is unpredictable (it depends on nk and the whole input note), an attacker cannot pre-craft an output whose rho makes its nullifier collide. The circuit also enforces nf1 ≠ nf2 (rejecting in1 == in2 and forcing distinct output rhos) and, as defense in depth, cm1 ≠ cm2 directly. See the Action circuit.
Genesis notes: deposits
Deposits enter the pool outside the rho-chain, so their secrets are derived deterministically from the deposit ledger nonce so the recipient can recover them by scanning (no ciphertext needed):
The wallet recomputes these while scanning AssetsDeposited, hashes the note, and confirms it equals the on-chain leaf. Refund notes minted during settlement use the same derivation with a nonce that folds in the bundle context.
Where commitments live
Each cm is a leaf in a depth-16 binary LeanIMT. Trees fill at 2^16 leaves and roll over (treeNumber++); each tree keeps its own rootHistory. A spend proves membership against a historical root (its anchor), which tolerates root rotation during the bundle-build window. See State Transitions.