A Decade of Workarounds
How Bitcoin Core's mempool policy evolved to support Lightning (and other Layer 2s), and why it took nearly ten years to do it well.

Imagine you’re building a layer 2 protocol on bitcoin with a system that supports time-sensitive transactions. If those transactions don’t confirm within a certain number of blocks, someone loses money. You’ve designed your system around Child Pays For Parent (CPFP), so when fees spike unexpectedly, the user attaches a high-fee child transaction to drag the parent into the next block.
Unfortunately, your counterparty can attach their own children first: a large, low-feerate child that meets the minimum relay fee (to make it into miner’s mempools) but won’t be mined any time soon. Or perhaps a chain of junk feerate children. Now you can’t attach yours since the parent has hit its descendant limit! Your time-sensitive transaction is stuck, and there’s nothing you can do about it.
This is transaction pinning. And for most of bitcoin’s history, there was no good answer to it.
The solutions that emerged over the following decade were a series of workarounds: special cases, carveouts, and topology restrictions designed to patch the most urgent holes. None of these were necessarily engineering failures. Some were necessary scaffolding that kept Lightning and other protocols functional while a more principled solution was being built. However, their limitations shaped how L2 protocols had to be designed, and several rules were destined for the dustbin of history.
This is the story of that decade: why the workarounds were necessary, what they actually did, and how Bitcoin Core finally shipped the tools to replace them.
Act 1: The Heuristics Era
The Bitcoin Core v0.12 Foundation (2015-2016)
To understand why that descendant limit exists in the first place, we need to go back to late 2015.
Bitcoin Core's mempool was getting more sophisticated. Designed to allow the mempool to be trimmed in busy times, developers introduced descendant package tracking (PR #6654), letting the mempool understand relationships between transactions, which ones depend on which. Shortly after, developers lowered the ancestor and descendant limits to 25 transactions and 101 KB per chain (PR #6771). A few months later, ancestor package and feerate tracking arrived (PR #7594), enabling miners to consider CPFP when selecting transactions for blocks.
These limits were based on fundamental computational constraints. Every time a transaction enters or leaves the mempool, the affected statistics need updating. Every time a miner constructs a block, transaction chains need to be evaluated. Deep chains mean more computation, and unbounded computation can lead to denial-of-service, but limits make the problem tractable.
Around the same time, opt-in Replace By Fee (RBF) landed (PR #6871). This was partly a political compromise as merchants worried that replaceable transactions would enable fraud, so replacement required explicit user and wallet signaling via the transaction’s nSequence field. The set of replacement rules called BIP125 required the new transaction to pay a higher total fee and a higher feerate, and prohibited introducing new unconfirmed parents; a series of heuristics.
That last rule is revealing. We reject new unconfirmed parents as a precaution; we simply can’t tell whether the new transaction is liable to be mined anytime soon, and similarly, if we are wasting people’s bandwidth and CPU relaying it. Does this replacement, with its new dependencies, actually improve the mempool? Without understanding the full transaction graph and its implications for mining, we can’t say so we reject it as a precaution.
Both the chain limits and the RBF rules stem from the same underlying problem: we don’t know how to efficiently compute what’s actually best for miners. So we impose constraints and heuristics that seem reasonable and enable useful features without obviously worsening things.
This shipped in Bitcoin Core v0.12.0 in February 2016. Lightning was still on the horizon, with various consensus changes to support it in-flight.
Pinning Gets Real (2017-2018)
In the background, OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY, and segwit are activated on mainnet.
Lightning Network launched on mainnet in early 2018. The long-awaited theoretical L2 is now operational.
Pinning vectors weren’t unknown, as researchers had discussed them for years. But live systems with real money forced the issue. It wasn’t enough to know that attacks were possible; protocol developers needed to understand exactly which attacks were practical, and what could be done about them within existing mempool policy.
In November 2018, our very own Matt Corallo posted to the bitcoin-dev mailing list with the diplomatically-titled “CPFP Carve-Out for Fee-Prediction Issues in Contracting Applications.” The substance was simple: Lightning commitment transactions could be pinned, and a quick fix was needed, even if it didn’t solve all problems.
The attack was straightforward. Lightning commitment transactions are co-owned; either party can broadcast. If your counterparty broadcasts and immediately attaches a tree of low-feerate children, they can exhaust the descendant limit. Now you can’t attach your own CPFP. Your time-sensitive transaction is stuck at the fee rate it was signed with, potentially weeks or months ago.
The mailing list discussion systematized the problem. What topologies do L2 protocols actually need? What subset of those can we defend with policy changes? The answer wasn’t “all of them,” it was “a very specific shape that Lightning uses.”
The Carveouts (v0.19, 2019)
The fix arrived in Bitcoin Core v0.19.0: the “CPFP carveout.”
The rule was narrow by design. If a transaction is already at its descendant limit, one additional child extending from the original parent is allowed, provided that the child is small (under 10 kvB) and has exactly one ancestor (the transaction being bumped). This was enough for Lightning: even if your counterparty bloats the descendant chain, you can still attach one small CPFP transaction.
One curious historical note: Corallo’s original mailing list post suggested a 1 kvB limit. The PR implemented 10 kvB. Nobody seems to have commented on the tenfold increase.
A companion rule, the single-conflict RBF carveout (PR #16421), addressed a follow-on problem: what if the attacker’s child could itself pin your carveout child through RBF rules? Whoops! The fix allowed replacements at the just oversized one-more-child package limits, but only when evicting exactly one transaction.
These carveouts are uncomfortable if you think about them too hard. They’re not general principles but Lightning-specific hacks baked into Bitcoin Core’s mempool policy. They work because Lightning commitment transactions have a known topology: one parent, limited children, two (and only two!) parties who each need to be able to fee-bump. Change that topology, and the carveouts don’t help you.
But they sorta worked, if you don’t think too hard about how miners would consistently get these transactions in the presence of semi-powerful adversaries. Lightning had a path forward, even if it was narrower than anyone wanted.
Act 2: Shrink the Problem (2019-2024)
The Long Wait
The carveouts perhaps bought time, but the underlying problems remained, and the carveouts don’t apply to a more general UTXO-sharing future.
L2 developers lived with these known limitations. The carveouts only helped the specific two-party, one-parent topology. Other pinning vectors remained open. The “no new unconfirmed parents” RBF rule meant you couldn’t bump a transaction by adding a high-fee parent; you could only replace it entirely or add a child. And the fundamental tension persisted: policies were heuristics because we couldn’t compute the optimal solution.
The mailing list accumulated proposals. A package relay that atomically submits a parent and child, allowing CPFP, could work at relay time, not just mining time. The soft fork known as “transaction sponsors” let third parties attach fees to arbitrary transactions. Various transaction introspection opcodes that might let contracts reason about their fee context.
Most ideas were stalled or abandoned. The fundamental blocker wasn’t a lack of ideas, it was that the mempool’s data structures couldn’t answer the questions these proposals needed to ask. “Is this package better than what it replaces?” sounds simple. Computing it efficiently for arbitrary transaction graphs is not.
The TRUC Insight
If we can’t compute incentive compatibility for arbitrary topologies, what if we restrict the topology until we can?
This was the insight behind Topologically Restricted Until Confirmation (TRUC), also known as v3 transactions (BIP 431). The restrictions are severe: a TRUC transaction can have at most one unconfirmed ancestor and one unconfirmed descendant. The child is limited to 1000 virtual bytes (ironically, the original one-more rule for CPFP carveout).
TRUC attacks the same computational problem differently than the carveouts did. The carveouts said, “We can’t solve the general case, so here’s a special exception for Lightning’s transaction structure.” TRUC says “we can’t solve the general case, so let’s define a restricted topology where we can solve it, supporting as many possible L2s as we can.”
Within the TRUC topology, the questions become tractable. Is this child better than the existing child? Easy to compare when there’s only one of each. Should we allow this replacement? The transaction graph is small enough to reason about directly.
The tradeoff is flexibility. TRUC transactions can’t have complex ancestry. But for L2 protocols that just need “one commitment transaction, perhaps 0 fees, plus one fee-bump from any counterparty,” that’s fine. You give up generality in exchange for actual security guarantees instead of heuristic-based hope.
Building on the Constrained Topology (v28, 2024)
With TRUC as the foundation, a stack of complementary features landed in Bitcoin Core v28.
1P1C Package Relay (PR #28970): A parent transaction below the mempool’s minimum feerate can now be submitted alongside a child that bumps it. The pair is evaluated atomically. This finally enables the pattern L2 developers always wanted: broadcast a commitment transaction with a stale feerate, attach a fee-bumping child, and have the package relayed and mined together.
Sibling Eviction (PR #29306): For TRUC transactions, a new child can evict an existing sibling even without double-spending a common input. If your counterparty attached a low-fee child to the commitment transaction, your higher-fee child can replace it, regardless of output spent. The pinning vector addressed by the CPFP carveout is now handled more cleanly within the TRUC model.
Pay-to-Anchor (P2A) (PR #30352): A standardized anyone-can-spend output type using a segwit v1 witness program (`OP_1 <0x4e73>`, address `bc1pfeessrawgf`). Unlike Lightning’s existing keyed anchor outputs, which require a signature or a 16-block delay, P2A is keyless and minimal. There’s no script to satisfy, just an empty witness. Combined with TRUC and 1P1C, this gives a clean fee-bumping pattern: the commitment transaction includes a P2A output, and whoever needs to bump it spends that output in a CPFP child with fewer bytes wasted on anchor overhead. This especially makes sense as the number of counterparties grows much larger than 2.
Full RBF by Default (PR #30493): Almost a footnote at this point. Eight years after the opt-in compromise, the default flipped to full RBF. The political battles were pitched but slowly resolved: The network had moved on with a majority of hashpower accepting them in their blocks.
Ephemeral Dust (v29, 2025)
One loose end: anchor outputs should be 0-value dust. They’re economically unspendable on their own, existing only to enable CPFP. Under normal policy, dust outputs aren’t relayed. The workaround was to set anchor outputs above the dust threshold, but this left UTXOs on-chain that nobody really wanted and sapped value from smart-contracting layers.
Ephemeral dust, shipped in v29, solves this. A transaction can include a dust output if that output is spent in the same package. The anchor exists for exactly one purpose: to be spent by the fee-bump child, and then it’s gone. No dust in the UTXO set.
With this, the TRUC stack is complete: TRUC + 1P1C + P2A + ephemeral dust. L2 protocols have a coherent principled path for fee-bumping that doesn’t rely on L2-specific carveouts.
TRUC’s restrictions are the price of tractability (and more robust pin-resistance). The general problem of arbitrary topologies and replacements remained unsolved.
Act 3: Compute It Properly (v31, 2026)
Cluster Mempool
For years, the question “Does this replacement make the mempool better?” couldn’t be answered efficiently. The mempool tracked ancestor-descendant relationships, but reasoning about how a change affected mining revenue required computations that didn’t scale.
Cluster mempool: shipping in Bitcoin Core v31. Changes that. A cluster mempool reorganizes the mempool using a different data structure entirely.
The core idea: group the mempool into clusters, where a cluster is a strictly limited (less than 64) set of connected components of transactions (any two transactions that share in-mempool relation). Within each cluster, maintain an optimal linearization, a valid ordering of transactions that maximizes fee revenue if mined in that order. Once these linearizations are set, the entire mempool of a node is totally ordered.
This structure makes the hard questions answerable. When a new transaction arrives, compute its cluster feerates. When a replacement is proposed, compute what the mempool would look like with and without it. Is it better? Accept it. The linearization tells you the mining priority; comparing linearizations tells you which mempool state is better.
The technical details are substantial: linearization algorithms, handling cluster splits and merges, and performance bounds. For those interested, Pieter Wuille’s Delving into Bitcoin posts and the cluster mempool tracking issue provide a thorough treatment. What matters for this story is what the new structure enables.
The Feerate Diagram
The key concept is the feerate diagram. Think of it as a curve representing the mempool’s mining value: at each point, how much cumulative fee have you collected for how much cumulative size? A mempool with good transactions has a diagram that rises steeply; a mempool full of low-feerate junk has one that rises slowly.
With the cluster mempool, every proposed change can be evaluated against a single criterion: does the replacement produce a better feerate diagram than the one it evicts?
This is what “incentive compatible” means. A replacement is good if it for sure gives miners more revenue. We just couldn’t compute the comparison efficiently until we had the right tools in place.
What Gets Deleted
With our more precise calculations, several replacement and policy rules are removed.
The “no new unconfirmed parents” during replacement rule: Gone. We can now evaluate whether new dependencies improve or worsen the mempool. If your replacement introduces a new parent but the overall package is better for mining, it’s accepted.
The CPFP carveout: Gone. The special case for “one extra child at the descendant limit” is no longer needed. Package evaluation handles the underlying use case properly.
The single-conflict RBF carveout: Gone. The heuristic is replaced by direct computation.
Topology restrictions for package RBF: Gone. TRUC’s restrictions were the price of tractability with the old mempool. With cluster mempool, more complex topologies can be evaluated correctly.
These heuristics and restrictions served their purpose and can now be retired.
What Remains
Cluster mempool solves the evaluation problem: given a proposed change, we can now compute whether it improves the mempool. But two related problems remain open.
Package relay in the general case. 1P1C works because the topology is simple: one parent, one child, try them together. But what about more complex cases? If a transaction has three unconfirmed parents, should we evaluate all four together? What if only two of those parents are necessary for the child to be worth mining?
The feerate diagram tells us whether a given package improves the mempool. It doesn’t tell us, from a set of peer-sent transactions, which subsets to try *together*. For 1P1C, the answer is obvious: If the parent is below floating mempool minfee, try it (again) with its child. For arbitrary topologies, it’s an unsolved discovery problem. A node receiving a low-feerate transactions along with unconfirmed ancestors and ancestors’ descendants doesn’t know what subset of those would make the most compelling package, nor how to communicate this to another node in a bandwidth and CPU DoS-resistant way.
Pinning resistance for general topologies. TRUC’s topology restrictions aren’t just about making evaluation tractable; they’re also what make pinning resistance achievable. With at most one parent and one child, there’s limited room for an attacker to attach junk. Sibling eviction handles the obvious attack.
For arbitrary topologies, pinning remains a problem. An attacker with access to a shared transaction can still attach descendants that complicate replacement, even if we can now correctly evaluate whether a proposed replacement is better. The ability to compute the right answer doesn’t prevent an adversary from making it expensive to compute in bitcoin fee terms.
TRUC remains the answer for protocols that need strong pinning resistance. Cluster mempool makes the general case *correct* in that replacements that improve the mempool are accepted, but not necessarily *safe* for time-sensitive transactors in adversarial settings. The topology restrictions are no longer required for computational tractability, but they may still be valuable for security.
Looking Back
A decade of workarounds kept L2 protocols alive.
The carveouts were uncomfortable Lightning-specific hacks in Bitcoin Core’s mempool policy. But they worked well enough, for long enough, while better solutions were developed. The TRUC stack formalized the topology constraints that made the problem tractable and provided L2 developers with a coherent path forward. And cluster mempool finally delivered the data structure breakthrough that lets policy be grounded in actual incentive compatibility rather than heuristics.
The pattern is worth noting. Sometimes you can’t solve a problem directly, and you have two choices: constrain the problem until it becomes solvable (TRUC), or build better tools until you can solve it properly (cluster mempool). Bitcoin Core did both, in sequence, and the result is a system that’s both more principled and more capable than what came before.
For L2 developers, the practical lesson is simpler. If you need strong pinning resistance today, use TRUC. The restrictions are the feature. And for everything else, your node’s mempool still gets better with or without wallets adopting any changes.
Timeline
| Version | Date | Change | Key PR |
|---------|------|--------|--------|
| v0.12.0 | Feb 2016 | Mempool package tracking | #6654 |
| v0.12.0 | Feb 2016 | Ancestor/descendant limits (25/101KB) | #6771 |
| v0.12.0 | Feb 2016 | Ancestor feerate index | #7594 |
| v0.12.0 | Feb 2016 | Opt-in RBF (BIP 125) | #6871 |
| v0.19.0 | Nov 2019 | CPFP carveout | #15681 |
| v0.19.0 | Nov 2019 | Single-conflict RBF carveout | #16421 |
| v28.0 | Oct 2024 | TRUC transactions (BIP 431) | #29496 |
| v28.0 | Oct 2024 | 1P1C package relay | #28970 |
| v28.0 | Oct 2024 | Sibling eviction | #29306 |
| v28.0 | Oct 2024 | Pay-to-Anchor (P2A) | #30352 |
| v28.0 | Oct 2024 | Full RBF default | #30493 |
| v29.0 | 2025 | Ephemeral dust | #30239 |
| v31.0 | 2026 | Cluster mempool | #33629 |










So what's currently the best way to 100% overtake a tx in a mempool?
E.g. when your privkey has leaked and an attacker has submitted a tx?