Subject: Re: [bitcoin-dev] A Stroll through Fee-Bumping Techniques : Input-Based vs Child-Pay-For-Parent

From: darosior <[email-masked]>
Date: Thu, 10 Jun 2021 13:18:53 +0000

Hi,

Another thing to consider when comparing these two techniques is anti-fee sniping protection. If you are going to feebump directly
your revocation transaction by adding inputs to it, the nLockTime has already been signed in advance. Therefore your are sponsoring
a transaction that could be included in any reorged block.

This is not a big deal for now but i'm concerned it may become one, especially since this type of transaction might be the highest fee-paying
ones on the network (there is a lot at stake). Having a new sighash type not masking the nLockTime so that it can be set by the feebumper
could help with this, even though the presumably low pre-signed fee can still be snipped (since the ALL signature is added to the feebump inputs).

The recent BIP proposal by Chris Belcher [0] also just uncovered (to me) a new hack: if the feebumping coins are less than 65,535 blocks old, we
could also set the nSequence of these coins to achieve the same purpose [1]. And this can be done with today's Bitcoin!

Antoine P.

[0] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-June/019048.html
[1] https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-January/002412.html
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
Le vendredi 28 mai 2021 à 6:13 AM, Antoine Riard <[email-masked]> a écrit :

>> Unfortunately, ACP | SINGLE is trivially pinable [0] (TL;DR: i can just attach an output paying immediately to me, and construct a tx chain spending it). We are using ACP | ALL for Revault,
>> which is the reason why we need a well laid-out pool of fee-bumping UTXOs (as you need to consume them entirely).
>
> Oh yes, I should have mentioned this pinning vector. The witnessScript I've in mind to make secure that type of chain of transactions would be one MuSig key for all contract participants, where signature are committed with SIGHASH_ANYPREVOUT | SIGHASH_IOMAP, one pubkey per participant to lockdown the transaction with SIGHASH_ALL. I think it works and prevents malicious in-flight attachment of input/output to a multi-party transaction ?
>
>> I believe that it's better to broadcast a single fan-out transaction creating your entire UTXO pool in advance. You could create one coin per contract you are watching which value would be
>> used to bump your transaction feerate from the presigned one to -say- the average feerate over the past month, and then have smaller coins that you could attach to any transaction to bump
>> by a certain threshold (say, 10sat/vbyte). You would create as many small coin as your reserve algorithm tells you (which could be "i need to be able, worst case, to close all my contracts
>> with the worst historical feerate." or (fractional reserve version) "i need to be able, worst case, to close 10% of my contracts at the average feerate of the past year, the remaining ones sorry
>> for my loss"). [1]
>
>> This method is both much more optimal (though you need to sometimes incur the cost of many small additional inputs) and also makes sure that your feebump does not depend on the confirmation of a first stage transaction (as you can only RBF with new inputs if they are confirmed).
>
> I see, so you spread your bumping UTXO pool in two ranges : at least one bumping utxo per contract, and a subpool of emergency smaller coins, ready to be attached on any contract. I think this strategy makes sense for vaults as you can afford a bunch of small coins at different feerates, spending the ones not used afterwards. And higher cells of feerate reserve as the worst historical feerate are relatively not that much compared to locked-in vaults value. That said, I'm more dubious about LN, where node operators might not keep the worst-case fee-bumping reserve, as the time value of the coins aren't worth the channel liquidity at stake.
>
>> Why not just attaching it at the tail of the chain? Bumping the last child with additional input would effectively be a CPFP for the entire chain in this case.
>
> Yes, input-based bumping targeting the tail of the chain works at the transaction level. But if you assume bounded visibility of network mempools, one of your counterparties might have broadcast a concurrent state, thus making your CPFP irrelevant for propagation. Though smarter tx-relay techniques such as "attach-on-contract-utxo-root" CPFP (or also known as "blinded CPFP") might solve this issue.
>
> Le jeu. 27 mai 2021 à 17:45, darosior <[email-masked]> a écrit :
>
>> Hi,
>>
>>> ## Input-Based
>>>
>>> I think input-based fee-bumping has been less studied as fee-bumping primitive for L2s [1]. One variant of input-based fee-bumping usable today is the leverage of the SIGHASH_ANYONECANPAY/SIGHASH_SINGLE malleability flags. If the transaction is the latest stage of the contract, a bumping input can be attached just-in-time, thus increasing the feerate of the whole package.
>>
>> Unfortunately, ACP | SINGLE is trivially pinable [0] (TL;DR: i can just attach an output paying immediately to me, and construct a tx chain spending it). We are using ACP | ALL for Revault,
>> which is the reason why we need a well laid-out pool of fee-bumping UTXOs (as you need to consume them entirely).
>>
>>> Input-based (today): If the bumping utxo is offering an adequate feerate point in function of network mempools congestion at time of broadcast, only 1 input. If a preliminary fan-out transaction to adjust feerate point must be broadcasted first, 1 input and 2 outputs more must be accounted for. Onchain footprint: 2 inputs + 3 outputs.
>>
>> I believe that it's better to broadcast a single fan-out transaction creating your entire UTXO pool in advance. You could create one coin per contract you are watching which value would be
>> used to bump your transaction feerate from the presigned one to -say- the average feerate over the past month, and then have smaller coins that you could attach to any transaction to bump
>> by a certain threshold (say, 10sat/vbyte). You would create as many small coin as your reserve algorithm tells you (which could be "i need to be able, worst case, to close all my contracts
>> with the worst historical feerate." or (fractional reserve version) "i need to be able, worst case, to close 10% of my contracts at the average feerate of the past year, the remaining ones sorry
>> for my loss"). [1]
>>
>> This method is both much more optimal (though you need to sometimes incur the cost of many small additional inputs) and also makes sure that your feebump does not depend on the confirmation
>> of a first stage transaction (as you can only RBF with new inputs if they are confirmed).
>>
>>> Input-based (today): In case of rebroadcast, the fee-bumping input is attached to the root of the chain of transactions and as such breaks the chain validity in itself. Beyond the rebroadcast of the updated root under replacement policy, the remaining transactions must be updated and rebroadcast. Rebroadcast footprint: the whole chain of transactions.
>>
>> Why not just attaching it at the tail of the chain? Bumping the last child with additional input would effectively be a CPFP for the entire chain in this case.
>>
>> Thanks for starting this discussion :)
>> Antoine
>>
>> [0] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-May/017835.html
>> [1] Credits to Jacob Swambo, who came up with the single fan-out transaction and with whom i'm discussing how to practically apply these ideas to Revault.