> 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.

# On-chain programs (/docs/architecture/programs)

Umbra's on-chain logic is eight Solana programs. The shielded pool holds the pooled tokens and the trees and settles every operation. Six others keep the records the pool relies on, and the eighth binds your main wallet to your platform wallet.

## How the programs fit together

No Umbra program calls another Umbra program. Trust crosses programs by reading accounts instead. The chart below shows which program reads whose accounts.

```mermaid
flowchart LR
SP["Shielded pool"] -->|"cluster"| GNR["Guardian node registry"]
SP -->|"node records"| SR["Screener registry"]
SP -->|"enclave record"| FE["Fee enclave"]
SP -->|"signer set"| ZR["Zone registry"]
GNR -->|"attestation markers"| NAV["Nitro attestation verifier"]
FE -->|"attestation markers"| NAV
NAV -->|"result markers"| P384["P-384 signature verifier"]
UR["User registry"]
```

*Which program reads which other program's accounts. No program calls another.*

When the shielded pool needs to know that the guardian cluster is Active, it reads the cluster account directly. It checks that the guardian node registry owns the account, that the account has the expected size and layout version, that its status is Active, and that its address is the one the cluster's seeds give. Only then does it read the cluster's key. The same pattern repeats along every arrow in the chart: the reader re-derives the address, checks the owner and the version, and reads only the fields it needs. Programs call only Solana's system, token and associated-token programs. Because nothing is invoked across Umbra programs, one program cannot make another act, and a program can only be fooled by an account that passes all of those checks.

The user registry stands apart. Nothing reads its accounts; its record is the transaction itself.

### What every program shares

Every program uses the same instruction envelope: a one-byte tag, a two-byte version and a payload whose length must be exact. A program dispatches on the tag and the version together. A known tag at a version the program does not serve is refused with its own error, so an old client cannot have its instruction read under a new format. See [versions](https://docs.umbraprivacy.com/docs/architecture/versions).

Every account starts with the same five-byte header. It records the account's status, its layout version and the bump of its program-derived address. A reader checks the version before it trusts any other field, and checks the status where the status matters, such as Active for a cluster or an enclave record.

Every program except the P-384 verifier and the user registry is governed the same way, through a shared timelock. Each governed operation has an authority record naming the one key that may propose it and the delay its proposals wait, at least one slot. A proposal commits to a hash of the exact change, opens once its delay has passed, and expires 216,000 slots later, a period the code counts as one day. Once a proposal is open, anyone may execute it, and the execution must carry exactly the change the proposal committed to. Replacing an operation's authority voids every proposal queued under the old one, and the replacement itself waits out every delay it would shorten. A bootstrap key, fixed when the program is built, creates the authority records once. See [governance and upgrades](https://docs.umbraprivacy.com/docs/security/governance).

## Shielded pool

The shielded pool holds the tokens and the private state, and settles every operation. Pooled tokens sit in pool token accounts: one per token, each the associated token account of a single program-derived authority, the pool token authority (code: VaultAuthority), and shared by every pool index. SOL sits instead as plain lamports in one account the program owns, the pool's lamport account, which every pool index also shares. No key can sign for that authority or that account, so tokens leave only when an instruction of this program pays them out.

For each pool index, the pool keeps a commitment tree of notes, an identity tree of registered identity commitments and a fee commitment tree. Each tree account keeps only its frontier and its 512 most recent roots; the leaves are written to the program's logs. The fee commitment tree's account also holds its fee store, where fee commitments wait until an insert appends them. Beside them sit three staging buffers, for nullifiers, registrations and fee-note nullifiers, where new keys wait until a forester inserts them into their indexed trees. The pool also holds the process policy (the fee rates and the proof-age window), one MintAllowance marker per token that may be deposited, and the accounts where relayer tips and escape-hatch fees accrue. Its Groth16 verifying keys are not in any account: they are compiled into the program, so only a program upgrade changes them.

Its operations fall into four groups:

- **User operations.** `register` publishes an identity commitment, co-signed by the guardian cluster and the data endorser. `process_3x3x2x2` settles every deposit, private transfer and withdrawal under the combined attester signature and two proofs. `escape_hatch` withdraws one note with no attester, under its own proof. See [operations](https://docs.umbraprivacy.com/docs/operations/deposit).
- **Forester commits.** Three instructions insert a batch of staged keys into the nullifier, registration or fee-nullifier tree. No account signs them: a batch-append proof is the only authority, so anyone may run a forester.
- **Payouts.** The protocol treasury collects fee notes with a proof over up to 20 of them at a time, paid only to the account governance named for that token, which is a wallet for SOL. A relayer collects its accrued tips, signing as the address they accrued to. Anyone may move accrued escape-hatch fees, but only to the treasury account governance named.
- **Governed changes.** Setting the process policy, allowing or stopping deposits of a token, and naming the treasury payout account all go through the timelock. No governed change touches a verifying key. Creating trees, staging buffers, pool token accounts and the lamport account needs no authority; only a payer signs.

The program has no pool-wide pause. Revoking a token's MintAllowance stops new deposits of it and nothing else; withdrawals and transfers of that token continue.

## Guardian node registry

The guardian node registry records guardian clusters and their member nodes, and keeps the aggregate key the pool checks the guardians' signatures against. A cluster account holds the committee's member table (up to 64 members), the Shamir threshold and active node count, up to four approved enclave measurements, and the aggregate BLS key, which is the plain sum of the members' keys. Adding or removing a member updates the sum in the same instruction.

A node joins in steps. Its operator registers it under a controller key, the cluster's leader approves it through a timelocked proposal, and the controller then boots it. To finish the boot, the controller must present the Nitro attestation verifier's marker for a document that binds the node's own account address, its enclave key and its new BLS key to a measurement the cluster approves, timestamped inside the cluster's freshness window, later than the node's previous attestation, and not from before the boot began beyond a small tolerance. The new key must come with a proof of possession, a signature by that key over itself, so nobody can register a key they do not hold.

A cluster is governed at two levels. Protocol governance activates a cluster, after checking a digest of its whole configuration, and can freeze or unfreeze it. Within the cluster, a leader key proposes the day-to-day changes: approving nodes and measurements, membership ceremonies, maintenance and its own freeze, each waiting its entry in the cluster's own delay table. A separate break-glass key per cluster can only replace the leader, replace itself or change its own delays. The cluster's status follows from all of this: Created, Active, AddingMember, RemovingMember, Maintenance, Degraded or Frozen, and the pool accepts only Active. A cluster is Degraded when a member is down or runs a measurement outside the approved set. Anyone may evict a node whose measurement is no longer approved. See [guardian nodes](https://docs.umbraprivacy.com/docs/guardian-nodes#who-controls-the-cluster).

## Nitro attestation verifier

The Nitro attestation verifier checks an AWS Nitro attestation document on chain, so a registry can rely on what an enclave says about itself. A document is too large for one transaction, so the uploader writes it in chunks into a buffer account, then calls `parse_and_verify`.

That instruction parses the document and checks its certificate chain. The chain's root key must hash to the root anchor in the verifier's configuration, every certificate must use ECDSA P-384 with SHA-384 and be valid at the document's timestamp, and every certificate that signs another must be a certificate authority. Each signature in the chain, and the document's own signature, must be proven by a result marker from the P-384 signature verifier. None of the document's PCR0, PCR1 and PCR2 may be all zeros, which is how a document from an enclave in debug mode reads. The document's timestamp must be within 300,000 milliseconds of chain time. If all of that holds, the verifier mints an attestation marker whose address commits to the document's user data, its measurement and its timestamp and to the address that opened the upload, so each opener has its own marker for a document, and closes the buffer. The marker records the epoch of the root anchor it was verified under. The measurement is a Keccak-256 hash of the enclave's first three platform configuration registers, PCR0, PCR1 and PCR2. The registries read these markers; they never parse a document themselves, and they refuse a marker whose epoch is not the configuration's current one.

Its one governed setting is the root anchor, changed only through the timelock. Each change advances the anchor's epoch, which retires every marker minted under the anchor it replaced. See [trusted execution](https://docs.umbraprivacy.com/docs/cryptography/trusted-execution).

## P-384 signature verifier

Solana has no syscall for the P-384 curve AWS signs with, so this program verifies one ECDSA P-384 signature in software, spread over several transactions. A requester opens a session with the public key and signature, absorbs the message in chunks, and finishes the hash. Anyone may then crank the session: each step advances the signature check by a bounded amount of work, so no single transaction exceeds its compute budget. When the check completes, the verdict is recorded, and the requester publishes an accepted verdict as a result marker, keyed to the requester and to what was signed.

The Nitro verifier reads those markers and accepts only ones minted for the same requester. The program has no governance: there is no setting to change.

## Screener registry

The screener registry records the screener and data endorser nodes the pool accepts, each as a node of one kind (screener or data endorser) at a numbered slot, with its BLS key. Registering a node, revoking it and rotating its key are all timelocked governance operations, and a proposal commits to the exact kind, slot and key. Registration is the only instruction that creates a node record, so nobody can take a slot before governance fills it. Every key must come with a proof of possession.

The pool takes the screener and data endorser records a transaction names, checks that each is this registry's Active node of the right kind, and adds their keys to the combined attester key. Revoking a node removes its record, after which the pool refuses it. See [screening](https://docs.umbraprivacy.com/docs/screening).

## Fee enclave

The fee enclave program keeps the single fee enclave's record: its BLS authorisation key, the treasury owner commitment that every fee note is bound to, its controller, its attested measurement and its status. A configuration account holds up to four approved measurements and the attestation freshness window.

Governance registers the enclave under a controller key, can hand it to another controller, sets the attestation policy, and switches the enclave on or off and freezes or unfreezes it, all through the timelock. The controller boots the enclave. To finish a boot it presents the Nitro verifier's marker for a document binding the enclave's key, the authorisation key, the treasury commitment and the current boot to an approved measurement, and the authorisation key must come with a proof of possession. The record serves, and the pool accepts it, only while it is attested, switched on, not frozen and on an approved measurement. If governance removes the record's measurement from the approved set, anyone may evict the enclave once 5,400 slots have passed since that change, which ends the record for good. See [the fee enclave](https://docs.umbraprivacy.com/docs/fees/fee-enclave).

## Zone registry

The zone registry records zones and the keys that sign for them, and keeps the Merkle root of those signers that the transaction circuit checks zone signatures against. A zone applies with an Ed25519 authority, a BabyJubJub signing key and six delays of its own choosing. Governance approves exactly that application, and the zone takes the next zone number.

After that, the zone's own authority manages it: it queues key rotations, handovers, delay changes, freezes and unfreezes, each taking effect only after its delay and within an execution window, and it can cancel any of them at once. The bootstrap authority can recover a zone whose keys are lost, behind the zone's recovery delay and subject to the zone's veto, and governance can revoke a zone. Each change to a zone's key or status rewrites its leaf in the signer-set tree, and anyone may rebuild the root from the leaves. The shielded pool accepts only the live root, and refuses it from the moment a leaf changes until a rebuild has folded the change, so a removed key stops verifying in the instruction that removes it; a transaction proved against a replaced root is proved again. A key rotation or an unfreeze also waits a cooldown, set by governance, since the zone's leaf last changed, which limits how often one zone can change the root. The tree starts at two levels of eight, 64 positions, and the registry admits at most 61 zones, so one transaction always rebuilds the root. See [zones](https://docs.umbraprivacy.com/docs/zones).

## User registry

The user registry has one instruction, `bind_platform_wallet`. Your main wallet and your platform wallet both sign it, so neither can be named without its consent, and it must be called directly by the transaction, never through another program, so a program handed your signature cannot rebind you. It creates and stores nothing. The successful instruction is the binding: it is listed under a fixed address derived from your main wallet, and a reader takes the latest one as current. See [the platform wallet](https://docs.umbraprivacy.com/docs/account/platform-wallet).

## Reference

**Program addresses**

| Program                    | Address (mainnet)                             |
| -------------------------- | --------------------------------------------- |
| fee-enclave                | `fees2eRjYhkrYWk5kpW5zomctJuNi6pnFogtQYPdZ7T` |
| guardian-node-registry     | `guardJCFiyrZYMtemR9RANvNPrCCbaJkgd81cixFMrD` |
| nitro-attestation-verifier | `nitroPQ4a4fm8Mo21XXDbUhvUD54y9ngVisc8abkwCA` |
| p384-signature-verifier    | `p384zZoBPJjXMdCdaQ3grDuon28ritB46pM2YVACJCr` |
| screener-registry          | `infraWB8UxfsauH1xggTNNaHHYwPNrSyzyKKQ8tJBnc` |
| shielded-pool              | `nimBUs55CbjkNfy8UvK48DqFTY7L2mdkmZMQC9mk6LK` |
| user-registry              | `user69YjhU8d8noiQy9H3zsPnSiT38DK8qZfmrWSLjL` |
| zone-registry              | `zoneuqdwPKk6VpmJf3CMZq5AaLHxCatTXKLVo7geBdh` |

Read at build time from `keys/program-ids.mainnet.toml`.

**Shielded pool instructions**

| Tag  | Instruction                           | Version | Payload bytes | Accounts |
| ---- | ------------------------------------- | ------- | ------------- | -------- |
| `0`  | `register`                            | v0      | 306           | 6        |
| `1`  | `vault_initialize`                    | v0      | 0             | 7        |
| `2`  | `initialize_submitter_tip_accrual`    | v0      | 32            | 5        |
| `3`  | `claim_submitter_tip`                 | v0      | 1             | 7        |
| `4`  | `process_policy_set`                  | v0      | 80            | 6        |
| `5`  | `initialize_commitment_tree`          | v0      | 2             | 3        |
| `6`  | `initialize_identity_tree`            | v0      | 2             | 3        |
| `7`  | `initialize_nullifier_turnstile`      | v0      | 2             | 3        |
| `8`  | `registration_turnstile_initialize`   | v0      | 2             | 3        |
| `9`  | `resize_turnstile`                    | v0      | 2             | 3        |
| `10` | `finalize_nullifier_turnstile`        | v0      | 2             | 2        |
| `11` | `finalize_registration_turnstile`     | v0      | 2             | 2        |
| `12` | `forester_commit`                     | v0      | 290           | 1        |
| `13` | `registration_forester_commit`        | v0      | 290           | 1        |
| `14` | `governance_initialize`               | v0      | 41            | 4        |
| `15` | `governance_propose`                  | v0      | 33            | 5        |
| `16` | `governance_cancel`                   | v0      | 0             | 4        |
| `17` | `initialize_fee_commitment_tree`      | v0      | 2             | 3        |
| `18` | `initialize_fee_turnstile`            | v0      | 2             | 3        |
| `19` | `finalize_fee_turnstile`              | v0      | 2             | 2        |
| `20` | `fee_forester_commit`                 | v0      | 290           | 1        |
| `21` | `execute_reassign_authority`          | v0      | 41            | 5        |
| `22` | `treasury_payout_address_set`         | v0      | 64            | 6        |
| `23` | `claim_fee_20`                        | v0      | 792           | 9        |
| `24` | `process_3x3x2x2`                     | v0      | 798           | 39       |
| `25` | `escape_hatch`                        | v0      | 329           | 15       |
| `26` | `initialize_escape_hatch_fee_accrual` | v0      | 2             | 5        |
| `27` | `claim_escape_hatch_fee`              | v0      | 3             | 8        |
| `28` | `mint_allowance_grant`                | v0      | 32            | 6        |
| `29` | `mint_allowance_revoke`               | v0      | 32            | 6        |
| `30` | `propose_reassign_authority`          | v0      | 41            | 6        |
| `31` | `committee_key_create`                | v0      | 12            | 7        |
| `32` | `committee_key_refresh`               | v0      | 0             | 5        |
| `33` | `insert_fee_commitments`              | v0      | 2             | 1        |
| `34` | `finalize_fee_commitment_tree`        | v0      | 2             | 2        |
| `35` | `lamport_vault_initialize`            | v0      | 0             | 3        |
| `36` | `release_escape_escrow`               | v0      | 0             | 6        |
| `37` | `finalize_commitment_tree`            | v0      | 2             | 2        |
| `38` | `finalize_identity_tree`              | v0      | 2             | 2        |

Read at build time from `contracts/solana/tools/umbra-manifest/manifest/shielded-pool.json`.

**Guardian node registry instructions**

| Tag  | Instruction                    | Version | Payload bytes | Accounts |
| ---- | ------------------------------ | ------- | ------------- | -------- |
| `0`  | `initialize_config`            | v0      | 0             | 3        |
| `1`  | `create_cluster`               | v0      | 64            | 7        |
| `2`  | `configure_cluster`            | v0      | 20            | 5        |
| `3`  | `activate_cluster`             | v0      | 8             | 8        |
| `4`  | `freeze_cluster`               | v0      | 8             | 5        |
| `5`  | `unfreeze_cluster`             | v0      | 8             | 5        |
| `6`  | `close_cluster`                | v0      | 8             | 8        |
| `7`  | `register_node`                | v0      | 41            | 4        |
| `8`  | `approve_node`                 | v0      | 16            | 6        |
| `9`  | `reassign_leader`              | v0      | 40            | 6        |
| `10` | `advance_boot`                 | v0      | 32            | 3        |
| `11` | `propose_controller_rotation`  | v0      | 32            | 4        |
| `12` | `finalize_controller_rotation` | v0      | 0             | 1        |
| `13` | `decommission`                 | v0      | 0             | 3        |
| `14` | `add_founding_member`          | v0      | 16            | 6        |
| `15` | `remove_founding_member`       | v0      | 16            | 7        |
| `16` | `begin_member_addition`        | v0      | 16            | 6        |
| `17` | `finalize_member_addition`     | v0      | 0             | 4        |
| `18` | `cancel_member_addition`       | v0      | 8             | 3        |
| `19` | `begin_member_removal`         | v0      | 16            | 6        |
| `20` | `finalize_member_removal`      | v0      | 0             | 5        |
| `21` | `cancel_member_removal`        | v0      | 0             | 4        |
| `22` | `set_cluster_maintenance`      | v0      | 8             | 5        |
| `23` | `clear_cluster_maintenance`    | v0      | 8             | 5        |
| `24` | `reject_node_application`      | v0      | 16            | 7        |
| `25` | `withdraw_node_application`    | v0      | 0             | 3        |
| `26` | `finalize_boot`                | v0      | 232           | 5        |
| `27` | `finalize_key_rotation`        | v0      | 264           | 5        |
| `28` | `evict_unapproved_node`        | v0      | 0             | 3        |
| `29` | `governance_initialize`        | v0      | 41            | 4        |
| `30` | `governance_propose`           | v0      | 33            | 5        |
| `31` | `governance_cancel`            | v0      | 0             | 4        |
| `32` | `execute_reassign_authority`   | v0      | 41            | 5        |
| `33` | `execute_freeze_cluster`       | v0      | 8             | 6        |
| `34` | `execute_unfreeze_cluster`     | v0      | 8             | 5        |
| `35` | `propose_reassign_authority`   | v0      | 41            | 6        |
| `36` | `propose_cluster_operation`    | v0      | 41            | 7        |
| `37` | `propose_leader_delays`        | v0      | 152           | 7        |
| `38` | `propose_bootstrap_delays`     | v0      | 32            | 7        |
| `39` | `cancel_cluster_proposal`      | v0      | 8             | 4        |
| `40` | `approve_measurement`          | v0      | 40            | 5        |
| `41` | `revoke_measurement`           | v0      | 40            | 5        |
| `42` | `begin_self_removal`           | v0      | 0             | 3        |
| `43` | `transfer_leader`              | v0      | 40            | 5        |
| `44` | `set_leader_delays`            | v0      | 152           | 6        |
| `45` | `rotate_bootstrap`             | v0      | 40            | 5        |
| `46` | `set_bootstrap_delays`         | v0      | 32            | 6        |
| `47` | `set_node_manifest`            | v0      | 48            | 6        |

Read at build time from `contracts/solana/tools/umbra-manifest/manifest/guardian-node-registry.json`.

**Nitro attestation verifier instructions**

| Tag  | Instruction                  | Version | Payload bytes | Accounts |
| ---- | ---------------------------- | ------- | ------------- | -------- |
| `0`  | `init_buffer`                | v0      | 9             | 3        |
| `1`  | `append_chunk`               | v0      | 804           | 2        |
| `2`  | `parse_and_verify`           | v0      | 194           | 14       |
| `3`  | `close_attestation`          | v0      | 32            | 2        |
| `4`  | `initialize_governance`      | v0      | 41            | 3        |
| `5`  | `initialize_config`          | v0      | 32            | 3        |
| `6`  | `governance_propose`         | v0      | 33            | 4        |
| `7`  | `governance_cancel`          | v0      | 0             | 4        |
| `8`  | `execute_update_root_anchor` | v0      | 32            | 5        |
| `9`  | `execute_reassign_authority` | v0      | 41            | 5        |
| `10` | `grow_buffer`                | v0      | 0             | 2        |
| `11` | `close_buffer`               | v0      | 0             | 2        |
| `12` | `propose_reassign_authority` | v0      | 41            | 5        |

Read at build time from `contracts/solana/tools/umbra-manifest/manifest/nitro-attestation-verifier.json`.

**P-384 signature verifier instructions**

| Tag | Instruction            | Version | Payload bytes | Accounts |
| --- | ---------------------- | ------- | ------------- | -------- |
| `0` | `open_verification`    | v0      | 208           | 3        |
| `1` | `absorb_message_chunk` | v0      | 800           | 2        |
| `2` | `finish_hashing`       | v0      | 0             | 1        |
| `3` | `step_verifying`       | v0      | 2             | 1        |
| `4` | `record_verdict`       | v0      | 0             | 1        |
| `5` | `publish_result`       | v0      | 0             | 4        |
| `6` | `close_result_marker`  | v0      | 32            | 2        |
| `7` | `close_verification`   | v0      | 0             | 2        |

Read at build time from `contracts/solana/tools/umbra-manifest/manifest/p384-signature-verifier.json`.

**Screener registry instructions**

| Tag | Instruction                  | Version | Payload bytes | Accounts |
| --- | ---------------------------- | ------- | ------------- | -------- |
| `0` | `initialize_governance`      | v0      | 41            | 3        |
| `1` | `governance_propose`         | v0      | 33            | 4        |
| `2` | `governance_cancel`          | v0      | 0             | 4        |
| `3` | `execute_reassign_authority` | v0      | 41            | 5        |
| `4` | `execute_register_node`      | v0      | 195           | 6        |
| `5` | `execute_revoke_node`        | v0      | 3             | 6        |
| `6` | `execute_rotate_node_key`    | v0      | 195           | 5        |
| `7` | `propose_reassign_authority` | v0      | 41            | 5        |

Read at build time from `contracts/solana/tools/umbra-manifest/manifest/screener-registry.json`.

**Fee enclave instructions**

| Tag  | Instruction                      | Version | Payload bytes | Accounts |
| ---- | -------------------------------- | ------- | ------------- | -------- |
| `0`  | `initialize_governance`          | v0      | 41            | 3        |
| `1`  | `initialize_config`              | v0      | 262           | 3        |
| `2`  | `governance_propose`             | v0      | 33            | 4        |
| `3`  | `governance_cancel`              | v0      | 0             | 4        |
| `4`  | `execute_reassign_authority`     | v0      | 41            | 5        |
| `5`  | `execute_set_attestation_policy` | v0      | 262           | 6        |
| `6`  | `execute_register_enclave`       | v0      | 32            | 6        |
| `7`  | `execute_rotate_controller`      | v0      | 32            | 5        |
| `8`  | `execute_close_enclave`          | v0      | 0             | 6        |
| `9`  | `execute_activate`               | v0      | 0             | 5        |
| `10` | `execute_deactivate`             | v0      | 0             | 6        |
| `11` | `execute_freeze`                 | v0      | 0             | 6        |
| `12` | `execute_unfreeze`               | v0      | 0             | 5        |
| `13` | `advance_boot`                   | v0      | 32            | 2        |
| `14` | `finalize_boot`                  | v0      | 296           | 5        |
| `15` | `finalize_key_rotation`          | v0      | 328           | 5        |
| `16` | `decommission`                   | v0      | 0             | 2        |
| `17` | `evict_unapproved_enclave`       | v0      | 0             | 2        |
| `18` | `propose_reassign_authority`     | v0      | 41            | 5        |

Read at build time from `contracts/solana/tools/umbra-manifest/manifest/fee-enclave.json`.

**Zone registry instructions**

| Tag  | Instruction                  | Version | Payload bytes | Accounts |
| ---- | ---------------------------- | ------- | ------------- | -------- |
| `0`  | `initialize_governance`      | v0      | 41            | 3        |
| `1`  | `governance_propose`         | v0      | 33            | 4        |
| `2`  | `governance_cancel`          | v0      | 0             | 4        |
| `3`  | `execute_reassign_authority` | v0      | 41            | 5        |
| `4`  | `initialize_zone_signer_set` | v0      | 8             | 3        |
| `5`  | `apply_zone`                 | v0      | 112           | 3        |
| `6`  | `withdraw_application`       | v0      | 0             | 2        |
| `7`  | `execute_approve_zone`       | v0      | 144           | 9        |
| `8`  | `propose_zone_key`           | v0      | 68            | 2        |
| `9`  | `propose_zone_authority`     | v0      | 36            | 2        |
| `10` | `accept_zone_authority`      | v0      | 4             | 2        |
| `11` | `propose_zone_delays`        | v0      | 52            | 2        |
| `12` | `open_recovery`              | v0      | 101           | 4        |
| `13` | `cancel_recovery`            | v0      | 4             | 4        |
| `14` | `execute_recovery`           | v0      | 4             | 5        |
| `15` | `execute_revoke_zone`        | v0      | 4             | 6        |
| `16` | `execute_set_tree_shape`     | v0      | 7             | 5        |
| `17` | `execute_set_parameters`     | v0      | 8             | 5        |
| `18` | `rebuild_root`               | v0      | 4             | 1        |
| `19` | `execute_zone_key`           | v0      | 4             | 2        |
| `20` | `execute_zone_delays`        | v0      | 4             | 1        |
| `21` | `propose_freeze_zone`        | v0      | 4             | 2        |
| `22` | `execute_freeze_zone`        | v0      | 4             | 2        |
| `23` | `propose_unfreeze_zone`      | v0      | 4             | 2        |
| `24` | `execute_unfreeze_zone`      | v0      | 4             | 2        |
| `25` | `cancel_zone_changes`        | v0      | 5             | 2        |
| `26` | `propose_reassign_authority` | v0      | 41            | 5        |

Read at build time from `contracts/solana/tools/umbra-manifest/manifest/zone-registry.json`.

**User registry instructions**

| Tag | Instruction            | Version | Payload bytes | Accounts |
| --- | ---------------------- | ------- | ------------- | -------- |
| `0` | `bind_platform_wallet` | v0      | 0             | 3        |

Read at build time from `contracts/solana/tools/umbra-manifest/manifest/user-registry.json`.

## Related

- [Governance and upgrades](https://docs.umbraprivacy.com/docs/security/governance): Who can change each program.
- [Versions](https://docs.umbraprivacy.com/docs/architecture/versions): Instruction and layout versions.
- [System map](https://docs.umbraprivacy.com/docs/architecture/overview): How the programs fit with everything else.


Last updated 12 October 2026
