We fully implement https://github.com/lightning/bolts/pull/1214 to stop
retransmitting `commit_sig` when our peer has already received it. We
also correctly set `next_commitment_number` to let our peer know whether
we have received their `commit_sig` or not.
We also retransmit `tx_signatures` (and, if requested, `commit_sig`)
after sending `channel_ready` in the 0-conf case. This was missing and
was a bug.
We do not send splice TLVs to peers that do not advertise splice support to avoid an issue with CLN using the splice TLVs for testing the (experimental) channel upgrade feature.
Offers allow a wide range of use-cases and it would be impossible
to cover everything in eclair, which is why we have relied on plugins
to manage offers. However most users will not need advanced
features, and we can handle default offer management that should
work for most users. Advanced users can still use a plugin to manage
more complex offer flows.
Supported use-cases:
- accepting donations
- selling items without inventory management
- compact (non-private) offers using our public node id
- private offers where our identity is protected by a blinded path
When blinded paths are used, the node operators specifies the
introduction node and the number of paths and their length.
Eclair will use its graph data to build payment paths based on
those parameters and add dummy hops / duplicate paths if
necessary.
In order to use opportunistic package relay (with 1-parent-1-child)
we must use confirmed inputs when funding our anchor transactions.
This will also be a requirement when using v3 transactions.
We also take this opportunity to honor the `require_confirmed_inputs`
parameter set by our peer during `interactive-tx`.
When the remote node supports the 'your_last_funding_locked' tlv we do not need to always resend `channel_ready` when there are no channel updates. The tlv removes the ambiguity about whether our last channel_ready was received.
We also changed how init features are computed so that in the testing framework `init` `reachNormal` and `reconnect` can all use the same set of init features defined by the testing tags.
When the `my_current_funding_locked_txid` TLV attribute confirms the latest funding tx we prune previous funding transaction similarly to receiving `splice_locked` from our peer for that txid.
When we receive `your_last_funding_locked_txid` that does not match our latest confirmed funding tx, then we know our peer did not receive our last `splice_locked` and retransmit it. Doing the same for `channel_ready` will be handled in a follow-up PR.
For public channels, nodes also retransmit `splice_locked` after `channel_reestablish` if they have not received `announcement_signatures` for the latest confirmed funding tx. This is needed to prompt our peer to also retransmit their own `splice_locked` and `announcement_signatures`.
For public channels, nodes respond to `splice_locked` with their own `splice_locked` if they have not already sent it since the last `channel_reestablish` - this to prevents exchanging an endless loop of `splice_locked` messages.
These changes ensure nodes have exchanged `splice_locked` (and `announcement_signatures` for public channels) after a disconnect and will be relevant for simple taproot channels to exchange nonces.
If the `your_last_funding_locked` tlv is not set then nodes always send `splice_locked` on reconnect to preserve previous behavior for retransmitting `splice_locked`.
Note: Previous behavior was susceptible to a race condition if one node sent a channel update after `channel_reestablish`, but before receiving `splice_locked` from a peer that had confirmed the latest funding tx while offline.
cf. https://github.com/lightning/bolts/issues/1223
When reconnecting in the Normal state, if a legacy channel does not have its latest remote funding status set to `Locked`, we set and store it to migrate older channels.
After reconnecting in other states, the remote funding status will be set to `Locked` and stored when receiving `channel_ready` or deferred if the node is still waiting for the funding tx to be confirmed locally.
If we've seen the (signed) remote commitment in our mempool, we now
actively favor it instead of trying to publish our local commitment.
It is more interesting to us since it doesn't have any CSV delays
and doesn't require 2nd-stage HTLC transactions.
Now that we've updated to Bitcoin Core 28.1, which supports 1p1c
opportunistic package relay, we should be able to get those remote
commitment transactions confirmed more easily.
Add scripts for taproot channels
These scripts have been generated with miniscript and are different from the ones included in the "simple taproot channels" proposal at e25132d8de.
The `to-revoke-script` is unchanged and not "miniscript compatible", because it includes a NOOP push of the local delayed payment pubkey, which is needed to spend the anchor output once the 16-blocks CSV delay has passed.
When using blinded payment paths, the fees of the blinded path should be paid by the recipient, not the sender.
- It is more fair: the sender chooses the non blinded part of the path and pays the corresponding fees, the recipient chooses the blinded part of the path and pays the corresponding fees.
- It is more private: the sender does not learn the actual fees for the path and can't use this information to unblind the path.
Co-authored-by: t-bast <bastien@acinq.fr>
Codecs shouldn't throw exceptions and should rather return an explicit
`Attempt.Failure` when decoding invalid input. We fix a few codecs that
create public keys to do avoid throwing.
We also wrap onion TLV streams into a `Try`: even though in theory none
of our codecs should throw, since we don't have good enough fuzzing in
place to guarantee that it, it's safer to catch exceptions in case a
codec isn't correctly implemented.
For single-funded channels where we are the funder, we previously only
waited for 1 confirmation before marking the funding transaction as
confirmed. This is fine because we trust ourselves to not double-spend
our own channels.
However, in #2969, we started assigning the `short_channel_id` when we
consider the funding transaction confirmed, and not after 6 blocks. We
thus now risk creating a `short_channel_id` after only 1 confirmation,
which is too early in case a reorg happens. This wouldn't cause loss
of funds because we would create invalid `channel_update`s and the
channel would likely not be usable.
Update Bitcoin Core to v28.x. This releases contains the following
interesting features:
- automatic utxo unlocking on wallet conflicts
- support for testnet4
- 1-parent 1-child package relay (channel force-close)
- `max_tx_weight` parameter to `fundrawtransaction`
We add support for the latest channel closing protocol described in
https://github.com/lightning/bolts/pull/1205. This is a prerequisite
for taproot channels.
We introduce a new `NEGOTIATING_SIMPLE` state where we exchange the
`closing_complete` and `closing_sig` messages, and allow RBF-ing previous
transactions and updating our closing script.
We stay in that state until one of the transactions confirms, or a force
close is detected. This is important to ensure we're able to correctly
reconnect and negotiate RBF candidates.
We keep this separate from the previous `NEGOTIATING` state to make it
easier to remove support for the older mutual close protocols once we're
confident the network has been upgraded.
Before relaying a trampoline payment, we check if the next node is one
of our direct peers. If that's the case, we check their features to see
if they support waking up through notifications, in which case we go
through the wake-up flow.
Note that we don't need this for channel relay, because:
- if it is a Bolt 12 payment, the recipient will use a `wallet_node_id`
to let us know that they support wake-up notifications
- if it is a Bolt 11 payment, we use a custom `short_channel_id` for
phoenix that also lets us know that they support wake-up notifications
We only store information about our peers when we succeed in making an
outgoing connection to them. The only information we stored was the
address that we used when connecting. We now also store the features
supported by our peer when we last connected to them.
Once we have a channel with a peer that connected to us, we store their
details in our DB. We don't store the address they're connecting from,
because we don't know if we will be able to connect to them using this
address, but we store their features.
When a new block is found, we want to check its confirmed transactions
to potentially trigger watches. This is especially important when a
channel is spent and we haven't seen the spending transaction in our
mempool before receiving it in a block. This is already supposed to be
handled through the ZMQ `rawtx` topic, where bitcoind should send us
every transaction it receives (either in the mempool or in a block).
But when using remote `bitcoind` instances, ZMQ seems to sometimes be
unreliable and silently drop some events. That's why we add another
mechanism for extra safety, where whenever a new block is found, we
fetch the last `N` blocks and re-process their transactions. We keep
a cache of the processed blocks to ensure that we don't needlessly
re-process them multiple times.
We were previously using a composite index on both the `channel_id` and
the `commitment_number` in the `htlc_infos` table. This table is used to
store historical HTLC information to be able to publish penalty txs when
a malicious peer publishes a revoked commitment. This table is usually
the largest DB table on nodes that relay a lot of payments, because it
grows with the number of HTLCs received and sent (and only shrinks when
channels are closed or spliced).
Using a composite index makes sense, but leads to increased memory usage
compared to separate indices, thus reducing performance because this is
a table on which we write a lot, but almost never read (only when we
detect a revoked force-close). The read performance doesn't seem to be
negatively impacted anyway when splitting the indices, and the memory
usage is greatly improved.
The migration may take some time depending on the size of the table,
but we cannot get around this.
Thanks to @DerEwige for the performance investigation that lead to
this change (see #2932 for more details).
When using dual-funding, both peers may contribute to the funding amount
and it usually cannot be known ahead of time how much the remote peer
will contribute, which usually leads to underestimating the channel
capacity and thus using a lower `max_htlc_value_in_flight` than what
should be used.
However, when we use liquidity ads, we will:
- contribute to the funding transaction if we're not the opener
- cancel the funding attempt if we're the opener and our peers doesn't
contribute at least the amount we requested
So in that case, we can use a better estimate of the channel capacity
when computing our `max_htlc_value_in_flight`.
This PR:
- uses _outpoints_ instead of _txids_ to track on-chain utxos, the later being insufficient when transactions have more than one output that belongs to us
- prints a detailed diff between two balance checks, by utxos and channels.
A splice tx could involve more than one parent channel. The Router must track the set of channels spent by a given spend tx until either:
1) If it is a splice, then matching channel announcements are received for each parent and the channels are updated in the routing graph.
2) If the spend tx is deeply buried without receiving matching channel announcements for a parent channel, then it can be removed from the routing graph.
If a splice tx spends more than one parent channel between the same nodes, then there's no way to know which new channel announcement corresponds to which parent channel. We simply update the first one found.
By default we sync with every peer when reconnecting, which can be a lot. We now only sync on reconnection with our top peers (by capacity of our shared channels).
We now support splicing on public channels: once the splice transaction
is confirmed and locked on both sides, nodes will exchange announcement
signatures that allows them to create a `channel_announcement` that they
then broadcast to the network.
This requires reworking the data model to include the announcement and
the real `short_channel_id` in each commitment, which lets us cleanly
distinguish real `short_channel_id`s from aliases (which are set at the
channel level regardless of the current commitments).
The flow now becomes:
- when the funding transaction of a commitment confirms, we set the
corresponding real `short_channel_id` in that commitment
- if the channel is public and we've received `channel_ready` or
`splice_locked`, we send our `announcement_signatures`
- if we receive `announcement_signatures` for a commitment for which
the funding transaction is unconfirmed, we stash it and replay it
when the transaction confirms
- if we receive `announcement_signatures` for a confirmed commitment,
and we don't have a more recently announced commitment, we generate
a `channel_announcement`, store it with the commitment and update
our router data
When creating a `channel_update` for a public channel, we always use
the `short_channel_id` that matches the latest announcement we created.
This is very important to guarantee that nodes receiving our updates
will not discard them because they cannot match it to a channel.
For private channels, we stop allowing usage of the `short_channel_id`
for routing: `scid_alias` MUST be used, which ensures that the channel
utxo isn't revealed.
Note that when migrating to taproot channels, `splice_locked` will be
used to transmit nonces for the announcement signatures, which will be
compatible with the existing flow (and similarly, `channel_ready` will
be used for the initial funding transaction). They are retransmitted
on reconnection to ensure that the announcements can be generated.
Now that we wait for at least 6 confirmations before considering a
channel confirmed, we can simplify our channel announcement logic.
Whenever a channel reaches the confirmed state, it can be announced
to the network (if nodes wish to announce it). We thus don't need
the "deeply buried" state and the "temporary" scid anymore.
The logic is much simpler to follow: when the channel confirms, we
internally update the real scid to match the confirmed funding tx
and send our `announcement_signatures`. When we receive our peer's
`announcement_signatures`, we stash them if the funding tx doesn't
have enough confirmations yet, otherwise we announce the channel and
create a new `channel_update` that uses the real scid.
Whenever we create a `channel_update`, we simply look at whether the
channel is announced or not to choose which scid to use.
This will make it much simpler to announce splice transactions, which
don't need a "deeply buried" state either and will instead simply rely
on whether the splice transaction is confirmed or not to generate
`announcement_signatures`.
* Verify maven dependency checksums
Maven build process will compute checksums for our dependencies and verify them against a local "trusted checksums" file, and fail the build if they do not match. This process is local and independent of checksums stored and downloaded from maven repositories.
SNAPSHOT dependencies are not verified (but released versions should never depend on SNAPSHOT dependencies).
* Allow funding without locks for liquidity griefing
When using liquidity ads, seller nodes may be vulnerable to liquidity
griefing attacks. They may disable utxo locking to protect against such
attacks, but the trade-off is that honest peers may also be affected by
having their funding transaction double-spent.
We thus expose a configuration flags to let node operators decide which
trade-off they choose, depending on how likely they think someone will
target them vs the UX they want to provide to their customers.
* Abort incoming channel after timeout
If a remote node starts opening a channel to us and then becomes
unresponsive, we abort the channel. This is particularly useful
when they're purchasing liquidity and we've locked utxos.
We previously handled `recommended_feerates` in our `whenUnhandled`
handler, but that doesn't work since we have a catch-all handler in
the `CONNECTED` state for all known lightning messages. We thus move
this handler into the `CONNECTED` state to avoid warnings in the logs.
* Watch explicit event for channel actor termination
We use an explicit event in the `Peer` when watching for child channel
actors being terminated. This should get rid of the warnings in the logs
about the `Terminated` event not being handled, or at least provide us
more hints of which actors aren't properly being tracked.
* Fix disconnect response in channel actors
We weren't watching for the right event, which creates a lot of log
lines saying that the `Disconnecting` event is unhandled.
* Ignore closing negotiation if closing or closed
If we receive an outdated closing message, we ignore it without creating
a warning in the logs.
* Ignore HTLC settlement commands while disconnected
We ignore HTLC settlement commands while we're disconnected, they will
be retried once the channel has been reestablished. We also ignore
commands asking us to sign the latest state or update fees.
* Get ready to store partial signatures
We currently store our peer's signature for our remote commit tx, so we can publish it if needed.
If we upgrade funding tx to use musig2 instead of multisig 2-of-2 we will need to store a partial signature instead.
For this, we add specific types for standard signature (64 bytes) and musig2 partial signatures + nonce.