@@ -3,6 +3,7 @@ package contractcourt
33import (
44 "bytes"
55 "fmt"
6+ "slices"
67 "sync"
78 "sync/atomic"
89 "time"
@@ -16,8 +17,10 @@ import (
1617 "github.com/davecgh/go-spew/spew"
1718 "github.com/lightningnetwork/lnd/chainntnfs"
1819 "github.com/lightningnetwork/lnd/channeldb"
20+ "github.com/lightningnetwork/lnd/fn"
1921 "github.com/lightningnetwork/lnd/input"
2022 "github.com/lightningnetwork/lnd/lnwallet"
23+ "github.com/lightningnetwork/lnd/lnwire"
2124)
2225
2326const (
@@ -970,28 +973,67 @@ func (c *chainWatcher) handleUnknownRemoteState(
970973}
971974
972975// toSelfAmount takes a transaction and returns the sum of all outputs that pay
973- // to a script that the wallet controls. If no outputs pay to us, then we
976+ // to a script that the wallet controls or the channel defines as its delivery
977+ // script . If no outputs pay to us (determined by these criteria), then we
974978// return zero. This is possible as our output may have been trimmed due to
975979// being dust.
976980func (c * chainWatcher ) toSelfAmount (tx * wire.MsgTx ) btcutil.Amount {
977- var selfAmt btcutil.Amount
978- for _ , txOut := range tx .TxOut {
981+ // There are two main cases we have to handle here. First, in the coop
982+ // close case we will always have saved the delivery address we used
983+ // whether it was from the upfront shutdown, from the delivery address
984+ // requested at close time, or even an automatically generated one. All
985+ // coop-close cases can be identified in the following manner:
986+ shutdown , _ := c .cfg .chanState .ShutdownInfo ()
987+ oDeliveryAddr := fn .MapOption (
988+ func (i channeldb.ShutdownInfo ) lnwire.DeliveryAddress {
989+ return i .DeliveryScript .Val
990+ })(shutdown )
991+
992+ // Here we define a function capable of identifying whether an output
993+ // corresponds with our local delivery script from a ShutdownInfo if we
994+ // have a ShutdownInfo for this chainWatcher's underlying channel.
995+ //
996+ // isDeliveryOutput :: *TxOut -> bool
997+ isDeliveryOutput := func (o * wire.TxOut ) bool {
998+ return fn .ElimOption (
999+ oDeliveryAddr ,
1000+ // If we don't have a delivery addr, then the output
1001+ // can't match it.
1002+ func () bool { return false },
1003+ // Otherwise if the PkScript of the TxOut matches our
1004+ // delivery script then this is a delivery output.
1005+ func (a lnwire.DeliveryAddress ) bool {
1006+ return slices .Equal (a , o .PkScript )
1007+ },
1008+ )
1009+ }
1010+
1011+ // Here we define a function capable of identifying whether an output
1012+ // belongs to the LND wallet. We use this as a heuristic in the case
1013+ // where we might be looking for spendable force closure outputs.
1014+ //
1015+ // isWalletOutput :: *TxOut -> bool
1016+ isWalletOutput := func (out * wire.TxOut ) bool {
9791017 _ , addrs , _ , err := txscript .ExtractPkScriptAddrs (
9801018 // Doesn't matter what net we actually pass in.
981- txOut .PkScript , & chaincfg .TestNet3Params ,
1019+ out .PkScript , & chaincfg .TestNet3Params ,
9821020 )
9831021 if err != nil {
984- continue
1022+ return false
9851023 }
9861024
987- for _ , addr := range addrs {
988- if c .cfg .isOurAddr (addr ) {
989- selfAmt += btcutil .Amount (txOut .Value )
990- }
991- }
1025+ return fn .Any (c .cfg .isOurAddr , addrs )
9921026 }
9931027
994- return selfAmt
1028+ // Grab all of the outputs that correspond with our delivery address
1029+ // or our wallet is aware of.
1030+ outs := fn .Filter (fn .PredOr (isDeliveryOutput , isWalletOutput ), tx .TxOut )
1031+
1032+ // Grab the values for those outputs.
1033+ vals := fn .Map (func (o * wire.TxOut ) int64 { return o .Value }, outs )
1034+
1035+ // Return the sum.
1036+ return btcutil .Amount (fn .Sum (vals ))
9951037}
9961038
9971039// dispatchCooperativeClose processed a detect cooperative channel closure.
0 commit comments