This week’s newsletter summarizes the disclosure of two denial-of-service
vulnerabilities in older versions of Eclair and describes a proposed scheme for
running complex multi-round contracts inside Lightning channels. Also included
are our regular sections announcing new releases and release candidates and
describing notable changes to popular Bitcoin infrastructure software.
News
-
● Disclosure of two DoS vulnerabilities fixed in Eclair v0.14.1: Erick
Cestari posted to Delving Bitcoin the responsible
disclosure of two denial-of-service (DoS)
vulnerabilities in the channel opening process of Eclair v0.14.0 and earlier.
Both were fixed in Eclair #3324 and released in v0.14.1 in July, and users running an older version should upgrade.The first, found by Matt Morehouse with his smite fuzzer, is a
race condition in a duplicatetemporary_channel_idcheck. Eclair checked
whether the ID was already in use before accepting anopen_channelmessage,
but did not record the new channel until a later step, so an attacker sending
several identicalopen_channelmessages in quick succession could get two
past the check. Eclair then created two channel states for one ID, and the
second replaced the first, leaving an unreachable channel state that held
about 25 kB of memory until the peer disconnected. Repeating the attack leaked
about 1 MB per second until the node ran out of memory or spent all of its CPU
on garbage collection.The second, found by Cestari, bypasses Eclair’s limit on the number of pending
channels whose funding transaction has not confirmed. The duplicate check only
looked at temporary IDs, so an attacker could start opening a channel, then
reuse that channel’s finalchannel_idas thetemporary_channel_idof the
nextopen_channel. The limiter counted the reused ID twice and dropped both
entries once the new channel received its final ID, so its count never rose
above two while the number of pending channels grew without bound. Each
pending channel stores a copy of the peer’sinitfeatures, and setting a
single unknown odd feature bit at a very high position inflated that copy to
about 65 kB. In Cestari’s test, one connection with no onchain cost exhausted
a node’s 4 GB of memory in about 48 minutes. Because pending channels are
written to the database, the node crashed again on every restart until its
memory limit was raised or the rows were deleted by hand.Replying to a question, Morehouse noted that mobile wallets that use an Eclair
node as their LSP, such as Phoenix, are unaffected because ACINQ patched its
nodes months ago. -
● Offchain contracts in Lightning channels: Adam Gibson posted
to the Bitcoin-Dev mailing list about a proposal for protocol,
called LN-GAP, to run complex, multi-round, two-party contracts inside a
Lightning channel while settling disputes onchain in a constant number of
transactions. In order to showcase the proposal, Gibson implemented a game
of chess, which he deems a good example of a game that is difficult to run
onchain, in which the winner takes the whole pot. Both a repository
and a paper for the proposal are available.Two players, Alice and Bob, agree on a certain set of rules. Each player makes
their own moves. In case of a dispute, Alice can enforce the rules onchain.
However, Gibson notes that Lightning can enforce rules about a published state,
but it cannot do so in case a counterparty stalls or stops responding.
To address this issue, Gibson introduces a venue, a committee of members whose
role is to attest whether a signed message (a move in a chess game and its
signature) was published before a certain deadline or not. The venue only needs
to attest the timeliness of the publication, not the content of the message.
In case of a dispute, Alice posts a transaction claiming that no event was
published by Bob; in turn, Bob can post a second transaction containing a
rebuttal (his move and the venue’s attestation); finally, Alice can post a
disproof, stating that Bob’s rebuttal doesn’t stand due to the event not being
compliant with the rules.In Gibson’s proposal, the venue never holds users’ funds. Moreover, it avoids
relying on FROST-style threshold signature in order to make fraud attributable
only to malicious members. To do so, attestation is done through per-member
“one-bit signatures” checked usingOP_CHECKSIGADD. Members are incentivized
by fees paid atomically over channels using adaptors.
However, the construction relies on an honest-majority assumption. If more than
half of the members of the venue collude with one of the parties involved, funds
can be stolen.Other than games, possible applications include proof-of-storage
contracts, where a provider forfeits a bond for failing to respond to a
challenge, and offchain dispute resolution similar to what
BitVMX-style zero-knowledge verifiers do onchain.
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 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.
-
● Eclair #3396, #3397, and #3400 fix
several ways a malicious channel peer could prevent Eclair from enforcing
HTLCs onchain during splicing (see
Newsletter #423). Previously, a peer could make
Eclair sign a splice transaction that could not be published promptly by
choosing a distant absolute locktime, adding inputs with relative
timelocks, providing nonstandard witnesses, exceeding the
standard transaction weight limit, or setting the signed transaction’s
feerate too low. The first PR adds checks for these cases. The second makes
Eclair retry commitment and penalty transactions that
were rejected by a conflicting unconfirmed transaction, as the peer may later
replace that transaction through RBF by double-spending one of
its other inputs. The retry fix also applies when the channel’s funding
transaction is unconfirmed, including zero-conf channels. The third fixes another recovery gap: if an RBF replacement of a
splice confirms after Eclair force-closes using a commitment for a sibling
attempt, Eclair now recognizes that the funding transaction has changed and
broadcasts a commitment transaction that spends the confirmed splice output.
Previously, funds could remain locked and HTLCs unenforced. -
● Eclair #3399 and #3394 fix two ways on-the-fly
funding could leave Eclair paying a downstream peer
without collecting the corresponding incoming HTLC (see
Newsletter #419). Previously, after Eclair stopped
tracking an expired payment, a new payment could reuse its payment hash. If
the downstream peer then claimed the original outgoing HTLC onchain,
revealing the preimage, Eclair could mistakenly fulfill the newer payment’s
incoming HTLCs instead of the original ones, allowing the original incoming
HTLCs to time out without paying Eclair. The first PR now checks if a
settlement belongs to the currently tracked payment and, if not, it uses the
incoming HTLC details retained with the settlement to fulfill the correct
HTLCs. The second PR ensures that funded payments are only forwarded over the
channel where liquidity was purchased. Previously, Eclair could forward over
another channel with the same peer, but would only check the funded channel
before failing upstream at expiry, even though the outgoing HTLC on the other
channel remained claimable. -
● Eclair #3395 fixes a bug where a spender could construct a malformed
payment onion packet with a valid HMAC that left an incoming HTLC unresolved. The spender could encode a per-hop payload length larger
than the packet’s actual capacity while still providing a valid HMAC.
Previously, Eclair did not validate the length before extracting the next
HMAC, causing an uncaught exception. The relayer would then resume without
failing the HTLC, and the malformed packet could also prevent HTLC cleanup
from initializing after a restart. Now, Eclair checks that the per-hop
payload, including its HMAC, fits within the packet. If it does not, Eclair
returnsInvalidOnionVersion, allowing normal failure handling. -
● Eclair #3401 fixes a bug that could cause a forwarding node to lose funds
after a disconnection. Eclair stores instructions to fulfill or fail
HTLCs until the corresponding channel updates are signed,
allowing them to be retried after reconnection. Previously, if a duplicate or
conflicting instruction was rejected because a fulfillment had already been
proposed but not signed, Eclair scheduled the deletion of the original stored
instruction. If the channel disconnected before signing, the unsigned update
was discarded, leaving no instruction to replay the fulfillment. The incoming
HTLC could then time out even though the outgoing HTLC had already been
fulfilled. Eclair now retains the original instruction until the settlement
is signed. -
● LDK #5080 fixes a bug where restarting during cooperative channel close
could prevent pending HTLCs from being failed back to their
upstream peer. Previously, when LDK restarted, it excluded channels
undergoing cooperative close from the lookup used to process HTLCs, even
though those channels could still have unresolved payments. Consequently,
when a downstream peer failed an HTLC, LDK could mistakenly treat the
upstream channel as nonexistent and discard the failure. LDK could also drop
incoming HTLCs awaiting onion decoding. This could leave HTLCs unresolved
until the upstream peer force-closed the channel at expiry. LDK now includes
channels undergoing shutdown when restoring the information needed to resolve
existing HTLCs. -
● LDK #5087 fixes a potential privacy leak in onion messages sent over blinded paths that use dummy hops
(see Newsletter #370). Dummy hops are additional
encrypted layers that the recipient processes to obscure its position in the
path. Previously, forwarding hops rejected intermediate onion layers
containing message-content TLV records, but dummy hops accepted them. A
malicious sender could insert these records at different, nonfinal layers and
observe whether the final message produced a response, potentially revealing
where the actual forwarding ended and the dummy hops began. LDK now rejects
message-content records at dummy hops as well. -
● LND #11068 fixes a missing check for auxiliary HTLC
signatures on experimental taproot overlay channels used for Taproot
Assets (see Newsletter #324). In these channels, a Taproot Assets signer (tapd) provides an
additional signature entry for each non-dust
HTLC alongside the usual Bitcoin signatures. Previously, if a peer sent a
commitment containing the required Bitcoin signatures but omitted some or all
of the auxiliary HTLC signature entries, the receiving LND node would
incorrectly accept it. If the channel is later force-closed, the missing
signatures could prevent the affected asset HTLCs from being resolved
onchain. LND now verifies that the number of received auxiliary signature
entries matches the number of non-dust HTLCs. If they differ, LND rejects the
commitment and force-closes the channel. -
● Rust Bitcoin #6956 introduces a
ScriptCodetype for the script data
used in legacy and segwit v0 signature hashing, which may differ from the
full script being spent. According to BIP143, when a P2WSH script
contains OP_CODESEPARATOR, signature hashing
excludes everything up to and including the last separator executed before
the signature check, while retaining any subsequent separators. Previously,
p2wsh_signature_hashaccepted a witness script, which could lead callers to
hash the complete script and produce an invalid signature. The API now
acceptsScriptCode, but callers must still identify the last executed
separator and shorten the script themselves. The PR also adds
P2wpkhScriptCode, a fixed-size, allocation-free representation of the
standard script used to sign P2WPKH inputs. -
● BDK #2319 fixes a bug where an Electrum-backed wallet could lose track of
a transaction’s confirmation after a reorg if the same transaction was mined
again at the same height. BDK could retain the displaced block’s header in
its cache and fail to recognize the transaction’s confirmation in the
replacement block, incorrectly showing it as unconfirmed. The fix refreshes
the header cache with newly fetched block headers during synchronization,
including after a one-block reorg.
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 October 20. The
discussion is also recorded and will be available from our podcasts
page.

