Skip to content

Instantly share code, notes, and snippets.

@Kixunil
Last active March 27, 2024 16:32
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Kixunil/6ae6f787db36d0d5ed3220f5bcece7f7 to your computer and use it in GitHub Desktop.
Save Kixunil/6ae6f787db36d0d5ed3220f5bcece7f7 to your computer and use it in GitHub Desktop.
Anyone can boost

Anyone can boost - a more efficient alternative to anchor outputs

Abstract

Bitcoin protocols using presigned transactions (e.g. Lightning Network, Firefish etc) face a problem with predicting fees of the presigned transactions. One possibility is to guess the future fee rate but that risks that the transaction will not be included in a block fast enough and it also risks wasting satoshis on fees. Another possibility is to use CPFP which may require adding more outputs - so called "anchor outputs". The drawbacks of anchor outputs are increased transaction size and potentially decreased privacy since the anchor outputs usually use "suspiciously low" amounts. Further, anchor outputs may pollute UTXO set if the presigned transaction confirms anyway (because it also had high enough fee) but the outputs are uneconomical to spend. This document proposes a new solution that could not only solve these issues but bring even more efficiency gains in the future.

Solution

As stated in the abstract, anchor outputs increase the size and thus the cost of transaction. So starting from the ideal (no additional data in the boosted transaction), we would like to boost any arbitrary transaction. We observe that this is actually already possible by paying big mining pools directly. However this is detrimental to mining decentralization, not very accessible to general public and the expected confirmation time is worse than in case of CPFP, when the whole network mines the transaction. A simple way to allow anyone boosting any transaction is to put the TXID of the boosted transaction into the boosting transaction's annex and have a consensus rule that the boosting transaction is only valid if the boosted tranation is in the same block. Let's call this "anyone can boost".

At first sight this looks broken because of the pinning problem. Today, if ANYONECANSPEND output is used an attacker could boost a transaction of someone else in a way that would make it stuck in the mempool. This is because of policy rules protecting the network against DoS attacks, so apparently the rules cannot be relaxed. The rules are designed specifically to impose cost on attackers.

The reason why anyone can boost is not actually broken is that multiple independent transactions can boost the same transaction. This brings another resource into the picture: new UTXOs. Thus when a transaction is boosted and a new transaction appears that is boosting it too, it can be considered by the anti-DoS rules separately. An attacker can't use this to DoS the network because it requires having multiple UTXOs which is already costly. When a transaction is boosted by two transactions the fees simply add up. It's also possible for a miner to ignore low-fee boosting transactions (presumably created by an attacker) and only include the high fee ones.

In other words, adding the boosting transaction to the mempool is equivalent to adding any other transaction to the mempool provided it pays sufficient fee. It's just a bit larger and its fee rate is computed differently.

Efficient fee boosting service

A simplistic chain analysis would assume that the boosted and boosting transactions are related because nobody would boost a transaction of someone else. This heuritic can be trivially broken by having an external service that boosts arbitrary transactions and gets paid via other means (LN). But this can be further improved by allowing boosting multiple transactions simply by putting more TXIDs into the boosting transaction. If two people are trying to boost two transactions at the same time they can almost halve the cost of the boosting transaction. An efficient boosting service would presumably collect orders and batch the boosts. Further it could RBF the boosts if some didn't confirm yet and new orders arrived in the meantime. Because of significant cost reduction use of such services would be highly incentivized undermining the heuristic.

Notably, such boosting service would not be trustless but non-delivery could be easily proven using LN invoice and preimage. Perhaps it is possible to make the service trustless but that's probably not worth the effort given how low the amounts are.

As an aside, there was recently a post in the local community that someone made a low-fee transaction without RBF enabled and the receiver couldn't CPFP. I assume such cases happen more than once. If this service existed the transaction could've been trivially boosted by anyone.

Another interesting example is someone saying that figuring out how to boost a transaction took him a while. (IIRC it was an LN channel open.) Having such service could greatly simplify fee boosting in many cases since one would only have to copy-paste the txid, which probably all wallets provide.

Known downsides

This requires a soft fork

Soft forks can be contentious and difficult to deploy. This rule is also unusual because it causes interaction between transaction within the same block. However the code should be pretty simple: put all tx ids into a set and then for each boosting transaction check that all of its txids are in the set. This allows loops but that shouldn't be a problem. The loops can be also disabled by simply progressively iterating over transactions and adding the txid to the set after its annexes were checked.

It may be possible to relax the RBF rules in some other way to enable external boosting for transactions that opt-into it. A vague idea was to allow replacing when each input of a transaction has ANYONECANPAY flag but its interaction with other rules is questionable. Perhaps this can be developed further but not needing an additional output is both more efficient and more user-friendly.

This requires having a special output

Unfortunately annex cannot be added to any signature but only to script spend taproot signatures. Since this feature is most useful for presigned transactions the entities performing them could simply prepare the outputs beforehand. (e.g. LN implementations could make it built-in) And for those who did not prepare the boosting services would provide an option.

Future witness versions could be designed with this in mind and enable annex regardless of spend type which would make things simpler and save even more space (key spend is cheaper).

This destroys fee betting

Currently it is possible for two people to bet on the height of the fees in the future: they make a transaction that moves their satoshis into 2-of-2 multisig and then pre-sign two transactions with different fee rates and lock times. However this is already vulnerable to miner collusion and to my knowledge nobody uses this. It could be preserved by requiring that the boosted transactions opt-in to boosting by using version 3 but that could decrease privacy and would reintroduce potential for stuck transactions that cannot be boosted.

Disclosure

I'm a contractor who wrote the core of Firefish smart contract, a protocol which would benefit from this feature. I was not paid to come up with this idea, I just believe this would be a generally useful feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment