In adb0afc523 we started raising
bucket weights to the power four in the historical model. This
improved our model's accuracy greatly, but resulted in a much
larger `total_valid_points_tracked`. In the same commit we
converted `total_valid_points_tracked` to a float, but retained the
64-bit integer math to build it out of integer bucket values.
Sadly, 64 bits are not enough to sum 1024 bucket pairs of 16-bit
integers multiplied together and then squared (we need 16*4 + 10 =
74 bits to avoid overflow). Thus, here we replace the summation
with 128-bit integers.
rustfmt blows up `where` clauses even for trivial lines, so we
should generally avoid them where possible. Here we remove some
extra ones from `wire.rs`.
This test checks to a 1msat precision the accounting of dust exposure
due to excess fees on counterparty commmitment and htlc transactions,
for both inbound and outbound htlcs.
The payments in this test previously failed for reasons other
than exhausting the dust exposure limit with excess fees. Upon payment
failures, we now check the logs to assert failures due to dust
exposure exhaustion.
Previously, we calculated the fee of the commitment transaction with n
htlcs, and the fee due to the candidate htlc, rounded the two fees to
the lower satoshi, and then summed the fees. This is not equal to how
fees of commitment transactions are calculated, which is to add up the
total weight of the (n+1) htlc commitment transaction, convert to fee,
then round to the lower satoshi.
This commit corrects this delta by running the full fee calculation
twice, once for the n htlc, and once for the (n+1) htlc counterparty
commitment transactions.
Previously, `get_pending_htlc_stats` did not account for the inbound
htlc because `can_accept_incoming_htlc` was called before the htlc was
irrevocably committed. But after commit d8d9dc7,
`can_accept_incoming_htlc` is called only when the htlc is irrevocably
committed, hence `get_pending_htlc_stats` does account for the inbound
htlc.
Nonetheless, in the case of a non-dust htlc, our calculation of the
counterparty tx dust exposure still assumed that
`get_pending_htlc_stats` did not account for the inbound htlc, causing
us to add the dust exposure due to that inbound htlc twice. This commit
removes this extra sum.
Since new updates are not allowed during quiescence (local updates enter
the holding cell), we want to ensure quiescence eventually terminates if
the handshake takes too long or our counterparty is uncooperative.
Disconnecting implicitly terminates quiescence, so the holding cell can
be freed upon re-establishing the channel (assuming quiescence is not
requested again).
With the introduction of `has_pending_channel_update`, we can now
determine whether any messages are owed to irrevocably commit HTLC
updates based on the current channel state. We prefer using the channel
state, over manually tracking as previously done, to have a single
source of truth. We also gain the ability to expect to receive multiple
messages at once, which will become relevant with the quiescence
protocol, where we may be waiting on a counterparty `revoke_and_ack` and
`stfu`.
We previously would avoid freeing our holding cells upon a
`revoke_and_ack` if a monitor update was in progress, which we checked
explicitly. With quiescence, if we've already sent `stfu`, we're not
allowed to make further commitment updates, so we must also avoid
freeing our holding cells in such cases.
Along the way, we also remove the special handling of in-progress
monitor updates now that it behaves the same as the handling of being
quiescent.
Quiescence is a new protocol feature that allows for channels to undergo
"fundamental" changes (i.e., protocol upgrade) while there are no
pending updates on either side. Its first use case will be to carry out
channel splices, to ensure new HTLC/fee updates are not made while a
splice is being negotiated.
Each side of the channel is allowed to send a `stfu` message if any of
their outbound updates are not pending for either side (i.e.,
irrevocably committed on both commitment transactions). Once both sides
exchange `stfu`, the channel becomes quiescent. A message timeout is
enforced during the quiescence handshake to ensure we can eventually
re-establish the channel and propose new HTLC/fee updates again.
Several new state flags have been added to `ChannelState::ChannelReady`
to track the progress of the quiescence handshake. Once the channel
becomes quiescent, all flags related to the handshake are cleared, and
the `QUIESCENT` flag is enabled. While quiescence is not a persistent
protocol (it implicitly terminates upon peer disconnection), and updates
cannot be made, we still need to track `MONITOR_UPDATE_IN_PROGRESS` as
it may be required by the quiescence-dependent protocol, like in the
case of splicing.
The existing `ChannelError::Warn` variant only sends the warning and
does not disconnect. There are certain cases where we want to just send
a warning, and other cases where we want to also disconnect, so we
keep both variants around.
For Trampoline, we'll need to keep track of both the outer and inner
onion's shared secrets. To this end, we're moving the secret
calculation inside `decode_next_payment_hop` such that, when applicable,
it can return both.
This commit introduces a config override struct parameter to the
accept_inbound_channel methods. With manual channel acceptance enabled,
users can modify the default configuration as needed.
This change defines anchor reserve requirements by calculating weights
and fees for the transactions that need to be confirmed on-chain in the
event of a unilateral closure. The calculation is given a set of
parameters as input, including the expected fee rate and number of
in-flight HTLCs.
When establishing a channel, the funding transaction may be replaced
either:
- after the funding transaction has confirmed using splicing,
- before the funding transaction has confirmed for v2 channel
establishment using tx_init_rbf, or
- before the splice's funding transaction has confirmed using
tx_init_rbf.
In each of these cases, fields in ChannelContext will need to be updated
once the funding transaction confirms. Additionally, the same fields for
a pending attempt may need to be considered instead of a previously
confirmed funding.
This commit introduces a FundingScope to hold the aforementioned fields.
It lives next to ChannelContext and will be needed whenever these fields
are accessed. The next few commits will move the relevant fields to
FundingScope and provide access to them whenever needed, allowing to
swap in another FundingScope when necessary.
This test ensures that PeerStorage & PeerStorageRetrieval handling behaves as expected. It simulates
receiving a dummy peer storage message, disconnecting and reconnecting peers, and
validates that the correct messages are exchanged during reestablishment.
- Added a test case `test_peer_storage` to verify the handling of `PeerStorageMessage`
and the validation of warning messages in the event of invalid peer storage retrieval.
- Simulated peer storage retrieval upon reconnection between nodes.
- Validated that a warning message is generated when `PeerStorageRetrievalMessage`
is received.
- Ensured the warning message contains the expected error description.
This commit introduces the handling and persistence of PeerStorage messages on a per-peer basis.
The peer storage is stored within the PeerState to simplify management, ensuring we do not need to remove it
when there are no active channels with the peer.
Key changes include:
- Add PeerStorage to PeerState for persistent storage.
- Implement internal_peer_storage to manage PeerStorage and its updates.
- Add resend logic in peer_connected() to resend PeerStorage before sending the channel reestablish message upon reconnection.
- Update PeerState's write() and read() methods to support PeerStorage persistence.
Introduce message types and handlers to enable the exchange of peer storage data between nodes.
PeerStorageMessage: Used to send encrypted backups to peers.
PeerStorageRetrievalMessage: Used to return a peer's stored data upon reconnection.
- Define two new message types: PeerStorageMessage and PeerStorageRetrievalMessage.
- Implement handlers for these messages in ChannelMessageHandler.
- Add SendPeerStorageMessage and SendPeerStorageRetrievalMessage to MessageSendEvent.
Introduce the 'ProvideStorage' feature to enable nodes to distribute
and store peer storage backups for channel partners. This functionality enhances
resilience by ensuring critical peer data is backed up and can be retrieved if needed.
- Added 'ProvideStorage' to the 'InitContext' & 'NodeContext'.
- Set feature bit for this feature inside 'provide_init_features()'
Now that each `InboundOnionPayload` variant corresponds to its own
struct, we can reference these same types inside `Hop` and thereby
avoid nesting that allowed invalid combinations, and instead store
supplemental data as each variant calls for.