On Bitcoin, anyone can read which outputs a transaction spends, which addresses it pays and how much. Monero hides all three by default, with a separate tool for each: ring signatures hide which output is being spent, one-time (stealth) addresses hide who receives, and RingCT hides the amount. None of this is optional. Every Monero transaction uses all three, so private transactions don't stand out from ordinary ones.
| What's hidden | Tool | Since |
|---|---|---|
| Sender (which output is spent) | Ring signatures (CLSAG, ring size 16) | Rings from launch; CLSAG 2020; size 16 since 2022 |
| Receiver | One-time addresses, subaddresses | Launch; subaddresses 2017 |
| Amount | RingCT: Pedersen commitments + Bulletproofs+ | RingCT 2017; Bulletproofs+ 2022 |
The receiver: one-time addresses
A Monero wallet has two private keys: a view key a and a spend key b, with public keys A = a·G and B = b·G. Your address encodes (A, B), but that address never appears on the chain. For each payment, the sender derives a fresh output key only the recipient can recognize:
r = random scalar chosen by the sender
R = r·G published in the transaction ("tx public key")
P_i = Hs(r·A ‖ i)·G + B one-time key for output i
Hs hashes to a scalar. The recipient scans each new transaction, computes Hs(a·R ‖ i)·G + B and checks whether it equals P_i. This works because r·A = a·R. If it matches, the output is theirs, and the private key to spend it is x = Hs(a·R ‖ i) + b. An observer sees only unrelated-looking one-time keys, even when the same address is paid a thousand times. (The real derivation also multiplies by the curve cofactor. It's left out here.)
Since 2022 each output also carries a one-byte view tag derived from the same shared secret. Wallets check the tag first and skip about 255 of every 256 outputs without doing the full computation, which makes scanning much faster.
Subaddresses extend this. From one wallet you can derive any number of addresses (starting with 8) that can't be linked to each other or to the primary address (starting with 4). Give each customer or order its own subaddress instead of reusing one address with payment IDs:
curl -s http://127.0.0.1:18082/json_rpc \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"0","method":"create_address",
"params":{"account_index":0,"label":"order-1042"}}'
monero-wallet-rpc returns the new subaddress and its index. Incoming transfers report that index, so you can match payments to orders.
The sender: ring signatures and key images
Each input in a Monero transaction references a ring of 16 existing outputs: the one actually being spent plus 15 decoys taken from the chain. The wallet picks decoys from a distribution that favors recent outputs, because real spends tend to be recent. A CLSAG signature (Concise Linkable Spontaneous Anonymous Group) proves the signer holds the private key for one of the 16 keys without revealing which one.
That raises a problem: if nobody knows which output was spent, how do nodes stop a double spend? Each signature includes a key image:
I = x·Hp(P)
Hp hashes to a curve point. The key image is deterministic: the same output always produces the same image, but it can't be linked back to P without the private key. Nodes store every key image they've seen and reject any transaction that repeats one. A spent output is never revealed, yet it can't be spent twice.
The amount: RingCT, Pedersen commitments and Bulletproofs+
Rings only work if any output can plausibly be a decoy for any other, which is impossible if amounts are public. RingCT (Ring Confidential Transactions) replaces each amount with a Pedersen commitment:
C = x·G + a·H x = random blinding factor, a = amount
Commitments are additively homomorphic, so nodes can check that inputs equal outputs plus the fee without learning any amount:
sum(input pseudo-commitments) − sum(output commitments) − fee·H = commitment to zero
The fee is the only public amount. Proving the sum isn't enough, though: a commitment to a negative number (a huge number modulo the curve order) could mint coins out of nothing. So every output carries a range proof that its amount lies between 0 and 2⁶⁴. Monero moved from Borromean signatures to Bulletproofs in 2018 and to Bulletproofs+ in 2022. They're aggregated per transaction and grow logarithmically with the number of outputs. The actual amount is encrypted to the recipient with the one-time shared secret, so only they can read it.
View keys vs spend keys
| Key | Lets you |
|---|---|
| Private spend key | Sign and spend. Never share it. |
| Private view key | Detect incoming outputs and read their amounts |
| Tx key (per transaction) | Prove to a third party that you paid a specific address |
A view-only wallet (monero-wallet-cli --generate-from-view-key) is how you give an auditor or a point-of-sale server visibility without spending power. It sees incoming funds, but it can't reliably see outgoing spends: detecting a spend requires key images, and computing those needs the spend key. Its balance can be too high unless you export key images from the full wallet and import them. To prove a single payment, use the transaction key:
[wallet 4Ab...]: get_tx_key <txid>
[wallet 4Ab...]: check_tx_key <txid> <tx_key> <recipient_address>
Mining and emission
Monero uses RandomX, adopted in November 2019. It runs randomly generated programs in a virtual machine designed around general-purpose CPUs (large caches, branching, floating point), which keeps ordinary CPUs competitive and has so far kept dedicated ASICs from taking over. Blocks target 2 minutes, and newly received outputs are locked for 10 blocks before they can be spent.
The main emission curve ended in mid-2022. Since then Monero has paid a tail emission of 0.6 XMR per block forever, about 157,680 XMR a year. That's under 1% annual inflation and falling as a percentage. The goal is a permanent block reward, so miners aren't paid by fees alone.
Where Monero's privacy ends
Monero's cryptography is strong. Most practical deanonymization comes from everything around it:
- Rings are small. Sixteen members is a statistical anonymity set. Weak decoy selection has been exploited in past research, and if an adversary controls or knows some ring members (because it sent you those outputs), the effective ring shrinks.
- Round trips. If an exchange pays you and you send funds straight back to it, the exchange sees its own output in your ring and can make a good guess.
- Merging outputs. Spending several outputs in one transaction shows they share an owner.
- Network metadata. Dandelion++ hides which node first broadcast a transaction, but a remote node you connect to sees your IP address and when you send. Run your own node, or connect over Tor.
- Timing and amounts at the edges. A KYC exchange knows who bought XMR, when and how much. Timing correlation can link deposits and withdrawals across services.
- Fewer on-ramps. Several large exchanges, including Binance and OKX, delisted XMR in 2024, so fewer regulated venues offer it.
- Hashrate concentration. In 2025 a single mining operation briefly controlled a majority of hashrate and caused multi-block reorgs. Wait for more confirmations on high-value payments.
The main planned upgrade is FCMP++ (full-chain membership proofs), which would replace 16-member rings with a proof that the spent output is one of every output on the chain. That would remove most decoy-based analysis. Treat it as planned until it activates in a network upgrade, and check the current release before relying on it.
Summary
| Question | Answer |
|---|---|
| Who sent it? | One of 16 ring members; key images prevent double spends |
| Who received it? | A one-time key only the recipient's view key can recognize |
| How much? | Pedersen commitment plus Bulletproofs+ range proof; only the fee is public |
| Who can audit? | Anyone you give the view key (incoming) or a tx key (one payment) |
| What still leaks? | Network metadata, timing, exchange records, output merging |
Get the weekly commit
New blockchain deep dives every week.