The idea of a soft fork to fix dynamic fee bumping was recently put back on the 
table. It might
sound radical, as what prevents today reasonable fee bumping for contracts with 
presigned
transactions (pinning) has to do with nodes' relay policy. But the frustration 
is understandable
given the complexity of designing fee bumping with today's primitives. [0]
Recently too, there was a lot of discussions around covenants. Covenants 
(conceptually, not talking
about any specific proposal) seem to open lots of new use cases and to be 
desired by (some?) Bitcoin
application developers and users.
I think that fee bumping using covenants has attractive properties, and it 
requires a soft fork that
is already desirable beyond (trying) to fix fee bumping. However i could not 
come up with a solution
as neat for other protocols than vaults. I'd like to hear from others about 1) 
taking this route for
fee bumping 2) better ideas on applying this to other protocols.


In a vault construction you have a UTxO which can only be spent by an 
Unvaulting transaction, whose
output triggers a timelock before the expiration of which a revocation 
transaction may be confirmed.
The revocation transaction being signed in advance (typically before sharing 
the signature for the
Unvault transaction) you need fee bumping in order for the contract to actually 
be enforceable.

Now, with a covenant you could commit to the revocation tx instead of 
presigning it. And using a
Taproot tree you could commit to different versions of it with increasing 
feerate. Any network
monitor (the brooadcaster, a watchtower, ..) would be able to RBF the 
revocation transaction if it
doesn't confirm by spending using a leaf with a higher-feerate transaction 
being committed to.

Of course this makes for a perfect DoS: it would be trivial for a miner to 
infer that you are using
a specific vault standard and guess other leaves and replace the witness to use 
the highest-feerate
spending path. You could require a signature from any of the participants. Or, 
at the cost of an
additional depth, in the tree you could "salt" each leaf by pairing it with 
-say- an OP_RETURN leaf.
But this leaves you with a possible internal blackmail for multi-party 
contracts (although it's less
of an issue for vaults, and not one for single-party vaults).
What you could do instead is attaching an increasing relative timelock to each 
leaf (as the committed
revocation feerate increases, so does the timelock). You need to be careful to 
note wreck miner
incentives here (see [0], [1], [2] on "miner harvesting"), but this enables the 
nice property of a
feerate which "adapts" to the block space market. Another nice property of this 
approach is the
integrated anti fee sniping protection if the revocation transaction pays a 
non-trivial amount of
fees.

Paying fees from "shared" funds instead of a per-watchtower fee-bumping wallet 
opened up the
blackmail from the previous section, but the benefits of paying from internal 
funds shouldn't be
understated.
No need to decide on an amount to be refilled. No need to bother the user to 
refill the fee-bumping
wallet (before they can participate in more contracts, or worse before a 
deadline at which all
contracts are closed). No need for a potentially large amount of funds to just 
sit on a hot wallet
"just in case". No need to duplicate this amount as you replicate the number of 
network monitors
(which is critical to the security of such contracts).
In addition, note how modifying the feerate of the revocation transaction in 
place is less expensive
than adding a (pair of) new input (and output), let alone adding an entire new 
transaction to CPFP.
Aside, and less importantly, it can be made to work with today's relay rules 
(just use fee thresholds
adapted to the current RBF thresholds, potentially with some leeway to account 
for policy changes).
Paying from shared funds (in addition to paying from internal funds) also 
prevents pervert
incentives for contracts with more than 2 parties. In case one of the parties 
breaches it, all
remaining parties have an incentive to enforce the contract.. But only one 
would otherwise pay for
it! It would open up the door to some potential sneaky techniques to wait for 
another party to pay
for the fees, which is at odd with the reactive security model.

Let's examine how it could be concretely designed. Say you have a vault wallet 
software for a setup
with 5 participants. The revocation delay is 144 blocks. You assume revocation 
to be infrequent (if
one happens it's probably a misconfigured watchtower that needs be fixed before 
the next
unvaulting), so you can afford infrequent overpayments and larger fee 
thresholds. Participants
assume the vault will be spent within a year and assume a maximum possible 
feerate for this year of
10ksat/vb.
They create a Taproot tree of depth 7. First leaf is the spending path (open to 
whomever the vault
pays after the 144 blocks). Then the leaf `i` for `i` in `[1, 127]` is a 
covenant to the revocation
transaction with a feerate `i * 79` sats/vb and a relative timelock of `i - 1` 
blocks.
Assuming the covenant to the revocation transaction is 33 bytes [3], that's a 
witness of:
    1 + 33     + 1 + 33 + 7 * 32 = 292 WU (73 vb)
    ^^^^^^       ^^^^^^^^^^^^^^
    witscript     control block
for any of the revocation paths. The revocation transaction is 1-input 
1-output, so in total it's
    10.5 +   41 + 73      + 43    = 167.5 vb
    ^^^^    ^^^^^^^^^^^    ^^^^
    header  input|witness  output
The transaction size is not what you'd necessarily want to optimize for first, 
still, it is smaller
in this case than using other feebumping primitives and has a smaller footprint 
on the UTxO set. For
instance for adding a feebumping input and change output assuming all Taproot 
inputs and outputs
(CPFP is necessarily even larger):
    5 * 64 +  1 + 5 * (32 + 1) + 1 + 33 = 520 WU (105 vb)
    ^^^^^^    ^^^^^^^^^^^^^^^    ^^^^^^
    witness      witscript       control
    10.5  +  41 + 105      + 41 + 16.5         + 2 * 43  = 300 vb
    ^^^^     ^^^^^^^^        ^^^^^^^^^           ^^^^^^
    header   input|witness   fb input|witness    outputs
>From there, you can afford more depths at the tiny cost of 8 more vbytes each. 
>You might want them
for:
- more granularity (if you can afford large enough timelocks)
- optimizing for the spending path rather than the revocation one
- adding a hashlock to prevent nuisance (with the above script a third party 
could malleate a
  spending path into a revocation one). You can use the OP_RETURN trick from 
above to prevent that.

Unfortunately, the timelocked-covenant approach to feebumping only applies to 
bumping the first
transaction of a chain (you can't pay for the parent with a timelock) so for 
instance it's not
usable for HTLC transactions in Lightning to bump the parent commitment tx. The 
same goes for
bumping the update tx in Coinpool.
It could be worked around by having a different covenant per participant 
(paying the fee from either
of the participants' output) behind a signature check. Of course it requires 
funds to already be in
the contract (HTLC, Coinpool leaf) to pay for your own unilateral close, but if 
you don't have any
fund in the contract it doesn't make sense to try to feebump it in the first 
place. The same goes
for small amounts: you'd only allocate up to the value of the contract (minus a 
dust preference) in
fees in order to enforce it.
This is less nice for external monitors as it requires a private key (or 
another secret) to be
committed to in advance) to be able to bump [4] and does not get rid of the 
"who's gonna pay for the
enforcement" issue in >2-parties contracts. Still, it's more optimal and usable 
than CPFP or adding
a pair of input/output for all the reasons mentioned above.


Thoughts?
Antoine


[0] 
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-November/019614.html
[1] 
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-November/019615.html
[2] 
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-December/019627.html
[3] That's obviously close to the CTV construction. But using another more 
flexible (and therefore
    less optimized) construction would not be a big deal. It might in fact be 
necessary for more
    elaborated (realistic?) usecases than the simple one detailed here.
[4] 
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-February/019879.html
_______________________________________________
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev

Reply via email to