> For AI agents: the documentation index is at https://docs.umbraprivacy.com/llms.txt, and every page is available as Markdown at its URL with .md appended.

# Notes (/docs/state/notes)

A note is the unit of private balance: a fixed amount of one token, owned by one party, that is spent whole and replaced. Your private balance is the sum of the unspent notes you can open, and the chain never sees any of them, only a commitment to each.

## Cash in an envelope

Think of a note as a banknote sealed in an envelope. The envelope sits in a public ledger where anyone can see that it exists, but only the owner knows what is inside. To pay, the owner does not tear the note in half. They hand in whole notes and have new ones issued: one for the payee and one for their own change. Each note handed in is cancelled so it cannot be handed in again; the [nullifiers](https://docs.umbraprivacy.com/docs/state/nullifiers) page explains how.

The code calls an identity-owned note a UTXO, short for unspent transaction output. The term comes from ledgers that keep value in discrete outputs, each spent in full by a later transaction that creates new outputs. Umbra's notes work the same way, except that the outputs are private.

## The thirteen fields

Every note has the same thirteen fields, whatever its kind. Six are small numbers, which the circuit range-checks to a fixed width whenever it builds a note's commitment; the other seven are full elements of the BN254 scalar field. They fall into five groups.

### Format, kind and zone

**Version.** The note format, as a 16-bit number. The SDK writes 1.

**Kind.** A 16-bit number the code calls the discriminator: 0 for a dummy, 1 for an identity-owned note, 2 for a program-owned note. The kind decides how the note is spent and how its nullifier is keyed; the three kinds are described below.

**Zone.** The note's zone number, up to 20 bits, or 0 for a note in no zone. A transaction that spends or creates a zoned note must carry that zone's signature. See [zones](https://docs.umbraprivacy.com/docs/zones).

### Value and time

**Amount.** The value, in the token's base units, up to 64 bits. A real note's amount is never 0, and a dummy's is always 0.

**Valid after and valid before.** Two 48-bit slot numbers that bound when the note can be spent: from the valid-after slot, and until the valid-before slot, where 0 means it never expires. The [validity windows](#validity-windows) section explains how they are checked.

### Randomness

**Blinding factor.** A random field element that makes the commitment hiding. Without it, anyone could hash guesses of the other fields and compare them with the commitment.

**Nullifier blinding factor.** A second random value, used only to derive the note's nullifier, together with the note's position in the tree. The blinding factor plays no part in the nullifier. See [nullifiers](https://docs.umbraprivacy.com/docs/state/nullifiers).

### Owner and token

**Owner commitment.** Who can spend the note: a registered identity commitment (sometimes called the user commitment), or for a program-owned note the commitment of a Solana address.

**Mint identifier.** Which token the note holds: a Poseidon hash of the mint address's two 16-byte halves. The circuit balances each token separately by this value.

### Provenance and memo

**Funding user commitment and funding program commitment.** Who paid for the note. The circuit sets them, not the sender, by the rule described after this list.

**Memo hash.** An opaque value the circuit carries into the commitment without interpreting it. The SDK writes 0.

No deposit, private transfer (Private Send) or withdrawal publishes any of these fields, though the public amount of a deposit or withdrawal lane can narrow down the notes behind it. The sender and the recipient know them. Beyond those two, the sender record carries each output's owner, token and amount under the per-transaction viewing key; the disclosure tree carries owner, amount, token, the funding user commitment and kind for zone authorities; and an [escape hatch](https://docs.umbraprivacy.com/docs/operations/escape-hatch) makes most of the spent note's fields public. The [disclosure](https://docs.umbraprivacy.com/docs/disclosure) page has the detail.

The two funding fields are set by the circuit, not chosen by the sender. For each output, the circuit checks whether any identity-owned input has the same token; if one does, the output's funding user commitment must be the sender's identity commitment (sometimes called the user commitment), and otherwise it must be 0. The funding program commitment follows the same rule for program-owned inputs. A recipient therefore learns who paid them whenever the sender spent a note of the same token, which is the usual case. A note funded only by a deposit carries 0 in both.

## Three kinds

**Identity-owned**

The owner commitment is a registered identity commitment. Its owner spends it by proving, inside the transaction proof, that they know the opening of that identity commitment and that it is in the identity tree. No key signs anything. The circuit also requires every identity-owned output's owner to be in the identity tree, so a note cannot be made out to an identity that has not registered. This is the ordinary note, and the one the code calls a UTXO.

**Program-owned**

The owner commitment is `H_off[34]` of a Solana address's two halves: a wallet, or a program-derived address that a program signs for. It is spent when that address signs the transaction as the spender authority. All program-owned inputs in one transaction must belong to the same address, and a spend of them makes that address and a mask of which input slots are program-owned part of the proof's public input. The owner commitment has no blinder, so anyone who knows the address can recognise it; the [nullifiers](https://docs.umbraprivacy.com/docs/state/nullifiers) page covers what that means for linking.

**Dummy**

A dummy fills a slot the transaction does not need. The circuit ties kind and amount together: a note is a dummy exactly when its amount is 0, so a dummy cannot carry value and a real note cannot be worth nothing. A dummy input is not checked for tree membership or for its validity window, but it still produces a real, fresh nullifier, which the chain stages like any other. A dummy output is appended to the note tree like any other, and its commitment looks like any other.

## Change, split and merge

Every value transaction has exactly three input slots and three output slots, plus up to two deposit lanes and two withdrawal lanes. Paying someone usually spends one or two of your notes and creates two: the payment and your change. The same shape merges several small notes into one, or splits one note into several. Unused slots hold dummies, so from the outside every transaction looks the same.

One transaction, the same shape every time. Notes spent: 2 input notes and 1 dummy. Deposit lanes: 0 deposits and 2 dummy. Notes created: 2 output notes and 1 dummy. Withdrawal lanes: 0 withdrawals and 2 dummy.

*A private transfer that spends two notes and creates a payment and a change note. The third slot on each side is a dummy.*

The chart below follows the amounts through that transaction: two of your notes and a dummy go in, and the payment, your change and a dummy come out.

```mermaid
flowchart LR
a["Your note: 60"] --> t{{"Transaction"}}
b["Your note: 50"] --> t
d["Dummy input: 0"] --> t
t --> p["Payee's note: 80"]
t --> c["Your change: 30"]
t --> e["Dummy output: 0"]
```

*A payment of 80 from notes of 60 and 50, with 30 returned as change.*

The amounts are illustrative and leave out fees. In a real transaction the protocol fee and any relayer tip also come out of the inputs; see [the fee model](https://docs.umbraprivacy.com/docs/fees/fee-model). A transaction can involve at most three distinct tokens across all its real notes and active lanes, and the circuit balances each token separately; see [value conservation](https://docs.umbraprivacy.com/docs/state/value-conservation).

## Validity windows

A note can carry a window of slots in which it is spendable. For every real input, the circuit checks that valid after is at or below the transaction's execution slot, and that valid before is either 0 or above it. The execution slot is a value the transaction names; the program accepts it only if it is no later than the current slot and no older than the proof-age window governance sets, between 300 and 216,000 slots. A transaction whose execution slot falls inside a note's window can therefore still land up to one proof-age window after the window has closed in real time.

## Where a note's contents live

The chain holds one 32-byte value per note: a leaf of the [note tree](https://docs.umbraprivacy.com/docs/state/note-tree), which wraps the note's [commitment](https://docs.umbraprivacy.com/docs/state/commitments) with the slot and position at which the chain appended it. Everything else lives off chain.

- **The encrypted note.** The sender encrypts twelve of the thirteen fields to the recipient: a 232-byte plaintext, sealed with ML-KEM-768 and AES-256-GCM into a 1,352-byte blob that starts with a 4-byte view tag. The data endorser archives it and the indexer serves it. The chain binds the blobs to the transaction through the memo digest, but does not store them. See [encryption](https://docs.umbraprivacy.com/docs/cryptography/encryption) and [receiving and syncing](https://docs.umbraprivacy.com/docs/operations/receive-and-sync).
- **The owner commitment** is left out of the plaintext. The recipient already knows it: it is their own identity commitment, or the commitment of their address.
- **The insertion slot and position** are not in the plaintext either, because the sender cannot know them in advance. The chain chooses them when it appends the leaf and records the first position in its program log, where the recipient and the indexer read them.

The recipient needs the blinding factor, the nullifier blinding factor, the slot and the position to rebuild the leaf, prove it is in the tree and later derive its nullifier. A payment from someone else is opened only through its encrypted copy: if the recipient can never obtain it, the note stays in the tree, still theirs, and unspendable.

## Related

- [Note commitments](https://docs.umbraprivacy.com/docs/state/commitments): How the thirteen fields become one hash and one tree leaf.
- [Nullifiers](https://docs.umbraprivacy.com/docs/state/nullifiers): How a note is cancelled when it is spent.
- [Value conservation](https://docs.umbraprivacy.com/docs/state/value-conservation): Why the outputs can never be worth more than the inputs.
- [The note tree](https://docs.umbraprivacy.com/docs/state/note-tree): Where every note's leaf is kept.


Last updated 12 October 2026
