Skip to content

Commit e8c0a63

Browse files
committed
contractcourt+lnwallet: move aux close finalization to chain watcher
We now execute the aux chan closer finalization within the chain watcher. This is better as we don't need to rely on the remote party being online and sending us a message. Instead we do the finalization once the on-chain transaction has been confirmed.
1 parent 58fae7d commit e8c0a63

File tree

2 files changed

+79
-27
lines changed

2 files changed

+79
-27
lines changed

contractcourt/chain_watcher.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,74 @@ func (c *chainWatcher) toSelfAmount(tx *wire.MsgTx) btcutil.Amount {
998998
return btcutil.Amount(fn.Sum(vals))
999999
}
10001000

1001+
// finalizeCoopClose calls the aux closer to finalize a cooperative close
1002+
// transaction that has been confirmed on-chain.
1003+
func (c *chainWatcher) finalizeCoopClose(aux AuxChanCloser,
1004+
closeTx *wire.MsgTx) error {
1005+
1006+
chanState := c.cfg.chanState
1007+
1008+
// Get the shutdown info to extract the local delivery script.
1009+
shutdown, err := chanState.ShutdownInfo()
1010+
if err != nil {
1011+
return fmt.Errorf("get shutdown info: %w", err)
1012+
}
1013+
1014+
// Build the AuxShutdownReq.
1015+
req := types.AuxShutdownReq{
1016+
ChanPoint: chanState.FundingOutpoint,
1017+
ShortChanID: chanState.ShortChanID(),
1018+
Initiator: chanState.IsInitiator,
1019+
CommitBlob: chanState.LocalCommitment.CustomBlob,
1020+
FundingBlob: chanState.CustomBlob,
1021+
}
1022+
1023+
// Shutdown info must be present in order to continue.
1024+
if shutdown.IsNone() {
1025+
return fmt.Errorf("failed to finalize coop close, shutdown " +
1026+
"info missing")
1027+
}
1028+
1029+
// Extract close outputs from the transaction. We need to identify
1030+
// which outputs belong to local vs remote parties.
1031+
var localCloseOutput, remoteCloseOutput fn.Option[types.CloseOutput]
1032+
1033+
// Get the delivery scripts for the local party.
1034+
var localDeliveryScript lnwire.DeliveryAddress
1035+
shutdown.WhenSome(func(s channeldb.ShutdownInfo) {
1036+
localDeliveryScript = s.DeliveryScript.Val
1037+
})
1038+
1039+
// Scan through the close transaction outputs to identify local and
1040+
// remote outputs.
1041+
for _, out := range closeTx.TxOut {
1042+
if len(localDeliveryScript) > 0 &&
1043+
slices.Equal(out.PkScript, localDeliveryScript) {
1044+
1045+
localCloseOutput = fn.Some(types.CloseOutput{
1046+
Amt: btcutil.Amount(out.Value),
1047+
PkScript: out.PkScript,
1048+
DustLimit: chanState.LocalChanCfg.DustLimit,
1049+
})
1050+
} else {
1051+
// This must be the remote output.
1052+
remoteCloseOutput = fn.Some(types.CloseOutput{
1053+
Amt: btcutil.Amount(out.Value),
1054+
PkScript: out.PkScript,
1055+
DustLimit: chanState.RemoteChanCfg.DustLimit,
1056+
})
1057+
}
1058+
}
1059+
1060+
desc := types.AuxCloseDesc{
1061+
AuxShutdownReq: req,
1062+
LocalCloseOutput: localCloseOutput,
1063+
RemoteCloseOutput: remoteCloseOutput,
1064+
}
1065+
1066+
return aux.FinalizeClose(desc, closeTx)
1067+
}
1068+
10011069
// dispatchCooperativeClose processed a detect cooperative channel closure.
10021070
// We'll use the spending transaction to locate our output within the
10031071
// transaction, then clean up the database state. We'll also dispatch a
@@ -1048,6 +1116,17 @@ func (c *chainWatcher) dispatchCooperativeClose(commitSpend *chainntnfs.SpendDet
10481116
ChannelCloseSummary: closeSummary,
10491117
}
10501118

1119+
// If we have an aux closer, finalize the cooperative close now that
1120+
// it's confirmed.
1121+
err = fn.MapOptionZ(
1122+
c.cfg.auxCloser, func(aux AuxChanCloser) error {
1123+
return c.finalizeCoopClose(aux, broadcastTx)
1124+
},
1125+
)
1126+
if err != nil {
1127+
return fmt.Errorf("finalize coop close: %w", err)
1128+
}
1129+
10511130
// With the event processed, we'll now notify all subscribers of the
10521131
// event.
10531132
c.Lock()

lnwallet/chancloser/chancloser.go

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -974,33 +974,6 @@ func (c *ChanCloser) ReceiveClosingSigned( //nolint:funlen
974974
}
975975
c.closingTx = closeTx
976976

977-
// If there's an aux chan closer, then we'll finalize with it
978-
// before we write to disk.
979-
err = fn.MapOptionZ(
980-
c.cfg.AuxCloser, func(aux AuxChanCloser) error {
981-
channel := c.cfg.Channel
982-
//nolint:ll
983-
req := types.AuxShutdownReq{
984-
ChanPoint: c.chanPoint,
985-
ShortChanID: c.cfg.Channel.ShortChanID(),
986-
InternalKey: c.localInternalKey,
987-
Initiator: channel.IsInitiator(),
988-
CommitBlob: channel.LocalCommitmentBlob(),
989-
FundingBlob: channel.FundingBlob(),
990-
}
991-
desc := types.AuxCloseDesc{
992-
AuxShutdownReq: req,
993-
LocalCloseOutput: c.localCloseOutput,
994-
RemoteCloseOutput: c.remoteCloseOutput,
995-
}
996-
997-
return aux.FinalizeClose(desc, closeTx)
998-
},
999-
)
1000-
if err != nil {
1001-
return noClosing, err
1002-
}
1003-
1004977
// Before publishing the closing tx, we persist it to the
1005978
// database, such that it can be republished if something goes
1006979
// wrong.

0 commit comments

Comments
 (0)