FCMP++ Explained: Full-Chain Membership Proofs, Designed for Innova
FCMP++ extends sender privacy from a fixed ring to the entire UTXO set via dual-curve Merkle trees over secp256k1 and Ed25519. Activation is scheduled at block 7,320,000.
Status note
FCMP++ is designed and specified but not yet active on Innova mainnet. Activation is scheduled at block 7,320,000 via a coordinated soft-fork upgrade. Until then, Innova's sender-privacy layer uses Lelantus one-out-of-many proofs (live today). Descriptions of FCMP++ in this post refer to its designed behavior post-activation.
What FCMP++ is
FCMP++ stands for Full-Chain Membership Proofs with Curves. It is a cryptographic construction that lets a spender prove "the UTXO I am spending is somewhere in the entire set of unspent outputs" without revealing which specific output is being spent.
Practical effect: the anonymity set expands from a fixed ring (typically 16 decoys in classical RingCT, or the shielded pool in Lelantus) to the entire active UTXO set — millions of outputs on a mature chain.
Innova's FCMP++ implementation is designed as a Layer 2 sender-privacy upgrade, integrated with the IDAG consensus layer's epoch-anchored privacy model. The activation block is scheduled at 7,320,000 in the IDAG specification, with a soft-fork migration framework that includes graceful fallback to Lelantus if FCMP++ proofs fail validation.
Why this matters — the anonymity-set ceiling
Privacy in Monero-style RingCT works via ring signatures over a fixed ring of decoys. When Alice spends, she constructs a signature that could have come from any of 16 outputs selected from chain history. An observer cannot tell which is real.
Two problems:
- The ring is small. Over time, heuristic analysis (decoy temporal ordering, churn detection, repeated appearance patterns) can statistically narrow the probability space below 1-in-16 for well-resourced adversaries.
- Decoy selection is a policy. Wallets choose decoys from the output distribution, which is itself information the adversary can model.
Lelantus (Innova's current sender-privacy mechanism) improves on this by expanding the set to the shielded pool. FCMP++ pushes further — the anonymity set becomes the entire UTXO set, chosen not by the wallet's heuristics but implicitly by the cryptographic proof. Millions of outputs, not 16.
The dual-curve tree construction
The novelty of FCMP++ over earlier full-chain-membership proposals is the dual-curve design. Innova's specified implementation:
| Property | Value |
|---|---|
| Tree arity | 256 (each internal node has up to 256 children) |
| Maximum depth | 8 levels |
| Maximum outputs | 256⁸ = ~1.8 × 10¹⁹ (effectively unlimited) |
| Even-depth curve | secp256k1 |
| Odd-depth curve | Ed25519 |
Levels alternate between the two curves. This enables efficient inner-product arguments across curves: a proof at level N can be verified cheaply against a commitment at level N+1 without requiring a single curve that supports both operations natively. The result is logarithmic proof size while avoiding the compute cost of forcing every operation onto one curve.
Once activated, at each epoch boundary (300 blocks post-DAG activation, ~5 minutes target), the finalized UTXO set will be committed to a curve tree root. The root will be included in the epoch's binding finality record, creating an immutable anchor that every FCMP++ proof references.
# Post-activation: get the FCMP++ curve tree root for the current epoch
innova-cli getepochcurvetreeroot
# Or for a specific epoch
innova-cli getepochcurvetreeroot 25000{
"epoch": 25000,
"curve_tree_root": "a3f8c1d2e4b5...",
"utxo_count": 12847392,
"tree_depth": 5,
"binding_finality": true
}Why this has taken time to ship
Full-chain membership proofs have been theoretically known for years. The blockers are practical:
- Proving time. Naive constructions take minutes to generate — unacceptable for interactive wallet use.
- Verification cost. Each proof must verify during block propagation; slow verification throttles throughput.
- Integration surface. Retrofitting membership proofs into a privacy protocol without breaking mempool, fee economics, light-client behavior, or bandwidth budgets is brutally hard.
- Activation coordination. Consensus-critical cryptographic upgrades need soft-fork discipline, fallback paths, and operator-readiness signals — which is exactly what IIP-style activation gates provide.
Innova's approach addresses each: the dual-curve design keeps proof sizes logarithmic (~log N in the UTXO set); curve tree roots are anchored to finalized epochs so verification references immutable anchors; and activation is scheduled via the IDAG soft-fork migration framework with graceful Lelantus fallback on failure.
Where FCMP++ sits in the privacy stack
FCMP++ is the sender-privacy (Layer 2) evolution of Innova's five-layer stack — it replaces Lelantus's whole-pool anonymity set with a whole-chain anonymity set. It does not create a new layer; it upgrades an existing one.
| Layer | Mechanism | Status |
|---|---|---|
| 1 | Pedersen + Bulletproof | Live |
| 2 | Lelantus → FCMP++ | Lelantus live; FCMP++ scheduled (block 7,320,000) |
| 3 | Stealth addresses + Silent Shielding | Live |
| 4 | Dandelion++ | Live |
| 5 | NullStake V1/V2 | Scheduled (block 9.5M / 10M) |
Because FCMP++ is integrated with IDAG's epoch-anchored privacy (Phase 3), the curve tree root references only finalized epochs — the anchor point is cryptographically immutable by the time a proof is constructed against it.
What this will unlock
From a user perspective, a post-activation FCMP++ spend will have:
- Anonymity set equal to the entire active UTXO pool — millions of outputs, not 16
- Verification time comparable to classical RingCT — block propagation stays fast
- Compatibility with Dynamic Selective Privacy — per-transaction privacy mode selection applies
- Graceful fallback. If FCMP++ proof construction or validation fails, the transaction is accepted via Lelantus proofs without a chain split. Coordinated via the soft-fork migration framework.
From a compliance perspective, FCMP++ composes with viewing-key auditability in the broader Innova stack (most notably NullStake). Selective transparency — explicit read access granted by the user — is preserved.
A note on the Monero FCMP++ track
FCMP++ is actively researched in the Monero community as well. Monero's contribution (from Luke "Kayaba" Parker and collaborators) produced the curve-tree construction that Innova's implementation adapts. Monero's mainnet activation is on a separate track governed by Monero's soft-fork discipline.
Innova's contribution is the packaged migration framework: soft-fork semantics, fallback behavior, upgrade sequencing, and integration with an epoch-anchored consensus finality layer. Which project activates FCMP++ on mainnet first is a coordination race, not a research race — the underlying cryptography is shared.
Next up in this silo
- Five-Layer Privacy Stack — where FCMP++ fits in the broader architecture
- NullStake: Zero-Knowledge Private Staking — Poseidon2 + BPAC, composes with FCMP++ curve trees (also scheduled)
- Dynamic Selective Privacy — the 8-mode per-transaction privacy selector, live today (upcoming post)
- IDAG Consensus — the four-phase migration underpinning FCMP++ and NullStake (upcoming)
Or browse the Innova product page for testnet links and the broader architecture.
More from Innova
Innova's Five-Layer Privacy Stack, Explained Layer by Layer
Innova stacks five independent privacy primitives. Layer 1 hides amounts (Pedersen + Bulletproofs). Layer 2 hides the sender (Lelantus, with FCMP++ as the evolution). Layer 3 hides the receiver (stealth and silent-payment addresses). Layer 4 hides the network origin (Dandelion++). Layer 5 hides staked amounts (NullStake).
NullStake: Zero-Knowledge Private Staking Designed for Innova
NullStake is Innova's designed zero-knowledge private staking protocol, with two generations scheduled for activation. V1 (Sigma protocol, ~1.8 KB proofs) activates at block 9,500,000 via IIP-0009. V2 (Poseidon2 + BPAC, ~720 bytes) activates at block 10,000,000 via IIP-0010. Until then, Innova uses transparent staking.