Hi Radix fam, I played ping pong with Claude about privacy and here’s what I came up with. Feel free to comment, suggest or criticize. Spoiler: I’m unable to implement this myself, but I think it would be a great addition to the Radix stack.
Proposal: A Native Privacy System for Radix
Proposal for the Radix community
Status: Concept — Open for discussion
Introduction
Public blockchains like Radix offer total transparency by design. While this transparency is a strength for DeFi and network security, it represents a major barrier to adoption for everyday payments: any counterparty receiving a payment can view the sender’s entire balance and transaction history.
This document proposes a privacy system consisting of three complementary tools, built on Radix’s existing primitives, without compromising DeFi composability or exposing the network to disproportionate regulatory risks.
The three tools form a logical sequence:
-
Stealth Addresses — hide the identities of parties in a payment
-
Validator Level 1 — obtain XRD without traceable history, reserved for stakers
-
Validator Level 2 — obtain XRD without traceable history, open to all
Terminology note: this document uses the term “validator” in accordance with the Radix ecosystem. A validator may also operate via a liquid staking contract aggregating multiple users — the described mechanism applies identically in both cases.
Tool 1 — Stealth Addresses
Problem solved
Today, when Alice pays Bob, Bob sees Alice’s address and can view her complete balance and full history. Conversely, Alice knows the stealth address to which she sent funds to Bob, and can monitor what he does with them afterwards. This is the equivalent of paying someone while giving them permanent access to your bank statement.
(The problem of post-payment surveillance by Alice is partially mitigated by Tool 2 through the natural mass of stakers, and definitively resolved by Tool 3 — see below.)
How it works
Bob publishes a unique stealth meta-address, composed of two public keys (see next section for integration with Radix Personas):
stealth_meta_address = (scan_public_key, spend_public_key)
For each payment, Alice generates an ephemeral random parameter and derives a unique, single-use ephemeral address. Bob scans the network with his private key to recognise addresses belonging to him. Each payment received by Bob arrives at a different address, with no apparent link between them.
Sender (Alice):
1. Retrieves Bob's stealth_meta_address from his Persona
2. Generates r, an ephemeral random parameter
3. Computes: stealth_address = hash(r × scan_key) + spend_key
4. Publishes r in clear in the transaction metadata
(r is public — it reveals nothing without Bob's private key)
5. Sends funds to stealth_address
Receiver (Bob):
1. Scans recent transactions
2. For each transaction, computes hash(r × scan_private_key)
3. If match → funds recognised and added to balance
4. Can spend with spend_private_key + hash(r × scan_private_key)
An observer sees a random address with no link to Bob, and a parameter r which, without Bob’s private scan key, yields no useful computation.
Integration with Personas
The stealth meta-address would be published as a standardised field in Persona metadata, already existing on Radix:
Persona (existing):
identity_address : "identity_1abc..."
persona_data : { name, email, ... }
Persona (extended):
+ stealth_meta_address : {
scan_public_key : "02abc...",
spend_public_key : "03def...",
version : 1
}
This field is public and visible to all — it reveals nothing about funds; it is solely a cryptographic key enabling the computation of payment addresses.
Separation of usage spheres
The system maintains a natural separation between two spheres:
DeFi sphere (transparent):
Swaps, lending, staking, governance...
Full composability preserved
User accepts visibility
Payments sphere (stealth):
Peer-to-peer payments
Merchant payments
Privacy by default
Stealth addresses are naturally incompatible with DeFi (smart contracts cannot manage changing addresses and bidirectional flows on ephemeral addresses), which constitutes an organic separation without requiring an explicit prohibition.
Required changes
At the Radix protocol level:
- Standardisation of a
stealth_meta_addressfield in Persona metadata (minor data schema modification)
At the wallet level:
-
Automatic generation of the stealth meta-address when creating a Persona
-
Automatic derivation of ephemeral stealth addresses when sending
-
Periodic background scan to detect incoming payments
-
Transparent aggregation of stealth balance for the user
-
Automatic selection of source addresses when spending (similar to UTXO management)
-
Automatic generation of a fresh stealth address for change
-
Transaction fee management via Radix’s native fee abstraction — fresh stealth addresses containing only received funds, fees must be handled by a third-party payer mechanism or included in the received amount
Important technical notes
Scanning and privacy: periodic scanning requires downloading recent transactions via a node. If Bob uses a third-party node, that node sees the tested transactions and could infer Bob’s stealth meta-address. For maximum privacy, using a personal node is recommended. This limitation is common to all existing stealth address systems.
Forward secrecy: since the stealth meta-address is permanently published in the Persona, a future compromise of the scan private key would allow retroactive identification of all received payments. Periodic rotation of the stealth meta-address in the Persona is recommended for users concerned about long-term privacy.
Level 0 — Standard Behaviour (Current Situation)
The validator operates in a fully transparent manner, with no modification from Radix’s current behaviour:
Staking rewards → staker's main wallet (visible on-chain)
All transactions → public and traceable
No obfuscation mechanism activated
This is the default behaviour of all current Radix validators. Levels 1 and 2 are additional options that the validator chooses to activate according to its policy and regulatory constraints. This choice is visible on-chain via the validator’s metadata.
Level 0 offers full compliance with all jurisdictions and requires no protocol or smart contract modification.
Tool 2 — Validator Level 1: Clean XRD for Stakers
Problem solved
Even with stealth addresses, a problem persists: funds have a traceable origin. If Alice receives XRD from an exchange or a known wallet, those XRD have a history. Moreover, Alice knows the stealth address to which she paid Bob — she can monitor what Bob does with it. Bob therefore needs to obtain XRD without a link to their previous history, to break this chain of traceability.
(This mechanism is accessible to the validator’s stakers. The case where Bob does not stake with this validator, or does not stake at all, is handled by Tool 3.)
How it works
Validators naturally host many stakers whose funds intermingle. This natural and involuntary mixing role can be formalised by allowing stakers to obtain “clean” XRD — without traceable history linked to their deposits.
Important note on the concept of “clean”: a clean XRD is not physically different from an ordinary XRD. “Clean” means that the traceability link between the origin of the funds and their destination has been broken by the obfuscation mechanism. Alice’s traced XRD can become Bob’s functionally clean XRD, because no observer can link the two.
Note on unstaking: withdrawing clean XRD is an entirely distinct operation from unstaking. Unstaking concerns the principal stake and is subject to Radix’s protocol delay (~1-2 weeks). Withdrawing clean XRD only concerns the rewards generated by that stake — these are not subject to the unstaking delay and are managed solely by the validator’s smart contract.
The mechanism relies on an NFT Claim Ticket:
Step 1 — Deposit
Bob deposits X XRD (standard denomination) into the validator
Bob generates S, a strictly confidential local secret, never published
Bob also provides a personal random seed to the contract
The contract records hash(S) — visible on-chain, but useless without S
The contract computes the expiration delay:
delay = hash(seed_bob + current_epoch) % (max - min) + min
The contract issues an NFT Claim Ticket containing:
- hash(S)
- the denomination
- the expiration epoch (random delay within the validator's range)
- the validator identifier
- Bob's stealth meta-address (for automatic sending at expiration)
Step 2 — Waiting (random delay imposed by the contract)
The validator accumulates deposits from many stakers
The delay, different for each deposit, breaks temporal correlation
Nobody other than Bob knows his seed, so his exact delay is unpredictable
Step 3a — Active withdrawal from a fresh stealth address
Bob presents S from a new never-used stealth address
The contract verifies that hash(S) exists in its list
The contract releases funds to this new address
The NFT Claim Ticket is burned (single use)
S is transmitted to the contract only for the duration of verification —
it is never persisted in the contract's storage
Step 3b — Automatic expiration (if Bob does not act within the delay)
The contract automatically derives a new stealth address
from the stealth meta-address recorded at deposit
Funds are sent to this fresh address
Bob finds them at the next wallet scan, without any action on his part
No traceable link is recreated to the original deposit address
On the expiration epoch
One epoch on Radix corresponds to approximately 5 minutes. The expiration delay is therefore expressed in number of epochs — for example a range of 2016 to 8640 epochs corresponds to between 7 and 30 days.
This delay differs for each deposit because it incorporates a seed provided by Bob at the time of deposit. Bob is the only person who knows this seed, so his exact delay is unpredictable to any external observer — which breaks temporal correlation between deposits and withdrawals.
The min/max range is defined in the smart contract. At Level 1, the operator can adjust it via an administration badge. At Level 2, it is set permanently at deployment and can no longer be modified — but seed-based variability remains fully intact within this range.
The automatic sending at expiration to a fresh stealth address (Step 3b) reduces the need to notify the user — funds are never lost, simply moved to an address that the wallet will recognise at the next scan.
The observer sees a deposit from one address, and a withdrawal to a different address with no apparent link. The secret S never appears in clear on the ledger.
Why an NFT rather than a badge
An NFT is a transferable object with no intrinsic link to an identity. Anyone who possesses the secret S can claim the funds — which reinforces anonymity since the contract cannot distinguish Bob from the original depositor. A badge, by contrast, is linked to an identity or status and would create a traceable link between deposit and withdrawal.
Contract security and auditability
The smart contract code is stored on-chain and executed identically by all validators. Any divergence in execution would be immediately detected by consensus. The contract can therefore be publicly audited by any developer before use, guaranteeing in particular that S is never persisted in storage and that funds are always released to the address specified by the caller.
The only theoretical residual attack surface is frontrunning: a malicious validator operating its own contract could see S in the parameters of a pending transaction and attempt to submit a competing transaction to appropriate the funds. This risk is strongly mitigated by three characteristics of Radix: finalisation in a few seconds leaves an extremely narrow attack window, the BFT consensus mechanism processes transactions in an orderly manner making opportunistic insertion very difficult, and the cost of the attack is high — the malicious validator must be precisely in the active validator set at the right moment, build a competing transaction within seconds with fees high enough to take priority, all for a unit gain limited to the amount of a single NFT Claim Ticket. It is nonetheless an additional reason for Level 2 to be designed as a fully autonomous smart contract, with no identifiable operator having privileged access to the mempool.
Fixed denominations
To avoid amount correlation, the validator only accepts standardised denominations:
10 / 50 / 100 / 500 / 1000 XRD
A deposit of 350 XRD would be decomposed into 3×100 + 1×50 — four separate operations with potentially different delays. If the desired amount cannot be decomposed exactly, the remainder is returned to the user’s wallet in their traced sphere — with no loss of privacy since those funds were already there.
Operator participation choice
Level 1 is optional for the validator. It chooses to activate this mechanism or not, according to its policy and regulatory constraints. This choice is visible on-chain via the validator’s metadata.
Positive ecosystem effects
This mechanism creates a virtuous cycle:
Wants clean XRD → must stake → XRD leave exchanges
→ less liquidity for sale → upward price pressure
→ more secure network → more attractive ecosystem
Privacy and network health pull in the same direction.
Regulatory argument
Level 1 is defensible before regulators (EU, FinCEN…) for several reasons:
-
Access is reserved for stakers, identifiable via their visible on-chain stake
-
The stake amount remains public — large fortunes are not invisible
-
A KYC entry point exists via the exchanges where XRD are initially purchased
-
The mechanism formalises something that already exists naturally in any active validator
Required changes
At the Radix protocol level:
-
Allow optional redirection of staking rewards to the validator’s smart contract, rather than to the staker’s main wallet
-
Standardisation of a metadata schema for validators indicating their participation level (0, 1 or 2)
At the wallet level:
-
Dedicated interface for deposit/withdrawal via the validator
-
Secure storage of secret S and seed in the wallet backup
-
Automatic management of delays and denominations
-
Distinction and tracking of clean XRD (from a validator) vs traced XRD (received directly)
-
Configurable accumulation threshold before sending to stealth address:
-
Default threshold: 10 XRD
-
Minimum threshold: 1 XRD (for small stakers)
-
Maximum threshold: 1000 XRD (for fewer addresses)
-
Maximum delay: 30 days (guaranteed receipt even if threshold not reached)
-
-
Configurable spending policy:
-
Clean priority — maximum protection, recommended for everyday payments
-
Automatic mixing — optimises fees by combining clean and traced
-
Manual selection — for advanced users
-
-
Contextual recommendation displayed by the wallet:
-
Clean XRD → “Ideal for everyday payments and peer-to-peer”
-
Traced XRD → “Recommended for DeFi, staking and governance”
-
At the smart contract level (without protocol modification):
The contract manages two distinct incoming flows, separately accounted for in a single vault:
Flow 1 — Redirected rewards (automatic):
Arrive from the protocol at each epoch
Accumulated internally until the staker-configured threshold
Sent to fresh stealth address when threshold reached or max delay elapsed
Flow 2 — Voluntary staker deposits (Level 1 only):
Sent manually by the validator's stakers
Subject to random delay via NFT Claim Ticket
Sent to fresh stealth address upon withdrawal
rewards_counter : XRD from Flow 1
deposits_counter : XRD from Flow 2
total_clean_reserve : rewards_counter + deposits_counter
-
Nullifier list to prevent double use of a secret S
-
Queue management if liquidity is insufficient at withdrawal time
-
Automatic sending to a fresh stealth address at expiration (no intervention required from Bob)
Tool 3 — Validator Level 2: Clean XRD for Everyone
Problem solved
Level 1 requires staking with the relevant validator, which excludes users who do not stake or who stake elsewhere.
But there is a more fundamental problem that Level 1 only partially resolves: Bob cannot spend freely without being traced by Alice. Alice knows the stealth address to which she sent the funds. Even if Bob spends from it to a new stealth address, Alice sees that movement. For Bob to spend freely, he must first break this link — obtain XRD without a history linked to the address Alice knows. Level 1 offers this possibility to the validator’s stakers, but not to all users.
Level 2 resolves both problems simultaneously: it opens the obfuscation mechanism to any user without prior condition, allowing Bob to break the traceability chain regardless of his staking situation.
Differences from Level 1
The mechanism is identical — NFT Claim Ticket, secret S, random delay, fixed denominations — with two differences:
Level 1: only the validator's stakers can deposit
anonymity set = validator's stakers (natural and legitimate)
Level 2: anyone can deposit traced XRD to obtain clean ones
anonymity set = all users (broader, less controlled)
How to obtain an NFT Claim Ticket at Level 2
Step 1 — Bob sends traced XRD to the validator's contract
(from any address, stealth or not)
Bob generates S (local secret) and a random seed
The contract records hash(S), computes the delay, issues the NFT Claim Ticket
Step 2 — Waiting for the random delay
Meanwhile, other users' deposits accumulate
The link between deposit and withdrawal becomes indiscernible in the mass
Step 3a — Active withdrawal
Bob presents S from a new fresh stealth address
The contract releases clean XRD, burns the NFT Claim Ticket
Step 3b — Automatic expiration
If Bob does not act within the delay, funds are automatically sent
to a fresh stealth address derived from his stealth meta-address
Internal accounting of the Level 2 validator
XRD in the vault are physically fungible, but the contract maintains three separate logical counters:
total_vault : all XRD combined
rewards_counter : XRD from staking (Flow 1)
staker_deposits_counter : XRD deposited by stakers (Flow 2)
external_deposits_counter: XRD deposited by external users (Flow 3)
total_clean_reserve : sum of the three counters
Priority rules and proportions
Stakers contribute to network security and validator liquidity — they benefit from priority on the available clean reserve. The recommended rule is a proportional allocation configurable by the validator at deployment:
70% of clean reserve → reserved for stakers (Flow 1 + Flow 2)
30% of clean reserve → available for external users (Flow 3)
This ratio is visible in the validator’s metadata before any deposit, so users know what to expect in terms of delays.
Tiered pricing by urgency
An external user can choose between two withdrawal modes, implemented as two distinct functions in the smart contract:
// Standard withdrawal — normal delay, base fees
fn standard_withdrawal(nft_claim: NonFungibleBucket) → Bucket
// Urgent withdrawal — reduced delay, increased fees
fn urgent_withdrawal(nft_claim: NonFungibleBucket,
urgency_fee: Bucket) → Bucket
Urgency fees are paid directly to the validator, creating an additional economic incentive to activate Level 2. They also serve as a deterrent against Sybil attacks — a rushed attacker pays significantly more.
Stakers benefit from urgent mode at no extra cost, as an advantage of their contribution to the network.
Issues specific to Level 2
The Sybil attack is the main risk: an attacker fills the validator with their own deposits to monitor withdrawals by elimination. Possible mitigations are long and random delays, and deposit limits per address — but without KYC, these measures remain imperfect.
Legal liability: without an identifiable operator, the smart contract is autonomous, but its initial deployment is traceable. The operator is exposed to regulatory risks similar to those faced by Tornado Cash developers in certain jurisdictions.
Regulatory positioning
Level 2 remains more defensible than Monero or Zcash because:
-
Transactions remain pseudonymous, not anonymous
-
Deposits with the validator are visible on-chain transactions — there is an entry trace, even if the deposit/withdrawal link is broken
-
Exchange entry points into the ecosystem maintain an initial KYC point
-
Amounts are constrained by fixed denominations — very large sums require many visible operations
But it is clearly more exposed than Level 1 and should be operated as a fully autonomous smart contract to minimise risks for an identifiable operator.
Required changes
At the protocol level: no additional changes beyond Level 1.
At the smart contract level:
-
Three distinct incoming flows with separate accounting (rewards, staker deposits, external deposits)
-
No staking verification for Flow 3 — open to all
-
70/30 priority rule configurable at deployment
-
Two withdrawal functions (standard and urgent) with tiered pricing
-
Delay range fixed permanently at deployment (non-modifiable)
-
Seed-based variability preserved within the range
-
Strengthened anti-Sybil mechanisms (longer delays, wider range)
-
Queue management if liquidity is insufficient
-
Designed for full autonomy without an identifiable operator
Overall Vision: The Complete Privacy Cycle
Alice wants to pay Bob anonymously:
[Alice]
Main wallet → Level 1 or 2 validator
→ Clean XRD on fresh stealth address
[Payment]
Alice's stealth address → Bob's stealth address
(Bob publishes his stealth meta-address via his Persona)
[Bob breaks post-payment traceability]
Received stealth address → Level 1 or 2 validator
→ Clean XRD on new stealth address
[Bob spends]
New stealth address → merchant's stealth address
At no step can an observer link Alice to Bob, nor Bob to his subsequent spending.
What the System Does Not Resolve (Honest Limitations)
System objective: protect the wealth and privacy of everyday users during daily payments. It is not intended to offer the total anonymity of Monero, but to prevent a merchant, peer, or casual observer from viewing a user’s balance and history from a single received transaction.
Amount correlation remains possible if validator traffic is low — hence the importance of adoption. Fixed denominations significantly mitigate this risk.
Visible stake at Level 1 reveals a range of staking income, even if spending remains private.
The first mile: the initial transfer from a public wallet to the first validator leaves a trace. This is unavoidable without deeper protocol modification.
Adoption is the condition for effectiveness: a validator with few users offers a weak anonymity set. The system protects better the more people use it. Level 2 is particularly exposed to this problem at launch — a bootstrapping strategy (economic incentives for early users, initial participation by large validators) would be necessary.
Sophisticated graph analysis: an analyst with additional off-chain data (IP addresses, network metadata, cross-referencing with external data) could potentially reconstruct certain links despite on-chain protections. The system resists naive analysis well, less so against advanced state-level or professional analysis.
Network (IP) protection: submitting a transaction reveals the sender’s IP address to the contacted nodes. For maximum privacy, using Tor or a VPN is recommended for stealth transactions. This point is beyond the scope of this proposal but must be known to users.
Summary of Required Changes
| Change | Level | Where |
|---|---|---|
| stealth_meta_address field in Personas | Fundamental | Protocol |
| Redirection of rewards to validator’s smart contract | Fundamental | Protocol |
| Level metadata (0/1/2) for validators | Minor | Protocol |
| Scan, aggregation, derivation of stealth addresses | Fundamental | Wallet |
| Fee management via native fee abstraction | Fundamental | Wallet |
| NFT Claim Ticket and secret management | Fundamental | Wallet |
| Configurable reward accumulation threshold | Fundamental | Wallet |
| Clean / traced XRD distinction + spending policy | Fundamental | Wallet |
| Optional rotation of stealth meta-address | Recommended | Wallet |
| Scrypto contract validator Level 1 | Level 1 | Smart contract |
| Scrypto contract validator Level 2 (3 flows, priority, urgency) | Level 2 | Smart contract |
Protocol modifications are surgical and well-delimited. The majority of the work resides in the wallet and smart contracts — meaning a large part of the system could be implemented by the community without waiting for a core protocol modification.
This document is a conceptual proposal open for discussion. Cryptographic and implementation details are intentionally simplified to facilitate understanding. A detailed technical specification would be the next step if the community receives these ideas favourably.