Commit message · Leo NashRewrite `get_available_balances_for_scope` using `tx_builder` functions
We no longer make use of `get_pending_htlc_stats`,
`get_dust_buffer_feerate`, `next_local_commit_tx_fee_msat`, and
`next_remote_commit_tx_fee_msat` in the `channel` module, and instead
make use of tooling from the `tx_builder` module.
`HTLCStats::pending_outbound_htlcs` and
`HTLCStats::pending_outbound_htlcs_value_msat` are now calculated in
`get_available_balances_for_scope`, and do not include outbound HTLCs in
states `AwaitingRemoteRevokeToRemove` and `AwaitingRemovedRemoteRevoke`.
`HTLCStats::pending_inbound_htlcs_value_msat` is now calculated in
`get_available_balances_for_scope`, and does not include inbound HTLCs
in state `LocalRemoved`.
To determine whether a HTLC is dust for the purpose of calculating total
dust exposure, we now refer only to `ChannelContext::feerate_per_kw`,
and ignore any upcoming fee updates stored in `pending_update_fee`.
The same applies for dust exposure due to excess fees; we ignore any fee
updates in `ChannelContext::pending_update_fee`, and only refer to
`ChannelContext::feerate_per_kw`.
For outbound feerate updates, this is ok because all such updates first
get placed in the holding cell. We validate dust exposure again upon
freeing the feerate update from the holding cell, and immediately
generate the corresponding commitment.
For inbound feerate updates, it is possible that the peer sends us a
feerate update that is in excess of our dust exposure limiting feerate,
at the same time that we send non-dust HTLCs that exhaust the max dust
exposure at the new feerate. This leads to a channel force-close when
the peer sends us their commitment signed including the HTLCs and the
new feerate.
Similar to the `HTLCStats` members above, when calculating dust
exposure on both holder and counterparty transactions in
`get_available_balances_for_scope`, we now do not include inbound HTLCs
in states `LocalRemoved`, and outbound HTLCs in states
`AwaitingRemoteRevokeToRemove` and `AwaitingRemovedRemoteRevoke`.
In the case where `is_outbound_from_holder` is true,
`max_reserved_commit_tx_fee_msat` and `min_reserved_commit_tx_fee_msat`
now do not include pending inbound HTLCs in state `LocalRemoved`.
In the case where `is_outbound_from_holder` is false,
`max_reserved_commit_tx_fee_msat` now also includes outbound HTLCs in
the holding cell, and does not include inbound HTLCs in state
`LocalRemoved`.
These fee values are also the result of the feerate getting multiplied
by the fee spike buffer increase multiple, instead of the final
commitment transaction fee getting multiplied by that multiple. This
results in higher values, as we multiply before the rounding down to the
nearest satoshi. This reduces the set of HTLC additions we would send.
Finally, these values also account for any non-dust HTLCs that
transition to dust at the higher feerate, resulting in lower values.
This increases the set of HTLC additions we would send, and previous
versions of LDK will fail only the single HTLC and not the channel in
case we breach their buffer.
85/100 · StrongMessage clarity
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
Why it was queueddefensive validationsigning or wallet pathsecond-pass: near security thresholdsecond-pass: security-sensitive path
AI analysis · Low 45/100This commit rewrites how LDK calculates how much money is available to send in a Lightning channel. It changes which pending payments are counted, how fees are estimated, and how 'dust' (very small) payments are handled. The commit message explicitly notes one risky side effect: under a specific timing of fee updates and HTLCs, the local node may force-close a channel that older LDK versions would have kept open. The change is a refactor with security-relevant behavioral differences, not a clear-cut fix for a known exploit.