Edit: This is the V2 of the proposal, updated after analysis of current stack code.
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
Updated following source code analysis of the full Radix stack
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.)
The StealthIdentity component
Why not Personas?
An earlier version of this proposal suggested publishing the stealth meta-address as an additional field in Radix Personas. Source code analysis of Sargon (the shared cryptographic library powering Radix wallets) revealed that this approach is architecturally incompatible: PersonaData is intentionally kept off-chain by design, and the Sargon codebase states this explicitly. No PersonaData is ever written to the ledger, and this is a deliberate choice — not a limitation to work around.
This led us to a cleaner solution: a dedicated on-chain primitive.
What the StealthIdentity is
The StealthIdentity is a Scrypto component deployed on-chain whose sole purpose is to publish a user’s stealth receiving capability — two public keys that anyone can use to send them a private payment:
StealthIdentity component:
scan_public_key : PublicKey // used to detect incoming payments
spend_public_key : PublicKey // used to derive the stealth address
version : u8
created_epoch : u64
Bob creates one StealthIdentity component and shares its address — via QR code, a messaging app, or any out-of-band channel. The component contains no personal data, no balance, no history. It is a cryptographic mailbox, nothing more.
On the path to a native primitive
The StealthIdentity is currently implemented as a standard Scrypto component — deployable today, without any protocol modification. This is a deliberate choice, not a compromise. It allows the design to be validated in real conditions, community feedback to be gathered, and a user base to be established before any protocol-level decision is made.
If adoption justifies it, the community can propose nativising StealthIdentity as a first-class Radix primitive via a protocol update. This upgrade would bring concrete benefits: a dedicated address prefix (instead of the generic
component_prefix), a preallocated address mechanism (no creation transaction required), reduced fees, and native support in explorers and tooling.What would not change for existing users:
The scan and spend private keys remain identical
All stealth addresses already used for receiving remain valid and accessible
The full payment history remains decryptable
The wallet user experience is unchanged
A nativisation is an upgrade, not a migration. Users who adopt the Scrypto component today are not committing to a temporary solution — they are adopting a design that is built to last, with a well-defined improvement path if the community chooses to pursue it.
How it works
For each payment, Alice retrieves Bob’s StealthIdentity address, fetches his two public keys from on-chain, and derives a unique single-use ephemeral address. Bob’s wallet periodically scans recent transactions to recognise payments addressed to him.
Sender (Alice):
1. Fetches Bob's StealthIdentity component address (shared out-of-band)
2. Retrieves scan_public_key and spend_public_key via Gateway API
3. Generates r, an ephemeral random parameter
4. Computes: stealth_address = hash(r × scan_key) + spend_key
5. Publishes r in the transaction's EncryptedMessage field
(r is public — it reveals nothing without Bob's private scan key)
6. Sends funds to stealth_address
Receiver (Bob):
1. Wallet queries Gateway API: transactions affecting his StealthIdentity
2. For each transaction, extracts r from the EncryptedMessage field
3. Computes hash(r × scan_private_key)
4. If match → funds recognised and added to stealth balance
5. Can spend using spend_private_key + hash(r × scan_private_key)
An observer sees funds sent to a random, unlinkable address, and a parameter r which is useless without Bob’s private scan key.
On the hint field: the Radix V2 transaction format already includes an EncryptedMessageV2 structure containing a dh_ephemeral_public_key field — this is exactly our parameter r. No new protocol field is needed; the mechanism reuses existing infrastructure.
On scanning efficiency: the Babylon Gateway indexes AffectedGlobalEntities for every transaction. Since payments touching Bob’s StealthIdentity component appear in this index, Bob’s wallet can query only transactions related to his component address — rather than scanning the entire chain. This makes scanning tractable without requiring a personal node.
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:
-
Redirection of staking rewards to the validator’s smart contract (rather than the staker’s main wallet) — required for Tools 2 and 3
-
Level metadata (0/1/2) for validators
At the wallet level:
-
Generation of scan and spend key pairs (HD-derived, integrated into Sargon)
-
Automatic derivation of ephemeral stealth addresses when sending
-
Efficient background scanning via Gateway API AffectedGlobalEntities filter
-
Transparent aggregation of stealth balance for the user
-
Automatic selection of source addresses when spending
-
Automatic generation of a fresh stealth address for change
-
Transaction fee management via Radix’s native fee abstraction
-
Distinction between superfungible (clean) and pseudofungible (traced) XRD, with configurable spending policy:
-
Superfungible priority — recommended for everyday payments
-
Automatic mixing — optimises fees
-
Manual selection — for advanced users
-
-
Contextual recommendation: superfungible XRD for payments, pseudofungible for DeFi
At the Scrypto level:
- StealthIdentity component blueprint (deployable today on Stokenet)
Important technical notes
Scanning and privacy: efficient scanning uses the Gateway API’s AffectedGlobalEntities filter, which requires Bob’s StealthIdentity address to be known to the querying node. For maximum privacy, using a personal node with direct database access is recommended — this allows scanning the raw message jsonb column without exposing query patterns to third-party infrastructure.
Forward secrecy: the StealthIdentity component publishes scan and spend public keys permanently. A future compromise of the scan private key would allow retroactive identification of received payments. Periodic creation of a new StealthIdentity component (and sharing the new address with contacts) is recommended for users with long-term privacy requirements.
Quantum resistance: the derivation scheme uses X25519 ECDH, which is vulnerable to a sufficiently powerful quantum computer (Shor’s algorithm). This is a known limitation shared by all current blockchain key schemes. A post-quantum upgrade path (replacing X25519 with a NIST-standardised KEM such as ML-KEM/Kyber) is well-defined and architecturally compatible — the cryptographic substitution is localised to the key encapsulation step without affecting the rest of the mechanism.
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: Superfungible 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.)
Terminology: pseudofungible and superfungible
Standard XRD carrying a traceable on-chain history is referred to as pseudofungible — fungible in value, but not in traceability. XRD whose traceability link has been broken through the obfuscation mechanism is referred to as superfungible — it has recovered its true and complete fungibility, indistinguishable from any other token of the same type.
The symmetry is intentional: pseudo (apparent fungibility) vs super (restored fungibility).
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 superfungible XRD — without traceable history linked to their deposits.
Note on unstaking: withdrawing superfungible 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 superfungible 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 provides a personal random seed to the contract
The contract records hash(S) — visible on-chain, 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 StealthIdentity 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 StealthIdentity 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 delay is expressed in epochs — for example a range of 2016 to 8640 epochs corresponds to between 7 and 30 days. The delay differs for each deposit because it incorporates a seed provided by Bob. Bob is the only person who knows this seed, making his exact delay unpredictable to external observers.
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 pseudofungible 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 superfungible 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 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
-
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)
-
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
Tool 3 — Validator Level 2: Superfungible 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 pseudofungible XRD to obtain superfungible ones
anonymity set = all users (broader, less controlled)
How to obtain an NFT Claim Ticket at Level 2
Step 1 — Bob sends pseudofungible 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 superfungible 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 StealthIdentity 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 in certain jurisdictions. Level 2 should be operated as a fully autonomous smart contract to minimise risks for any identifiable party.
Regulatory positioning
Level 2 remains more defensible than fully anonymous networks 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
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
→ Superfungible XRD on fresh stealth address
[Payment]
Alice's stealth address → Bob's stealth address
(Bob shares his StealthIdentity component address out-of-band)
[Bob breaks post-payment traceability]
Received stealth address → Level 1 or 2 validator
→ Superfungible XRD on new stealth address
[Bob spends]
New stealth address → merchant's stealth address
(merchant also has a StealthIdentity component)
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 fully private networks, 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.
Quantum resistance: the current derivation scheme uses classical elliptic curve cryptography. A sufficiently powerful quantum computer could retroactively deanonymise stealth payments. This is a known limitation shared by the entire current blockchain ecosystem. A post-quantum upgrade path exists and is architecturally compatible.
Summary of Required Changes
| Change | Level | Where |
|---|---|---|
| StealthIdentity Scrypto component blueprint | Fundamental | Smart contract (deployable now) |
| Redirection of rewards to validator’s smart contract | Fundamental | Protocol |
| Level metadata (0/1/2) for validators | Minor | Protocol |
| HD key derivation for scan/spend keys in Sargon | Fundamental | Wallet |
| Stealth address derivation module in Sargon | Fundamental | Wallet |
| Efficient scanning via AffectedGlobalEntities Gateway filter | Fundamental | Wallet |
| Stealth balance aggregation in wallet | Fundamental | Wallet |
| Fee management via native fee abstraction | Fundamental | Wallet |
| NFT Claim Ticket and secret management | Fundamental | Wallet |
| Configurable reward accumulation threshold | Fundamental | Wallet |
| Superfungible / pseudofungible distinction + spending policy | Fundamental | Wallet |
| Optional StealthIdentity rotation | Recommended | Wallet |
| Scrypto contract validator Level 1 | Level 1 | Smart contract |
| Scrypto contract validator Level 2 (3 flows, priority, urgency) | Level 2 | Smart contract |
The majority of the work resides in the wallet and smart contracts. The StealthIdentity component is deployable on Stokenet today without any protocol modification. Protocol changes are limited to reward redirection and validator metadata — surgical, well-delimited, and independent of the wallet work.
This document is a conceptual proposal open for discussion. It has been informed by direct analysis of the Sargon, radixdlt-scrypto, babylon-node, babylon-gateway, radix-engine-toolkit, and radix-dapp-toolkit source code repositories. 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.