@@ -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 ()
0 commit comments