Skip to content

Commit e1b969c

Browse files
XLS-96 - Document Confidential Transfers (#201)
1 parent 97c78f1 commit e1b969c

12 files changed

Lines changed: 772 additions & 0 deletions

docs/_snippets/common-links.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
[amendment]: https://xrpl.org/docs/concepts/networks-and-servers/amendments
66
[common fields]: https://xrpl.org/docs/references/protocol/transactions/common-fields/
77
[common ledger entry fields]: https://xrpl.org/docs/references/protocol/ledger-data/common-fields/
8+
[ConfidentialMPTClawback transaction]: /docs/xls-96-confidential-transfers/references/transactions/confidentialmptclawback.md
9+
[ConfidentialMPTConvert transaction]: /docs/xls-96-confidential-transfers/references/transactions/confidentialmptconvert.md
10+
[ConfidentialMPTConvertBack transaction]: /docs/xls-96-confidential-transfers/references/transactions/confidentialmptconvertback.md
11+
[ConfidentialMPTMergeInbox transaction]: /docs/xls-96-confidential-transfers/references/transactions/confidentialmptmergeinbox.md
12+
[ConfidentialMPTSend transaction]: /docs/xls-96-confidential-transfers/references/transactions/confidentialmptsend.md
13+
[ConfidentialTransfers amendment]: https://xls.xrpl.org/xls/XLS-0096-confidential-mpt.html
814
[credentials]: https://xrpl.org/docs/concepts/decentralized-storage/credentials
915
[EscrowFinish]: https://xrpl.org/docs/references/protocol/transactions/types/escrowfinish
1016
[`flags` field]: https://xrpl.org/docs/references/protocol/transactions/common-fields#flags-field
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
---
2+
seo:
3+
description: Confidential transfers keep MPT balances and transaction amounts private while maintaining public auditability of the total token supply.
4+
labels:
5+
- Multi-Purpose Tokens, MPTs, Tokens
6+
- Confidential Transfers
7+
---
8+
# Confidential Transfers
9+
10+
Confidential Transfers on the XRP Ledger allow Multi-Purpose Token (MPT) holders to keep their balances and transfer amounts private using [EC-ElGamal encryption](https://en.wikipedia.org/wiki/ElGamal_encryption) and [Zero-Knowledge Proofs (ZKPs)](https://en.wikipedia.org/wiki/Zero-knowledge_proof). Individual balances and transfer amounts remain shielded from the public ledger while maintaining compliance mechanisms for issuers and regulators to verify total supply and meet regulatory obligations. This addresses the need for institutional-grade privacy in financial applications while preserving auditability.
11+
12+
Public and confidential balances can coexist for the same token, meaning the same MPT can have some balances held publicly and others held privately. Token holders can convert their public balance to confidential form and back as needed.
13+
14+
{% admonition type="info" name="Note" %}
15+
Confidential transfers are only available for direct payments between accounts. They do not work with other transaction types, such as those involving the XRPL DEX, escrows, or checks.
16+
{% /admonition %}
17+
18+
_(Requires the [ConfidentialTransfers amendment][] {% not-enabled /%})_
19+
20+
## Key Features of Confidential Transfers
21+
22+
The Confidential Transfers feature is built on three core design principles: issuer second account model, a multi-ciphertext architecture for privacy and compliance, and the split-balance model for reliable transfers.
23+
24+
### Issuer Second Account Model
25+
26+
Issuers introduce confidential tokens into circulation via a dedicated **second account** instead of their primary issuer account. The issuer's primary account cannot hold confidential balances because its balance doesn't count toward tokens in circulation.
27+
28+
To issue confidential tokens, issuers fund their second account with a public balance, then use the second account to convert the public balance to confidential form using the [ConfidentialMPTConvert transaction][].
29+
30+
The flow to issue confidential tokens is as follows:
31+
32+
1. The Issuer creates an MPT issuance.
33+
2. The Issuer creates a dedicated _second account_.
34+
3. The Issuer sends a public MPT amount to the dedicated _second account_.
35+
4. The dedicated _second account_ converts the public balance to a confidential balance.
36+
37+
Because the XRP Ledger treats the second account as a regular _holder_, its balance counts towards tokens in circulation, which allows validators to enforce [supply caps](https://xrpl.org/docs/concepts/tokens/fungible-tokens/multi-purpose-tokens#supply-cap) without needing to decrypt confidential balances.
38+
39+
In summary, this approach enables confidential distribution, where the issuer converts tokens once on the second account and distributes them directly to users, rather than requiring each holder to individually convert their balances from public to private.
40+
41+
### Multi-Ciphertext Architecture
42+
43+
A single confidential balance is represented by multiple parallel ciphertexts, each serving a distinct purpose:
44+
45+
- **Holder encryption:** The holder's balance is encrypted under their own public key, granting exclusive spending authority.
46+
47+
- **Issuer encryption:** The holder's balance is also encrypted under the issuer's public key, creating an encrypted mirror for supply verification and compliance without granting spending capability.
48+
49+
- **Optional auditor encryption:** If configured, the holder's balance is additionally encrypted under an auditor's public key, enabling independent verification and [on-chain selective disclosure](#on-chain-selective-disclosure).
50+
51+
Public keys must be generated off-chain using EC-ElGamal over secp256k1 encryption.
52+
53+
{% admonition type="info" name="Note" %}
54+
This encryption method is not considered quantum-safe. In the future, the XRP Ledger may migrate to post-quantum friendly schemes, such as those based on lattice cryptography. The specific migration path and timeline for achieving quantum resistance remains an open area of research.
55+
{% /admonition %}
56+
57+
#### Key Registration
58+
59+
To participate in confidential transfers, holders must first convert their public balance to confidential form using the [ConfidentialMPTConvert transaction][]. This initial conversion serves as the opt-in mechanism and registers the holder's ElGamal public key on the ledger, enabling them to receive and [manage confidential balances](#managing-confidential-balances).
60+
61+
Issuers and auditors register their keys when [enabling confidential transfers](#privacy-controls) on an MPT issuance.
62+
63+
{% admonition type="danger" name="Warning" %}
64+
**If a holder loses their private key, their confidential funds are permanently lost.**
65+
Issuer and auditor keys also cannot be changed or cleared once registered.
66+
{% /admonition %}
67+
68+
#### Zero-Knowledge Proofs
69+
70+
The XRP Ledger relies on a set of ZKPs to validate confidential transactions without revealing balances or transfer amounts. The following proof types are used:
71+
72+
- **Schnorr Proof of Knowledge**: Proves ownership of the private key is associated with the ElGamal public key.
73+
74+
- **Plaintext–ciphertext equality proofs:** Prove that a publicly known amount is correctly encrypted.
75+
76+
- **Plaintext equality proofs:** Prove that multiple ciphertexts encrypt the same plaintext value, ensuring consistency of a confidential amount across the sender, receiver, issuer, and optional auditor.
77+
78+
- **ElGamal–Pedersen equality proofs:** Link encrypted values to Pedersen commitments, allowing confidential amounts and balances to be used as inputs to range proofs without revealing the underlying values.
79+
80+
- **Range proofs:** Prove that confidential amounts and post-transfer balances are within valid ranges, enforcing non-negativity and preventing overspending.
81+
82+
Validators can verify confidential transactions by checking these cryptographic proofs without ever learning the underlying amounts. For example, when a holder sends tokens confidentially, the transaction includes encrypted values and proofs that mathematically demonstrate: the sender has sufficient balance, the amount is non-negative, and all encrypted amounts (holder, issuer, auditor) represent the same value.
83+
84+
Validators can only check the mathematical correctness of these proofs to ensure the transaction is valid, but cannot see the actual amounts involved.
85+
86+
### Split-Balance Model
87+
88+
To prevent the _stale proof_ problem, where an incoming transfer could invalidate a proof that a holder just created for an outgoing transfer, each account's confidential balance is divided into two parts:
89+
90+
- **Spending Balance:** A stable balance used to generate proofs for outgoing transactions.
91+
- **Inbox Balance:** Receives all incoming confidential transfers.
92+
93+
When a holder receives a confidential transfer, the amount goes into their inbox. Before it can be spent, the holder must merge it into their spending balance using the [ConfidentialMPTMergeInbox transaction][]. If a merge is not explicitly performed, incoming funds accumulate in the inbox, remaining safe but unspendable until consolidated into the spending balance.
94+
95+
After a merge, the inbox is reset to a deterministic "encrypted zero" value. This zero value is a valid ElGamal ciphertext that represents zero, but is indistinguishable from other ciphertexts to observers without the private key.
96+
97+
#### Version Counter
98+
99+
Each time your spending balance changes, a **version counter** increments by 1 and is bound to newly generated proofs to prevent [replay attacks](https://en.wikipedia.org/wiki/Replay_attack). This ensures that old proofs cannot be reused maliciously.
100+
101+
## Privacy Properties
102+
103+
Confidential transfers keep transaction amounts and balances private while certain information remains publicly visible on the ledger.
104+
105+
**Private:**
106+
107+
- Transaction amounts are encrypted.
108+
- Account balances are encrypted and only visible to the holder, issuer, and any configured auditors. Validators and network observers see only encrypted ciphertexts and cryptographic proofs, never the underlying amounts.
109+
- Distribution of confidential supply across holders. The ledger does not publicly reveal which specific accounts hold how much of the confidential supply.
110+
111+
**Public:**
112+
113+
- Sender and receiver addresses.
114+
- The type of transaction being submitted.
115+
- Total token supply. The ledger publicly tracks two plaintext values: `OutstandingAmount` (total tokens in circulation) and `ConfidentialOutstandingAmount` (how much of that total is held confidentially). Validators use these values to enforce supply caps without decrypting any balances.
116+
- Conversion amounts when converting between public and confidential forms.
117+
118+
Note that in low-volume scenarios, publicly visible elements can reveal patterns. For example, if an account converts 1,000,000 tokens to confidential form and later converts 800,000 tokens back to public form, observers know that 200,000 tokens remain in confidential form. However, they cannot determine whether those tokens were transferred to other accounts or are still held by the original account, because encrypted balances for zero are indistinguishable from non-zero balances.
119+
120+
It's important to keep in mind that privacy is stronger when more participants make confidential transactions.
121+
122+
## Auditability and Compliance
123+
124+
The XRP Ledger supports two approaches for auditing hidden balances, on-chain selective disclosure and issuer-mediated auditing, along with a specialized clawback compliance mechanism.
125+
126+
### On-Chain Selective Disclosure
127+
128+
Issuers can configure an auditor when creating an MPT issuance by registering the auditor's ElGamal public key. This encrypts each holder's confidential balance under the auditor's public key, allowing the auditor to independently decrypt and verify balances off-chain without requiring cooperation from the issuer or holder. For example, a regulator designated as an auditor can use their own private key to decrypt a holder's confidential balance from the ledger, providing independent verification.
129+
130+
### Issuer-Mediated Auditing
131+
132+
As an alternative, issuers can provide auditing access by sharing their own ElGamal private key with auditors. Since the issuer maintains an encrypted mirror of all holder balances, the issuer's key provides read-only access to all confidential balances and transaction amounts. For example, when a regulator requests access to a user's transaction history, the issuer can provide the regulator with their ElGamal private key. The regulator can then use this key to decrypt the relevant confidential balances and transaction amounts directly from the ledger.
133+
134+
This approach is operationally simpler but requires the auditor to trust that the issuer is providing complete and accurate information, and it grants the auditor the same decryption capabilities as the issuer.
135+
136+
### Confidential Clawback
137+
138+
While issuers retain the same [compliance controls](https://xrpl.org/docs/concepts/tokens/fungible-tokens/multi-purpose-tokens#compliance-controls) they have with public transactions, clawback operations work differently for confidential balances.
139+
140+
The [ConfidentialMPTClawback transaction][] allows issuers to claw back a holder's **entire** confidential balance. Off-chain, the issuer decrypts their mirror copy of the holder's balance and generates a cryptographic proof validating the plaintext amount. The issuer then submits the transaction with the plaintext amount and proof.
141+
142+
Validators verify the proof provides cryptographic certainty that the plaintext amount matches the encrypted balance. If valid, both the holder's spending and inbox balances are set to encrypted zero, the version counter is reset to 0, and the clawed back tokens are removed from circulation.
143+
144+
## Privacy Controls
145+
146+
Issuers can enable confidential features by setting the **Can Confidential Amount** flag on an MPT issuance. This can be done either during the initial [MPTokenIssuanceCreate transaction](../references/transactions/updated-transactions.md#mptokenissuancecreate) or later using an [MPTokenIssuanceSet transaction](../references/transactions/updated-transactions.md#mptokenissuanceset).
147+
148+
By default, the privacy setting is mutable, so it can be toggled on and off as long as no confidential balances exist. Once confidential balances exist, the flag can no longer be disabled.
149+
150+
When enabling confidential transfers, the issuer must also register their ElGamal public key, and if required, an auditor's public key.
151+
152+
{% admonition type="warning" name="Warning" %}
153+
If the issuer enables the **Cannot Mutate Can Confidential Amount** flag at any time, the privacy setting becomes permanent and cannot be changed, even if no confidential balances exist.
154+
{% /admonition %}
155+
156+
## Managing Confidential Balances
157+
158+
Token holders can manage confidential balances through four operations:
159+
160+
- **Convert to confidential:** The [ConfidentialMPTConvert transaction][] converts public tokens to confidential form. The conversion amount is visible in plaintext, and the holder's public key is registered during their first conversion.
161+
162+
- **Send confidentially:** The [ConfidentialMPTSend transaction][] transfers confidential tokens between holders. The transfer amount remains encrypted and hidden from public view, with ZKPs ensuring transaction validity. This transaction supports the same authorization requirements as standard MPT payments, including [Deposit Authorization](https://xrpl.org/docs/concepts/accounts/depositauth) and [Credential](https://xrpl.org/docs/concepts/decentralized-storage/credentials) requirements.
163+
164+
- **Merge incoming transfers:** The [ConfidentialMPTMergeInbox transaction][] consolidates received tokens into the Spending Balance, making them available to send. This operation increments a version counter to prevent replay attacks.
165+
166+
- **Convert back to public:** The [ConfidentialMPTConvertBack transaction][] converts confidential tokens back to public form, making the amount visible on the ledger again.
167+
168+
{% admonition type="info" name="Note" %}
169+
Confidential transactions are larger and more computationally expensive than standard MPT transactions due to the inclusion of encrypted ciphertexts and ZKPs. However, they currently **don't** incur a higher transaction fee.
170+
{% /admonition %}
171+
172+
## Amendment Status
173+
174+
| Amendment | ConfidentialTransfers |
175+
|:------------------------------------ |:---------------------|
176+
| Amendment ID | 2110E4A19966E2EF517C0A8C56A5F35099D7665B0BB89D7B126B30D50B86AAD5 |
177+
| Status | In Development |
178+
| Default Vote (Latest stable release) | No |
179+
| Pre-amendment functionality retired? | No |
180+
181+
## See Also
182+
183+
- **Concepts:**
184+
- [Multi-Purpose Tokens](https://xrpl.org/docs/concepts/tokens/fungible-tokens/multi-purpose-tokens)
185+
- **References:**
186+
- [ConfidentialMPTConvert transaction][]
187+
- [ConfidentialMPTConvertBack transaction][]
188+
- [ConfidentialMPTSend transaction][]
189+
- [ConfidentialMPTMergeInbox transaction][]
190+
- [ConfidentialMPTClawback transaction][]
191+
- [Updated Ledger Entries](../references/updated-ledger-entries.md)
192+
- [Updated Transactions](../references/transactions/updated-transactions.md)
193+
194+
{% raw-partial file="/docs/_snippets/common-links.md" /%}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import * as React from "react";
2+
import {
3+
LandingContainer,
4+
LandingLayout,
5+
ButtonToXRPL,
6+
FeatureHeader,
7+
FeatureContent
8+
} from "../../components/landing";
9+
import { AmendmentTracker } from "../../components/AmendmentTracker";
10+
import { Button } from "@redocly/theme";
11+
import { Card } from "@redocly/theme/markdoc/components/Cards/Card";
12+
import { Cards } from "@redocly/theme/markdoc/components/Cards/Cards";
13+
14+
export const frontmatter = {
15+
seo: {
16+
title: "XLS-96 Confidential Transfers",
17+
description:
18+
"Learn how Confidential Transfers keep MPT balances and transaction amounts private while maintaining public auditability.",
19+
},
20+
};
21+
22+
export default function Page() {
23+
const KEY_DATE_EVENTS = [
24+
"XLS Spec Live",
25+
"Available to Test on Devnet",
26+
"Open for Voting on Mainnet",
27+
"Vote Consensus"
28+
];
29+
30+
const [keyDates, setKeyDates] = React.useState(
31+
KEY_DATE_EVENTS.map(event => ({ date: "🔄 Loading...", event }))
32+
);
33+
34+
const handleKeyDatesUpdate = React.useCallback((newKeyDates: any[]) => {
35+
setKeyDates(newKeyDates);
36+
}, []);
37+
38+
return (
39+
<LandingLayout>
40+
<LandingContainer>
41+
<FeatureHeader
42+
title="XLS-96 Confidential Transfers"
43+
subtitle="Private auditable transactions for Multi-Purpose Tokens (MPTs)."
44+
/>
45+
46+
<FeatureContent
47+
description={
48+
<>
49+
The Confidential Transfers feature provides institutional-grade privacy for Multi-Purpose Tokens using advanced cryptography (EC-ElGamal and ZKPs).
50+
Individual balances and transfer amounts remain shielded from the public ledger while maintaining compliance mechanisms for authorized parties (issuers, auditors, or designated entities) to verify total supply and meet regulatory obligations.
51+
<br /><br />
52+
<strong>Confidential Devnet:</strong> https://confidential.devnet.rippletest.net
53+
<br />
54+
<strong>Devnet Faucet:</strong> https://confidential-faucet.devnet.rippletest.net
55+
</>
56+
}
57+
keyDates={keyDates}
58+
/>
59+
60+
<AmendmentTracker
61+
amendmentId="2110E4A19966E2EF517C0A8C56A5F35099D7665B0BB89D7B126B30D50B86AAD5"
62+
xlsSpecDate="2026-01-15"
63+
devnetDate="2025-12-01"
64+
onKeyDatesUpdate={handleKeyDatesUpdate}
65+
/>
66+
67+
<Cards columns={3}>
68+
<Card
69+
title="XLS Spec"
70+
to="https://xls.xrpl.org/xls/XLS-0096-confidential-mpt.html"
71+
>
72+
<p>
73+
Technical spec for the feature outlining requirements, design,
74+
and implementation details.
75+
</p>
76+
<Button size="large" variant="primary">
77+
Read the XLS Spec
78+
</Button>
79+
</Card>
80+
81+
<Card title="Documentation" to="/docs/xls-96-confidential-transfers/concepts/confidential-transfers">
82+
<p>
83+
Explore key concepts, find detailed references, and follow
84+
step-by-step tutorials.
85+
</p>
86+
<Button size="large" variant="primary">
87+
Read the Docs
88+
</Button>
89+
</Card>
90+
91+
</Cards>
92+
</LandingContainer>
93+
</LandingLayout>
94+
);
95+
}
96+

0 commit comments

Comments
 (0)