lnwallet/chancloser: record the remote close output only when accepted

In this commit, we hold off on recording the remote party's close output until
we've decided we can act on their Shutdown. ReceiveShutdown wrote the field
before it looked at the state, so a Shutdown that arrives at a point where we
have nothing to do with it, say once we've already finished the negotiation,
would still overwrite the output we settled on before being turned away with
ErrInvalidState. The output we report for the close then describes a message we
rejected.

Nothing acts on this today, as we hand the outputs to the caller only after
ClosingTx tells it the negotiation finished, but the field is what we report to
the party that asked for the close, so we may as well only fill it in from a
message we accepted.
This commit is contained in:
Olaoluwa Osuntokun 2026-08-04 15:49:26 -07:00 committed by ziggie
parent 2ca05213a2
commit 84ddced2b5
No known key found for this signature in database
GPG key ID: 1AFF9C4DCED6D666

View file

@ -593,10 +593,13 @@ func (c *ChanCloser) ReceiveShutdown(msg lnwire.Shutdown) (
noShutdown := fn.None[lnwire.Shutdown]()
// We'll track their remote close output, even if it's dust in BTC
// terms, it might still carry value in custom channel terms.
// terms, it might still carry value in custom channel terms. We only
// commit it to our state in the branches below that go on to accept the
// message: a Shutdown that shows up at a point where we can't act on it
// has no business overwriting an output we already settled on.
_, dustAmt := c.cfg.Channel.RemoteBalanceDust()
_, remoteBalance := c.cfg.Channel.CommitBalances()
c.remoteCloseOutput = fn.Some(CloseOutput{
remoteCloseOutput := fn.Some(CloseOutput{
Amt: remoteBalance,
DustLimit: dustAmt,
PkScript: msg.Address,
@ -643,6 +646,7 @@ func (c *ChanCloser) ReceiveShutdown(msg lnwire.Shutdown) (
// address. We'll use this when we craft the closure
// transaction.
c.remoteDeliveryScript = msg.Address
c.remoteCloseOutput = remoteCloseOutput
// We'll generate a shutdown message of our own to send across
// the wire.
@ -692,6 +696,7 @@ func (c *ChanCloser) ReceiveShutdown(msg lnwire.Shutdown) (
// address, we'll record their preferred delivery closing
// script.
c.remoteDeliveryScript = msg.Address
c.remoteCloseOutput = remoteCloseOutput
// At this point, we can now start the fee negotiation state, by
// constructing and sending our initial signature for what we