mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-26 01:33:02 +01:00
contractcourt: consider delivery addresses when evaluating toSelfAmount
This commit fixes #8535 by changing how we assess toSelfAmount inside the chainWatcher. In certain cases users may wish to close out channel funds to external delivery addresses set either during open or close. Prior to this change we only consider addresses that our wallet is aware of. This change now identifies outputs as to_self outputs if the delivery script matches OR if our wallet is aware of the address. In certain edge cases it can be possible for there to be more than one output that matches these criteria and in that case we will return the sum of those values.
This commit is contained in:
parent
56048133f2
commit
30e10322b2
@ -3,6 +3,7 @@ package contractcourt
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@ -16,8 +17,10 @@ import (
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -970,28 +973,67 @@ func (c *chainWatcher) handleUnknownRemoteState(
|
||||
}
|
||||
|
||||
// toSelfAmount takes a transaction and returns the sum of all outputs that pay
|
||||
// to a script that the wallet controls. If no outputs pay to us, then we
|
||||
// to a script that the wallet controls or the channel defines as its delivery
|
||||
// script . If no outputs pay to us (determined by these criteria), then we
|
||||
// return zero. This is possible as our output may have been trimmed due to
|
||||
// being dust.
|
||||
func (c *chainWatcher) toSelfAmount(tx *wire.MsgTx) btcutil.Amount {
|
||||
var selfAmt btcutil.Amount
|
||||
for _, txOut := range tx.TxOut {
|
||||
_, addrs, _, err := txscript.ExtractPkScriptAddrs(
|
||||
// Doesn't matter what net we actually pass in.
|
||||
txOut.PkScript, &chaincfg.TestNet3Params,
|
||||
)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// There are two main cases we have to handle here. First, in the coop
|
||||
// close case we will always have saved the delivery address we used
|
||||
// whether it was from the upfront shutdown, from the delivery address
|
||||
// requested at close time, or even an automatically generated one. All
|
||||
// coop-close cases can be identified in the following manner:
|
||||
shutdown, _ := c.cfg.chanState.ShutdownInfo()
|
||||
oDeliveryAddr := fn.MapOption(
|
||||
func(i channeldb.ShutdownInfo) lnwire.DeliveryAddress {
|
||||
return i.DeliveryScript.Val
|
||||
})(shutdown)
|
||||
|
||||
for _, addr := range addrs {
|
||||
if c.cfg.isOurAddr(addr) {
|
||||
selfAmt += btcutil.Amount(txOut.Value)
|
||||
}
|
||||
}
|
||||
// Here we define a function capable of identifying whether an output
|
||||
// corresponds with our local delivery script from a ShutdownInfo if we
|
||||
// have a ShutdownInfo for this chainWatcher's underlying channel.
|
||||
//
|
||||
// isDeliveryOutput :: *TxOut -> bool
|
||||
isDeliveryOutput := func(o *wire.TxOut) bool {
|
||||
return fn.ElimOption(
|
||||
oDeliveryAddr,
|
||||
// If we don't have a delivery addr, then the output
|
||||
// can't match it.
|
||||
func() bool { return false },
|
||||
// Otherwise if the PkScript of the TxOut matches our
|
||||
// delivery script then this is a delivery output.
|
||||
func(a lnwire.DeliveryAddress) bool {
|
||||
return slices.Equal(a, o.PkScript)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return selfAmt
|
||||
// Here we define a function capable of identifying whether an output
|
||||
// belongs to the LND wallet. We use this as a heuristic in the case
|
||||
// where we might be looking for spendable force closure outputs.
|
||||
//
|
||||
// isWalletOutput :: *TxOut -> bool
|
||||
isWalletOutput := func(out *wire.TxOut) bool {
|
||||
_, addrs, _, err := txscript.ExtractPkScriptAddrs(
|
||||
// Doesn't matter what net we actually pass in.
|
||||
out.PkScript, &chaincfg.TestNet3Params,
|
||||
)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return fn.Any(c.cfg.isOurAddr, addrs)
|
||||
}
|
||||
|
||||
// Grab all of the outputs that correspond with our delivery address
|
||||
// or our wallet is aware of.
|
||||
outs := fn.Filter(fn.PredOr(isDeliveryOutput, isWalletOutput), tx.TxOut)
|
||||
|
||||
// Grab the values for those outputs.
|
||||
vals := fn.Map(func(o *wire.TxOut) int64 { return o.Value }, outs)
|
||||
|
||||
// Return the sum.
|
||||
return btcutil.Amount(fn.Sum(vals))
|
||||
}
|
||||
|
||||
// dispatchCooperativeClose processed a detect cooperative channel closure.
|
||||
|
2
go.mod
2
go.mod
@ -35,7 +35,7 @@ require (
|
||||
github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f
|
||||
github.com/lightningnetwork/lnd/cert v1.2.2
|
||||
github.com/lightningnetwork/lnd/clock v1.1.1
|
||||
github.com/lightningnetwork/lnd/fn v1.0.5
|
||||
github.com/lightningnetwork/lnd/fn v1.0.9
|
||||
github.com/lightningnetwork/lnd/healthcheck v1.2.4
|
||||
github.com/lightningnetwork/lnd/kvdb v1.4.8
|
||||
github.com/lightningnetwork/lnd/queue v1.1.1
|
||||
|
4
go.sum
4
go.sum
@ -448,8 +448,8 @@ github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf
|
||||
github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U=
|
||||
github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0=
|
||||
github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ=
|
||||
github.com/lightningnetwork/lnd/fn v1.0.5 h1:ffDgMSn83avw6rNzxhbt6w5/2oIrwQKTPGfyaLupZtE=
|
||||
github.com/lightningnetwork/lnd/fn v1.0.5/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U=
|
||||
github.com/lightningnetwork/lnd/fn v1.0.9 h1:VPljrzHGh0Wfs2NZe/ugUfH0hl6/L2eXW0LLXMUEy3s=
|
||||
github.com/lightningnetwork/lnd/fn v1.0.9/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U=
|
||||
github.com/lightningnetwork/lnd/healthcheck v1.2.4 h1:lLPLac+p/TllByxGSlkCwkJlkddqMP5UCoawCj3mgFQ=
|
||||
github.com/lightningnetwork/lnd/healthcheck v1.2.4/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I=
|
||||
github.com/lightningnetwork/lnd/kvdb v1.4.8 h1:xH0a5Vi1yrcZ5BEeF2ba3vlKBRxrL9uYXlWTjOjbNTY=
|
||||
|
Loading…
x
Reference in New Issue
Block a user