Skip to main content

How X25519 Compliance Grants Work

Encrypted token account balances in Umbra are stored as ciphertexts on-chain. By default, only you can read your own balance - Arcium MPC will not re-encrypt your ciphertexts for a third party without explicit authorization. An X25519 compliance grant is an on-chain PDA that grants that authorization. Once the PDA exists, Arcium MPC is permitted to re-encrypt your ciphertexts under the grantee’s X25519 key. The grantee can then decrypt the output locally using their own private key - without you needing to be online.
The grant PDA is a marker account - its presence on-chain is the authorization. No data is stored in it beyond the discriminator.
Once a re-encryption instruction is executed, the grantee receives a ciphertext encrypted under their own X25519 key. They hold this permanently. More critically: because Rescue is a stream cipher, possessing a re-encrypted ciphertext for a given nonce allows the grantee to derive the full keystream for that nonce. This means all past and future encryptions produced under the same nonce are also permanently readable by the grantee - not just the single ciphertext that was re-encrypted. Revoking the grant stops future re-encryption requests but cannot undo this. Treat each nonce as a scope of permanent disclosure once any re-encryption instruction for it has been executed.

Prerequisites

1. Your X25519 Public Key (Granter Key)

For user-granted compliance grants, the granterX25519 parameter is your MVK (master viewing key) X25519 public key - the Curve25519 key derived from your master seed’s MVK X25519 keypair. This is distinct from the user account X25519 key used for encrypting token balances. The MVK X25519 key is used to prove ownership of the master viewing key during grant creation. The SDK derives it internally via the masterViewingKeyX25519KeypairGenerator dependency. You can derive and read your MVK X25519 public key from the client:

2. Receiver’s X25519 Public Key

The receiverX25519 is the grantee’s X25519 public key. This is the key that Arcium MPC will re-encrypt the ciphertext under. The receiver derives it from their own master seed. The receiver can share their X25519 public key with you out-of-band, or you can look it up from their registered user account:

3. Nonce

A compliance grant authorizes re-encryption of any Rescue cipher encryption scoped to a specific X25519 public key + nonce combination. Only ciphertexts encrypted under that exact pubkey and nonce are covered - anything encrypted under a different nonce is outside the scope of the grant. The nonce is also part of the on-chain PDA seed, so multiple independent grants (e.g. to different parties or different nonces) can coexist simultaneously. Generate a random nonce using the SDK’s utility:
Store the nonce - you will need it to delete the grant later, to look up the PDA, and to pass as the inputEncryptionNonce when triggering re-encryption.
Because Rescue is a stream cipher, a grantee who obtains a re-encrypted ciphertext for a given nonce can derive the keystream for that nonce and read all encryptions produced under it - not just the one that was re-encrypted. Use a fresh nonce for each grant and each disclosure scope. Never reuse a nonce across grants you intend to keep independent.

Creating a User-Granted Compliance Grant

The transaction includes an Ed25519 signature over the grant parameters, produced using your MVK X25519 keypair’s Ed25519 component. This proves to the on-chain program that the granter controls the master viewing key - without revealing the key itself.

Querying a Grant

Check whether a grant is active before attempting re-encryption:
The grant PDA is derived deterministically from these three values, so the query is a pure account existence check with no network round-trip beyond the RPC call.

Re-Encrypting Ciphertexts (Grantee Workflow)

Once the grant is active, the grantee calls the re-encryption function. This triggers an Arcium MPC computation that decrypts the granter’s Shared-mode ciphertexts and re-encrypts them under the receiver’s X25519 key.

Parameters

X25519PublicKey
required
The granter’s MVK X25519 public key. Must match the key used when the grant was created.
X25519PublicKey
required
The receiver’s (grantee’s) X25519 public key. Arcium MPC will re-encrypt the output under this key.
RcEncryptionNonce
required
The 128-bit nonce from the grant creation. Used to locate the grant PDA on-chain.
RcEncryptionNonce
required
The nonce of the specific ciphertext you want re-encrypted. This is the nonce associated with the encrypted token account state at a specific point in time.
readonly Uint8Array[]
required
An array of 1 to 6 ciphertext values (32 bytes each). Unused slots are padded with zero bytes. These are the raw encrypted balance ciphertexts fetched from the on-chain encrypted token account.
Re-encryption follows the dual-instruction pattern. The SDK submits the handler, waits for Arcium MPC to produce the re-encrypted output, then waits for the callback to confirm. The re-encrypted ciphertext is written on-chain in an MPC callback data PDA.

Revoking a Grant

Delete the grant PDA to prevent future re-encryption requests. The grant parameters must exactly match the original creation.
Deleting the grant closes the PDA and returns the rent lamports to the fee payer.
Revoking a grant stops future re-encryption requests but does not affect anything the grantee has already received. Any ciphertext they obtained before revocation remains permanently accessible to them - there is no mechanism to claw it back. Revocation is a forward-only control.

Full End-to-End Workflow Example


PDA Structure

For reference, the grant PDA is derived from these seeds (using Arcium-encoded byte representations):
The PDA’s existence is the authorization - it contains no data beyond the account discriminator.