V3 transactions is a proposed set of mempool policies with the aim of allowing transactions to use Child-Pays-For-Parent (CPFP), anchor outputs, and package relay as the primary method of paying for fees in contracting protocols such as Lightning. In this article we will go over how V3 transactions and anchor outputs are meant to work, their role in protocols such as Lightning. Finally we’ll show that their dependence on CPFP makes them significantly more expensive in terms of blockspace, and thus fees, than using Replace-by-Fee (RBF) techniques, increasing the cost of force-closes by approximately 2x in most cases. We’ll also explain how V3 transactions are a potential threat to mining decentralization due to the fact that out-of-band fee payment can be significantly cheaper than anchor outputs.

Thanks goes to Fulgur Ventures for sponsoring this research. They had no editorial control over the contents of this post and did not review it prior to publication.

Contents

  1. Background
    1. Anchor Channels
    2. Package Relay
  2. V3 Transactions
  3. Replace-by-Fee
    1. Fee Allocation
    2. HTLCs and Replace-by-Fee
    3. Hybrid Replace-by-Fee + Anchors
    4. Efficiency
    5. Non-Native Asset Protocols
  4. Anchor Outputs Are a Danger to Mining Decentralization
  5. Protocol Design
  6. Recommendations
  7. Footnotes

Background

Lightning channels and similar protocols work by exchanging pre-signed transactions that are not meant to be mined except in exceptional circumstances. Namely, lack of agreement between the parties. In these exceptional circumstances — such as the other party to a channel going off-line — funds are recovered by signing and broadcasting the necessary transactions. For example, in a typical case without HTLCs pending, the parties to the channel would both have a commitment transaction corresponding to the latest state of the channel that spends the 2-of-2 multisig holding the channel funds, to pubkeys controlled by each party.

The problem is that fee rates required for inclusion in a block change regularly, and dramatically. Secondly, Bitcoin Core currently requires that transaction meet a minimum fee rate to be considered for inclusion into the mempool of a node. This minimum fee rate varies depending on demand, as the total maximum size of a node’s mempool is fixed.

While the Lightning protocol has a mechanism for peers to negotiate the fee-rate of the pre-signed transactions, this mechanism can not predict the future. Thus there frequently are circumstances where the fee-rates of pre-signed transactions are either too low for timely inclusion in a block, or higher than necessary, wasting funds on fees.

In certain cases an unexpected increase in fees can even make resolving the channel state impossible, because the minimum fee necessary for inclusion into a mempool can increase beyond the fee-rate of the pre-signed transaction. This is particularly harmful if HTLCs are outstanding, as they can have a strict time window in which they must resolve, or funds can be lost.

Anchor Channels

A partial solution that has been implemented in Lightning is Anchor Channels. These make use of two key technologies:

  1. Child-Pays-For-Parent (CPFP): if a child transaction has a higher feerate than its unconfirmed parent, the fee for the child transaction effectively pays for the parent, making it worthwhile to mine the parent.
  2. Anchor Outputs: zero or near-zero value outputs added to a transaction for the sole purpose of being spent by a CPFP fee-bumping transaction.

With Anchor Channels, two anchor outputs of dust-sized value are added to commitment transactions for the purpose of allowing the local and/or remote end of the channel to use CPFP to increase the effective fee of the commitment transaction in the event that the fee chosen is too small to be mined in a reasonable amount of time.

Both anchor outputs have a script of the form:

<local_funding_pubkey/remote_funding_pubkey> OP_CHECKSIG OP_IFDUP
OP_NOTIF
    OP_16 OP_CHECKSEQUENCEVERIFY
OP_ENDIF

You might wonder why an output with essentially no value even has a OP_CHECKSIG operator. Why not use a bare-minimum OP_TRUE output? After all, if someone else spends the output, doesn’t that mean they are simply paying to get our transaction mined?

Unfortunately, we have to deal with transaction pinning attacks: methods that make RBF fee bumping prohibitively expensive or even impossible. Basically, if the output was just an OP_TRUE, an attacker could broadcast a transaction using a pinning attack technique that spends the OP_TRUE anchor output in such a way that it is expensive or even impossible for us to use RBF to pay a high enough fee to get the commitment transaction mined in a reasonable amount of time.

Thus the OP_CHECKSIG ensures that only the parties actually in the channel can spend the anchor outputs, preventing any pinning attacks. Equally, this is why there are two anchor outputs: we do not want one party to be able to use transaction pinning against the other party.

In fact, the two anchor outputs are redundant: the to_remote output could have served as the to_remote_anchor output, as I discovered while writing this blog post. Only one anchor output is necessary.1

Package Relay

Currently, Bitcoin Core evaluates transactions for inclusion in the mempool in isolation, without taking into account any child transactions. Thus even with anchor channels it is possible for fee-rates to increase so much that the commitment transaction is ineligible for inclusion due to the mempool size limit. In this circumstance, anchor outputs can’t use the CPFP mechanism, as the parent transaction never got into the mempool to begin with.

Package Relay aims to solve this problem by evaluating packages of transactions, as a whole. With package relay, even a zero feerate parent could be accepted into the mempool so long as the package contains a child that pays for the parent via CPFP.

If package relay were implemented, anchor channels would work in all circumstances. They would still be inefficient compared to replace-by-fee — as we will discuss later — but they would at least work regardless of mempool conditions.

V3 Transactions

The V3 Transactions proposal combines package relay, ephemeral anchors, and new mempool acceptance rules in an attempt to improve on anchor channels and anchor outputs. Notably, the “V3” in “V3 Transactions” refers to a new non-consensus nVersion 3, which miners and nodes are expected to altruistically treat differently by preventing the outputs of V3 transactions from being spent in certain ways.

Thus we have three parts to the V3 transaction proposal:

  1. Package Relay: Quite simply, V3 transactions assumes that package relay has been implemented. Though note that package relay is a separate feature, that by itself has nothing to do with V3 transactions.
  2. Ephemeral Anchors: Anchor outputs with (potentially) zero value, and a simple OP_TRUE or equivalent script, along with mempool rules that allow the dust rule to be ignored in packages that both create and spend less than dust-valued transaction outputs in the same package. Notably, this keeps less than dust-valued outputs out of the UTXO set, as they are created and spent in the same block.
  3. Non-Consensus restrictions on spending the outputs of V3 transactions, intended to prevent pinning attacks. As we discussed above, OP_TRUE anchors are vulnerable to pinning attacks; the V3 spending restrictions are intended to prevent these attacks.

By “non-consensus”, what we mean is that the actual block validity rules have not been changed. Rather, Bitcoin Core will reject transactions attempting to spend outputs of V3 transactions — even if they are valid and profitable for miners — if those transactions do not meet certain criteria, the main one being that transactions spending unconfirmed V3 outputs will be rejected unless they are less than \(1000\mathrm{vB}\) in size. This restriction prevents significant transaction pinning attacks, which in turn makes it possible for the anchor output to be a simple OP_TRUE that anyone can spend. Since the transaction spending that output can’t be pinned, if a 3rd party does spend it with a low-fee transaction, anyone can simply replace that transaction with a higher fee transaction.

At least, that is the idea. Unfortunately, because the \(1000\mathrm{vB}\) limit is much bigger than a typical commitment transaction and ephemeral anchor spend, attackers can still do cheap and effective pinning attacks against third parties. Exactly how cheap and how effective depends on the mempool environment. But an attacker spending little to no money can increase the fees the victim pays for a Lightning channel force-close by a factor of ~1.5x, with the maximum possible increase in a one-shot attack being ~3.7x.

Replace-by-Fee

One obvious solution to this problem is to simply pre-sign transactions at different fee rates. While at first glance this may seem inefficient, computers are fast and bandwidth is cheap: a (musig2) signing operation with secp256k1 typically takes on the order of \(100\mathrm{us}\) to complete per key23, and produces a 64 byte signature. Since transactions variants can be generated deterministically, only the parameters for the deterministic generation, and the signatures themselves, need to be exchanged. Not the full transactions. Lightning already uses this technique: the exact form of transactions is nailed down by the Lightning specification.

How many fee variants are needed? According to mempool.space’s data, over the past six years the fees required to get into the next block have ranged from about \(1\frac{\mathrm{sat}}{\mathrm{vB}}\) to \(500\frac{\mathrm{sat}}{\mathrm{vB}}\).

If our range of fees is from \(a\) to \(b\), inclusive, with each increment being \(r\), we can compute how many increments \(N\) we need as follows:

\[b = ar^n \implies N = \left \lceil \frac{\ln \left( \frac{b}{a} \right)}{\ln \left(r \right)} \right \rceil + 1\]

For example, if you wanted to cover \(10\frac{\mathrm{sat}}{\mathrm{vB}}\) to \(1000\frac{\mathrm{sat}}{\mathrm{vB}}\), with \(10\%\) increments, you’d only need 50 fee variants, for a total size of 3200 bytes, taking just \(5\mathrm{ms}\) to sign (single core). Given the very good scalability of Lightning, this overhead is reasonable.

Update: turns out AINCQ’s Phoenix wallet recently implemented a partial version of RBF for channels in the underlying lightning-kmq library.

Fee Allocation

Existing Lightning channels actually need two commitment transactions, the remote commitment and the local commitment, as the commitment transaction for each side is slightly different; the above fee variants calculation refers to the number of variants on each side, not the total number. Each commitment transaction is signed by the other party, which introduces the ability to allocate fees to different sides. In most cases, it would make sense to take the fees from the side that broadcast the commitment transaction; each side is signing a transaction that gives the other side the ability to spend their own money to fees, if they choose to, by counter signing4 the transaction and broadcasting it.

If fees are allocated to the side that chooses to broadcast the commitment transaction, the maximum fee rate can be the entire value of the channel on that side; the counterparty can’t grief the other side by broadcasting a high-fee commitment, as the only commitment transactions they can broadcast spend their money to fees. This has the advantage of making it impossible to be in a situation where a sufficiently high fee-rate isn’t available: if more than the entire local balance of the channel needs to go to fees to get it mined, it is pointless for the local party to try to get the commitment transaction mined. They might as well wait for fees to decrease, or abandon the channel funds.

Thanks goes to Antoine Poinsot for bringing up the need for this section to clearly explain this point.

HTLCs and Replace-by-Fee

Lightning commitment transaction HTLC outputs can only be spent by pre-signed HTLC-Timeout or HTLC-Success transactions. These separate transactions are required because the HTLC output may have been created by a revoked commitment, and we need to give the other side a chance to use the revocation pubkey. In anchor channels, these HTLC transactions are pre-signed with SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, allowing the local side to fee-bump these transactions by adding additional inputs and outputs.

Since additional inputs and outputs can be added the minimum relay fee is not a problem: we can always add a sufficiently large input/output to meet the minimum. Thus one way to use replace-by-fee commitment transactions is to simply pre-sign HTLC timeout/success transactions for each variant, and continue using the “add an input” mechanism. This simply increases the work done per HTLC by a factor of \(N\), and again, because these transactions are made deterministically, this is cheap and easy.

Signing multiple fee variants for the HTLC timeout/success transactions is also possible. While at worst this requires on the order of \(N^2\) total work, a reduction is possible by recognizing that usually the HTLC transactions will usually need fees close to that of the commitment transactions. Note how fee variants are the preferable option for end-user wallets such as Phoenix, which try to have a single UTXO per user, and thus don’t have any spare UTXO’s to add to HTLC outputs.

Finally SIGHASH_ANYPREVOUT would fix the \(N^2\) problem by allowing any HTLC fee variant to spend any commitment transaction fee variant.

Hybrid Replace-by-Fee + Anchors

A hybrid approach is also possible. Fee variants can be used for part of the fee range, with an anchor-output containing variant being signed for the highest fee variant.

Efficiency

Replace-by-fee is significantly more efficient than anchor outputs because it only requires a single transaction. A typical V3-using Lightning channel commitment transaction is \(163\mathrm{vB}\) in size5, and requires a \(152\mathrm{vB}\) ephemeral output transaction6 to pay for fees, \(315\mathrm{vB}\) in total.

Since a RBF-using commitment transaction doesn’t need an anchor output, it’s just \(154\mathrm{vB}\) in size, with no second transaction needed. V3 transactions are at least twice the size, and thus twice the cost, as using RBF.

But it gets worse: V3 transactions require extra outputs to be kept around purely for the purpose of fee bumping. Maintaining these extra outputs is difficult and expensive for many Lightning nodes, in particular, smaller nodes/wallets. It’s difficult to decide what % of total funds to allocate to these outputs, and of course, blockspace has to be used up creating them.

Most analysis’s of Bitcoin’s ultimate scaling capacity ignore this: with anchor outputs, each Lightning user needs at least two UTXO’s to be created, not just one, cutting the total possible number of global users who can be on-boarded to Lightning by approximately half.

A particularly bad example of this problem is seen in user-oriented wallets like Phoenix7 that aim to keep all user funds in a single Lightning channel, using splice-ins and splice-outs to add and withdraw on-chain funds.

Non-Native Asset Protocols

Protocols such as RGB Lightning channels and LND’s taproot assets that aim to use Lightning-style channels with non-Bitcoin assets may be forced to tie up more BTC than desired to use RBF techniques, as the assets they are actually trying to trade can’t be directly used to pay fees. For large channels this is probably not a problem, as the BTC value will be small in comparison to the channel value. But smaller channels may need to use other techniques.

For example, SIGHASH_ANYPREVOUT could allow commitment transactions to be signed with SIGHASH_ANYONECANPAY, allowing RBF fee bumping by adding additional inputs if needed. Of course, this potentially invites problems such as transaction pinning.

Thanks goes to Brandon Black for pointing out this issue.

Anchor Outputs Are a Danger to Mining Decentralization

Since Anchor Outputs are so much less efficient than RBF — about 2x the cost — they pose a significant danger to mining decentralization because of out-of-band fee payment. The problem is that if you have an anchor-using transaction that you need to get mined, it costs twice as much blockspace to get the transaction mined via the intended mechanism — the anchor output — as it does by getting a miner to include the transaction without the anchor output spend.

Some large miners are already accepting out-of-band payments for transactions, allowing you to pay them directly to get your transaction mined; only large miners can reasonably offer this service, as only large miners find blocks sufficiently frequently to make out-of-band fee payments worthwhile. Decentralized mining pools such as P2Pool and Braidpool have absolutely no hope of being able to offer out-of-band fee payments at all.

Since a typical anchor-output using Lightning channel takes 2x more block space, a large miner could easily offer out-of-band fee payments at, say, a 25% discount, giving them a substantial 25% premium over their smaller competitors. Given that mining pool fees are highly competitive, on the order of 1% or 2%, being able to earn a 25% premium over your competitors is an enormous advantage. With Lightning, offering this as a service in an automated, convenient, way would be quite easy to implement.

We must not build protocols that put decentralized mining at a disadvantage. On this basis alone, there is a good argument that V3 transactions and ephemeral anchor outputs should not be implemented.

Protocol Design

We as a community should ask how such an inefficient proposal, with significant potential harm to mining decentralization, has managed to progress as far as it has. The V3 transactions pull-reqs have been around in various forms for over a year now without a BIP or any real design documents. In particular, the author recently admitted8 that their understanding of the size of a typical Lightning commitment transaction was dramatically wrong, leading to the V3 transaction pinning problem mentioned above.

With complex protocol decisions such as this, we should not rush into implementing code. We should identify actual use-cases and work through the efficiency and implications of these use-cases. The documentation around V3 transactions accessible via the pull-req simply does not have that kind of analysis at the moment; as far as I’m aware, I’m the first person to properly compare it to other solutions.

Recommendations

  1. Package relay should probably be added to Bitcoin Core. CPFP is useful outside of contracting protocols, for example, to bump the fees of payments sent to you. The alternative in those cases is to either get the sender to bump fees — not always practical — or use out-of-band fee payment. Secondly, Lightning has already shipped anchor channels, which would benefit immediately from CPFP.
  2. Existing usage of anchor outputs should be phased out due to the above-mentioned miner decentralization risks; new anchor output support should not be added to new protocols or Bitcoin Core.
  3. V3 transactions should not be be shipped at the moment. It has no compelling use-cases right now without ephemeral outputs, which should be discouraged, and in its current form is still vulnerable to transaction pinning.

Footnotes

  1. [Lightning-dev] The remote anchor of anchor channels is redundant, Peter Todd, lightning-dev mailing list, 2023-12-13 

  2. https://github.com/jonasnick/musig-benchmark 

  3. https://github.com/tarcieri/rust-secp256k1-ecdsa-bench 

  4. In the case of interactive joint signature protocols like MuSig2, remember that “counter signing” simply means completing the last step of the signing process. 

  5. Assuming 1 taproot input (musig), 2 taproot outputs, and one ephemeral anchor output. 

  6. Assuming 1 ephemeral anchor spend, 1 taproot input, and 1 taproot output. 

  7. Introducing the new Phoenix: a 3rd generation self-custodial Lightning wallet 

  8. “Let’s say N is 1000vB. AFAIK commitment transactions aren’t usually smaller than this”