XLS: Confidential Key Rotation #599
Replies: 2 comments 1 reply
|
Updating the draft for ConfidentialMPTMirrorUpdate transaction part, so the holder mode supports all the paths as the issuer flow:
Holder Self-Migration Mode (Submitted by the holder. The holder decrypts their own sfConfidentialBalanceSpending with their private key and re-encrypts it under the relevant new public key(s). Require sfConfidentialBalanceInbox to be canonically zero.)
|
|
Is there any consideration for allowing a holder to delete their MPToken when the encrypted balance is zero as part of this amendment? Currently, holders can only delete it when the COA is 0, which isn’t ideal. Perhaps in the future, we should also consider a feature to clear the encrypted balance fields when the underlying value is zero. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
ElGamal Key Rotation for Confidential MPTs
1. Abstract
This amendment extends XLS-0096 (Confidential Transfers for Multi-Purpose Tokens) with ElGamal key rotation for all three participant roles: issuer, auditor, and holder. It introduces 3 new transaction types (
ConfidentialMPTMirrorUpdate,ConfidentialMPTHolderKeyUpdate,ConfidentialMPTRecoverBalance), extends one existing transaction type (MPTokenIssuanceSet), and adds new fields to theMPTokenIssuanceandMPTokenledger objects. Key rotation is supported for both voluntary and loss-recovery scenarios. All new cryptographic constructions reuse existing primitives from XLS-0096 (compact Chaum-Pedersen equality proofs, Schnorr proofs of knowledge) and introduce no new cryptographic assumptions.2. Motivation
XLS-0096 encrypts MPT balances using ElGamal keys held by issuers, holders, and auditors. These keys are independent of XRPL signing keys and currently have no rotation mechanism. This gap creates three unresolved operational risks:
First, a compromised ElGamal key - at any role - gives an attacker persistent read access to confidential balances with no remediation path.
Second, operations teams change over time. XRPL signing key rotation is handled by existing primitives (
SetRegularKey,SignerListSet). No equivalent exists for ElGamal keys held by any role.Third, auditor key loss or a change in supervisory authority breaks regulatory visibility into all holder balances with no recovery path. For regulated issuances operating under compliance obligations, the inability to rotate the auditor key is a go-live blocker.
This amendment defines the rotation and recovery mechanisms required to address all three scenarios across all three roles. It directly addresses the limitation acknowledged in XLS-0096 FAQ A.6: "If a holder loses their ElGamal private key, they will be unable to decrypt or spend their confidential balances, which will remain valid on-ledger but are effectively locked and irrecoverable by that holder."
3. Definitions & Terminology
Terms not defined here carry the same meaning as in XLS-0096.
MPTokenIssuancethat increments on each ElGamal key rotation for the issuer or auditor role.MPTokenthat tracks the last key epoch at which the holder's issuer or auditor mirror ciphertext was re-encrypted.MPTokenIssuance. A stale mirror is encrypted under an old key and cannot be combined homomorphically with new transaction deltas encrypted under the current key. Validators enforce staleness checks on all confidential transactions that touch the issuer or auditor mirror - see Section 14.1 for the full list of affected transactions and failure conditions.ConfidentialMPTMirrorUpdatefor each holder after a key rotation to re-encrypt mirror ciphertexts under the new key.sfRecoveryKey): A transient field onMPTokenset by the holder to authorize replacement of their ElGamal key when they have lostsk_H.4. Scope
4.1. Modified Transaction Types
MPTokenIssuanceSet: Extended to allow replacement ofIssuerEncryptionKeyandAuditorEncryptionKeywhen already present, enabling issuer and auditor key rotation.4.2. New Transaction Types
ConfidentialMPTMirrorUpdate: Re-encrypts a single holder's issuer and/or auditor mirror ciphertext under the new key. Operates in two modes selected byHolderfield presence:-Issuer mode (
Holderpresent): submitted by the issuer using a Chaum-Pedersen equality proof anchored to the on-ledger issuer mirror.Holderabsent): submitted by the holder using a cross-key equality proof anchored toConfidentialBalanceSpending. RequiresConfidentialBalanceInboxto be canonical zero.ConfidentialMPTHolderKeyUpdate(transaction type 91): Rotates a holder's ElGamal key, authorizes recovery, or cancels pending recovery. Operates in three modes selected by transaction flag:tfHolderKeyRotation): holder re-encryptsConfidentialBalanceSpendingandConfidentialBalanceInboxunder the new key atomically.tfHolderKeyRecovery): holder has lostsk_H; registers new key asRecoveryKeyfor issuer-completed recovery.tfCancelRecovery): holder clears a pendingRecoveryKeyauthorization.ConfidentialMPTRecoverBalance: Completes holder key loss recovery by re-encrypting balances under the authorized new key. Submitted by the issuer.4.3. Modified Ledger Entries
MPTokenIssuance: Three new fields -IssuerKeyEpoch,AuditorKeyEpoch.MPToken: Three new fields -IssuerKeyMirrorEpoch,AuditorKeyMirrorEpoch,RecoveryKey.5. Specification
5.1. Key Rotation Model
Issuer key rotation proceeds in two phases. First, the issuer submits
MPTokenIssuanceSetwith a newIssuerEncryptionKey, incrementingIssuerKeyEpoch. After this transaction is accepted, all new issuer mirror delta ciphertexts must be encrypted under the new key. Second, the issuer submitsConfidentialMPTMirrorUpdateonce per holder to re-encrypt each holder's issuer mirror under the new key.Until a holder's mirror is migrated, confidential transactions for that holder are rejected. The underlying reason is cryptographic: in
ConfidentialMPTSendand other transactions, the holder correctly reads the currentIssuerEncryptionKey(pk_I') from the issuance and constructsIssuerEncryptedAmountunder it. However, the on-ledger accumulatedIssuerEncryptedBalanceis still under the old key (pk_I). Adding a delta underpk_I'to an accumulated balance underpk_Iis cryptographically invalid - ciphertexts under different keys cannot be combined homomorphically.The epoch check (
IssuerKeyMirrorEpoch < IssuerKeyEpoch) makes this detectable cleanly:IssuerKeyMirrorEpochon the holder'sMPTokenagainstIssuerKeyEpochonMPTokenIssuance, the wallet knows the send will fail and can warn the holder and block submission before it reaches the networkAuditor key rotationfollows the identical pattern usingAuditorEncryptionKeyandAuditorKeyEpoch.Auditor key late-registration by issuer allows the issuer to register auditor key after the issuer key was already registered.
ConfidentialMPTKeyRotationamendment: when registering the key for the auditor first time, it has to be registered together with the issuer key inMPTokenIssuanceSet. The issuer is not allowed to register issuer key in one transaction and later register auditor key in another transaction.ConfidentialMPTKeyRotationamendment: with the issuer key already registered, the issuer can register the auditor key in a separateMPTokenIssuanceSetwhenever they want to enable auditor.Holder self-migration is available as an alternative to issuer-driven active re-encryption in all rotation scenarios. Rather than waiting for the issuer to submit
ConfidentialMPTMirrorUpdate, any holder may self-migrate their issuer or auditor mirror by submittingConfidentialMPTMirrorUpdatewithout aHolderfield, using a cross-key equality proof anchored to theirConfidentialBalanceSpending. Prerequisites:ConfidentialMPTMergeInboxmust be run first (inbox must be canonical zero), and the holder must havesk_H. See Section 9.9 for the full proof construction.Simultaneous issuer and auditor key rotation: The issuer may rotate both
IssuerEncryptionKeyandAuditorEncryptionKeyin a singleMPTokenIssuanceSettransaction, though this is rare in practice. In this case, per-holder migration may be performed in a singleConfidentialMPTMirrorUpdatetransaction with bothIssuerEncryptedAmountandAuditorEncryptedAmountpresent. A single compact AND-composed Chaum-Pedersen equality proof covers both statements under one Fiat-Shamir challenge.Multiple successive rotations: The issuer may rotate multiple times before completing migration. Holders with stale mirrors are blocked from transacting at the per-transaction level regardless of how many epochs behind they are.
ConfidentialMPTMirrorUpdatebridges directly from the holder's current epoch to the latest epoch in one step. In issuer mode, this requires the issuer to retain the historical secret key corresponding to the epoch the holder is currently at - if that key has been destroyed, the holder must self-migrate by submittingConfidentialMPTMirrorUpdatewithout aHolderfield instead.Holder key rotation is self-contained via
ConfidentialMPTHolderKeyUpdatewithtfHolderKeyRotation. No issuer involvement required.Holder key loss recovery is a two-step process: the holder registers the new key on-chain via
ConfidentialMPTHolderKeyUpdatewithtfHolderKeyRecovery, then the issuer completes recovery viaConfidentialMPTRecoverBalance.Issuer key loss is handled via holder-driven mirror reconstruction for both issuer and auditor mirrors. In the issuer key loss scenario, holder self-migration is the only path for issuer mirrors since the issuer cannot decrypt old mirrors without
sk_I. For auditor mirrors, the issuer can still perform active re-encryption via the issuer mirror (sk_I) even whensk_Ais lost - holder self-migration is an alternative but not the only path. See Section 13.5.2. Re-encryption Strategy
Active re-encryption is the recommended strategy. The issuer submits
ConfidentialMPTMirrorUpdatefor all holders after rotating the key. The issuer is recommended to lock each holder'sMPTokenbefore submittingConfidentialMPTMirrorUpdateand unlock after success. Note: this is a recommendation, not a requirement. The epoch staleness check already prevents the holder from successfully transacting with a stale mirror - the lock only prevents the holder from wasting fees on transactions that will be rejected. However, lock +ConfidentialMPTMirrorUpdate+ unlock = 3 transactions per holder, tripling migration transaction volume at large holder counts. Issuers should weigh this cost against the UX benefit.Prioritization for bulk migration:
The issuer may rotate keys multiple times. Holders with stale mirrors are blocked from transacting at the per-transaction level regardless of how many epochs behind they are. See Section 14.1.
Clawback and migration urgency: Clawback is blocked for any unmigrated holder after key rotation - the issuer must complete
ConfidentialMPTMirrorUpdatebefore executingConfidentialMPTClawbackfor that holder.Historical key retention: After multiple successive rotations, migrating a holder still at an old epoch requires the historical secret key for that epoch to decrypt their on-ledger mirror. If the issuer has destroyed a historical key before all holders at that epoch were migrated, those holders must fall back to self-migration (Section 9.9). Issuers should retain historical secret keys until all holders at each epoch are fully migrated.
5.3. Epoch Tracking and Migration Attestation
IssuerKeyEpochandAuditorKeyEpochonMPTokenIssuance, together withIssuerKeyMirrorEpochandAuditorKeyMirrorEpochon eachMPToken, provide complete on-chain attestation of migration progress. Whether a holder's mirror is stale is trivially known on-ledger in O(1) - no off-ledger information required.A holder who executes
ConfidentialMPTConvertafter a key rotation will have theirMPTokeninitialized with ciphertexts under the current key and epoch fields set to the current epoch values. These holders are never stale - they start at the current epoch with no migration needed.6. Ledger Entry:
MPTokenIssuanceThe existing
MPTokenIssuanceledger object is extended with three new fields. All other fields, flags, ownership, reserves, deletion conditions, and the object identifier are unchanged from XLS-0033.6.1. Fields
IssuerKeyEpochnumberUINT32AuditorKeyEpochnumberUINT32Note: To accommodate existing
MPTokenIssuanceledger objects that lack epoch fields even when keys are registered, the epoch value should remain absent after initial registration. It is set to 1 only when rotating a key for the first time successfully, and then increments with each subsequent rotation.6.2. Invariants
IssuerKeyEpoch, if present, must be ≥ 1.AuditorKeyEpoch, if present, must be ≥ 1.IssuerEncryptionKeymust be present ifIssuerKeyEpochis present.AuditorEncryptionKeymust be present ifAuditorKeyEpochis present.6.3. Example JSON
After issuer and auditor key rotation:
{ "LedgerEntryType": "MPTokenIssuance", "Flags": 128, "Issuer": "rIssuerAccountAddress", "MPTokenIssuanceID": "000000012A9F1D3C...", "MaximumAmount": "1000000000", "OutstandingAmount": "500000000", "ConfidentialOutstandingAmount": "250000000", "IssuerEncryptionKey": "02a1b2c3d4e5f6...", "AuditorEncryptionKey": "02b1c2d3e4f5a6...", "IssuerKeyEpoch": 1, "AuditorKeyEpoch": 1, "PreviousTxnID": "A1B2C3D4...", "PreviousTxnLgrSeq": 1234567 }7. Ledger Entry:
MPTokenThe existing
MPTokenledger object is extended with three new fields. All other fields, flags, ownership, reserves, and the object identifier are unchanged from XLS-0033.7.1. Fields
IssuerKeyMirrorEpochnumberUINT32IssuerKeyEpochat which this holder's issuer mirror was last re-encrypted. Stale whenIssuerKeyMirrorEpoch<IssuerKeyEpochonMPTokenIssuance. Not stored when at default value 0.AuditorKeyMirrorEpochnumberUINT32AuditorKeyEpochat which this holder's auditor mirror was last re-encrypted. Stale whenAuditorKeyMirrorEpoch<AuditorKeyEpochonMPTokenIssuance. Not stored when at default value 0.RecoveryKeystringBLOBConfidentialMPTHolderKeyUpdatein recovery mode (tfHolderKeyRecovery). Cleared by exactly two paths: (1)ConfidentialMPTRecoverBalancewhen the issuer completes recovery; (2)ConfidentialMPTHolderKeyUpdatewithtfCancelRecoverywhen the holder explicitly cancels. Has no automatic expiry.7.2. Deletion
Deletion conditions are unchanged from XLS-0033. The
MPTokendeletion question raised byRecoveryKeyis a non-issue: per XLS-0096 Section 7.4, anMPTokencannot be deleted once confidential fields have been initialized, even if all balances contain canonical encrypted zero. SinceRecoveryKeyonly appears on initializedMPTokenobjects (Invariant I8), anMPTokenwithRecoveryKeyset can never be deleted. No new deletion concern is introduced by this amendment.7.3. Invariants
IssuerKeyMirrorEpoch, if present, must be ≤IssuerKeyEpochon the parentMPTokenIssuance(treated as 0 if absent).AuditorKeyMirrorEpoch, if present, must be ≤AuditorKeyEpochon the parentMPTokenIssuance(treated as 0 if absent).RecoveryKey, if present, must be a well-formed compressed secp256k1 point (33 bytes) and must differ from the currentHolderEncryptionKey.RecoveryKeymust not be present on anMPTokenthat has noHolderEncryptionKeyregistered. A holder initializes confidential state via their firstConfidentialMPTConvert(withHolderEncryptionKeypresent, MPTAmount may be zero).RecoveryKeyis only meaningful for holders who have completed this initialization.7.4. Example JSON
Fully migrated holder:
{ "LedgerEntryType": "MPToken", "Flags": 0, "MPTokenIssuanceID": "000000012A9F1D3C...", "Account": "rHolderAccountAddress", "HolderEncryptionKey": "02c1d2e3f4a5b6...", "ConfidentialBalanceSpending": "02d1e2f3a4b5c6...", "ConfidentialBalanceInbox": "02e1f2a3b4c5d6...", "ConfidentialBalanceVersion": 3, "IssuerEncryptedBalance": "02f1a2b3c4d5e6...", "IssuerKeyMirrorEpoch": 1, "AuditorEncryptedBalance": "02a1b2c3d4e5f6...", "AuditorKeyMirrorEpoch": 1, "PreviousTxnID": "B2C3D4E5...", "PreviousTxnLgrSeq": 1234568 }Holder with active recovery authorization:
{ "LedgerEntryType": "MPToken", "Flags": 0, "MPTokenIssuanceID": "000000012A9F1D3C...", "Account": "rHolderAccountAddress", "HolderEncryptionKey": "02c1d2e3f4a5b6...", "ConfidentialBalanceSpending": "02d1e2f3a4b5c6...", "ConfidentialBalanceInbox": "02e1f2a3b4c5d6...", "ConfidentialBalanceVersion": 3, "IssuerEncryptedBalance": "02f1a2b3c4d5e6...", "IssuerKeyMirrorEpoch": 1, "RecoveryKey": "02g1h2i3j4k5l6...", "PreviousTxnID": "C3D4E5F6...", "PreviousTxnLgrSeq": 1234569 }8. Transaction:
MPTokenIssuanceSetThe existing
MPTokenIssuanceSettransaction is extended to allow replacement ofIssuerEncryptionKeyandAuditorEncryptionKeywhen already present. Some existing guards in preclaim must be relaxed:IssuerEncryptionKeyandAuditorEncryptionKeyonce already present on the issuance object (tecNO_PERMISSION). This guard is relaxed to allow replacement when the field is already present. Key rotation does not reintroduce the vulnerability this guard was introduced to prevent - when rotating, the field already exists and every holder'sMPTokenalready has the corresponding ciphertext column.sfConfidentialOutstandingAmount> 0 guard: The current implementation unconditionally rejects updates toIssuerEncryptionKeywhensfConfidentialOutstandingAmountis already present (i.e. COA > 0). This guard must also be relaxed. Key rotation is only meaningful and necessary precisely when COA > 0 - if COA were zero, no holder would have a mirror yet and none of the migration logic would be needed. Maintaining this guard makes key rotation impossible in any real deployment.ConfidentialMPTKeyRotationamendment, an issuer cannot register an auditor key inMPTokenIssuanceSetunless the issuer key is being registered in the same transaction. This meansthe issuer can either register the issuer key alone or register both keys together initially. With the
ConfidentialMPTKeyRotationamendment, the issuer can now register an auditor key at any time after the issuer key is already registered or rotated—allowing them to opt in whenever they want. The only constraint is that an auditor key cannot be registered before an issuer key.The guard against adding
IssuerEncryptionKeywhenlsfMPTCanHoldConfidentialBalanceis not enabled remains unchanged - confidential transfers must be enabled before keys can be set or rotated.All existing
MPTokenIssuanceSetbehavior (lock/unlock,DomainID) is completely unaffected.8.1. Fields
IssuerEncryptionKeyAuditorEncryptionKey8.2. Failure Conditions
8.2.1. Data Verification
IssuerEncryptionKeyis present but is not exactly 33 bytes or is not a well-formed compressed secp256k1 point. (temMALFORMED)AuditorEncryptionKeyis present but is not exactly 33 bytes or is not a well-formed compressed secp256k1 point. (temMALFORMED)Note: Pre-
ConfidentialMPTKeyRotationamendment:AuditorEncryptionKeyis present withoutIssuerEncryptionKeyreturnstemMALFORMED; Now it is allowed in preflight and will be further verified in preclaim.8.2.2. Protocol-Level Failures
AuditorEncryptionKeyis being registered for the first time (not present on the issuance), but the issuance has noIssuerEncryptionKeyand the currentMPTokenIssuanceSettransaction does not provide one. (tecNO_PERMISSION)IssuerEncryptionKeymatches the current on-ledger value (no-op rotation). (tecNO_PERMISSION)AuditorEncryptionKeymatches the current on-ledger value (no-op rotation). (tecNO_PERMISSION)8.3. State Changes
When
IssuerEncryptionKeyis present and valid:IssuerEncryptionKeyonMPTokenIssuance← new key valueIssuerEncryptionKeyalready existed,IssuerKeyEpochonMPTokenIssuance←IssuerKeyEpoch+ 1 (field created with value 1 if previously absent); on initial registration, leave the epoch absent.When
AuditorEncryptionKeyis present and valid:AuditorEncryptionKeyonMPTokenIssuance← new key valueAuditorKeyEpochonMPTokenIssuance←AuditorKeyEpoch+ 1; on initial registration, leave the epoch absent.8.4. Example JSON
{ "TransactionType": "MPTokenIssuanceSet", "Account": "rIssuerAccountAddress", "MPTokenIssuanceID": "000000012A9F1D3C...", "IssuerEncryptionKey": "02a1b2c3d4e5f6...", "Fee": "120", "Sequence": 42 }9. Transaction:
ConfidentialMPTMirrorUpdateRe-encrypts a single holder's issuer and/or auditor mirror ciphertext under the new key after a key rotation. Submitted by the issuer once per holder per rotation. A holder may also self-migrate their issuer mirror. Every migration re-encrypts one or both of a holder's mirror balances under a rotated key, and proves the new ciphertext still encrypts the same balance without revealing it.
9.1. Use Cases
sfHolder):IssuerEncryptedBalanceunder the newpk_I'.AuditorEncryptedBalanceunder the newpk_A'.sfHolderfield. The holder decrypts their ownsfConfidentialBalanceSpendingwith their private key and re-encrypts it under the relevant new public key(s). RequiresfConfidentialBalanceInboxto be canonically zero, which means the holder has runConfidentialMPTMergeInboxfirst):9.2. Fields
Whether it is issuer mode or holder mode is determined by
Holderfield's presence. IfHolderis present, it is issuer mode. IfHolderis absent, it is holder self-migration mode.TransactionTypestringUINT16ConfidentialMPTMirrorUpdate, which is 90.AccountstringACCOUNTIDMPTokenIssuanceIDstringUINT192HolderstringACCOUNTIDIssuerEncryptedAmountstringBLOBsfIssuerEncryptedAmountfrom XLS-0096. Present to migrate holder's issuer mirror.AuditorEncryptedAmountstringBLOBsfAuditorEncryptedAmountfrom XLS-0096. Present to migrate holder's auditor mirror.PreviousIssuerEncryptionKeystringBLOBsfIssuerEncryptedBalancewas encrypted under. Required whenHolderandIssuerEncryptedAmountare both present, and forbidden otherwise.ZKProofstringBLOB9.3. Transaction Fee
10x base fee, consistent with XLS-0096 confidential transactions.
9.4. Failure Conditions
9.4.1. Data Verification
ConfidentialMPTKeyRotationorConfidentialTransferamendment is not enabled. (temDISABLED)Holderis present butAccountis not the issuer of theMPTokenIssuanceID. (temMALFORMED)Holderis present):Accountis the same asHolder. (temMALFORMED)Holderis absent):Accountis the issuer. (temMALFORMED)IssuerEncryptedAmountnorAuditorEncryptedAmountis present. (temMALFORMED)IssuerEncryptedAmountorAuditorEncryptedAmounthas an invalid length or represents an invalid elliptic curve point. (temBAD_CIPHERTEXT)PreviousIssuerEncryptionKeyis present but is not a valid 33-byte compressed elliptic curve point. (temMALFORMED)PreviousIssuerEncryptionKeydoes not follow the presence rule: the field is required only whenHolderandIssuerEncryptedAmountare both present, and must be absent in every other case. (temMALFORMED)ZKProoflength is not exactly the expected proof size for the detected mode. (TBD bytes - see Section 16) (temMALFORMED)9.4.2. Protocol-Level Failures
Accountdoes not exist. (terNO_ACCOUNT)MPTokenIssuancedoes not exist. (tecOBJECT_NOT_FOUND)lsfMPTCanHoldConfidentialBalanceflag set, or has no registeredsfIssuerEncryptionKey. (tecNO_PERMISSION)Holderaccount does not exist. (tecNO_TARGET)MPTokenobject does not exist. (tecOBJECT_NOT_FOUND)MPTokenhas nosfIssuerEncryptedBalance, there is no mirror to re-encrypt. (tecNO_PERMISSION)AuditorEncryptedAmountis present but the issuance has no registeredsfAuditorEncryptionKey. (tecNO_PERMISSION)IssuerEncryptedAmountis present but the holder'ssfIssuerKeyMirrorEpochis already greater than or equal to the issuance'ssfIssuerKeyEpoch, the mirror is not stale. (tecNO_PERMISSION)AuditorEncryptedAmountpresent,IssuerEncryptedAmountabsent): the holder'ssfIssuerKeyMirrorEpochdoes not equal the issuance'ssfIssuerKeyEpoch, the issuer mirror must be brought up to date first. (tecNO_PERMISSION)AuditorEncryptedAmountis present, the holder already has ansfAuditorEncryptedBalance, andsfAuditorKeyMirrorEpochis already greater than or equal to the issuance'ssfAuditorKeyEpoch— the mirror is not stale. First-time registration of an auditor mirror is exempt. (tecNO_PERMISSION)sfConfidentialBalanceInboxis absent or is not the canonical encrypted zero — the holder must runConfidentialMPTMergeInboxfirst. (tecNO_PERMISSION)ZKProoffails the compact Chaum-Pedersen equality proof verification. (tecBAD_PROOF)ZKProoffails the cross-key equality proof verification. (tecBAD_PROOF)9.5. State Changes
If
IssuerEncryptedAmountis present:sfIssuerEncryptedBalanceon the holder'sMPTokenis replaced byIssuerEncryptedAmount.sfIssuerKeyMirrorEpochon theMPTokenis set to the issuance's currentsfIssuerKeyEpoch.If
AuditorEncryptedAmountis present:sfAuditorEncryptedBalanceon the holder'sMPTokenis set toAuditorEncryptedAmount, creating the field if the holder did not previously have an auditor mirror.sfAuditorKeyMirrorEpochon theMPTokenis set to the issuance's currentsfAuditorKeyEpoch, unless that epoch is 0, in which case the field is left absent. An absent mirror epoch is equivalent to 0, so this only arises on first-time registration of an auditor mirror before any auditor key rotation has occurred.9.6. Example JSON
Which of
IssuerEncryptedAmountandAuditorEncryptedAmounta transactioncarries depends on the use case, at least one must be present, and both may be.
PreviousIssuerEncryptionKeyfollows from that: it is required whenever thetransaction is in issuer mode and carries
IssuerEncryptedAmount, and must beabsent in every other case.
Issuer mode:
{ "TransactionType": "ConfidentialMPTMirrorUpdate", "Account": "rIssuerAccountAddress", "MPTokenIssuanceID": "000000012A9F1D3C...", "Holder": "rHolderAccountAddress", "IssuerEncryptedAmount": "02a1b2c3d4e5f6...", "AuditorEncryptedAmount": "02c3d4e5f6a7b8...", "PreviousIssuerEncryptionKey": "02b7c8d9e0f1a2...", "ZKProof": "03f1e2d3c4b5a6..." }Holder mode:
{ "TransactionType": "ConfidentialMPTMirrorUpdate", "Account": "rHolderAccountAddress", "MPTokenIssuanceID": "000000012A9F1D3C...", "IssuerEncryptedAmount": "02a1b2c3d4e5f6...", "AuditorEncryptedAmount": "02c3d4e5f6a7b8...", "ZKProof": "03a1b2c3d4e5f6..." }9.7. Holder Self-Migration of Issuer Mirror
In addition to the issuer-submitted path, a holder may self-migrate their issuer mirror using a cross-key equality proof. This is enabled by the protocol's equality proof guarantee:
ConfidentialBalanceSpendingalways encodes the same balance b as the issuer mirror. The holder knows b by decryptingConfidentialBalanceSpendingvia sk_H, and pk_I' is public on-ledger.Prerequisites:
ConfidentialMPTMergeInboxbefore self-migrating. The issuer mirror encodes total balance b = b_s + b_in. The cross-key equality proof anchors toConfidentialBalanceSpendingwhich encodes only b_s. IfConfidentialBalanceInboxis non-zero, the proof would produce an incorrect issuer mirror. Validators enforce thatConfidentialBalanceInboxequals the canonical encrypted zero before accepting a holder-submitted mirror update.ConfidentialBalanceVersionviaTransactionContextID.ZKP construction: The holder proves knowledge of (b, sk_H, r') such that:
ConfidentialBalanceSpending= Enc_{pk_H}(b) via sk_H (decryption anchor)IssuerEncryptedAmount= Enc_{pk_I'}(b) via fresh randomness r'Proof size: ~228 bytes (4 group elements + 3 scalars). This is particularly useful in the issuer key loss scenario (Section 13) where the issuer cannot perform active re-encryption.
10. Transaction:
ConfidentialMPTHolderKeyUpdateAllows a holder to rotate their ElGamal key (rotation mode), authorize key replacement after key loss (recovery mode), or revoke a pending recovery authorization (cancel mode). Mode is selected by transaction flag.
10.1. Use Cases
tfHolderKeyRotation): Holder decryptsConfidentialBalanceSpendingandConfidentialBalanceInbox, re-encrypts under pk_H', submits equality proofs. Atomic - no issuer involvement. The holder may optionally runConfidentialMPTMergeInboxbefore rotating - after merge,ConfidentialBalanceInboxisEncZerowhich is publicly verifiable under pk_H' without a ZKP, marginally reducing the proof size. This costs an extra transaction (See D10 for discussion on this.)tfHolderKeyRecovery): Holder registers pk_H' asRecoveryKeyonMPToken, consenting to issuer-completed recovery viaConfidentialMPTRecoverBalance.10.2. Fields
TransactionTypestringUINT16ConfidentialMPTHolderKeyUpdate, which is 91.AccountstringACCOUNTIDMPTokenIssuanceIDstringUINT192FlagsnumberUINT32tfHolderKeyRotation,tfHolderKeyRecovery, ortfCancelRecovery.HolderEncryptionKeystringBLOBpk_H'. Required in Rotation and Recovery modes; must be absent in Cancel mode. Must differ from the current value.ConfidentialBalanceSpendingstringBLOBConfidentialBalanceInboxstringBLOBZKProofstringBLOB10.3. Flags
tfHolderKeyRotation0x00000001tfHolderKeyRecovery0x00000002sfRecoveryKeyfor issuer-completed recovery.tfCancelRecovery0x00000004RecoveryKeyfrom the holder'sMPToken.Exactly one of the three flags must be set.
10.4. Transaction Fee
10x base fee, consistent with XLS-0096 confidential transactions.
10.5. Failure Conditions
10.5.1. Data Verification
ConfidentialMPTKeyRotationamendment is not enabled. (temDISABLED)tfHolderKeyRotation,tfHolderKeyRecovery, nortfCancelRecoveryis set, or more than one is set. (temINVALID_FLAG)MPTokenIssuanceID- the issuer cannot hold confidential balances. (temMALFORMED)HolderEncryptionKeyis not exactly 33 bytes. (temMALFORMED)ConfidentialBalanceSpendingorConfidentialBalanceInboxis missing. (temMALFORMED)ConfidentialBalanceSpendingorConfidentialBalanceInboxis present. (temMALFORMED)HolderEncryptionKeyorZKProofis present - cancel mode requires no additional fields beyondTransactionType, Account,MPTokenIssuanceID, and Flags. (temMALFORMED)ConfidentialBalanceSpendingorConfidentialBalanceInboxhas an invalid length or represents an invalid elliptic curve point. (temBAD_CIPHERTEXT)ZKProofis absent or its length is not exactly the expected size for the selected mode. (TBD bytes - see Section 16) (temMALFORMED)10.5.2. Protocol-Level Failures
MPTokenIssuanceor the holder'sMPTokenobject does not exist. (tecOBJECT_NOT_FOUND)lsfMPTCanHoldConfidentialBalanceflag set. (tecNO_PERMISSION)MPTokenis missing confidential state (HolderEncryptionKey,ConfidentialBalanceSpending, orConfidentialBalanceInbox). (tecNO_PERMISSION)HolderEncryptionKeyequals the current on-ledgerHolderEncryptionKey(no-op). (tecNO_PERMISSION)IssuerKeyMirrorEpoch<IssuerKeyEpoch- holder's issuer mirror is stale, must migrate before rotating. (tecNO_PERMISSION)AuditorKeyMirrorEpoch<AuditorKeyEpoch- holder's auditor mirror is stale, must migrate before rotating (if auditor configured). (tecNO_PERMISSION)MPTokenhasConfidentialBalanceFrozen= true. See Notes for Discussion D7. (tecNO_PERMISSION)RecoveryKeyis already set on theMPToken- a pending recovery authorization exists. (tecNO_PERMISSION)RecoveryKeyis not set on theMPToken- nothing to cancel. (tecNO_PERMISSION)ZKProof(Schnorr PoK) fails to verify againstHolderEncryptionKey. (tecBAD_PROOF)ZKProof(Schnorr PoK) fails to verify againstHolderEncryptionKey. (tecBAD_PROOF)Cancel mode (
tfCancelRecovery): No additional fields are required beyondTransactionType, Account,MPTokenIssuanceID, and Flags. The transaction must be signed by the holder's XRPL signing key. No cryptographic proof is required - the holder's signing key signature is sufficient authorization to cancel their own pending recovery.Operational note: This is a wallet-level concern - validators cannot detect in-flight transactions. When a
ConfidentialMPTSendand aConfidentialMPTHolderKeyUpdate(rotation) are submitted close together, both proofs are bound toConfidentialBalanceVersionviaTransactionContextID. Whichever transaction lands second will find the version has already incremented and will be rejected withtecBAD_PROOF. No funds are lost - just a rejected transaction requiring resubmission. To avoid this, wallet software should:ConfidentialMPTSendtransactions before initiating rotation.ConfidentialMPTSendbefore submitting the rotation Ticket. Standard Sequence numbers enforce ordering naturally; Tickets break this ordering and can cause sends and rotation to land in unpredictable order.10.6. State Changes
Rotation mode:
HolderEncryptionKeyonMPToken← new key valueConfidentialBalanceSpendingonMPToken← new ciphertextConfidentialBalanceInboxonMPToken← new ciphertextConfidentialBalanceVersiononMPToken←ConfidentialBalanceVersion+ 1Recovery mode:
RecoveryKeyonMPToken←HolderEncryptionKey(new value)Cancel mode:
RecoveryKeyonMPToken← cleared (field removed)HolderEncryptionKey,ConfidentialBalanceSpending,ConfidentialBalanceInbox,ConfidentialBalanceVersionare not modified10.7. Example JSON
Rotation mode:
{ "TransactionType": "ConfidentialMPTHolderKeyUpdate", "Account": "rHolderAccountAddress", "MPTokenIssuanceID": "000000012A9F1D3C...", "Flags": 1, "HolderEncryptionKey": "02a1b2c3d4e5f6...", "ConfidentialBalanceSpending": "02b1c2d3e4f5a6...", "ConfidentialBalanceInbox": "02c1d2e3f4a5b6...", "ZKProof": "03d1e2f3a4b5c6...", "Fee": "120", "Sequence": 46 }Recovery mode:
{ "TransactionType": "ConfidentialMPTHolderKeyUpdate", "Account": "rHolderAccountAddress", "MPTokenIssuanceID": "000000012A9F1D3C...", "Flags": 2, "HolderEncryptionKey": "02a1b2c3d4e5f6...", "ZKProof": "03f1e2d3c4b5a6...", "Fee": "120", "Sequence": 47 }11. Transaction:
ConfidentialMPTRecoverBalanceCompletes holder key loss recovery. The issuer re-encrypts the holder's balance under the authorized
RecoveryKeyand submits a compact Chaum-Pedersen equality proof. Validators enforce thatRecoveryKeyis present - the issuer cannot act without prior holder authorization.11.1. Fields
TransactionTypestringUINT16ConfidentialMPTRecoverBalance, which is 92.AccountstringACCOUNTIDMPTokenIssuanceIDstringUINT192HolderstringACCOUNTIDConfidentialBalanceSpendingstringBLOBRecoveryKey. Becomes the new spending balance.ZKProofstringBLOBConfidentialBalanceSpendingencrypts the same value as the on-ledgerIssuerEncryptedBalance.Note on
ConfidentialBalanceInbox: After recovery,ConfidentialBalanceInboxis reset toEncZero(pk_H'). No value is lost. The issuer mirrorIssuerEncryptedBalancealways reflects the holder's total confidential balance b = b_s + b_in - guaranteed by XLS-0096's equality proof invariant on every transaction. When the issuer completesConfidentialMPTRecoverBalance, they decrypt the mirror to get the full b and re-encrypt it entirely intoConfidentialBalanceSpendingunder pk_H'. The inbox is reset to zero because the full balance - including what was in the inbox - is now consolidated into spending.Additionally, any incoming confidential transfers that arrived in the inbox during the recovery window (between the holder's Step 1 authorization and the issuer's Step 2 completion) are also captured - incoming sends update
IssuerEncryptedBalancehomomorphically, so the issuer mirror at Step 2 already reflects those transfers. The holder effectively receives a free merge as part of recovery.11.2. Transaction Fee
10x base fee, consistent with XLS-0096 confidential transactions.
11.3. Failure Conditions
11.3.1. Data Verification
ConfidentialMPTKeyRotationamendment is not enabled. (temDISABLED)MPTokenIssuanceID. (temMALFORMED)temMALFORMED)ConfidentialBalanceSpendinghas an invalid length or represents an invalid elliptic curve point. (temBAD_CIPHERTEXT)ZKProofis absent or its length is not exactly the expected compact Chaum-Pedersen equality proof size. (TBD bytes - see Section 16) (temMALFORMED)11.3.2. Protocol-Level Failures
tecNO_TARGET)MPTokenIssuanceor the holder'sMPTokenobject does not exist. (tecOBJECT_NOT_FOUND)lsfMPTCanHoldConfidentialBalanceflag set. (tecNO_PERMISSION)MPTokenhas no pendingRecoveryKey- holder has not authorized recovery. (tecNO_PERMISSION)IssuerKeyMirrorEpoch<IssuerKeyEpoch) - the issuer must first migrate the mirror viaConfidentialMPTMirrorUpdatebefore recovery can proceed, so the proof can be verified against the current issuer key. (tecNO_PERMISSION)ZKProoffails the compact Chaum-Pedersen equality verification againstIssuerEncryptedBalanceandRecoveryKey. (tecBAD_PROOF)11.4. State Changes
HolderEncryptionKeyonMPToken←RecoveryKeyConfidentialBalanceSpendingonMPToken← new ciphertextConfidentialBalanceInboxonMPToken←EncZero(canonical encryption of zero under pk_H')ConfidentialBalanceVersiononMPToken←ConfidentialBalanceVersion+ 1RecoveryKeyonMPToken← cleared (field removed)IssuerEncryptedBalanceandAuditorEncryptedBalanceunchanged11.5. Example JSON
{ "TransactionType": "ConfidentialMPTRecoverBalance", "Account": "rIssuerAccountAddress", "MPTokenIssuanceID": "000000012A9F1D3C...", "Holder": "rHolderAccountAddress", "ConfidentialBalanceSpending": "02a1b2c3d4e5f6...", "ZKProof": "03f1e2d3c4b5a6..." }12. Clawback and Freeze Interactions with Key Rotation
12.1. Clawback
Per XLS-0096,
ConfidentialMPTClawbackburns the holder's confidential balance - it decreases both OA and COA permanently and requires a ZKP proving the issuer mirror encrypts the revealed amount, anchored to the on-ledgerIssuerEncryptedBalance.After issuer key rotation,
ConfidentialMPTClawbackverifies the ZKP againstsfIssuerEncryptionKeyonMPTokenIssuance- whichever key is currently recorded there, not a caller-selectable key. After rotation,sfIssuerEncryptionKeyis pk_I'. An unmigrated holder'sIssuerEncryptedBalanceis still encrypted under pk_I (the old key), so the issuer's ZKP - which must use sk_I to prove against the old mirror - will fail verification against pk_I'.Clawback is therefore blocked for unmigrated holders after key rotation. The issuer must first migrate the holder's mirror via
ConfidentialMPTMirrorUpdatebefore executing clawback. There is no path to claw back an unmigrated holder using the old key after rotation.This adds a new failure condition to
ConfidentialMPTClawback(existing XLS-0096 transaction):tecNO_PERMISSIONIssuerKeyMirrorEpoch<IssuerKeyEpoch- mirror is stale. Issuer must migrate the holder's mirror viaConfidentialMPTMirrorUpdatebefore clawback.Post-clawback state: After a successful clawback,
IssuerEncryptedBalanceis reset to canonical encrypted zero andIssuerKeyMirrorEpochis updated to the currentIssuerKeyEpoch.HolderCountis unchanged because the holder's confidential state remains initialized.Issuer key loss and clawback: If the issuer has lost sk_I, clawback is impossible for all holders - the required ZKP cannot be produced against pk_I' without sk_I', and the old mirrors cannot be migrated without sk_I. Clawback authority is restored progressively as holders self-migrate their mirrors under pk_I'. See Section 13.
12.2. Freeze
Per XLS-0096, freezing a holder sets
lsfMPTLockedon theirMPToken, blockingConfidentialMPTSendandConfidentialMPTConvertBackbut not incoming transfers orConfidentialMPTMergeInbox.The following key rotation transactions interact with freeze status:
ConfidentialMPTMirrorUpdatewhile frozen: Permitted. The issuer is re-encrypting the mirror ciphertext, not enabling spending. Freeze status is unchanged.ConfidentialMPTHolderKeyUpdatein rotation mode while frozen: Open Product question. See Notes for Discussion D7.ConfidentialMPTHolderKeyUpdatein recovery mode while frozen: Permitted. The holder is registeringRecoveryKeyonly - no balance is modified and no spending capability is granted.ConfidentialMPTRecoverBalancewhile frozen: Permitted. The issuer is re-encrypting the holder's balance under the new key - no value is moved and freeze status remains in effect after recovery. The holder regains the ability to decrypt their balance but cannot spend until unfrozen.13. Issuer Key Loss
13.1. Problem
The issuer has irrecoverably lost sk_I. They can no longer decrypt any holder's issuer mirror, execute clawbacks, or perform active mirror re-encryption. The XRPL signing key is unaffected.
13.2. Impact
ConfidentialMPTClawbackverifies the ZKP against the currentsfIssuerEncryptionKeyonMPTokenIssuance. After registering a new pk_I', all holder mirrors are stale - clawback is blocked for every holder until their mirror is migrated. Without sk_I, the issuer cannot performConfidentialMPTMirrorUpdateto migrate mirrors, so clawback authority is suspended across the board.13.3. Recommended Approach: Loss Prevention
The primary recommendation is loss prevention through institutional key management:
13.4. Recovery Path: Holder-Driven Mirror Reconstruction
Issuer key loss creates an asymmetric situation analogous to holder key loss - the party who cannot act cryptographically requires the other party to complete the migration. The key difference from normal rotation is:
Normal rotation (issuer driven):
ConfidentialMPTMirrorUpdate(with Holder field) for each holderIssuer key loss (holder driven):
ConfidentialMPTMirrorUpdate(without Holder field) themselvesConfidentialBalanceSpendingvia sk_H and re-encrypt it under the new pk_I' using the cross-key equality proof (Section 9.9)This is a one-step process per holder - unlike holder key loss recovery which requires two steps (holder authorizes, issuer completes). Here the holder acts alone with no issuer involvement needed for their mirror.
How it works:
MPTokenIssuanceSet(they still have their XRPL signing key).IssuerKeyEpochincrements.IssuerKeyMirrorEpoch<IssuerKeyEpoch.ConfidentialMPTMergeInboxfirst, then submitsConfidentialMPTMirrorUpdatewithout a Holder field with the cross-key equality proof to self-migrate their issuer mirror. Merge is required because the cross-key equality proof anchors toConfidentialBalanceSpendingwhich encodes only b_s - ifConfidentialBalanceInboxis non-zero, the new issuer mirror would encode b_s instead of the full b = b_s + b_in, producing a mirror that doesn't match the holder's actual total balance and breaking clawback correctness. Holders may also self-migrate their auditor mirror in the same transaction if needed.Limitation: Inactive holders. Holders who do not transact will not self-migrate their issuer mirrors. The issuer cannot force-migrate issuer mirrors without sk_I, so clawback authority remains suspended until they act. Their auditor mirrors also cannot be actively migrated from the stale issuer mirror:
sk_I'can decrypt only an issuer mirror that the holder has already reconstructed underpk_I'. Auditor visibility therefore remains blocked unless the holder self-migrates an appropriate mirror.Limitation: Historical decryption. The issuer cannot decrypt historical ciphertexts from before the key loss.
13.5. Fallback: Inactive Holders
There is no clean on-chain fallback for inactive holders when the issuer has lost sk_I. The options are:
Option 1: Wait. Inactive holders will self-migrate when they next transact confidentially - they will hit the epoch staleness check and be prompted to submit
ConfidentialMPTMirrorUpdate. The issuer regains clawback authority progressively as holders act.Option 2: Off-chain communication. The issuer contacts inactive holders off-chain to prompt them to self-migrate. No protocol changes needed.
Option 3: Accept permanent suspension. For holders who remain permanently inactive, the issuer's clawback authority over those specific holders is permanently suspended. The issuer can still claw back active holders whose mirrors are reconstructed.
Note:
ConfidentialMPTConvertBackis not a viable fallback here. It requires the holder to have sk_H to produce the required ZKP - active holders with sk_H already have a better path via Section 13.4 self-migration without publicly revealing their balance. And inactive holders who will not self-migrate are equally unlikely to voluntarily convert back to public.ConfidentialMPTClawbackis also unavailable without sk_I.14. Operational Considerations
14.1. Epoch Staleness as a Mandatory Validation Check
Epoch consistency is a mandatory validation step for every confidential transaction that touches the issuer or auditor mirror. After key rotation, the on-ledger
IssuerEncryptedBalance(orAuditorEncryptedBalance) is under the old key while any new transaction delta is under the new key. These cannot be combined homomorphically - ciphertexts under different keys cannot be added. The epoch check makes this detectable and actionable: validators reject stale-mirror transactions cleanly rather than failing at the cryptographic combination step, and wallet software can proactively detect staleness by comparingIssuerKeyMirrorEpochon the holder'sMPTokenagainstIssuerKeyEpochonMPTokenIssuance(and similarly for auditor) before constructing or submitting transactions.Validators must check both
IssuerKeyMirrorEpoch==IssuerKeyEpochandAuditorKeyMirrorEpoch==AuditorKeyEpoch(treating absent as 0) before processing the following existing XLS-0096 transactions:ConfidentialMPTSendtecNO_PERMISSIONIssuerKeyMirrorEpoch<IssuerKeyEpoch- issuer mirror is stale.ConfidentialMPTSendtecNO_PERMISSIONAuditorKeyMirrorEpoch<AuditorKeyEpoch- auditor mirror is stale (if auditor configured).ConfidentialMPTSendtecNO_PERMISSIONIssuerKeyMirrorEpoch<IssuerKeyEpoch- issuer mirror is stale.ConfidentialMPTSendtecNO_PERMISSIONAuditorKeyMirrorEpoch<AuditorKeyEpoch- auditor mirror is stale (if auditor configured).ConfidentialMPTConverttecNO_PERMISSIONIssuerKeyMirrorEpoch<IssuerKeyEpoch- issuer mirror is stale.ConfidentialMPTConverttecNO_PERMISSIONAuditorKeyMirrorEpoch<AuditorKeyEpoch- auditor mirror is stale (if auditor configured).ConfidentialMPTConvertBacktecNO_PERMISSIONIssuerKeyMirrorEpoch<IssuerKeyEpoch- issuer mirror is stale.ConfidentialMPTConvertBacktecNO_PERMISSIONAuditorKeyMirrorEpoch<AuditorKeyEpoch- auditor mirror is stale (if auditor configured).The holder must wait for the issuer to submit
ConfidentialMPTMirrorUpdate- or self-migrate via the cross-key equality proof (Section 9.9) - before they can transact confidentially.14.2. Migration Throughput
Each
ConfidentialMPTMirrorUpdatecarries a new mirror ciphertext (~66 bytes) and a compact Chaum-Pedersen equality proof. Fees are 10x base fee. Traversing the entire holders are done off-chain.14.3. Wallet Implementation Guidance
Wallet software implementing
ConfidentialMPTHolderKeyUpdatein rotation mode must:ConfidentialMPTSendtransactions are pending before initiating rotation.ConfidentialBalanceVersionbump will invalidate their proofs.ConfidentialBalanceSpendingare consumed or cancelled before submitting rotation.If this check is missed: There is no ambiguous state and no funds are at risk. The outcome depends on which transaction lands first:
ConfidentialBalanceVersionand is rejected withtecBAD_PROOF. The holder's full balance is intact under pk_H'. The holder reconstructs the send proof under the new key and resubmits.ConfidentialBalanceVersionbumps andConfidentialBalanceSpendingis debited normally. The rotation proof - constructed against the old version - is rejected withtecBAD_PROOF. The holder reconstructs the rotation proof against the updated state and resubmits.In both cases the result is a cleanly rejected transaction requiring resubmission - not a partial or ambiguous state. Clawback is unaffected in either scenario:
ConfidentialMPTClawbackusesIssuerEncryptedBalance(the issuer mirror), notConfidentialBalanceSpendingorConfidentialBalanceVersion. The operational note is a UX concern, not a safety concern.14.4. Issuer Recovery Request Detection
After a holder submits
ConfidentialMPTHolderKeyUpdatewithtfHolderKeyRecovery,RecoveryKeyis set on theirMPToken. The issuer needs to detect this to submitConfidentialMPTRecoverBalancepromptly. Two complementary mechanisms are recommended:Option 1: Real-time WebSocket subscription
The issuer subscribes to the XRPL WebSocket API and listens for
ConfidentialMPTHolderKeyUpdatetransactions withtfHolderKeyRecoveryflag set. When one arrives, the issuer is notified in real-time and can immediately prepare and submitConfidentialMPTRecoverBalance. Clio is optimized for WebSocket API calls for validated ledger data and supports transaction stream subscriptions.Option 2: Periodic Clio query (catch-up mechanism)
As a reliability backstop for missed WebSocket events (e.g. connection drops), the issuer periodically pages through Clio's
mpt_holdersmethod. Each result supplies anmptoken_index; the issuer then queries that ledger entry and filters the returnedMPTokenobjects forRecoveryKey. This requires per-holder lookups unlessmpt_holdersis extended to returnRecoveryKey.{ "command": "mpt_holders", "mpt_issuance_id": "000000012A9F1D3C...", "ledger_index": "validated" }For each returned
mptoken_index, the issuer retrieves the correspondingMPTokenledger entry and checks whetherRecoveryKeyis present.Recommended approach: Both mechanisms together. Option 1 provides real-time processing of recovery requests; Option 2 provides periodic catch-up for events missed during WebSocket downtime. The polling interval for Option 2 can be tuned based on the issuer's SLA for recovery completion.
No protocol changes required. Both mechanisms use existing XRPL and Clio infrastructure. This is purely an operational implementation concern for issuers.
14.5. Regulatory Verification
A regulator (or any observer) can verify migration completion by comparing
IssuerKeyEpochonMPTokenIssuanceagainstIssuerKeyMirrorEpochon eachMPToken. While traversing all the holders off-chain, the issuer can easily tellif the migration is complete or not.
14.6. Ledger Replay Integrity
Each XRPL ledger version is a complete, immutable snapshot including
IssuerEncryptionKeyas it was at that moment. When replaying a historical transaction from before a key rotation, the replaying node uses theMPTokenIssuancestate from that exact ledger version - preserving the old key. This is identical to how signing key rotation works on XRPL.14.7. Interaction with Existing XLS-0096 Transactions
After issuer key rotation,
ConfidentialMPTConvert,ConfidentialMPTSend, andConfidentialMPTConvertBackmust use the new pk_I' for issuer mirror ciphertexts. Clients that read the current key from the issuance object will naturally use the new key.For
ConfidentialMPTClawback, the issuer must use sk_I' after the holder's mirror has been migrated. An unmigrated holder cannot be clawed back with sk_I; the issuer must migrate the mirror first.15. Security Considerations
15.1. Key Compromise vs. Key Loss
Key compromise - attacker has the key, legitimate holder still does. Attacker retains read access until re-encryption is complete. Rotation is the remediation.
Key loss - legitimate holder no longer has the key. Recovery paths require counterparty involvement. Loss prevention is the primary recommendation.
15.2. No New Cryptographic Assumptions
All constructions reuse existing XLS-0096 primitives: compact Chaum-Pedersen equality proofs, Schnorr proofs of knowledge, Bulletproofs. No new cryptographic assumptions introduced.
15.3. Issuer Visibility During Re-encryption
The decrypt-then-re-encrypt approach requires the issuer to learn b. This is inherent and consistent with the issuer's existing visibility via the mirror ciphertext in XLS-0096. No new privacy exposure introduced.
15.4. No Schnorr PoK for Issuer and Auditor Key Rotation
Consistent with XLS-0096's existing behavior for initial key setting. A rogue issuer key only harms the issuer's own mirror and clawback capability.
15.5.
ConfidentialBalanceVersionIncrement on Holder Key RotationConfidentialMPTHolderKeyUpdatein rotation mode incrementsConfidentialBalanceVersion, invalidating in-flightConfidentialMPTSendproofs. See Section 14.3.15.6. Two-Step Recovery Authorization
The holder's authorization (
tfHolderKeyRecovery) is signed by the holder's XRPL signing key. Validators enforce thatRecoveryKeyis present before acceptingConfidentialMPTRecoverBalance. The issuer cannot act unilaterally.15.7.
RecoveryKeyLiveness ConcernIf the issuer never completes recovery, the holder remains locked out indefinitely. See Notes for Discussion D1. Per XLS-0096, clawback burns tokens rather than returning them - this is not a viable workaround.
15.8. Issuer Key Loss and Clawback Authority
After key rotation, clawback is blocked for any holder whose
IssuerKeyMirrorEpoch<IssuerKeyEpoch- the ZKP is verified against the currentsfIssuerEncryptionKey, not a caller-selectable key. Loss of sk_I therefore suspends clawback authority for all holders - without sk_I the issuer cannot migrate mirrors, and without migrated mirrors clawback cannot proceed. Authority is restored progressively as holders self-migrate their mirrors under pk_I'.15.9. Successive Rotations and Historical Key Retention
The protocol does not enforce a global gate preventing successive rotations before migration is complete. Per-transaction staleness checks (
IssuerKeyMirrorEpoch<IssuerKeyEpoch) enforce correctness at the point of use for each individual holder, regardless of how many epochs behind they are.An operational security consideration: after multiple successive rotations, migrating a holder still at an old epoch requires the historical secret key for that epoch. If an issuer destroys a historical secret key before all holders at that epoch are migrated (e.g. during an emergency rotation due to compromise), those holders cannot be actively migrated and must fall back to self-migration (Section 9.9). Issuers should retain historical secret keys until all holders at each epoch are fully migrated.
15.10. Holder Self-Migration Security
For holder self-migration (Section 9.9), validators must enforce:
ConfidentialBalanceInboxequals canonical encrypted zero before accepting the transaction.ConfidentialBalanceVersionviaTransactionContextID.IssuerEncryptedAmountis verifiable under the currentIssuerEncryptionKeyfromMPTokenIssuance.15.11. Seed-Derived ElGamal Keys
Wallets may derive ElGamal keys from the XRPL account seed. This eliminates key loss for standard single-signature accounts but does not solve key compromise. Multi-sig accounts cannot use seed derivation. See Appendix A.
16. Analysis of Transaction Cost and Performance
16.1. Cryptographic Proof Summary
MPTokenIssuanceSet(rotation)ConfidentialMPTMirrorUpdateConfidentialMPTMirrorUpdateConfidentialMPTMirrorUpdateConfidentialMPTHolderKeyUpdateConfidentialMPTHolderKeyUpdateConfidentialMPTRecoverBalanceAll new transactions are charged 10x the base fee, consistent with XLS-0096.
17. Permissions
Per XLS-0074 (Granular Account Permissions), an account can grant another account permission to submit specific transaction types on its behalf. This amendment introduces new delegatable permissions.
17.1. Issuer-Side Delegation
ConfidentialMPTMirrorUpdateAt large holder counts, the issuer may want to delegate bulk mirror re-encryption to a separate operational account without granting full
MPTokenIssuanceSetauthority. A bulk migration operator should not be able to rotate keys, lock or unlock holder balances, or modify other issuance properties.Proposed permission:
ConfidentialMPTMirrorUpdateis independently delegatable under XLS-0074.ConfidentialMPTRecoverBalanceThe issuer may want a dedicated recovery operations account that can complete holder key loss recovery without full issuer authority.
Proposed permission:
ConfidentialMPTRecoverBalanceis independently delegatable under XLS-0074.Whether these two permissions should be separately delegatable or combined into a single issuer operational permission is an open question. See Notes for Discussion D9.
MPTokenIssuanceSet(key rotation) uses the existingMPTokenIssuanceSetpermission under XLS-0074. Key rotation must always be submitted by the primary issuer account or an account explicitly grantedMPTokenIssuanceSetauthority.17.2. Holder-Side Delegation
ConfidentialMPTHolderKeyUpdate- Rotation ModeA custody provider may want to submit key rotation on behalf of the holder. Rotation mode requires sk_H to construct the equality proofs - if the custody provider constructs the proofs, they have access to sk_H by definition. Granting them signing authority is not a meaningful additional security risk.
Proposed permission:
ConfidentialMPTHolderKeyUpdaterotation mode is delegatable under XLS-0074.ConfidentialMPTHolderKeyUpdate- Recovery ModeRecovery mode is more sensitive - it sets
RecoveryKeyon the holder'sMPToken, effectively authorizing key replacement. Unlike rotation mode, recovery mode does not require sk_H. Delegation therefore grants meaningful additional authority. Whether recovery mode should be delegatable is an open question. See Notes for Discussion D8.17.3. Permission Summary
MPTokenIssuanceSet(key rotation)MPTokenIssuanceSetpermissionMPTokenIssuanceSetoperationsConfidentialMPTMirrorUpdate(issuer mode)ConfidentialMPTMirrorUpdateMPTokenIssuanceSetauthorityConfidentialMPTMirrorUpdate(holder mode)ConfidentialMPTHolderKeyUpdate(rotation mode)ConfidentialMPTHolderKeyUpdateConfidentialMPTHolderKeyUpdate(recovery mode)ConfidentialMPTRecoverBalanceConfidentialMPTRecoverBalanceConfidentialMPTMirrorUpdateTBD - see D918. Rationale
18.1. Reuse of Existing Transaction Types for Key Rotation
Issuer and auditor key rotation reuse
MPTokenIssuanceSet. Two existing preclaim guards must be relaxed:MPTokenalready has the corresponding ciphertext column.sfConfidentialOutstandingAmount> 0 guard: Also relaxed. This guard unconditionally rejects key updates when COA > 0. Key rotation is only meaningful precisely when COA > 0 - if COA were zero, no holder would have a mirror yet. Maintaining this guard makes key rotation impossible in any real deployment.18.2. Decrypt-then-Re-encrypt over Proxy Re-encryption
Standard PRE constructions require bilinear pairings, incompatible with secp256k1. PRE also introduces new trust assumptions. Decrypt-then-re-encrypt uses existing primitives and the issuer already has visibility by design.
18.3. Active Re-encryption over Lazy Re-encryption
After issuer key rotation, two capabilities are blocked for unmigrated holders: confidential transactions (old and new key ciphertexts cannot be combined homomorphically) and clawback (ZKP verified against current
sfIssuerEncryptionKey, not a caller-selectable key). Active re-encryption keeps restoration of both capabilities entirely under the issuer's control. The issuer may rotate multiple times without waiting for full migration - per-transaction staleness checks enforce correctness at the point of use.18.4. Single
ConfidentialMPTMirrorUpdatefor Both MirrorsAvoids a new transaction type while keeping fields explicitly named and independently optional.
18.5. Old Ciphertext Omitted
Validators read the old ciphertext directly from on-ledger
MPTokenstate. Retransmitting is redundant.18.6. Explicit Flags for Mode Detection in
ConfidentialMPTHolderKeyUpdatetfHolderKeyRotation/tfHolderKeyRecovery/tfCancelRecoverymake validator logic unambiguous, eliminate edge cases with partial field sets, and align with XRPL's existing convention. This was chosen over inferring mode from field presence/absence.18.7. Reuse of Existing SFields in
ConfidentialMPTMirrorUpdateConfidentialMPTMirrorUpdatereuses the existingsfIssuerEncryptedAmountandsfAuditorEncryptedAmountfields from XLS-0096 rather than defining new fields. Field reuse across transaction types with context-specific semantics is standard XRPL practice -sfAmount,sfDestination, and many other fields carry transaction-type-specific meanings. No new serialized field definitions are required.18.8. Mode Detection in
ConfidentialMPTMirrorUpdateConfidentialMPTMirrorUpdateuses theMPTokenAuthorizepattern for mode detection - the Holder field presence distinguishes issuer mode (present) from holder mode (absent). This is consistent with XLS-0033'sMPTokenAuthorizewhich uses field presence to distinguish holder vs issuer submission paths.19. Backwards Compatibility
This amendment introduces no backwards incompatibilities. Existing
MPTokenIssuanceandMPTokenobjects require no migration. New fields are not stored when at their default value and their absence is well-defined. The relaxation of theMPTokenIssuanceSetpreclaim guard is additive - previously accepted transactions continue to be accepted unchanged.Appendix A: Seed-Derived ElGamal Keys
A wallet-level convention can eliminate ElGamal key loss as a concern by deriving keys deterministically from the XRPL account seed:
For holders:
For issuers:
This requires zero protocol changes. The protocol registers the public key on-chain and does not know or care how it was derived.
What this solves: Key loss becomes impossible as long as the seed exists. Simplifies custody - backing up the seed covers both signing and ElGamal keys.
Limitations:
Recommendation: Default wallet convention for standard single-signature accounts. Protocol-level recovery mechanisms remain available as fallbacks.
Appendix B: Design Discussion
B.1. Lazy vs. Active Re-encryption
Rejected. After issuer key rotation, old and new key ciphertexts cannot be combined homomorphically. Holders cannot transact until their mirror is migrated, making active re-encryption the only viable path.
B.2. Holder Self-Migration as Foundation for Issuer Key Loss Recovery
The protocol's equality proof guarantee means the holder always knows b from sk_H. This enables the cross-key equality proof construction that is the basis for both Section 9.9 and Section 13.4.
B.3. Why Holder-Driven Recovery Requires Issuer On-Chain Involvement
The holder cannot re-encrypt balances without sk_I. Knowing b in plaintext is not sufficient - the ZKP requires sk_I to produce a proof anchored to
IssuerEncryptedBalance. The source of b off-chain (issuer, auditor, or anyone else) does not matter - the cryptographic constraint is the same.B.4. Clawback Semantics Under XLS-0096
Per XLS-0096,
ConfidentialMPTClawbackburns the holder's balance (decreases both OA and COA permanently) rather than crediting the issuer's public reserve. This means clawback + re-issuance is not a symmetric recovery path - it permanently destroys tokens. The two-step recovery design is strongly preferred.B.5. Explicit Flags vs. Field Presence for Mode Detection
Explicit flags (
tfHolderKeyRotation/tfHolderKeyRecovery) make validator logic unambiguous, eliminate edge cases with partial field sets, and align with XRPL's existing convention. This was chosen over inferring mode from field presence/absence.Appendix C: FAQ
C.1: Why can't I use my XRPL signing key to recover my ElGamal key?
The keys are cryptographically independent - no derivation path exists from one to the other. See Appendix A for a wallet convention that eliminates this problem for standard single-signature accounts.
C.2: What happens if I lose my ElGamal key?
You cannot decrypt or spend your confidential balances, but your XRPL signing key is unaffected. Submit
ConfidentialMPTHolderKeyUpdatewithtfHolderKeyRecoveryto register a new key, then wait for the issuer to complete recovery. This directly addresses XLS-0096 FAQ A.6.C.3: Can I rotate my key while I have pending confidential sends?
No. Rotation increments
ConfidentialBalanceVersion, invalidating in-flight send proofs. Queue rotation until all pending sends are confirmed.C.4: What happens to my inbox balance during key loss recovery?
It is reset to canonical encrypted zero. Any value in the inbox is consolidated into the spending balance via the issuer mirror. No value is lost.
C.5: Can the issuer rotate my key without my consent?
No.
ConfidentialMPTRecoverBalanceis rejected ifRecoveryKeyis not set on yourMPToken. The issuer cannot act without your prior on-chain authorization.C.6: How long does bulk mirror re-encryption take at scale?
Each
ConfidentialMPTMirrorUpdatecarries a new mirror ciphertext and compact Chaum-Pedersen equality proof. Fees are 10x base fee. Traversing the entire holders list is done off-chain.C.7: Can the issuer rotate keys multiple times in quick succession?
Yes - the protocol does not enforce a global gate blocking successive rotations. Holders with stale mirrors are blocked from transacting at the per-transaction level regardless of how many epochs behind they are.
ConfidentialMPTMirrorUpdatebridges directly from any old epoch to the current epoch in one step.C.8: How can I verify that all mirrors have been migrated?
Compare
IssuerKeyEpochonMPTokenIssuanceagainstIssuerKeyMirrorEpochon eachMPToken. Whether a mirror is stale is trivially known on-ledger in O(1).C.9: Does ledger replay break after key rotation?
No. Each XRPL ledger version is a complete, immutable snapshot preserving the
IssuerEncryptionKeythat was active at that moment. Replaying a historical transaction uses theMPTokenIssuancestate from that exact ledger version. This is identical to how signing key rotation works on XRPL.Notes for Discussion (Non-Normative)
This section is non-normative. It contains open questions that must be resolved before this XLS can be finalized.
D1:
RecoveryKeyLifecycle and LivenessScenario 1: Issuer never completes Step 2 - RESOLVED No automatic expiry. Forcing expiry penalizes a holder already in a degraded state with no ledger health benefit.
Scenario 2: Holder wants to abort - RESOLVED The holder cancels a pending recovery authorization by submitting
ConfidentialMPTHolderKeyUpdatewithtfCancelRecovery. No cryptographic proof required - the holder's XRPL signing key signature is sufficient. This works even if the holder has not recovered sk_H.Scenario 3: Second
ConfidentialMPTHolderKeyUpdatein recovery mode - openThree sub-cases to consider:
Sub-case A: Same pk_H' submitted again. Pure no-op -
RecoveryKeyis already set to this value. Should this be rejected or allowed (idempotent accept)?Sub-case B: Different pk_H' submitted. Holder wants to change their recovery key. Two options:
tfCancelRecoveryfirst, then resubmit. Two transactions, explicit intent, no race condition.RecoveryKey, constructed proof material, and submittedConfidentialMPTRecoverBalance. If holder overwrites before issuer's transaction lands, issuer's recovery fails (proof is for old key) and issuer must start over. Not a safety issue - no funds at risk - but wastes issuer effort.Sub-case C: Issuer submits
ConfidentialMPTRecoverBalancein the same ledger. If recovery lands first,RecoveryKeyis cleared and the second authorization succeeds (no conflict). If authorization lands first, recovery fails (key mismatch). Both are safe outcomes.Current spec rejects Sub-case A and B with
tecNO_PERMISSION. Whether Sub-case A should be idempotent and whether Sub-case B should allow overwrite are open questions. Resolution needed before Draft can be finalized.Scenario 4:
MPTokendeletion withRecoveryKeyset - RESOLVED Non-issue. Per XLS-0096 Section 7.4, anMPTokencannot be deleted once confidential fields have been initialized. SinceRecoveryKeyonly appears on initializedMPTokenobjects, deletion is already blocked by XLS-0096. No new protocol handling required.D2: Enforcing Migration Completeness Before Second Rotation - RESOLVED
No global enforcement of "no second rotation until first migration complete" is needed. The per-transaction staleness check (
IssuerKeyMirrorEpoch<IssuerKeyEpoch) enforces correctness at the point of use for each individual holder. A holder with a stale mirror is blocked from transacting regardless of how many epochs behind they are.ConfidentialMPTMirrorUpdatebridges directly from any old epoch to the current epoch in one step.The transactor architecture confirms this is the right approach:
ConfidentialMPTMirrorUpdateis a per-holder transaction, so the transactor only sees one holder at a time and cannot enforce a global migration completeness check across all holders.D3: Granular Permission Delegation
Issuer-side: Should
ConfidentialMPTMirrorUpdatebe delegatable to a separate bulk migration account without granting fullMPTokenIssuanceSetauthority?Holder-side: Should
ConfidentialMPTHolderKeyUpdatebe delegatable to a custody provider?Resolution needed before Draft can be finalized.
D4: Freeze and Holder Key Rotation
Should
ConfidentialMPTHolderKeyUpdatein rotation mode be permitted whilelsfMPTLocked= true? The holder is re-encrypting their balance without moving value, which does not inherently enable spending that was not already permitted. However, allowing key rotation on frozen accounts introduces operational complexity. Resolution needed before Draft can be finalized.D5: Recovery Mode Delegation
Should
ConfidentialMPTHolderKeyUpdatein recovery mode be delegatable under XLS-0074?Option A: Not delegatable - holder must sign directly. Recovery authorization is sensitive and infrequent; requiring the holder's direct XRPL signature ensures explicit on-chain consent.
Option B: Delegatable with a separate explicit permission distinct from rotation mode delegation, so custody providers cannot trigger recovery without being specifically authorized for it.
Resolution needed before Draft can be finalized.
D6: Issuer-Side Permission Granularity
Should
ConfidentialMPTMirrorUpdateandConfidentialMPTRecoverBalancebe separately delegatable permissions, or combined into a single issuer operational permission? Separate permissions allow finer-grained access control - a bulk migration operator does not need recovery authority and vice versa. Combined permissions simplify the permission model but grant broader authority than necessary for each use case.Resolution needed before Draft can be finalized.
All reactions