openingd: fail open_channel at receipt when both initial balances <= their reserve - #9480
Open
Amperstrand wants to merge 1 commit into
Open
Conversation
…their reserve BOLT ElementsProject#2 requires the receiving node to fail the channel if both to_local and to_remote of the initial commitment transaction are <= the opener's channel_reserve_satoshis (a receiving-node MUST under open_channel receipt handling). CLN implements the comparison, but in initial_commit_tx() (common/initial_commit_tx.c, whose FIXME says it should be in ElementsProject#2), so it only fires at funding_created receipt -- after accept_channel has already gone out. Project the initial balances at open_channel receipt (funder to_local = funding - push - base fee - 2x330 anchor outputs; accepter to_remote = push) and fail the negotiation before accept_channel is sent, using the same fee math as initial_commit_tx() (commit_tx_base_fee + the 660-sat anchor correction). The misplaced check stays as the authoritative backstop at funding_created. An in-suite test would need a raw-wire opener: a stock fundchannel reserve is pre-checked with the reserve doubled ('Not opening because if they used the same setting as us ... below 10000sat'), which blocks every shape that trips this check. Validated with a BOLT8 wire peer driving the reporter's exact parameters (100k funding, 20k push, 87k reserve: pre-fix accept_channel, post-fix rejection citing the projected balances 78778000msat / 20000000msat). Changelog-Fixes: ElementsProject#9475 Fixes: ElementsProject#9475
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BOLT #2 requires the receiving node to fail the channel if both
to_localandto_remoteof the initial commitment transaction are<= the opener's
channel_reserve_satoshis— a receiving-node MUSTunder
open_channelreceipt handling, not a generalchannel-establishment rule. CLN implements the comparison, but in
initial_commit_tx()(common/initial_commit_tx.c, whose FIXME saysit should be in #2), so it only fires at
funding_createdreceipt —after
accept_channelhas already gone out (#9475).This projects the initial balances at
open_channelreceipt (funderto_local= funding − push − base fee − 2×330 anchor outputs; accepterto_remote= push) and fails the negotiation beforeaccept_channelis sent, using the same fee math as
initial_commit_tx()(
commit_tx_base_fee+ the 660-sat anchor correction).Notes for reviewers:
initial_commit_tx()check stays: it remains theauthoritative backstop at
funding_created, and covers the funderside's own construction.
fundchannelreserve is pre-checked with the reserve doubled ("Not opening
because if they used the same setting as us channel capacity with
funding 100000sat, reserves 44000sat/44000sat, … channel capacity is
9935sat, which is below 10000sat" on the reporter's 100k funding;
43000sat passes), which blocks every shape that trips this check. I
validated with a ~300-line BOLT8 wire peer (noise-XK initiator,
spec-vector-pinned) driving the reporter's exact parameters instead:
pre-fix
accept_channel, post-fix rejection citing the projectedbalances (78778000msat / 20000000msat); boundary shifts
86,100→77,092 at feerate 2000 and the static_remotekey (724-weight)
path lands at 78,551/78,552, both exactly on the projection. The complete wire-peer source, per-cell results, and boundary math are in this gist: https://gist.github.com/Amperstrand/c2078688f93800cf7723cad2670c8044
balance below reserve) still lock in spendable-zero channels — that
is spec-legal (only the MAY "considers
channel_reserve_satoshistoo large" would catch it); a follow-up could discuss a cap like
lnd's 20%-of-capacity bound (lnwallet/reservation.go:
channelCapacity / 5) or eclair'smax-reserve-to-funding-ratio = 0.05.reporter's exact params, pre- vs post-fix wire (v26.06.7) — expand
boundary shift at feerate 2000 — anchors and static_remotekey paths both land on the BOLT3 projection — expand
Fixes #9475