Skip to content

Fix simple close checks - #9417

Open
rustyrussell wants to merge 5 commits into
ElementsProject:masterfrom
rustyrussell:guilt/fix-simple-close-checks
Open

Fix simple close checks#9417
rustyrussell wants to merge 5 commits into
ElementsProject:masterfrom
rustyrussell:guilt/fix-simple-close-checks

Conversation

@rustyrussell

Copy link
Copy Markdown
Collaborator

It's still an experimental option, but two fixes:

  1. Get lightningd to be more thorough in checking the tx. In particular, make sure it pays us! This was caught by an LLM.
  2. Don't save their closing tx as canonical. We checked it was well-formed, but it could be super low-fee, so only use ours as the "last_tx".

The first was found by our internal LLM-assisted scanning. The second was found by me when fixing the first.

And fix prototypes which caused mocks to break.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
@rustyrussell
rustyrussell force-pushed the guilt/fix-simple-close-checks branch from cf1ed1e to a558e14 Compare August 14, 2026 02:06
We're going to need it if lightningd wants to double-check the tx
it gets from simpleclosed.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
From lightningd's perspective, there are two messages:
1. We got a signature on our closing tx.
2. We got a signature on their closing tx.

The closer/closee naming is confusing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
simpleclosed checks it, but for thoroughness (and to prevent bugs and
avoid any potential exploits in it) we need to check it too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
We want our own closing tx, but theirs might be too low-fee to use.

Broadcast it, as a courtesy, but don't *rely* on it!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: `experimental-simple-close` now doesn't save peer's closing transaction, so it can't be stuck with a too-low-fee tx.
@rustyrussell
rustyrussell force-pushed the guilt/fix-simple-close-checks branch from a558e14 to 8e22298 Compare August 14, 2026 02:09
@madelinevibes
madelinevibes requested a review from Andezion August 21, 2026 11:08
Comment thread tests/test_closing.py
# find both in any order rather than two sequential wait_for_log calls.
l1.daemon.wait_for_logs(['Simple close: stored closer tx',
'Simple close: stored closee tx'])
'Simple close: broadcast closee tx'])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As i see simple_close_control.c now logs "Simple close: stored our tx" and "Simple close: broadcast their tx". And test_simple_close_closee_only below, at line 4424 and 4426 got the rename right


const char *err = close_tx_check(tmpctx, channel, tx);
const char *err = close_tx_check(tmpctx, channel, tx,
feerate_for_close(channel));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feerate_for_close() is called here to derive max_feerate_wepay, but it's also called once earlier in peer_start_simpleclosed() to set the feerate that simpleclosed actually builds the tx with. Between those two calls, mutual_close_feerate() can change - update_feerates runs on a timer independent of blocks (poll_seconds defaults to 30s), and peer_start_simpleclosed isnt re-invoked while we're waiting on the peers closing_sig. Should the actual feerate used by simpleclosed be passed back through the wire message instead of recomputed here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants