pull down to refresh

Welcome to Latest Strikes, your weekly report of the latest Lightning-related news. In this issue, we got Core Lightning and LND releases, a fee-siphoning vulnerability affecting some ecash mints, and more!

Sorry this issue is coming out a bit late — I was travelling recently, but we'll be back to our usual schedule starting next week!

Core Lightning ReleaseCore Lightning Release

Core Lightning v26.06 was released.

It extends the migration from the pay command to xpay we covered when the new version was at the release candidate stage. In this released version, xpay is closer to feature parity with pay, with notably the ability to pass a label to a payment[1], tie a payment to an invoice fetched from an offer (in order to ensure the offer is only paid once)[2], or some privacy enhancements such as adding a CLTV offset to a payment's route in order to limit the ability for other nodes to infer the destination of a payment.

This release also adds a new experimental plugin, which will become a core plugin as it matures. Called bwatch, its purpose is to do all the block parsing on behalf of the lightningd daemon, which is currently doing the job. When parsing a block, bwatch notifies lightningd if it finds anything of interest, by watching various objects such as addresses or outpoints. It also notifies on new block and block reorgs, for example letting lightningd confirm a channel funding is properly confirmed before activating the channel. Cache persistence and rehydration allow for very quick catchups after a reboot, while a clever construction[3] ensures that no notification is missed.

On top of all that, this release also brings (among other things):

  • a graceful command to gracefully stop the node ;
  • splicing improvements (mostly avoiding to abort on some hedge cases) ;
  • a Unix-domain sink for OpenTelemetry traces (this is huge when running a big node in production along with an extensive infrastructure) ;
  • Bolt12 Payer Proofs, which are still marked as experimental.

LND ReleaseLND Release

LND v0.21.0 was released, bringing a full metric tonne of bug fixes, performance improvements, as well as basic Onion Message forwarding with rate limiting. Here are a few morceaux choisis:

  • the payment store is migrated from the legacy key-value database to native SQL. This is part of a long transition process, which brings considerable performance and stability improvements. This is the first time this migration is shipped as production code: it previously required the test_native_sql flag to even be part of the build ; now it ships with all builds, and is available to users with the native-sql setting enabled ;
  • while we're on the topic of databases, with this release LND will now use a "tombstone" for closed channels on kvdb-on-sql databases, simply marking the channel as closed rather than deleting all the associated state records. This prevents a database hold on old channels with a lot of history, where these cascading deletions could lock access to the database for several seconds, preventing payment forwarding in the meantime. The tombstones will be cleared automatically when migrating to the native SQL database. Note that users of kvdb-on-sql databases should treat this upgrade as one-way for the database, since downgrading the node would "resurrect" any channel closed in the meantime. bbolt and etcd are unaffected ;
  • the old payments RPCs are removed in this release as announced previously. Users who haven't done so yet must now migrate to their V2 equivalents (e.g. SendPayment -> SendPaymentV2) ;
  • a new "fast initial sync" feature is available for neutrino-backed nodes. Instead of performing the initial sync peer-to-peer, the node can now bootstrap its block headers and compact filter headers chains[4] from disk or an HTTP endpoint, reducing the initial syncing time quite considerably. Crucially, data downloaded this way is still validated the same way as data obtained directly from the P2P network. The data source can either be the disk, if the user already has header files on disk (for example from an already synced Neutrino node) or an HTTP endpoint such as block-dn, which serves blocks, filters and their respective headers. This new feature is off by default, and can be enabled by specifying the data sources for block/filter headers in the configuration[5] ;
  • LND now properly handles reorgs when it comes to channel closures.

Fee Siphoning Attack In NutshellFee Siphoning Attack In Nutshell

Floppy (a.k.a 1440000bytes) disclosed a fee siphoning attack affecting nutshell and presumably the Cashu Dev Kit. The vulnerability allows an attacker to steal funds from cashu mint operators that use LNBits as the Lightning backend for their mint without sane defaults.

When a user wants to withdraw funds from the mint, the mint needs to melt (i.e. "consume", "spend") enough of the user's ecash tokens to cover the amount they want to send and the Lightning Network transaction fee. However, the exact fee cannot always be known beforehand (for example, the cheapest route may fail and a slightly more expensive one succeed). A common practice for custodial services such as ecash mints is to reserve a fixed amount from the user balance when initiating the withdrawal, pinch from this amount to cover the fee, and credit back whatever remains from this "fee reserve" to the user once the withdrawal is settled.

For this to work, it requires the mint's Lightning backend to take this fee reserve into account, and fail the payment if the fee that would be paid is higher than the fee reserve. Most Lightning implementations offer two ways to specify this maximum fee amount: a default applied to all payments, and a per-payment option that takes precedence when specified. However, LNBit's API doesn't expose such a per-payment option[6], only a global parameter. This can be seen clearly in the (now removed) pay_invoice method for the LNBits connector in nutshell, where the fee_limit_msat is passed but never used.

It is hence possible for an attacker to steal funds from a mint by withdrawing to a node for which the only route is through another node the attacker controls that requires a high routing fee (one that exceeds nutshell's reserve). The mint pays to the attacker the difference between the fee reserve and the actual fee. Note that even if LNBits doesn't expose a per-payment fee cap, it still has a global cap that is the same for all payments, set using the LNBITS_RESERVE_FEE_PERCENT configuration parameter. This attack can hence be exploited only if the mint operator also sets nutshell's fee cap (LIGHTNING_FEE_PERCENT) to a value that is below LNBits'.

The LNBits backend has since been removed from nutshell[7], and cashu's creator calle explicitly advised to stop using it as a Lightning backend for your mint. For mint operators that don't want to move away from LNBits, floppy suggests to:

  • set nutshell's LIGHTNING_FEE_PERCENT variable, which governs how much the mint will reserve for fee as a percentage, to at least the same value as LNBITS_RESERVE_FEE_PERCENT, which is the variable that LNBits uses to cap how much a payment can pay in fees,
  • set nutshell's LIGHTNING_RESERVE_FEE_MIN to at least 2,000 sats to ensure even very small payments always pay a fee.

Fee siphoning attacks are nothing new. There's a brilliant Reddit post from 5 years ago where Reckless Satoshi (the former maintainer of RoboSats) details how they were able to perform such an attack on various custodial services, and we at LNMarkets were among the ones who learnt at the time. In this particular case, removing LNBits support seems a reasonable answer, since it's the only backend that doesn't support passing a per-payment fee cap, making safety rely solely on operators correctly setting up their mint.

StackerNews Discussion

Quick StrikesQuick Strikes

Bye RustyBye Rusty

Last week was also the last release of Rusty Russell as maintainer in Core Lightning. With his experience, Rusty was objectively pivotal to how well the open Lightning protocol development turned out. Thank you for your incredible work, and fair winds on your new ventures.

StackerNews Discussion | Nostr Note | X Post

–––

That's it for today! Thank you so much for reading this far, and until next week!

  1. Commit 74673df.

  2. Ibid.

  3. Basically, instead of considering a block fully parsed once it's done, bwatch waits on an acknowledgement from lightningd, ensuring the main daemon properly received all the relevant data.

  4. Neutrino-backed nodes behave as light clients when it comes to on-chain data, using BIP157 client-side filtering. They download (typically from other peers) the chain of block headers and the chain of compact filters headers. Like the block headers, the filters headers form a chain (the Nth header references the N-1th), but as the name implies the content is the summary of the corresponding compact filter rather than that of a block. A compact filter typically contains all script public keys that were spent or created in a given block, with the exception of outputs that are known to be unspendable (e.g. OP_RETURNs). The node can validate both header chains, then download each compact filter (one per block) and see (locally) if it contains anything of interest. If so, it can then request the full block corresponding to this specific filter. This design saves a lot of bandwidth while drastically improving privacy.

  5. See LND's docs for more details about data sources and enabling this fast sync mode.

  6. API Docs

  7. Note: this only affects the main branch, and no release have been published yet that contains these changes.

someone made a very cool data visualizer called Lightning Observatory, where you can see nodes, channel opens and updates real time. Pretty cool! StackerNews Discussion ;

Cool site doesn’t work well on mobile.

reply

Yep, node data doesn't even seem to load for me on mobile.

reply