mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
mod+chanfunding: use coin selection strategy for channel funding
The wallet assembler is now aware of the node config level coin selection strategy, so we can use it when creating new channels.
This commit is contained in:
parent
f7198c4105
commit
9bdddbcc56
12
go.mod
12
go.mod
@ -10,11 +10,11 @@ require (
|
||||
github.com/btcsuite/btcd/btcutil/psbt v1.1.8
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
|
||||
github.com/btcsuite/btcwallet v0.16.10-0.20240127010340-16b422a2e8bf
|
||||
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2
|
||||
github.com/btcsuite/btcwallet/wallet/txrules v1.2.0
|
||||
github.com/btcsuite/btcwallet/walletdb v1.4.0
|
||||
github.com/btcsuite/btcwallet/wtxmgr v1.5.0
|
||||
github.com/btcsuite/btcwallet v0.16.10-0.20240206195028-1f3534b00d14
|
||||
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4
|
||||
github.com/btcsuite/btcwallet/wallet/txrules v1.2.1
|
||||
github.com/btcsuite/btcwallet/walletdb v1.4.1
|
||||
github.com/btcsuite/btcwallet/wtxmgr v1.5.1
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
|
||||
@ -77,7 +77,7 @@ require (
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
|
||||
github.com/aead/siphash v1.0.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 // indirect
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 // indirect
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect
|
||||
github.com/btcsuite/winsvc v1.0.0 // indirect
|
||||
|
32
go.sum
32
go.sum
@ -71,19 +71,15 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
|
||||
github.com/btcsuite/btcd v0.22.0-beta.0.20220204213055-eaf0459ff879/go.mod h1:osu7EoKiL36UThEgzYPqdRaxeo0NU8VoXqgcnwpey0g=
|
||||
github.com/btcsuite/btcd v0.23.1/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||
github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A=
|
||||
github.com/btcsuite/btcd v0.24.1-0.20240123000108-62e6af035ec5 h1:8BHBWvtP6kkzvmCpyWEznq4eS0gfLOSVuXLesv413Xs=
|
||||
github.com/btcsuite/btcd v0.24.1-0.20240123000108-62e6af035ec5/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
||||
github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.1/go.mod h1:nbKlBMNm9FGsdvKvu0essceubPiAcI57pYBNnsLAa34=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00=
|
||||
github.com/btcsuite/btcd/btcutil/psbt v1.1.8 h1:4voqtT8UppT7nmKQkXV+T9K8UyQjKOn2z/ycpmJK8wg=
|
||||
@ -95,20 +91,18 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcwallet v0.16.10-0.20240127010340-16b422a2e8bf h1:eNjj5R0tKP48NQxDkuKr+C9frZsdzTAemEwu75ZDQg0=
|
||||
github.com/btcsuite/btcwallet v0.16.10-0.20240127010340-16b422a2e8bf/go.mod h1:LzcW/LYkQLgDufv6Ouw4cOIW0YsY+A60MTtc61/OZTU=
|
||||
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 h1:etuLgGEojecsDOYTII8rYiGHjGyV5xTqsXi+ZQ715UU=
|
||||
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2/go.mod h1:Zpk/LOb2sKqwP2lmHjaZT9AdaKsHPSbNLm2Uql5IQ/0=
|
||||
github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 h1:BtEN5Empw62/RVnZ0VcJaVtVlBijnLlJY+dwjAye2Bg=
|
||||
github.com/btcsuite/btcwallet/wallet/txrules v1.2.0/go.mod h1:AtkqiL7ccKWxuLYtZm8Bu8G6q82w4yIZdgq6riy60z0=
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.2/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448=
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 h1:PszOub7iXVYbtGybym5TGCp9Dv1h1iX4rIC3HICZGLg=
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448=
|
||||
github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU=
|
||||
github.com/btcsuite/btcwallet/walletdb v1.4.0 h1:/C5JRF+dTuE2CNMCO/or5N8epsrhmSM4710uBQoYPTQ=
|
||||
github.com/btcsuite/btcwallet/walletdb v1.4.0/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU=
|
||||
github.com/btcsuite/btcwallet/wtxmgr v1.5.0 h1:WO0KyN4l6H3JWnlFxfGR7r3gDnlGT7W2cL8vl6av4SU=
|
||||
github.com/btcsuite/btcwallet/wtxmgr v1.5.0/go.mod h1:TQVDhFxseiGtZwEPvLgtfyxuNUDsIdaJdshvWzR0HJ4=
|
||||
github.com/btcsuite/btcwallet v0.16.10-0.20240206195028-1f3534b00d14 h1:GnTInK5UIkDJw9alXR4JeOmKmodJu/5qYknZWqp1Sk0=
|
||||
github.com/btcsuite/btcwallet v0.16.10-0.20240206195028-1f3534b00d14/go.mod h1:3EItwIQcrXGkcQlO1OginQ3Ab8YgE8kxka9hjgFuWxM=
|
||||
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 h1:poyHFf7+5+RdxNp5r2T6IBRD7RyraUsYARYbp/7t4D8=
|
||||
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4/go.mod h1:GETGDQuyq+VFfH1S/+/7slLM/9aNa4l7P4ejX6dJfb0=
|
||||
github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 h1:UZo7YRzdHbwhK7Rhv3PO9bXgTxiOH45edK5qdsdiatk=
|
||||
github.com/btcsuite/btcwallet/wallet/txrules v1.2.1/go.mod h1:MVSqRkju/IGxImXYPfBkG65FgEZYA4fXchheILMVl8g=
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 h1:nmcKAVTv/cmYrs0A4hbiC6Qw+WTLYy/14SmTt3mLnCo=
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4/go.mod h1:YqJR8WAAHiKIPesZTr9Cx9Az4fRhRLcJ6GcxzRUZCAc=
|
||||
github.com/btcsuite/btcwallet/walletdb v1.4.1 h1:NGIGoxx3trpaWqmdOeuhju7KJKp5UM96mQL21idF6RY=
|
||||
github.com/btcsuite/btcwallet/walletdb v1.4.1/go.mod h1:7ZQ+BvOEre90YT7eSq8bLoxTsgXidUzA/mqbRS114CQ=
|
||||
github.com/btcsuite/btcwallet/wtxmgr v1.5.1 h1:2yXhMGa4DNz16Mi0e8dVoiFXKOznXlxiGLhB3hKj2uA=
|
||||
github.com/btcsuite/btcwallet/wtxmgr v1.5.1/go.mod h1:tO4FBSdann0xg/Jtm0grV7t1DzpQMK8nThYVtvSJo/8=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||
github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc=
|
||||
@ -446,7 +440,6 @@ github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f
|
||||
github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI=
|
||||
github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf0d0Uy4qBjI=
|
||||
github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U=
|
||||
github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg=
|
||||
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.2 h1:6u+DHMvpHj09KH2Uw39fsbjydq9JvG23Rc99i+mhI1A=
|
||||
@ -639,7 +632,6 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec h1:FpfFs4EhNehiVfzQttTuxanPIT43FtkkCFypIod8LHo=
|
||||
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec/go.mod h1:BZ1RAoRPbCxum9Grlv5aeksu2H8BiKehBYooU2LFiOQ=
|
||||
go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY=
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type chanFundUtxoSelectionTestCase struct {
|
||||
@ -131,8 +132,7 @@ func testChannelUtxoSelection(ht *lntest.HarnessTest) {
|
||||
localAmt: btcutil.Amount(250_000),
|
||||
expectedBalance: btcutil.Amount(250_000),
|
||||
remainingWalletBalance: btcutil.Amount(350_000) -
|
||||
btcutil.Amount(250_000) -
|
||||
fundingFee(2, true),
|
||||
btcutil.Amount(250_000) - fundingFee(2, true),
|
||||
},
|
||||
// We are spending the entirety of two selected coins out of
|
||||
// three available in the wallet and expect no change output and
|
||||
@ -147,8 +147,7 @@ func testChannelUtxoSelection(ht *lntest.HarnessTest) {
|
||||
200_000, 50_000,
|
||||
},
|
||||
expectedBalance: btcutil.Amount(200_000) +
|
||||
btcutil.Amount(50_000) -
|
||||
fundingFee(2, false),
|
||||
btcutil.Amount(50_000) - fundingFee(2, false),
|
||||
remainingWalletBalance: btcutil.Amount(100_000),
|
||||
},
|
||||
// Select all coins in wallet and use the maximum available
|
||||
@ -162,15 +161,14 @@ func testChannelUtxoSelection(ht *lntest.HarnessTest) {
|
||||
selectedCoins: []btcutil.Amount{200_000, 100_000},
|
||||
commitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||
localAmt: btcutil.Amount(300_000) -
|
||||
reserveAmount -
|
||||
fundingFee(2, true),
|
||||
reserveAmount - fundingFee(2, true),
|
||||
expectedBalance: btcutil.Amount(300_000) -
|
||||
reserveAmount -
|
||||
fundingFee(2, true),
|
||||
reserveAmount - fundingFee(2, true),
|
||||
remainingWalletBalance: reserveAmount,
|
||||
},
|
||||
// Select all coins in wallet towards local amount except for a
|
||||
// anchor reserve portion.
|
||||
// Select all coins in wallet towards local amount except for an
|
||||
// anchor reserve portion. Because the UTXOs are sorted by size
|
||||
// by default, the reserve amount is just left in the wallet.
|
||||
{
|
||||
name: "selected, reserve from selected",
|
||||
initialCoins: []btcutil.Amount{
|
||||
@ -181,9 +179,9 @@ func testChannelUtxoSelection(ht *lntest.HarnessTest) {
|
||||
},
|
||||
commitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||
localAmt: btcutil.Amount(300_000) -
|
||||
fundingFee(3, true),
|
||||
fundingFee(2, true),
|
||||
expectedBalance: btcutil.Amount(300_000) -
|
||||
fundingFee(3, true),
|
||||
fundingFee(2, true),
|
||||
remainingWalletBalance: reserveAmount,
|
||||
},
|
||||
// Select all coins in wallet and use more than the maximum
|
||||
@ -197,8 +195,7 @@ func testChannelUtxoSelection(ht *lntest.HarnessTest) {
|
||||
selectedCoins: []btcutil.Amount{200_000, 100_000},
|
||||
commitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||
localAmt: btcutil.Amount(300_000) -
|
||||
reserveAmount + 1 -
|
||||
fundingFee(2, true),
|
||||
reserveAmount + 1 - fundingFee(2, true),
|
||||
chanOpenShouldFail: true,
|
||||
expectedErrStr: "reserved wallet balance " +
|
||||
"invalidated: transaction would leave " +
|
||||
@ -229,8 +226,7 @@ func testChannelUtxoSelection(ht *lntest.HarnessTest) {
|
||||
selectedCoins: []btcutil.Amount{200_000},
|
||||
commitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||
expectedBalance: btcutil.Amount(200_000) -
|
||||
reserveAmount -
|
||||
fundingFee(1, true),
|
||||
reserveAmount - fundingFee(1, true),
|
||||
remainingWalletBalance: reserveAmount,
|
||||
},
|
||||
// Confirm that already spent outputs can't be reused to fund
|
||||
@ -249,8 +245,7 @@ func testChannelUtxoSelection(ht *lntest.HarnessTest) {
|
||||
success := ht.Run(
|
||||
tc.name, func(tt *testing.T) {
|
||||
runUtxoSelectionTestCase(
|
||||
ht, tt, alice, bob, tc,
|
||||
reserveAmount,
|
||||
ht, alice, bob, tc, reserveAmount,
|
||||
)
|
||||
},
|
||||
)
|
||||
@ -264,7 +259,7 @@ func testChannelUtxoSelection(ht *lntest.HarnessTest) {
|
||||
|
||||
// runUtxoSelectionTestCase runs a single test case asserting that test
|
||||
// conditions are met.
|
||||
func runUtxoSelectionTestCase(ht *lntest.HarnessTest, t *testing.T, alice,
|
||||
func runUtxoSelectionTestCase(ht *lntest.HarnessTest, alice,
|
||||
bob *node.HarnessNode, tc *chanFundUtxoSelectionTestCase,
|
||||
reserveAmount btcutil.Amount) {
|
||||
|
||||
@ -366,4 +361,12 @@ func runUtxoSelectionTestCase(ht *lntest.HarnessTest, t *testing.T, alice,
|
||||
int64(tc.remainingWalletBalance),
|
||||
0,
|
||||
)
|
||||
|
||||
// Ensure the anchor channel reserve was carved out.
|
||||
if commitType == lnrpc.CommitmentType_ANCHORS {
|
||||
balance := alice.RPC.WalletBalance()
|
||||
require.EqualValues(
|
||||
ht, reserveAmount, balance.ReservedBalanceAnchorChan,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package chanfunding
|
||||
import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcwallet/wallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
@ -11,12 +12,12 @@ import (
|
||||
type CoinSource interface {
|
||||
// ListCoins returns all UTXOs from the source that have between
|
||||
// minConfs and maxConfs number of confirmations.
|
||||
ListCoins(minConfs, maxConfs int32) ([]Coin, error)
|
||||
ListCoins(minConfs, maxConfs int32) ([]wallet.Coin, error)
|
||||
|
||||
// CoinFromOutPoint attempts to locate details pertaining to a coin
|
||||
// based on its outpoint. If the coin isn't under the control of the
|
||||
// backing CoinSource, then an error should be returned.
|
||||
CoinFromOutPoint(wire.OutPoint) (*Coin, error)
|
||||
CoinFromOutPoint(wire.OutPoint) (*wallet.Coin, error)
|
||||
}
|
||||
|
||||
// CoinSelectionLocker is an interface that allows the caller to perform an
|
||||
|
@ -6,20 +6,20 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcwallet/wallet"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
)
|
||||
|
||||
// ErrInsufficientFunds is a type matching the error interface which is
|
||||
// returned when coin selection for a new funding transaction fails to due
|
||||
// returned when coin selection for a new funding transaction fails due to
|
||||
// having an insufficient amount of confirmed funds.
|
||||
type ErrInsufficientFunds struct {
|
||||
amountAvailable btcutil.Amount
|
||||
amountSelected btcutil.Amount
|
||||
}
|
||||
|
||||
// Error returns a human readable string describing the error.
|
||||
// Error returns a human-readable string describing the error.
|
||||
func (e *ErrInsufficientFunds) Error() string {
|
||||
return fmt.Sprintf("not enough witness outputs to create funding "+
|
||||
"transaction, need %v only have %v available",
|
||||
@ -33,33 +33,33 @@ type errUnsupportedInput struct {
|
||||
PkScript []byte
|
||||
}
|
||||
|
||||
// Error returns a human readable string describing the error.
|
||||
// Error returns a human-readable string describing the error.
|
||||
func (e *errUnsupportedInput) Error() string {
|
||||
return fmt.Sprintf("unsupported address type: %x", e.PkScript)
|
||||
}
|
||||
|
||||
// Coin represents a spendable UTXO which is available for channel funding.
|
||||
// This UTXO need not reside in our internal wallet as an example, and instead
|
||||
// may be derived from an existing watch-only wallet. It wraps both the output
|
||||
// present within the UTXO set, and also the outpoint that generates this coin.
|
||||
type Coin struct {
|
||||
wire.TxOut
|
||||
|
||||
wire.OutPoint
|
||||
}
|
||||
|
||||
// selectInputs selects a slice of inputs necessary to meet the specified
|
||||
// selection amount. If input selection is unable to succeed due to insufficient
|
||||
// funds, a non-nil error is returned. Additionally, the total amount of the
|
||||
// selected coins are returned in order for the caller to properly handle
|
||||
// change+fees.
|
||||
func selectInputs(amt btcutil.Amount, coins []Coin) (btcutil.Amount, []Coin, error) {
|
||||
func selectInputs(amt btcutil.Amount, coins []wallet.Coin,
|
||||
strategy wallet.CoinSelectionStrategy,
|
||||
feeRate chainfee.SatPerKWeight) (btcutil.Amount, []wallet.Coin, error) {
|
||||
|
||||
// All coin selection code in the btcwallet library requires sat/KB.
|
||||
feeSatPerKB := btcutil.Amount(feeRate.FeePerKVByte())
|
||||
|
||||
arrangedCoins, err := strategy.ArrangeCoins(coins, feeSatPerKB)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
satSelected := btcutil.Amount(0)
|
||||
for i, coin := range coins {
|
||||
for i, coin := range arrangedCoins {
|
||||
satSelected += btcutil.Amount(coin.Value)
|
||||
if satSelected >= amt {
|
||||
return satSelected, coins[:i+1], nil
|
||||
return satSelected, arrangedCoins[:i+1], nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,8 +69,9 @@ func selectInputs(amt btcutil.Amount, coins []Coin) (btcutil.Amount, []Coin, err
|
||||
// calculateFees returns for the specified utxos and fee rate two fee
|
||||
// estimates, one calculated using a change output and one without. The weight
|
||||
// added to the estimator from a change output is for a P2WKH output.
|
||||
func calculateFees(utxos []Coin, feeRate chainfee.SatPerKWeight) (btcutil.Amount,
|
||||
btcutil.Amount, error) {
|
||||
func calculateFees(utxos []wallet.Coin,
|
||||
feeRate chainfee.SatPerKWeight) (btcutil.Amount, btcutil.Amount,
|
||||
error) {
|
||||
|
||||
var weightEstimate input.TxWeightEstimator
|
||||
for _, utxo := range utxos {
|
||||
@ -129,13 +130,17 @@ func sanityCheckFee(totalOut, fee btcutil.Amount) error {
|
||||
// specified fee rate should be expressed in sat/kw for coin selection to
|
||||
// function properly.
|
||||
func CoinSelect(feeRate chainfee.SatPerKWeight, amt, dustLimit btcutil.Amount,
|
||||
coins []Coin) ([]Coin, btcutil.Amount, error) {
|
||||
coins []wallet.Coin,
|
||||
strategy wallet.CoinSelectionStrategy) ([]wallet.Coin, btcutil.Amount,
|
||||
error) {
|
||||
|
||||
amtNeeded := amt
|
||||
for {
|
||||
// First perform an initial round of coin selection to estimate
|
||||
// the required fee.
|
||||
totalSat, selectedUtxos, err := selectInputs(amtNeeded, coins)
|
||||
totalSat, selectedUtxos, err := selectInputs(
|
||||
amtNeeded, coins, strategy, feeRate,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@ -198,12 +203,15 @@ func CoinSelect(feeRate chainfee.SatPerKWeight, amt, dustLimit btcutil.Amount,
|
||||
// amt in total after fees, adhering to the specified fee rate. The selected
|
||||
// coins, the final output and change values are returned.
|
||||
func CoinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
|
||||
dustLimit btcutil.Amount, coins []Coin) ([]Coin, btcutil.Amount,
|
||||
dustLimit btcutil.Amount, coins []wallet.Coin,
|
||||
strategy wallet.CoinSelectionStrategy) ([]wallet.Coin, btcutil.Amount,
|
||||
btcutil.Amount, error) {
|
||||
|
||||
// First perform an initial round of coin selection to estimate
|
||||
// the required fee.
|
||||
totalSat, selectedUtxos, err := selectInputs(amt, coins)
|
||||
totalSat, selectedUtxos, err := selectInputs(
|
||||
amt, coins, strategy, feeRate,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
@ -259,8 +267,9 @@ func CoinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
|
||||
// available. If insufficient funds are available this method selects all
|
||||
// available coins.
|
||||
func CoinSelectUpToAmount(feeRate chainfee.SatPerKWeight, minAmount, maxAmount,
|
||||
reserved, dustLimit btcutil.Amount, coins []Coin) ([]Coin,
|
||||
btcutil.Amount, btcutil.Amount, error) {
|
||||
reserved, dustLimit btcutil.Amount, coins []wallet.Coin,
|
||||
strategy wallet.CoinSelectionStrategy) ([]wallet.Coin, btcutil.Amount,
|
||||
btcutil.Amount, error) {
|
||||
|
||||
var (
|
||||
// selectSubtractFee is tracking if our coin selection was
|
||||
@ -280,7 +289,7 @@ func CoinSelectUpToAmount(feeRate chainfee.SatPerKWeight, minAmount, maxAmount,
|
||||
// First we try to select coins to create an output of the specified
|
||||
// maxAmount with or without a change output that covers the miner fee.
|
||||
selected, changeAmt, err := CoinSelect(
|
||||
feeRate, maxAmount, dustLimit, coins,
|
||||
feeRate, maxAmount, dustLimit, coins, strategy,
|
||||
)
|
||||
|
||||
var errInsufficientFunds *ErrInsufficientFunds
|
||||
@ -320,6 +329,7 @@ func CoinSelectUpToAmount(feeRate chainfee.SatPerKWeight, minAmount, maxAmount,
|
||||
if selectSubtractFee {
|
||||
selected, outputAmount, changeAmt, err = CoinSelectSubtractFees(
|
||||
feeRate, totalBalance-reserved, dustLimit, coins,
|
||||
strategy,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
@ -329,7 +339,7 @@ func CoinSelectUpToAmount(feeRate chainfee.SatPerKWeight, minAmount, maxAmount,
|
||||
// Sanity check the resulting output values to make sure we don't burn a
|
||||
// great part to fees.
|
||||
totalOut := outputAmount + changeAmt
|
||||
sum := func(coins []Coin) btcutil.Amount {
|
||||
sum := func(coins []wallet.Coin) btcutil.Amount {
|
||||
var sum btcutil.Amount
|
||||
for _, coin := range coins {
|
||||
sum += btcutil.Amount(coin.Value)
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcwallet/wallet"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -61,7 +62,7 @@ func TestCalculateFees(t *testing.T) {
|
||||
|
||||
type testCase struct {
|
||||
name string
|
||||
utxos []Coin
|
||||
utxos []wallet.Coin
|
||||
|
||||
expectedFeeNoChange btcutil.Amount
|
||||
expectedFeeWithChange btcutil.Amount
|
||||
@ -71,7 +72,7 @@ func TestCalculateFees(t *testing.T) {
|
||||
testCases := []testCase{
|
||||
{
|
||||
name: "one P2WKH input",
|
||||
utxos: []Coin{
|
||||
utxos: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -87,7 +88,7 @@ func TestCalculateFees(t *testing.T) {
|
||||
|
||||
{
|
||||
name: "one NP2WKH input",
|
||||
utxos: []Coin{
|
||||
utxos: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: np2wkhScript,
|
||||
@ -103,7 +104,7 @@ func TestCalculateFees(t *testing.T) {
|
||||
|
||||
{
|
||||
name: "not supported P2KH input",
|
||||
utxos: []Coin{
|
||||
utxos: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2khScript,
|
||||
@ -148,7 +149,7 @@ func TestCoinSelect(t *testing.T) {
|
||||
type testCase struct {
|
||||
name string
|
||||
outputValue btcutil.Amount
|
||||
coins []Coin
|
||||
coins []wallet.Coin
|
||||
|
||||
expectedInput []btcutil.Amount
|
||||
expectedChange btcutil.Amount
|
||||
@ -161,7 +162,7 @@ func TestCoinSelect(t *testing.T) {
|
||||
// This will obviously lead to a change output of
|
||||
// almost 0.5 BTC.
|
||||
name: "big change",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -183,7 +184,7 @@ func TestCoinSelect(t *testing.T) {
|
||||
// This should lead to an error, as we don't have
|
||||
// enough funds to pay the fee.
|
||||
name: "nothing left for fees",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -199,7 +200,7 @@ func TestCoinSelect(t *testing.T) {
|
||||
// as big as possible, such that the remaining change
|
||||
// would be dust but instead goes to fees.
|
||||
name: "dust change",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -222,7 +223,7 @@ func TestCoinSelect(t *testing.T) {
|
||||
// We got just enough funds to create a change output above the
|
||||
// dust limit.
|
||||
name: "change right above dustlimit",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -244,7 +245,7 @@ func TestCoinSelect(t *testing.T) {
|
||||
{
|
||||
// If more than 20% of funds goes to fees, it should fail.
|
||||
name: "high fee",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -265,6 +266,7 @@ func TestCoinSelect(t *testing.T) {
|
||||
|
||||
selected, changeAmt, err := CoinSelect(
|
||||
feeRate, test.outputValue, dustLimit, test.coins,
|
||||
wallet.CoinSelectionLargest,
|
||||
)
|
||||
if !test.expectErr && err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
@ -323,7 +325,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
name string
|
||||
highFee bool
|
||||
spendValue btcutil.Amount
|
||||
coins []Coin
|
||||
coins []wallet.Coin
|
||||
|
||||
expectedInput []btcutil.Amount
|
||||
expectedFundingAmt btcutil.Amount
|
||||
@ -337,7 +339,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
// should lead to a funding TX with one output, the
|
||||
// rest goes to fees.
|
||||
name: "spend all",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -358,7 +360,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
// We have 1.0 BTC available and spend half of it. This
|
||||
// should lead to a funding TX with a change output.
|
||||
name: "spend with change",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -379,7 +381,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
// The total funds available is below the dust limit
|
||||
// after paying fees.
|
||||
name: "dust output",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -397,7 +399,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
// is below the dust limit. The remainder should go
|
||||
// towards the funding output.
|
||||
name: "dust change",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -416,7 +418,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
{
|
||||
// We got just enough funds to create an output above the dust limit.
|
||||
name: "output right above dustlimit",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -436,7 +438,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
// Amount left is below dust limit after paying fee for
|
||||
// a change output, resulting in a no-change tx.
|
||||
name: "no amount to pay fee for change",
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -456,7 +458,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
// If more than 20% of funds goes to fees, it should fail.
|
||||
name: "high fee",
|
||||
highFee: true,
|
||||
coins: []Coin{
|
||||
coins: []wallet.Coin{
|
||||
{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
@ -481,6 +483,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
|
||||
|
||||
selected, localFundingAmt, changeAmt, err := CoinSelectSubtractFees(
|
||||
feeRate, test.spendValue, dustLimit, test.coins,
|
||||
wallet.CoinSelectionLargest,
|
||||
)
|
||||
if err != nil {
|
||||
switch {
|
||||
@ -551,7 +554,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
minValue btcutil.Amount
|
||||
maxValue btcutil.Amount
|
||||
reserved btcutil.Amount
|
||||
coins []Coin
|
||||
coins []wallet.Coin
|
||||
|
||||
expectedInput []btcutil.Amount
|
||||
expectedFundingAmt btcutil.Amount
|
||||
@ -564,7 +567,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
// This should lead to a funding TX with one output, the rest
|
||||
// goes to fees.
|
||||
name: "spend exactly all",
|
||||
coins: []Coin{{
|
||||
coins: []wallet.Coin{{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
Value: 1 * coin,
|
||||
@ -582,7 +585,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
// This should lead to a funding TX with one output, the rest
|
||||
// goes to fees.
|
||||
name: "spend more",
|
||||
coins: []Coin{{
|
||||
coins: []wallet.Coin{{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
Value: 1 * coin,
|
||||
@ -600,7 +603,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
// This should lead to a funding TX with one output and a
|
||||
// change to subtract the fees from.
|
||||
name: "spend far below",
|
||||
coins: []Coin{{
|
||||
coins: []wallet.Coin{{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
Value: 1 * coin,
|
||||
@ -619,7 +622,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
// This should lead to a funding TX with one output where the
|
||||
// fee is subtracted from the total 1 BTC input value.
|
||||
name: "spend little below",
|
||||
coins: []Coin{{
|
||||
coins: []wallet.Coin{{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
Value: 1 * coin,
|
||||
@ -638,7 +641,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
// The total funds available is below the dust limit after
|
||||
// paying fees.
|
||||
name: "dust output",
|
||||
coins: []Coin{{
|
||||
coins: []wallet.Coin{{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
Value: int64(
|
||||
@ -655,7 +658,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
// If more than 20% of available wallet funds goes to fees, it
|
||||
// should fail.
|
||||
name: "high fee",
|
||||
coins: []Coin{{
|
||||
coins: []wallet.Coin{{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
Value: int64(
|
||||
@ -677,7 +680,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
// check could result in a local amount higher than the maximum
|
||||
// amount that was expected.
|
||||
name: "sanity check for correct maximum amount",
|
||||
coins: []Coin{{
|
||||
coins: []wallet.Coin{{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
Value: 1 * coin,
|
||||
@ -695,7 +698,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
// value as change and still maxing out the funding amount.
|
||||
name: "sanity check for correct reserved amount subtract " +
|
||||
"from total",
|
||||
coins: []Coin{{
|
||||
coins: []wallet.Coin{{
|
||||
TxOut: wire.TxOut{
|
||||
PkScript: p2wkhScript,
|
||||
Value: 1 * coin,
|
||||
@ -720,6 +723,7 @@ func TestCoinSelectUpToAmount(t *testing.T) {
|
||||
err := CoinSelectUpToAmount(
|
||||
feeRate, test.minValue, test.maxValue,
|
||||
test.reserved, dustLimit, test.coins,
|
||||
wallet.CoinSelectionLargest,
|
||||
)
|
||||
if len(test.expectErr) == 0 && err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
|
@ -31,7 +31,7 @@ type FullIntent struct {
|
||||
|
||||
// InputCoins are the set of coins selected as inputs to this funding
|
||||
// transaction.
|
||||
InputCoins []Coin
|
||||
InputCoins []wallet.Coin
|
||||
|
||||
// ChangeOutputs are the set of outputs that the Assembler will use as
|
||||
// change from the main funding transaction.
|
||||
@ -268,12 +268,12 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
|
||||
var (
|
||||
// allCoins refers to the entirety of coins in our
|
||||
// wallet that are available for funding a channel.
|
||||
allCoins []Coin
|
||||
allCoins []wallet.Coin
|
||||
|
||||
// manuallySelectedCoins refers to the client-side
|
||||
// selected coins that should be considered available
|
||||
// for funding a channel.
|
||||
manuallySelectedCoins []Coin
|
||||
manuallySelectedCoins []wallet.Coin
|
||||
err error
|
||||
)
|
||||
|
||||
@ -309,8 +309,8 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
|
||||
}
|
||||
|
||||
var (
|
||||
coins []Coin
|
||||
selectedCoins []Coin
|
||||
coins []wallet.Coin
|
||||
selectedCoins []wallet.Coin
|
||||
localContributionAmt btcutil.Amount
|
||||
changeAmt btcutil.Amount
|
||||
)
|
||||
@ -357,7 +357,9 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
|
||||
// enough funds in the wallet to cover for a reserve.
|
||||
reserve := r.WalletReserve
|
||||
if len(manuallySelectedCoins) > 0 {
|
||||
sumCoins := func(coins []Coin) btcutil.Amount {
|
||||
sumCoins := func(
|
||||
coins []wallet.Coin) btcutil.Amount {
|
||||
|
||||
var sum btcutil.Amount
|
||||
for _, coin := range coins {
|
||||
sum += btcutil.Amount(
|
||||
@ -390,6 +392,7 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
|
||||
err = CoinSelectUpToAmount(
|
||||
r.FeeRate, r.MinFundAmt, r.FundUpToMaxAmt,
|
||||
reserve, w.cfg.DustLimit, coins,
|
||||
w.cfg.CoinSelectionStrategy,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -423,6 +426,7 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
|
||||
selectedCoins, localContributionAmt, changeAmt,
|
||||
err = CoinSelectSubtractFees(
|
||||
r.FeeRate, r.LocalAmt, dustLimit, coins,
|
||||
w.cfg.CoinSelectionStrategy,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -435,6 +439,7 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
|
||||
localContributionAmt = r.LocalAmt
|
||||
selectedCoins, changeAmt, err = CoinSelect(
|
||||
r.FeeRate, r.LocalAmt, dustLimit, coins,
|
||||
w.cfg.CoinSelectionStrategy,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -507,9 +512,10 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
|
||||
// outpointsToCoins maps outpoints to coins in our wallet iff these coins are
|
||||
// existent and returns an error otherwise.
|
||||
func outpointsToCoins(outpoints []wire.OutPoint,
|
||||
coinFromOutPoint func(wire.OutPoint) (*Coin, error)) ([]Coin, error) {
|
||||
coinFromOutPoint func(wire.OutPoint) (*wallet.Coin, error)) (
|
||||
[]wallet.Coin, error) {
|
||||
|
||||
var selectedCoins []Coin
|
||||
var selectedCoins []wallet.Coin
|
||||
for _, outpoint := range outpoints {
|
||||
coin, err := coinFromOutPoint(
|
||||
outpoint,
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcwallet/wallet"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
@ -2530,7 +2531,7 @@ func NewCoinSource(w *LightningWallet) *CoinSource {
|
||||
// ListCoins returns all UTXOs from the source that have between
|
||||
// minConfs and maxConfs number of confirmations.
|
||||
func (c *CoinSource) ListCoins(minConfs int32,
|
||||
maxConfs int32) ([]chanfunding.Coin, error) {
|
||||
maxConfs int32) ([]wallet.Coin, error) {
|
||||
|
||||
utxos, err := c.wallet.ListUnspentWitnessFromDefaultAccount(
|
||||
minConfs, maxConfs,
|
||||
@ -2539,9 +2540,9 @@ func (c *CoinSource) ListCoins(minConfs int32,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var coins []chanfunding.Coin
|
||||
var coins []wallet.Coin
|
||||
for _, utxo := range utxos {
|
||||
coins = append(coins, chanfunding.Coin{
|
||||
coins = append(coins, wallet.Coin{
|
||||
TxOut: wire.TxOut{
|
||||
Value: int64(utxo.Value),
|
||||
PkScript: utxo.PkScript,
|
||||
@ -2556,13 +2557,13 @@ func (c *CoinSource) ListCoins(minConfs int32,
|
||||
// CoinFromOutPoint attempts to locate details pertaining to a coin based on
|
||||
// its outpoint. If the coin isn't under the control of the backing CoinSource,
|
||||
// then an error should be returned.
|
||||
func (c *CoinSource) CoinFromOutPoint(op wire.OutPoint) (*chanfunding.Coin, error) {
|
||||
func (c *CoinSource) CoinFromOutPoint(op wire.OutPoint) (*wallet.Coin, error) {
|
||||
inputInfo, err := c.wallet.FetchInputInfo(&op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &chanfunding.Coin{
|
||||
return &wallet.Coin{
|
||||
TxOut: wire.TxOut{
|
||||
Value: int64(inputInfo.Value),
|
||||
PkScript: inputInfo.PkScript,
|
||||
|
Loading…
Reference in New Issue
Block a user