At a minimum, we probably want to make HTLC transactions v3. If we really want to fix pinning, we may also need to make all HTLC spending paths use presigned v3 transactions.
Why make HTLC transactions v3?
- v3 allows them to be relayed as part of the commitment package.
- I think v3 also prevents MitM pinning attacks where someone extracts the
SIGHASH_SINGLE | SIGHASH_ANYONECANPAY
signature and uses it to construct and pin a low feerate conflicting transaction.
Fixing HTLC pinning
With no other changes, HTLC transactions are still vulnerable to pinning attacks since the remote path can be spent by non-v3 transactions. For example:
- Alice offers HTLC1 to Mallory, which times out at block T. Alice also offers HTLC2 to Mallory, which times out at block T+5.
- Mallory has preimages for both HTLCs, but she withholds them.
- At block T-1, Alice broadcasts her commitment with a single child transaction that spends the ephemeral anchor, Alice’s local balance, and HTLC1 via the presigned HTLC-timeout transaction.
- Mallory is unable to pin any competing transaction in this case, due to v3 policy.
- The commitment and child transaction confirm in block T.
- At block T+4, Alice broadcasts her HTLC-timeout transaction claiming HTLC2. At the same time, Mallory broadcasts a low feerate preimage spend of HTLC2 and pins it in mempools. With good connectivity and timing, Mallory can partition mempools such that Alice’s mempool contains the HTLC-timeout and all other mempools contain the pinned preimage spend.
Because Mallory’s preimage spend can opt out of v3 policy, she is able to pin her transaction in mempools while preventing Alice from learning the preimage or confirming her HTLC-timeout transaction.
One way to fix this pinning vector is to start requiring presigned v3 transactions for HTLC remote spends.