/ home / newsletters /
Bitcoin Optech Newsletter #353
This week’s newsletter describes a recently discovered theoretical consensus failure vulnerability and links to a proposal to avoid reuse of BIP32 wallet paths. Also included are our regular sections summarizing a Bitcoin Core PR Review Club meeting, announcing new releases and release candidates, and describing notable code changes to popular Bitcoin infrastructure software.
News
-
● BIP30 consensus failure vulnerability: Ruben Somsen posted to the Bitcoin-Dev mailing list about a theoretical consensus failure that could occur now that checkpoints have been removed from Bitcoin Core (see Newsletter #346). In short, the coinbase transactions of blocks 91722 and 91812 are duplicated in blocks 91880 and 91842. BIP30 specifies that those second two blocks should be handled the way the historic version of Bitcoin Core handled them in 2010, which is by overwriting the earlier coinbase entries in the UTXO set with the later duplicates. However, Somsen notes that a reorg of either or both later blocks would result in the duplicate entry (or entries) being removed from the UTXO set, leaving it devoid also of the earlier entries due to the overwriting. But, a newly started node that never saw the duplicate transactions would still have the earlier transactions, giving it a different UTXO set that could result in a consensus failure if either transaction is ever spent.
This wasn’t an issue when Bitcoin Core had checkpoints as they required all four blocks mentioned above to be part of the best blockchain. It’s not really an issue now, except in a theoretical case where Bitcoin’s proof-of-work security mechanism breaks. Several possible solutions were discussed, such as hardcoding additional special case logic for these two exceptions.
-
● Avoiding BIP32 path reuse: Kevin Loaec posted to Delving Bitcoin to discuss options for preventing the same BIP32 wallet path from being used with different wallets, which could lead to a loss of privacy due to output linking and a theoretical loss of security (e.g., due to quantum computing). He suggested three possible approaches: use a randomized path, use a path based on the wallet birthday, and use a path based on an incrementing counter. He recommended the birthday-based approach.
He also recommended dropping most of the BIP48 path elements as unnecessary due to the increasingly widespread use of descriptor wallets, especially for multisig and complex script wallets. However, Salvatore Ingala replied to suggest keeping the coin type part of the BIP48 path as it helps ensure keys for use with different cryptocurrencies are kept segregated, which is enforced by some hardware signing devices.
Bitcoin Core PR Review Club
In this monthly section, we summarize a recent Bitcoin Core PR Review Club meeting, highlighting some of the important questions and answers. Click on a question below to see a summary of the answer from the meeting.
Add bitcoin wrapper executable is a PR by
ryanofsky that introduces a new bitcoin
binary which
can be used to discover and launch the various Bitcoin Core binaries.
Bitcoin Core v29 shipped with 7 binaries (e.g. bitcoind
, bitcoin-qt
and bitcoin-cli
), but that number is set to increase in the future when multiprocess binaries
are shipped as well. The new bitcoin
wrapper maps commands (e.g.
gui
) to the correct monolithic (bitcoin-qt
) or multiprocess
(bitcoin-gui
) binary. In addition to discoverability, the wrapper also
provides forward compatibility so binaries can be reorganized without
the user interface changing.
With this PR, a user can launch Bitcoin Core with bitcoin daemon
or
bitcoin gui
. Directly launching the bitcoind
or bitcoin-qt
binaries is still possible and not affected by this PR.
-
From issue #30983, four packaging strategies were listed. Which specific drawbacks of the “side‑binaries” approach does this PR address?
The side-binaries approach assumed by this PR involves releasing the new multiprocess binaries alongside the existing monolithic binaries. With this many binaries, it can be confusing for users to find and figure out the binary they need for their purpose. This PR takes a lot of the confusion away by providing a single entry point, with an overview of options and a help string. One reviewer suggested the addition of fuzzy search to facilitate this even further. ➚
-
GetExePath()
does not usereadlink("/proc/self/exe")
on Linux even though it would be more direct. What advantages does the current implementation have? What corner cases might it miss?There may be other non-Windows platforms that do not have the proc filesystem. Other than that, neither the author nor guests could identify any drawbacks of using procfs. ➚
-
In
ExecCommand
, explain the purpose of thefallback_os_search
Boolean. Under what circumstances is it better to avoid letting the OS search for the binary on thePATH
?If it looks like the wrapper executable was invoked by path (e.g. “/build/bin/bitcoin”) rather than by search (e.g. “bitcoin”), it is assumed the user is using a local build and
fallback_os_search
is set tofalse
. This boolean is introduced to unintentionally mix binaries from different sources. For example, if the user didn’t locally buildgui
, then/build/bin/bitcoin gui
should not fall back to the system installedbitcoin-gui
. The author is considering removing thePATH
search entirely, and user feedback would be helpful. ➚ -
The wrapper searches
${prefix}/libexec
only when it detects that it is running from an installedbin/
directory. Why not always searchlibexec
?The wrapper should be conservative about what paths it tries to execute, and encourage standard
PREFIX/{bin,libexec}
layouts, not encourage packagers to create nonstandard layouts or work when binaries are arranged in unexpected ways. ➚ -
The PR adds an exemption in
security-check.py
because the wrapper contains no fortifiedglibc
calls. Why does it not contain them, and would adding a trivialprintf
tobitcoin.cpp
break reproducible builds under the current rules?The wrapper binary is so simple it does not contain any calls that can be fortified. If it does in the future, the exemption in security-check.py can be removed. ➚
Releases and release candidates
New releases and release candidates for popular Bitcoin infrastructure projects. Please consider upgrading to new releases or helping to test release candidates.
- ● LND 0.19.0-beta.rc4 is a release candidate for this popular LN node. One of the major improvements that could probably use testing is the new RBF-based fee bumping for cooperative closes.
Notable code and documentation changes
Notable recent changes in Bitcoin Core, Core Lightning, Eclair, LDK, LND, libsecp256k1, Hardware Wallet Interface (HWI), Rust Bitcoin, BTCPay Server, BDK, Bitcoin Improvement Proposals (BIPs), Lightning BOLTs, Lightning BLIPs, Bitcoin Inquisition, and BINANAs.
-
● Core Lightning #8227 adds Rust-based
lsps-client
andlsps-service
plugins that implement a communication protocol between LSP nodes and their clients, using a JSON-RPC format over BOLT8 peer-to-peer messages, as specified in BLIP50 (see Newsletter #335). This lays the foundation for implementing incoming liquidity requests as specified in BLIP51, and JIT channels as specified in BLIP52. -
● Core Lightning #8162 updates the handling of peer-initiated pending channel opens by retaining them indefinitely, up to a limit of the 100 most recent. Previously, unconfirmed channel opens were forgotten after 2016 blocks. In addition, closed channels are now held in memory to allow a node to respond to a peer’s
channel_reestablish
message. -
● Core Lightning #8166 enhances the
wait
RPC command by replacing its singledetails
object with subsystem-specific objects:invoices
,forwards
,sendpays
, andhtlcs
. In addition, thelisthtlcs
RPC now supports pagination via newcreated_index
andupdated_index
fields and theindex
,start
, andend
parameters. -
● Core Lightning #8237 adds a
short_channel_id
parameter to thelistpeerchannels
RPC command to return only a specific channel, if provided. -
● LDK #3700 adds a new
failure_reason
field to theHTLCHandlingFailed
event to provide additional information about why the HTLC failed, and whether the cause was local or downstream. Thefailed_next_destination
field is renamed tofailure_type
and theUnknownNextHop
variant is deprecated, and replaced by the more generalInvalidForward
. -
● Rust Bitcoin #4387 refactors BIP32 error handling by replacing the single
bip32::Error
with separate enums for derivation, child number/path parsing, and extended key parsing. This PR also introduces a newDerivationError::MaximumDepthExceeded
variant for paths exceeding 256 levels. These API changes break the backwards compatibility. -
● BIPs #1835 updates BIP48 (see Newsletter #135) to reserve the script type value 3 for taproot (P2TR) derivations in deterministic multisig wallets with the m/48’ prefix, in addition to the existing P2SH-P2WSH (1′) and P2WSH (2′) script types.
-
● BIPs #1800 merges BIP54, which specifies the consensus cleanup soft fork proposal to fix a number of long-standing vulnerabilities in the Bitcoin protocol. See Newsletter #348 for a detailed description of this BIP.
-
● BOLTs #1245 tightens BOLT11 by disallowing non-minimal length encodings in invoices: the expiry (x), the CLTV expiry delta for the last hop (c), and feature bits (9) fields must be serialized in minimal length without leading zeros, and readers should reject any invoice that contains leading zeros. This change was motivated by fuzz testing that detected that when LDK reserialize non-minimal invoices to minimal (stripping out the extra zeros), it causes the invoice’s ECDSA signature to fail validation.
Want more?
For more discussion about the topics mentioned in this newsletter, join us for the weekly Bitcoin Optech Recap on Riverside.fm at 16:30 UTC on May 13. The discussion is also recorded and will be available from our podcasts page.