This week’s newsletter includes our regular sections with the summary of a Bitcoin Core PR Review Club meeting, a list of new software releases and release candidates, and descriptions of notable changes to popular Bitcoin infrastructure software.
No significant news this week.
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.
Miniscript support in Output Descriptors is a PR authored by Antoine Poinsot and Pieter Wuille to introduce watch-only support for Miniscript in descriptors. Participants reviewed the PR over two meetings. Topics of discussion included the uses of Miniscript, considerations for malleability, and the implementation of the descriptor parser.
Which types of analysis enabled by Miniscript would be helpful for which use cases or applications?
Several use cases and types of analysis were discussed. Miniscript enables analysis of the maximum witness size and thus the ‘worst case’ cost to spend the output at a given feerate. Predictable transaction weights help L2 protocol developers write more reliable fee-bumping mechanisms. Additionally, given some policy, the compiler generates a minimal Miniscript script (not necessarily the smallest possible, since Miniscript only encodes a subset of all scripts), which may be smaller than a hand-crafted one. Participants noted that Miniscript has helped optimize LN templates in the past. Finally, composition allows multiple parties to combine complex spending conditions and guarantee the resulting script’s correctness without fully understanding all of them. ➚
Miniscript expressions can be represented as trees of nodes, where each node represents a fragment. What does it mean when a node is “sane” or “valid”? Do they mean the same thing?
Each node has a fragment type (e.g.
multi, etc.) and arguments. A valid node’s arguments match what the fragment type expects. A sane node must be valid and its script semantics must match its policy, be consensus-valid and standardness-compliant, only have non-malleable solutions, not mix timelock units (i.e. use both block height and time), and not have duplicate keys. As defined, these two properties are not identical; every sane node is valid, but not every valid node is sane. ➚
What does it mean for an expression to be non-malleably satisfiable? After segwit, why do we still need to worry about malleability?
A script is malleable if a third party (i.e. someone who doesn’t have access to the corresponding private keys, among other assumptions) can modify it and still satisfy the spending condition(s). Segwit didn’t remove the possibility of transaction malleation; it ensured that transaction malleation wouldn’t break the validity of unconfirmed descendants, but malleability can still be problematic for other reasons. For example, if an attacker can stuff extra data into the witness and still satisfy the spending conditions, they can lower the transaction’s feerate and negatively impact its propagation. A ‘non-malleably satisfiable expression’ does not give third parties such options to modify an existing satisfaction into another valid satisfaction. A more complete answer can be found here. ➚
Which function is responsible for parsing the output descriptor strings? How does it determine whether the string represents a
MiniscriptDescriptor? How does it resolve a descriptor that can be parsed in multiple ways?
ParseScriptin script/descriptor.cpp is responsible for parsing output descriptor strings. It tries all other descriptor types first, and then calls
miniscript::FromStringto see if the string is a valid Miniscript expression. Due to this order of operations, descriptors that can be interpreted as both miniscript and non-miniscript (e.g.
wsh(pk(...))) are parsed as non-miniscript. ➚
When choosing between two available satisfactions, why should the one that involves fewer signatures, rather than the one which results in a smaller script, be preferred?
Third parties attempting to malleate a transaction (i.e. without access to private keys) can remove signatures, but not create new ones. Choosing the satisfaction with additional signatures leaves the option for a third party to malleate the script and still satisfy the spending conditions. For example, the policy
or(and(older(21), pk(B)), thresh(2, pk(A), pk(B)))has two spending paths: it can always be spent when both A and B sign, or after 21 blocks when just B signs. After 21 blocks, both satisfactions are available, but if a transaction with both A and B’s signatures is broadcast, a third party could remove A’s signature and still satisfy the other spending path. On the other hand, if the broadcasted transaction only contains B’s signature, the attacker cannot satisfy the other spending condition unless it forges A’s signature. ➚
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.
Notable code and documentation changes
Notable changes this week in Bitcoin Core, Core Lightning, Eclair, LDK, LND, libsecp256k1, Hardware Wallet Interface (HWI), Rust Bitcoin, BTCPay Server, BDK, Bitcoin Improvement Proposals (BIPs), and Lightning BOLTs.
● Bitcoin Core #24408 adds an RPC to fetch mempool transactions spending from a given outpoint, streamlining the search for outpoints by selecting transactions individually rather than from a list of txids retrieved from
getrawmempool. This is useful in Lightning when locating a spending transaction after a channel funding transaction has been spent or examining why an RBF transaction failed to broadcast by fetching the conflicting transaction.
● BOLTs #910 updates the LN specification with two changes. The first allows Short Channel Identifier (SCID) aliases which can improve privacy and also allow referencing a channel even when its txid is unstable (i.e., before its deposit transaction has received a reliable number of confirmations). The second specification change adds an
option_zeroconffeature bit that may be set when a node is willing to use zero-conf channels.