Skip to content

router: Use aggregate capacity for first-hop fragmentation check#2

Open
martinsaposnic wants to merge 1 commit intolsp-0.1.8from
first-hop-aggregate-fragmentation-check
Open

router: Use aggregate capacity for first-hop fragmentation check#2
martinsaposnic wants to merge 1 commit intolsp-0.1.8from
first-hop-aggregate-fragmentation-check

Conversation

@martinsaposnic
Copy link

The routing fragmentation mitigation heuristic requires each channel to contribute at least payment_amount / max_path_count to avoid excessive path splitting. This makes sense for network paths where each additional path incurs base fees and increases failure probability.

However, for first hops this is overly restrictive. Multiple channels to the same peer converge immediately at the first hop - there's no actual network-level fragmentation. A 2M sat channel and a 48M sat channel to the same peer should be usable together for a 50M sat payment, but currently the small channel gets rejected (threshold would be 5M sat with default max_path_count=10), leaving only 48M available.

This change checks the aggregate capacity across all first-hop channels to a peer. If the aggregate meets the contribution threshold, individual channels are allowed regardless of their size.

The routing fragmentation mitigation heuristic requires each channel to
contribute at least `payment_amount / max_path_count` to avoid excessive
path splitting. This makes sense for network paths where each additional
path incurs base fees and increases failure probability.

However, for first hops this is overly restrictive. Multiple channels to
the same peer converge immediately at the first hop - there's no actual
network-level fragmentation. A 2M sat channel and a 48M sat channel to
the same peer should be usable together for a 50M sat payment, but
currently the small channel gets rejected (threshold would be 5M sat
with default max_path_count=10), leaving only 48M available.

This change checks the aggregate capacity across all first-hop channels
to a peer. If the aggregate meets the contribution threshold, individual
channels are allowed regardless of their size.
amackillop pushed a commit that referenced this pull request Mar 18, 2026
When the counterparty initiates an RBF and we have no new contribution
queued via QuiescentAction, we must re-use our prior contribution so
that our splice is not lost. Track contributions in a new field on
PendingFunding so the last entry can be re-used in this scenario.

Each entry stores the feerate-adjusted version because that reflects
what was actually negotiated and allows correct feerate re-adjustment
on subsequent RBFs. Only explicitly provided contributions (from a
QuiescentAction) append to the vec. Re-used contributions are replaced
in-place with the version adjusted for the new feerate so they remain
accurate for further RBF rounds, without growing the vec.

Add test_splice_rbf_acceptor_recontributes to verify that when the
counterparty initiates an RBF and we have no new QuiescentAction
queued, our prior contribution is automatically re-used so the splice
is preserved.

Add test_splice_rbf_recontributes_feerate_too_high to verify that when
the counterparty RBFs at a feerate too high for our prior contribution
to cover, the RBF is rejected rather than proceeding without our
contribution.

Add test for sequential RBF splice attempts

Add test_splice_rbf_sequential that exercises three consecutive RBF
rounds on the same splice (initial → RBF #1 → RBF #2) to verify:
- Each round requires the 25/24 feerate increase (253 → 264 → 275)
- DiscardFunding events reference the correct funding txid from each
  replaced candidate
- The final RBF splice can be mined and splice_locked successfully

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant