Note
A Subaddress Is Not a Separate Identity: Janus Outputs, Sweeps, and the Seed Boundary
Subaddresses give you receive unlinkability against observers and honest payers. They do not give you identity isolation against an active counterparty, your own consolidation transactions, or a service's account database.
2026-10-21 · privacy, monero, subaddresses, janus-attack, carrot, fcmp, unlinkability, opsec, threat-model, civil-liberties
Listen · 9 min · AI voice

Monero's own documentation says subaddresses are what you should use by default to receive. That advice is sound. A fresh subaddress per payer or purpose stops a casual counterparty from noticing that two payments went to the same person, and it costs nothing in scan speed or seed management.
But a subaddress is a door, not a house. Every subaddress in a wallet hangs off one private view key and one seed. Against a passive observer reading the chain, the doors look unrelated. Against a counterparty who already holds two of your doors and wants to know if they open into the same house, there is a specific, documented test, the Janus attack, and the thing that makes it work is not cryptography breaking. It's you saying "got it, thanks."
Thesis: subaddresses give you receive unlinkability against observers and honest payers. They do not give you identity isolation against an active counterparty, against your own consolidation transactions, or against a service's account database. If two roles must never be linked, the boundary is a separate seed, not a separate subaddress.
How subaddresses are built (and why they share a root)
The subaddress scheme was proposed in 2016 (research-lab issue #7) as a wallet-level feature. It doesn't change consensus. Each subaddress (C, D) (view public key, spend public key) is derived deterministically from the wallet's private view key plus an account index and a subaddress index. Monero Docs describes the derivation on its subaddress page: a scalar m = Hs("SubAddr" || a || account || index) built from the private view key a, which tweaks the spend key for that index.
Two consequences follow directly:
- One scan covers every door. Your wallet recognises payments to all subaddresses with the same private view key, which is why there's no scan-speed penalty. It is also why the view key is a wide lens rather than a per-door peephole (see our view-key note).
- Accounts are labels, not walls. The docs describe accounts as a "soft grouping" of subaddresses under the same root. The Janus disclosure says it plainly: "Separate accounts under a single seed are still susceptible."
Neither is a flaw. They are the price of one seed, one backup, one scan. The problem only starts when someone treats that shared root as if it were several separate identities.
The Janus attack, mechanically
The Monero project disclosed the attack in October 2019 in Subaddress Janus attack. Here's the setup in plain terms.
You give a counterparty subaddress B. They suspect you also own subaddress A, perhaps from a donation page, an old invoice, or a forum signature. Instead of building a normal payment to B, they build a hybrid output. In the disclosure's notation, a normal payment to subaddress (C_j, D_j) publishes a transaction public key s·D_j and an output key Hs(s·C_j)·G + D_j. The Janus sender instead publishes s·D_i and Hs(s·C_i)·G + D_j, mixing a key from A into what looks like a payment to B.
If A and B come from the same wallet, your wallet recognises the output and credits it to B. Nothing looks wrong. If they don't, nobody can spend the output and the funds are gone. So the sender pays real money for each guess.
Then comes the leak. The disclosure lists three conditions, and all three must hold:
- Both subaddresses come from one seed.
- The attacker knows which subaddress to test and crafts the special transaction.
- The recipient confirms receipt off-chain, by hand or automatically.
Without step 3, the attacker learns nothing, because the chain doesn't tell them whether you recognised the output. An automatic "payment received" email, a webhook-driven order page, or a service that credits a deposit all count as confirmation. The disclosure gives an example: an attacker who also has a deposit subaddress at the same service can send a crafted output and see whether their own account gets credited. That confirms your address belongs to the same service without you saying a word.
What it can't do matters too. It can't steal funds, inflate supply, or help passive chain analysts: "Passive non-colluding observers... do not gain any advantage." It is an active, targeted, paid probe of one specific guess.
Three other ways doors get linked
Janus gets the attention, but in practice these are more common.
Consolidation sweeps. Monero Docs warns against sweeping several subaddresses' balances in one transaction: "That links the subaddresses together on the blockchain." A transaction that spends outputs received at A and B shows that someone controlled both, at least to whoever sent those outputs. The docs add that this "will never get worse than not using subaddresses in the first place," but if separation was the goal, one tidy sweep undoes it. Their mitigation is to consolidate with separate transactions, one per subaddress.
Accounts at a service. If you have an account at the service paying you, as the docs put it, "your payouts are already linked in the service database, regardless of Monero." Fresh subaddresses hide nothing from a party that already keys everything to your login.
The human layer. Reusing a payment description, a username, a payout schedule, or a reply style across two roles links them faster than any cryptography. Subaddresses protect the address field and nothing else.
What Carrot changes
Carrot is the addressing protocol designed to sit on top of the planned FCMP++ consensus upgrade (background). Its spec lists "Janus attack mitigation" among the features for all wallets, including existing ones, with no key migration.
The mechanism is a 16-byte encrypted Janus anchor in each output. In a normal transfer the anchor is random and lets the recipient re-derive the sender's ephemeral private key and check that the ephemeral public key was built correctly. In the spec's words, a Janus output makes the recipient "derive different values of the enote ephemeral pubkey... and Janus anchor, and thus will not recognize the output." The crafted payment simply doesn't show up in your balance, so there is nothing to confirm.
The same input-binding design also gives a stateless fix for the older burning bug, where duplicate output keys could trick a wallet into counting funds it couldn't fully spend.
Two cautions. First, Carrot changes how wallets construct and scan outputs; it does not stop sweep linkage, service databases, or human-layer reuse. Second, it ships with a network upgrade. Until that upgrade is active on the network you use and your wallet software implements it, treat the 2019 rules as current: don't confirm receipts to people you're compartmentalising from, and don't share deposit subaddresses.
Who this matters for
Most people use subaddresses to tell incoming payments apart: one per invoice, per donor, per marketplace order. The Janus disclosure says that if this is your use, "this attack does not affect you," and that most merchants are unaffected.
It matters when the separation itself is the point. Think of a journalist with a public tip jar and a private personal wallet, a pseudonymous developer funded under a handle they keep apart from their legal name, or an organiser in a country where receiving money for a cause can be used against them. For them, "same wallet" is the fact an adversary is paying to learn, and an automatic thank-you note answers it for free.
The rule that travels is short: separate identity, separate seed. Use subaddresses inside an identity, and a different wallet between identities.
What this is not
This isn't a claim that subaddresses are broken or that integrated addresses or single-address reuse are safer. The docs and the disclosure both say subaddresses remain the right default. It isn't a wallet or service ranking, and it's not a timeline promise for FCMP++ or Carrot activation, so check the release notes for the software in front of you. It isn't legal, tax, or compliance guidance on proving or hiding income. And it covers no prices, trading, swaps, or custody choices. It's about which link each tool cuts, and which it leaves in place.
Related on CryptoDecentral
- Privacy pillar
- A View Key Is Not a Transparent Chain
- An Anonymity Set Is Not a Ring Size
- From Rings of 16 to the Whole Chain: What FCMP++ Changes
- On-Chain Privacy Is Not Network Privacy: Node Choice, Tor, and I2P
Further reading (primary)
- Monero Docs: Subaddress (derivation, accounts, sweep caveat)
- Monero project: Subaddress Janus attack disclosure (2019)
- Carrot addressing protocol spec (Janus anchor, sections 2.1.2, 7.3.5, 7.7)
- Monero research-lab issue #7: original subaddress proposal
- Monero project: FCMP++ overview
- Monero project: Burning bug post-mortem
Sources
- https://docs.getmonero.org/public-address/subaddress/
- https://www.getmonero.org/2019/10/18/subaddress-janus.html
- https://github.com/jeffro256/carrot/blob/master/carrot.md
- https://github.com/monero-project/research-lab/issues/7
- https://www.getmonero.org/2024/04/27/fcmps.html
- https://www.getmonero.org/2018/09/25/a-post-mortum-of-the-burning-bug.html