Protocol
Operations

Receive and sync

How an encrypted note reaches its recipient, how your device finds your notes among everyone's, and how it works out your balance and history.

Umbra's clients, not the protocol

Re-deriving your keys from your account signature, as this page describes, is what Umbra's SDKs and client interfaces do. The protocol never sees how your keys were made; a client that stores or derives them another way syncs the same notes.

Nobody tells you that you have been paid. Your device downloads every encrypted note the pool has produced, tries each one with your key, and keeps the ones that open. The chain never records who a note is for, so downloading everything is also what keeps it that way.

Summary

When a transaction creates notes, the sender's device encrypts each one to its recipient and the data endorser archives them. The chain records their commitments and a digest that binds them to the transaction, and the indexer publishes both. Your device opens the notes that are yours, learns from the published nullifiers which are spent, and decrypts the sender records of your own transactions to rebuild your history.

Preconditions

  • You are registered, so senders can resolve your encryption key (see receiving payments).
  • Your device has re-derived your ML-KEM-768 secret key and outgoing viewing key from the account signature.
  • The indexer's note archive and read service are reachable.

How a note reaches you

A note travels in two parts: delivery when the sender's transaction lands, and discovery whenever your device syncs.

flowchart LR
A["Sender encrypts"] --> B["Endorser archives"]
A --> C["Pool appends commitment"]
B --> D["Indexer publishes"]
C --> D
D --> E["Your device scans"]
E --> F["Balance and history"]

The indexer joins the off-chain archive with the on-chain commitments, and your device reads only what the indexer publishes.

Part 1: delivery

Delivery is complete before you do anything. None of it involves your device, and none of it names you.

sequenceDiagram
participant S as Sender's device
participant E as Data endorser
participant P as Shielded pool
participant I as Indexer
S->>E: three encrypted notes
E->>E: check memo digest, archive
E-->>S: signature
S->>P: transaction
P->>P: append three commitments
I->>P: read leaves and nullifiers
I->>I: join leaves with the archive

1. The sender's device encrypts each new note

Every value transaction produces exactly three encrypted notes, one per output. An output without value gets a dummy note of the same fixed size, so the archive cannot tell real notes from padding.

The sender's device encapsulates to the owner's ML-KEM-768 public key to get a shared secret. SHAKE256 derives two values from it under separate labels: a short view tag, published in the clear, and the AES-256-GCM key that encrypts the note, which also takes in the note commitment. The tag reveals nothing about the key. See encryption.

2. The data endorser checks and archives the encrypted notes

Encrypted notes are not stored on chain. Instead, the transaction carries a memo digest, a hash that commits to its three encrypted notes. The data endorser recomputes it, refuses to sign unless it matches, and archives the notes before returning its signature. Every attester signs a payload that contains the digest, so the archive holds exactly the notes the transaction committed to, and nobody can swap them later. The endorser cannot check that the notes open, because it does not hold the recipients' keys.

3. The shielded pool appends the note commitments

When the transaction lands, the pool appends its three note commitments to the note tree, each stamped with its slot and position. The commitment fixes the note's contents and the encrypted note carries them, so together they are everything a recipient needs.

4. The indexer publishes three feeds

The indexer joins each leaf with its encrypted note and publishes three feeds for each pool index:

  • Notes: every leaf in order, with its encrypted note. Your device scans all of it.
  • Nullifiers: every nullifier the pool has recorded, which your device reads to find its spends.
  • Records: each transaction's encrypted sender record, the random value its viewing key is derived from, and its public deposit and withdrawal legs. Your device fetches only the records it needs.

Older rows sit in files on a content-distribution network and the newest come from the indexer's read API. Your device takes rows only from finalized slots.

Part 2: discovery on your device

Your device syncs from where it last stopped and works in a fixed order: notes, then nullifiers, then sender records.

sequenceDiagram
participant Y as Your device
participant I as Indexer
Y->>I: notes feed from cursor
I-->>Y: leaves and encrypted notes
Y->>Y: decapsulate, check view tag
Y->>Y: open matches, recompute
Y->>I: nullifier feed
I-->>Y: published nullifiers
Y->>Y: mark your spent notes
Y->>I: records of your spends
I-->>Y: encrypted sender records
Y->>Y: decrypt, update balance

5. Your device trial-decrypts every note

Your device cannot tell which notes are yours without trying each one. For every note, it decapsulates the ML-KEM-768 ciphertext with your secret key, derives the view tag from the shared secret with SHAKE256, and compares it with the published one. Only on a match does it derive the AES-256-GCM key from the secret and the note commitment and open the ciphertext, with the note commitment as associated data. A note moved to another leaf therefore fails to open.

The view tag skips decryption for notes that are not yours, but every note still costs one decapsulation. The work of syncing grows with the size of the pool, not with the number of notes you own.

6. Your device opens each match and recomputes it

An opened note gives its amount, token, zone, validity window, memo hash and funding field, among other fields. It does not carry its owner, because the owner is you: your device fills in its own identity commitment, then recomputes the note's commitment and nullifier.

A note names its token only by an irreversible hash of the mint address, so if your wallet does not know the token, the scan pauses at that note and resumes from it once the token is added.

7. Your device marks spent notes

Your device checks the nullifier feed against your notes' nullifiers, and a match marks the note spent. A note cannot be spent before the slot it was created in, so the device reads nullifiers only as far as its notes scan has reached, and never meets one of your spends before the note it spends.

8. Your device fetches the sender records of its spends

For each transaction that spent one of your notes, your device fetches its sender record. It decrypts the record with a per-transaction viewing key, re-derived from your outgoing viewing key, the transaction's nullifiers and the record's random value. The record gives the token and amount of each note spent, and the owner, token and amount of each note created.

9. Your device updates its store and your balance

Your device writes the notes, spends and records to its local store, advances its position in each feed, and recomputes your balance.

Balance and history

Your balance is the sum of your unspent notes, per token and per zone. A note counts once its leaf arrives and stops counting once its nullifier does.

What you received comes from the notes themselves. When the sender spent an identity-owned note of the same token, the funding field is the sender's identity commitment, which can be followed on chain to their wallets. What you sent comes from sender records. You cannot read the sender records of transactions that paid you, because they are encrypted under the sender's key.

Everything your device needs is published by the indexer, so a new device that re-derives your keys rebuilds your balance and history by syncing again (see recovery). The chain alone holds only commitments and digests, which is not enough.

A payment arriving for you
What anyone downloading the archive can read
Note commitment
One field element per note
Tree position and slot
Stamped by the chain
View tag
4 bytes
ML-KEM ciphertext
1,088 bytes
Recipient
Private
Amount
PrivateInside the encrypted note
Token
PrivateInside the encrypted note
Sender
PrivateOnly the recipient may learn it, through funded by
Every note in the archive looks like this, including dummies.

What can go wrong

  • The archive or read service is down. Your notes are safe in the pool, but your device cannot find new ones or build a spend until the indexer is back.
  • A note is in a token your wallet does not know. The scan pauses there until the token is added.
  • A sender encrypted a note wrongly. The endorser checks that the notes match the transaction, not that they open. A note encrypted to the wrong key or with the wrong contents cannot be opened or spent by anyone, and its value is lost.
  • The indexer serves wrong data. Syncing trusts the indexer and does not check the feeds against the chain or prove that a note is in the tree. The transaction proof checks membership against a recent root when you spend, so wrong data shows up as a failed proof, and a leaf that is not really in the tree cannot be spent.

Privacy notes

  • Downloading every note keeps your notes private from the indexer, because the requests do not depend on which notes are yours.
  • Fetching sender records is selective, so the read service learns which transactions you sent.
  • When you spend, the context service receives your identity commitment, the positions and nullifiers of the notes you are spending, and the recipient in one request. See how privacy is lost.
  • Every request comes from your network address, and requests to Umbra's services carry an access key.

Last updated

On this page