Release candidate 1 for 0.17.3. Changes since 0.17.2 are listed below. Two notes on swaps first:
- Swaps on mainnet are not available at present. Boltz, the swap provider compiled into CLBOSS, suspended all swaps on 2026-08-03, and its host names no longer resolve. A mainnet node on this release gets no quotation and makes no swap; nothing is paid. The swap changes in this release were validated on signet.
- The swap invoice check (#329) is the fix that would have mattered during the eMudhra certificate authority key compromise of October 2026. An impersonated provider endpoint could have had CLBOSS pay an invoice of its choosing; the check removes that path, whatever the host's trust store contains.
Upgrading from 0.17.2
- Finish or wait out any swap in flight before upgrading, and before
downgrading again. The swap table gains ten columns on first
use, and a swap created by one version cannot be claimed by the
other, so it ends at its timeout and the payment fails back to the
node. TheBoltz::Servicelog lines show one in flight. Earlier
releases still run on the upgraded database.
Changed
- Boltz swaps use the provider's API v2 with taproot lockups: the swap
is created at/v2/swap/reverse, polled at/v2/swap/{id}, quoted
from the v2 pairs, and claimed cooperatively with one MuSig2 key-path
signature, or through the claim leaf with our own signature and the
preimage when the provider does not co-sign. Before paying, the setup
writes both tapscript leaves itself and accepts the provider's only
when they match byte for byte. The claim waits until our own node has
the lockup three blocks deep, is recorded before the preimage is sent,
is replaced when the going feerate rises above its own, and is tracked
in our own blocks until the lockup is spent, whatever the provider
reports; a spend that does not pay us is logged as the loss it is.
The API v1 code is gone; the v1 table columnredeemScriptstays,
empty, beside the newclaimScript,refundScript,refundPubkey,
createdHeight,lockupSearchedHeight,spendSearchedHeight,
preimageRevealed,lockupTx,claimTxandclaimFeerate(#254). - The vendored libsecp256k1 moves from 0.3.2 to 0.6.0, which carries
the MuSig2, extrakeys and schnorrsig modules that taproot swaps
need.
Fixed
- A Boltz endpoint answering with something other than JSON, such
as an HTML error page or an empty body, surfaced as an unhandled
"Parse error near character '<'" with a backtrace and no hint of
which request failed, and afeeratesresponse without the
opening estimate failed the same way. The connection now reports
a parse failure or a missing result as an API error naming the
endpoint, the handlers log that text with the response, and the
fee lookup warns and falls back to 2000 perkw (#269). - C++ exceptions are unwound by libgcc's unwinder on Debian and
Ubuntu builds. Those distributions build libunwind with its own
exception unwinder, and with-lunwindahead of libstdc++ on the
link line it took over every throw in CLBOSS and its tests, which
mademake checkfail under valgrind. The build now links
libgcc_s explicitly ahead of libunwind. - A swap whose newaddr or swap-provider conversation died
mid-flight could wedge SwapManager for the process lifetime:
the flag serializing each processing loop was only cleared when
the loop's queue drained, and the response that would have
advanced it sometimes never arrives. The periodic tick now
restarts a loop whose current request has had no answer for
30 minutes; the previous remedy was restarting Core Lightning. - A swap invoice from the provider was paid as received. The
payer now checks the decoded invoice against the swap: the
payment hash must be of the preimage CLBOSS generated and the
amount must be the one the provider was asked for; any other
invoice is logged and left unpaid. Before this check, anyone
able to impersonate the provider's HTTPS endpoint, for example
with a certificate issued under a compromised certificate
authority, could have had CLBOSS pay an invoice of their
choosing for the swap amount (#329). - With two or more channels to one peer, the fee modifier by
balance read only the first live channel, applied the multiplier
it derived to all of them and recorded that one channel's balance
as the peer's. It now sums our balance and the capacity over
the peer's live channels, so the multiplier reflects the whole
position and the balance samplesPeerTrackRecordand the
contrib tools read are the peer's (#352). - With two or more channels to one peer, the active prober sized
its probe from the first live channel listed, which could be the
smaller one. It now probes through the channel with the most to
spend; the probe names that channel, so its amount stays within
one channel (#352). clboss-auto-closeon a peer with more than one channel issued
close id=<node>, which lightningd refuses ("Peer has multiple
channels"); the error was logged and the close retried every
cycle. It now closes each closable channel by channel id
(#352).contrib/clboss-channel-sizingreads a peer's balance history
recorded before 0.17.3 against the one channel it describes. Those
samples carry the first channel's balance and capacity, not the
peer's sum, and the tool apportioned them over all of the peer's
channels, so a peer that opened a 5M channel beside a 1M one showed
the 1M channel at several times its real turns. When the newest
sample's total is not the peer's summed capacity, the channel whose
capacity matches reads the samples and the peer's other channels
read as young (#352).- A new signet node can find peers again. Signet has no DNS seed, so
the hardcoded seeds are the only way in, and all four of them had
stopped accepting connections; they are replaced with seven nodes
that accept them.
Credits
Thanks to the contributors to this release:
- The contributor who sent the API v2 draft: the first version of
the Boltz API v2 code, with taproot reverse swaps and MuSig2
claims (#254). - @Mohil-Ahuja: the three fixes for several channels to one peer
(#368, #371, #369), the balance-sample fix in
contrib/clboss-channel-sizing(#378) and the replacement signet
seeds (#379). - @Amperstrand: reported that a swap invoice was paid without a
check of its payment hash (#329). - @tsjk: runs the signet swap backend that the swap changes were
tested against.