FCMP++ — Full-Chain Membership Proofs, Plus Spend Authorization, Plus Linkability — is the most significant cryptographic upgrade in Monero's twelve-year history. It retires CLSAG ring signatures (see the prior CLSAG/RingCT schema) and replaces them with a zero-knowledge membership proof over the entire set of past outputs. The anonymity set jumps from 16 to ~150 million. Decoy selection — and every heuristic attack built on it — disappears.
Today, when you spend an output, your wallet picks 15 random decoys and CLSAG proves the signature was made by one of these 16. The anonymity set is small, fixed, and built from a heuristic decoy selection algorithm that has been the subject of academic attacks for years. FCMP++ throws all of that out.
Each input is mixed with 15 chain-sampled decoys. The signer proves one of these 16 keys is theirs, without revealing which. Anonymity set is hard-capped: bigger rings = linearly bigger transactions.
A zero-knowledge proof that the spent output is somewhere in the entire UTXO set — every output the chain has ever produced. No decoys. No selection algorithm. The proof scales logarithmically, so the tx stays small even as the chain grows.
The mechanism is fundamentally different. Instead of listing decoys, FCMP++ produces a compact succinct proof: roughly 3 KB, verifiable in tens of milliseconds, attesting that the prover knows a valid output somewhere in a Merkle-tree-like structure built from every output on chain. The on-chain transaction never names a specific output — it just shows the proof.
CLSAG was a beautiful piece of cryptography — 25% smaller and faster than its predecessor MLSAG — but the underlying ring-signature paradigm has a hard ceiling. FCMP++ doesn't just enlarge the ring; it abandons the ring entirely.
CLSAG cost grows linearly with ring size. Doubling the anonymity set doubles the bytes on chain and the verifier time. Getting to 1000+ members this way is infeasible.
Decoys are sampled via a gamma distribution matched to real spend timing. But timing analysis, EAE (Eve-Alice-Eve), and flooding attacks all exploit the fact that the real input often stands out statistically among the 15 chosen decoys.
If an attacker creates many outputs and observes which appear later as decoys, they learn correlation data. With small rings, repeated sampling concentrates evidence over time. Larger rings would help, but see (α).
Ring signatures answer "which of these N wallets signed?" — and the cryptographer chooses N. FCMP++ answers "which of every wallet that has ever existed signed?" — and the answer is structurally unanswerable. The chain itself becomes the anonymity set, automatically, without any heuristic.
FCMP++ is not one technique but a careful composition of six. Each was a research effort in its own right; the elegance is in how they fit together. The whole construction has been formally verified gadget-by-gadget by Veridise and is undergoing final integration audit by Trail of Bits.
A Merkle-tree variant where every node is a Pedersen commitment instead of a hash. Internal nodes commit to their children's commitments. Membership in the tree can be proven in zero-knowledge with only O(log n) work.
Two curves engineered so each one's base field equals the other's scalar field. This "tower cycle" sits above Ed25519, letting the proof recursively verify commitments at each tree level without expensive emulation.
An extension of Bulletproofs+ supporting arbitrary arithmetic circuits (not just range proofs). This is what actually generates the succinct membership proof. Same family Monero already uses for amounts.
Liam Eagen's trick: scalar multiplications inside the ZK circuit are normally extremely expensive. EC divisors prove them by checking that a polynomial vanishes at specific points — orders of magnitude faster.
A Schnorr-style signature proving the prover knows the private key for the output they're spending. Replaces the "I signed it" half of what CLSAG used to do. Includes FROST-style multisig.
Key images survive — they're still emitted per input, still uniquely identify a spent output, still rejected on duplicate. The math is updated to suit the new key derivation, but the role is unchanged.
Every output that has ever existed on chain becomes a leaf in a giant tree. Each level of the tree is a Pedersen commitment to a fixed-arity batch of children. The whole tree's root sits in consensus state — every node maintains it incrementally as new blocks land. To spend, the prover demonstrates "I know a path from some leaf to this root, and I know the spend key of that leaf" — without revealing which leaf.
As blocks arrive, every node maintains the tree. New outputs become leaves, parent commitments are recomputed. The root is part of consensus — every full node agrees on it.
The prover's wallet walks the path from its real output up to the root, generating a ZK proof at each level showing "this commitment opens to the one below" — without revealing which child.
The verifier knows only the public root. The aggregated proof checks the entire path was traversed consistently. Tens of milliseconds. ~3 KB.
A naive ZK proof over an elliptic curve has to do all its scalar arithmetic in the curve's scalar field. But the values it's proving statements about (Pedersen commitments) live in the curve's base field. The mismatch forces expensive emulation: simulating one field's arithmetic inside another, costing thousands of constraints per multiplication. FCMP++'s answer: use a pair of curves where this mismatch vanishes.
If Helios's base field is F_p and scalar field is F_q, then Selene's base field is F_q and scalar field is F_p. Points on Helios can be efficiently described by scalars on Selene, and vice versa. This is what makes the recursive tree-path proof tractable — each level of the tree alternates curves, and the arithmetic always "fits" the curve doing the proving.
Critically, the existing Ed25519 keys you already have do not change. Helios and Selene "tower over" Ed25519 — they're added above the existing curve, not replacing it. Your wallet keys, your historical outputs, your stealth address derivation: all preserved. This is what lets FCMP++ ship as a clean hard fork without forcing users to migrate funds to new key formats. That was the original FCMP plan, tied to the Seraphis next-gen protocol; the "++" version explicitly removes the Seraphis dependency.
Surprisingly little of the transaction format dies. Stealth addresses, Pedersen commitments, range proofs, key images, the balance equation — all preserved. The change is surgical: swap CLSAG out, swap FCMP + GSP in. Everything that wasn't a ring signature continues working exactly as documented in the CLSAG/RingCT schema.
| Field | Today (CLSAG · v16) | After FCMP++ |
|---|---|---|
| RECEIVER PRIVACY · unchanged | ||
| Stealth address | P = Hs(rKv)·G + Ks | Same. Sender derivation untouched. |
| View tags | 1-byte hint per output (since v15) | Same. |
| Encrypted amounts | ecdhInfo via shared secret | Same. |
| AMOUNT PRIVACY · unchanged | ||
| Pedersen commitments | C = a·G + x·H | Same. |
| Range proofs | Bulletproofs+ | Same family (BP+, possibly BP++ further out). |
| Balance equation | Σ in − Σ out − fee·H = 0 | Same. |
| SENDER PRIVACY · this is the big change | ||
| Anonymity set | 16 ring members (15 decoys + real) | Every output ever created (~150M+). |
| Selection method | Gamma-distributed decoy sampling | None. The chain itself is the set. |
| Sender proof | One CLSAG σ = {s[16], c1, D} per input | One FCMP membership proof + one GSP spend signature per input. |
| key_offsets | 15 deltas pointing at ring members | Gone. The proof references the root, not specific outputs. |
| Per-input size | ~640 bytes (CLSAG @ ring 16) | ~3 KB (FCMP proof + GSP sig), independent of chain size. |
| DOUBLE-SPEND PROTECTION · unchanged role | ||
| Key image | I = x·Hp(P), in vin.k_image | Still emitted per input. Math updated for the new key derivation. Same uniqueness guarantee. |
From 16 to ~150 million. Statistical deanonymization becomes effectively impossible.
An entire class of timing & flooding attacks evaporates because there is no selection algorithm to attack.
~3 KB per input vs ~640 B today. Net per-tx growth is moderate because rings (which scaled with members) go away.
Generating an FCMP++ proof is more compute than signing CLSAG. Verification stays fast though (~tens of ms).
The original "FCMPs" proposal (MoneroKon 2023) was designed to ship alongside Seraphis — the planned next-generation transaction protocol with new key formats and a redesigned RingCT. That coupling kept FCMPs in research limbo while Seraphis itself was still being designed. In March 2024, during a spam-attack debate, kayabaNerve proposed an alternative.
Anonymity over every output, not a sampled subset. The defining feature.
Proof that the spent output is in the curve-tree of all outputs. The "M" verb.
Plural — one per input. Each proof is independent and combinable.
The Generalized Schnorr Protocol sig. Replaces the "I signed it" half of CLSAG, so FCMPs can deploy without Seraphis providing it.
Key images — the double-spend prevention layer that the original FCMPs design delegated to Seraphis. The "++" version reintroduces them directly.
FCMP++ ships as a hard fork to today's RingCT-style txs. Seraphis itself remains a longer-term project, no longer blocking the privacy upgrade.
FCMP++ has been under active development since 2024, with funding through Monero's Community Crowdfunding System. Spec, implementation, sub-circuit verification, and a first audit have all completed. The remaining steps are integration audit and the actual hard fork. Current status (as of mid-2026):
helioselene, ec-divisors, the arithmetic circuit, the Generalized Schnorr Protocol, and a 2-round FROST-style multisig variant.helioselene and ec-divisors libraries. Winner achieved ~22% speedup. Subsequent improvements push it further.monerod codebase. The final pre-fork de-risking step.