This week’s newsletter summarizes a discussion about storing data in transaction witnesses and references a conversation about mitigating LN jamming. Also included are our regular sections with the summary of a Bitcoin Core PR Review Club meeting and descriptions of notable changes to popular Bitcoin infrastructure software.
● Discussion about storing data in the block chain: users of a new project recently began storing large amounts of data in the witness data for transactions containing segwit v1 (taproot) inputs. Robert Dickinson posted to the Bitcoin-Dev mailing list to inquire about whether a size limit should be imposed to discourage such data storage.
Andrew Poelstra replied that there is no effective way to prevent data storage. Adding new restrictions to prevent unwanted data storage in witnesses would undermine advantages discussed during taproot’s design (see Newsletter #65) and would likely only result in the data being stored in other ways. Those other ways might raise costs for those generating the data—but probably not by enough to significantly discourage the behavior—and the alternative storage methods might create new problems for traditional Bitcoin users.
● Summary of call about mitigating LN jamming: Carla Kirk-Cohen and Clara Shikhelman posted to the Lightning-Dev mailing list a summary of a recent video conversation about attempts to address channel jamming attacks. Topics discussed included upgrade mechanism tradeoffs, a simple proposal for upfront fees derived from a recent paper (see Newsletter #226), the CircuitBreaker software (see Newsletter #230), an update on reputation credentials (see Newsletter #228), and related work from the Lightning Service Provider (LSP) specification working group. See the mailing list post for extended summaries and a transcript.
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.
Track AddrMan totals by network and table, improve precision of adding fixed seeds
is a PR by Martin Zumsande, co-authored by Amiti Uttarwar, that
allows the Bitcoin Core client to more reliably find outbound peers
in certain situations.
It does this by enhancing
(the peer address manager) to keep track of the number of address entries
separately by network and “tried” versus “new” type, which in turn allows
better use of fixed seeds. This is the first step in a larger effort to
improve outbound peer selection.
When is a network considered reachable?
A network is assumed to be reachable unless we’re sure we can’t access it, or our configuration has specified one or more other networks using the
-onlynet=configuration option (then only those are considered reachable, even if other network types are actually available). ➚
How is an address received over the P2P network treated depending on whether the address’s network is reachable vs. non-reachable – do we store it (add it to
AddrMan) and/or forward it to peers?
If its network is reachable, we relay the address to two randomly-chosen peers, else we relay it to 1 or 2 peers (whether 1 or 2 is randomly-chosen). We only store the address if its network is reachable. ➚
How can a node currently get stuck with only unreachable addresses in
AddrMan, finding no outbound peers? How does this PR fix it?
-onlynetconfiguration changes. For example, suppose the node has always been run with
AddrManhas no I2P addresses. Then the node is restarted with
-onlynet=i2p. The fixed seeds have some I2P addresses, but without the PR, the node won’t use them since the
AddrManisn’t completely empty (it has some onion addresses from before). With the PR, the startup code will add some I2P fixed seeds, since
AddrMancontains zero addresses of that (now reachable) network type. ➚
When an address we’d like to add to
AddrMancollides with an existing address, what happens? Is the existing address always dropped in favor of the new address?
No, generally the existing address is retained (not the new one), unless the existing address is deemed ‘terrible’ (see
Why would it be beneficial to have an outbound connection to each reachable network at all times?
A selfish reason is that it’s harder to eclipse attack the node, since the attacker would need to run nodes on multiple networks. A non-selfish reason is that it helps keep the overall network together, avoiding chain splits caused by network partitions. If half the nodes, including miners, ran with
-onlynet=xand the other half, including miners, ran
-onlynet=y, then two chains could emerge. Even without the PR, a node operator can manually add a connection for each available network type using the
-addnodeconfiguration option or the
Why is the current logic in
ThreadOpenConnections(), even with the PR, insufficient to guarantee that the node has an outbound connection to each reachable network at all times?
Nothing in the PR guarantees any particular distribution of peers among the reachable networks. For example, if we had 10k clearnet addresses and only 50 I2P addresses in
AddrMan, it’s very likely that all our peers will be clearnet (IPv4 or IPv6). ➚
What would be the next steps towards this goal (see the previous question) after this PR?
The next planned steps are to add logic to the connection-making process to attempt to have at least one connection to each reachable network. This PR prepares for that. ➚
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 #25880 makes the stalling timeout adaptive during the initial synchronization. Bitcoin Core requests blocks from multiple peers in parallel. If one peer is significantly slower than others to the point that the node gets stuck waiting for the next block, we disconnect the stalling peer after a timeout. In some situations this could cause a node with a low-bandwidth connection to disconnect multiple peers in a row when a heavy block could not be transferred within the timeout. This code change amends the behavior of nodes to dynamically adapt the timeout: the timeout is incremented for each disconnected peer while no block is received, and after blocks start arriving again, the timeout is scaled back block-by-block.
● Core Lightning #5679 provides a plugin to run SQL queries on CLN’s list commands. This patch also handles deprecations more gracefully as it can ignore anything deprecated before it was released as introduced in Core Lightning #5867.
● Core Lightning #5821 adds
preapproveinvoice(pre-approve invoice) and
preapprovekeysend(pre-approve keysend) RPCs that allow the caller to send either a BOLT11 invoice or keysend payment details to Core Lightning’s signing module (
hsmd) to verify the module is willing to sign the payment. For some applications, such as those where the amount of money that can be spent is rate limited, asking for pre-approval might produce fewer problems than simply attempting the payment and dealing with failure.
● Core Lightning #5849 makes backend changes that allow a node to handle over 100,000 peers each with one channel. Although someone running such a node in production is not likely in the near future—it would take over a dozen entire blocks to just open that many channels—testing the behavior helped the developer make several performance improvements.
● Eclair #2565 now requests that funds from a closed channel be sent to a new onchain address, rather than an address which was generated when the channel was funded. This may decrease output linking, which helps improve user privacy. An exception to this policy is when the user enables the LN protocol option
upfront-shutdown-script, which is a request sent to the channel partner at funding time to only use the closing address specified at that time (see Newsletter #158 for details).
● LND #6527 adds the ability to encrypt the server’s on-disk TLS key. LND uses TLS for authenticating remote connections to its control channel, i.e. to run APIs. The TLS key will be encrypted using data from the node’s wallet, so unlocking the wallet will unlock the TLS key. Unlocking the wallet is already required to send and accept payments.