There was a bug in LND and btcd which was exposed by a perfectly valid 998-of-999 Taproot multisig transaction broadcast by Burak on October 9th 2022. This transaction met the Taproot consensus rules activated on the network in November 2021, was included in a block by a miner and verified by all Bitcoin Core full nodes (and as far as I know alternative implementations other than btcd).
(The transaction was analyzed here by AdamISZ.)
The Taproot consensus rule upgrade included in BIP342:
Script size limit: The maximum script size of 10000 bytes does not apply. Their size is only implicitly bounded by the block weight limit.
btcd full nodes rejected the transaction and the block the transaction was included in and its blockchain stalled. The btcd wire parsing library was still enforcing the maximum script size limit from SegWit version 0 for SegWit version 1 transactions.
This impacted all LND nodes (both those backed by a Bitcoin Core full node and those backed by a btcd full node) because the btcd wire parsing library that deserializes raw blocks is a LND dependency.
As Olaoluwa Osuntokun (LND, btcd maintainer) stated on Twitter:
The issue was in btcd’s wire parsing library that deserializes raw blocks, the initial implementation of segwit v0 included a consensus level check for witness size limits but also hoisted this check up to the wire parsing layer
With segwit v1, this prior limit of the max accepted witness size was removed, in place of things like the sigop cost abstraction, effectively leaving the limit to the max block weight/size
btcd’s initial segwit v1 implementation correctly updated the consensus logic, but failed to also update the defense-in-depth check in the wire parsing layer (when parsing off the wire you want some sort of upper limit)
With regards to who it will impact and whether they will lose money, this depends on the LND user, on whether channel counterparties seek to exploit this bug and how quickly users are able to update to LND v0.15.2. Other Lightning node implementations (Core Lightning, eclair, LDK etc) are unaffected. If the LND node is backed by a btcd full node then the btcd full node will also need updating. There are two ways this bug could be exploited if LND users aren’t able to update speedily. Channel counterparties could broadcast a revoked state and unless the LND node comes back up within 2 weeks or an external watchtower is employed money could be lost this way. In addition if the LND node is a routing node money could be lost by its inability to close a channel if HTLC hash preimage(s) are not provided by channel counterparties prior to the timeout.
There was further discussion on why the Taproot (BIP341) static test vectors didn’t catch the bug in the LND repo. Olaoluwa Osuntokun again:
btcd is/was using this test vectors. The issue here is that the code the parsed the witnesses for these test vectors isn’t the same code that’s used to read blocks off the wire. When a new block comes in, we fetch the raw block then attempt to decode it, which triggered this issue.
This bug was also covered in Bitcoin Optech.
Leave a Reply