V3 transaction policy for anti-pinning

In my head, the idea here is that opting into v3 is a collaboration between (some) node operators and transaction creators to ignore potentially valid transactions in order to more readily relay high feerate alternatives.

So currently you might see txs:

  • :white_check_mark: P = small parent, low feerate
  • :white_check_mark: C1 = huge child, low feerate, high fee
  • :x: C2 = small child, high feerate, modest fee, conflicts with C1

and end up with P and C1 stuck in your mempool and refuse to accept or relay C2, even though due to its high fee, it might well even be included in the next block. That remains a reasonable decision by individual nodes, as simply replacing C1 by C2 would make nodes vulnerable to relay spam: broadcast many C1’s with lots of data, get that distributed across the network for free, then replace those txs with C2’s, making sure that you’re only actually paying a small amount in fees for all that relay spam. This is known as the “free relay” problem.

The workaround that v3 makes available is simply that C1 is now rejected in the first place in many cases. This prevents free relay (C1 isn’t relayed at all), and solves the incentive compatibility problem where a tx that would be acceptable in the next block (C2) isn’t relayed at all.

This works okay even if only adopted by a proportion of the network: C2 is still able to propagate over the subgraph of nodes that implement this policy eventually reach miners that run a policy compatible with this policy, who will eventually mine it.

It is in no way a perfect solution to pinning – some systems will be designed in a way that a large child is sometimes necessary and those systems won’t be able to opt-in to v3 rules. Also, even relatively small children can create a fee amount/rate pin, and there are other pinning vectors than high-fee/low-feerate. That’s fine: making things incrementally better for some people is still making things better.

The limitations with v3 are quite annoying: one ancestor / one descendant means you can only have a pair of related v3 txs in the mempool, and nothing more complicated. In particular you can’t do batch CPFP where a single v3 child pays for a bunch of v3 parents. But again, slightly better is still better, and relaxing policy rules if we figure out better ways of doing things is less problematic than restricting policy rules.

With just the v3 constraints, I think you’d want to design your protocol such that either parent transactions only have a single output that’s spendable immediately – that way any CPFP spends will naturally conflict with each other and RBF rules will apply, and the size limits applying to the child tx will limit the maximum fees those children will need to pay. However if there are multiple immediately spendable outputs that all have an n-of-n multisig arrangement, and all the txs that spend those outputs spend some common output, that could work as well. That approach seems unlikely to be useful in practice though?

When you add the ephemeral anchor rule, in particular that the EA output must be spent for the tx that creates the EA output to remain in the mempool, it becomes okay to allow other outputs to be immediately spendable: each child must spend the EA output, so they must conflict with each other, and RBF rules are applied. That seems to me like a significant bonus in flexibility – allowing lightning commitment tx balance outputs to be spent unilaterally by the same tx that spends the EA output, which I think would be problematic otherwise.

2 Likes