Skip to content

Commit 99339f7

Browse files
Chinwendu20yyforyongyu
authored andcommitted
multi: expand SendOutputs and CreateSimpleTx to take utxos
This commit updates the interface methods from `lnwallet.WalletController` to take optional input set which can be used to create the tx.
1 parent 468ca87 commit 99339f7

File tree

8 files changed

+66
-38
lines changed

8 files changed

+66
-38
lines changed

lnrpc/walletrpc/walletkit_server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,8 +811,8 @@ func (w *WalletKit) SendOutputs(ctx context.Context,
811811
// requirement, we can request that the wallet attempts to create this
812812
// transaction.
813813
tx, err := w.cfg.Wallet.SendOutputs(
814-
outputsToCreate, chainfee.SatPerKWeight(req.SatPerKw), minConfs,
815-
label, coinSelectionStrategy,
814+
nil, outputsToCreate, chainfee.SatPerKWeight(req.SatPerKw),
815+
minConfs, label, coinSelectionStrategy,
816816
)
817817
if err != nil {
818818
return nil, err

lntest/mock/walletcontroller.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
base "github.com/btcsuite/btcwallet/wallet"
1717
"github.com/btcsuite/btcwallet/wallet/txauthor"
1818
"github.com/btcsuite/btcwallet/wtxmgr"
19+
"github.com/lightningnetwork/lnd/fn"
1920
"github.com/lightningnetwork/lnd/lnwallet"
2021
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
2122
)
@@ -33,6 +34,10 @@ type WalletController struct {
3334
Utxos []*lnwallet.Utxo
3435
}
3536

37+
// A compile time check to ensure this mocked WalletController implements the
38+
// WalletController.
39+
var _ lnwallet.WalletController = (*WalletController)(nil)
40+
3641
// BackEnd returns "mock" to signify a mock wallet controller.
3742
func (w *WalletController) BackEnd() string {
3843
return "mock"
@@ -140,15 +145,15 @@ func (w *WalletController) ImportTaprootScript(waddrmgr.KeyScope,
140145
}
141146

142147
// SendOutputs currently returns dummy values.
143-
func (w *WalletController) SendOutputs([]*wire.TxOut,
144-
chainfee.SatPerKWeight, int32, string,
145-
base.CoinSelectionStrategy) (*wire.MsgTx, error) {
148+
func (w *WalletController) SendOutputs(fn.Set[wire.OutPoint], []*wire.TxOut,
149+
chainfee.SatPerKWeight, int32, string, base.CoinSelectionStrategy) (
150+
*wire.MsgTx, error) {
146151

147152
return nil, nil
148153
}
149154

150155
// CreateSimpleTx currently returns dummy values.
151-
func (w *WalletController) CreateSimpleTx([]*wire.TxOut,
156+
func (w *WalletController) CreateSimpleTx(fn.Set[wire.OutPoint], []*wire.TxOut,
152157
chainfee.SatPerKWeight, int32, base.CoinSelectionStrategy,
153158
bool) (*txauthor.AuthoredTx, error) {
154159

lnwallet/btcwallet/btcwallet.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import (
1919
"github.com/btcsuite/btcd/wire"
2020
"github.com/btcsuite/btcwallet/chain"
2121
"github.com/btcsuite/btcwallet/waddrmgr"
22+
"github.com/btcsuite/btcwallet/wallet"
2223
base "github.com/btcsuite/btcwallet/wallet"
2324
"github.com/btcsuite/btcwallet/wallet/txauthor"
2425
"github.com/btcsuite/btcwallet/wallet/txrules"
2526
"github.com/btcsuite/btcwallet/walletdb"
2627
"github.com/btcsuite/btcwallet/wtxmgr"
2728
"github.com/davecgh/go-spew/spew"
2829
"github.com/lightningnetwork/lnd/blockcache"
30+
"github.com/lightningnetwork/lnd/fn"
2931
"github.com/lightningnetwork/lnd/input"
3032
"github.com/lightningnetwork/lnd/keychain"
3133
"github.com/lightningnetwork/lnd/kvdb"
@@ -977,8 +979,9 @@ func (b *BtcWallet) ImportTaprootScript(scope waddrmgr.KeyScope,
977979
// NOTE: This method requires the global coin selection lock to be held.
978980
//
979981
// This is a part of the WalletController interface.
980-
func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
981-
feeRate chainfee.SatPerKWeight, minConfs int32, label string,
982+
func (b *BtcWallet) SendOutputs(inputs fn.Set[wire.OutPoint],
983+
outputs []*wire.TxOut, feeRate chainfee.SatPerKWeight,
984+
minConfs int32, label string,
982985
strategy base.CoinSelectionStrategy) (*wire.MsgTx, error) {
983986

984987
// Convert our fee rate from sat/kw to sat/kb since it's required by
@@ -995,6 +998,14 @@ func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
995998
return nil, lnwallet.ErrInvalidMinconf
996999
}
9971000

1001+
// Use selected UTXOs if specified, otherwise default selection.
1002+
if len(inputs) != 0 {
1003+
return b.wallet.SendOutputsWithInput(
1004+
outputs, nil, defaultAccount, minConfs, feeSatPerKB,
1005+
strategy, label, inputs.ToSlice(),
1006+
)
1007+
}
1008+
9981009
return b.wallet.SendOutputs(
9991010
outputs, nil, defaultAccount, minConfs, feeSatPerKB,
10001011
strategy, label,
@@ -1014,10 +1025,10 @@ func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
10141025
// NOTE: This method requires the global coin selection lock to be held.
10151026
//
10161027
// This is a part of the WalletController interface.
1017-
func (b *BtcWallet) CreateSimpleTx(outputs []*wire.TxOut,
1018-
feeRate chainfee.SatPerKWeight, minConfs int32,
1019-
strategy base.CoinSelectionStrategy,
1020-
dryRun bool) (*txauthor.AuthoredTx, error) {
1028+
func (b *BtcWallet) CreateSimpleTx(inputs fn.Set[wire.OutPoint],
1029+
outputs []*wire.TxOut, feeRate chainfee.SatPerKWeight, minConfs int32,
1030+
strategy base.CoinSelectionStrategy, dryRun bool) (
1031+
*txauthor.AuthoredTx, error) {
10211032

10221033
// The fee rate is passed in using units of sat/kw, so we'll convert
10231034
// this to sat/KB as the CreateSimpleTx method requires this unit.
@@ -1047,9 +1058,12 @@ func (b *BtcWallet) CreateSimpleTx(outputs []*wire.TxOut,
10471058
}
10481059
}
10491060

1061+
// Add the optional inputs to the transaction.
1062+
optFunc := wallet.WithCustomSelectUtxos(inputs.ToSlice())
1063+
10501064
return b.wallet.CreateSimpleTx(
10511065
nil, defaultAccount, outputs, minConfs, feeSatPerKB,
1052-
strategy, dryRun,
1066+
strategy, dryRun, []wallet.TxCreateOption{optFunc}...,
10531067
)
10541068
}
10551069

lnwallet/interface.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
base "github.com/btcsuite/btcwallet/wallet"
1919
"github.com/btcsuite/btcwallet/wallet/txauthor"
2020
"github.com/btcsuite/btcwallet/wtxmgr"
21+
"github.com/lightningnetwork/lnd/fn"
2122
"github.com/lightningnetwork/lnd/keychain"
2223
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
2324
)
@@ -344,8 +345,8 @@ type WalletController interface {
344345
// be used when crafting the transaction.
345346
//
346347
// NOTE: This method requires the global coin selection lock to be held.
347-
SendOutputs(outputs []*wire.TxOut, feeRate chainfee.SatPerKWeight,
348-
minConfs int32, label string,
348+
SendOutputs(inputs fn.Set[wire.OutPoint], outputs []*wire.TxOut,
349+
feeRate chainfee.SatPerKWeight, minConfs int32, label string,
349350
strategy base.CoinSelectionStrategy) (*wire.MsgTx, error)
350351

351352
// CreateSimpleTx creates a Bitcoin transaction paying to the specified
@@ -360,9 +361,10 @@ type WalletController interface {
360361
// SHOULD NOT be broadcasted.
361362
//
362363
// NOTE: This method requires the global coin selection lock to be held.
363-
CreateSimpleTx(outputs []*wire.TxOut, feeRate chainfee.SatPerKWeight,
364-
minConfs int32, strategy base.CoinSelectionStrategy,
365-
dryRun bool) (*txauthor.AuthoredTx, error)
364+
CreateSimpleTx(inputs fn.Set[wire.OutPoint], outputs []*wire.TxOut,
365+
feeRate chainfee.SatPerKWeight, minConfs int32,
366+
strategy base.CoinSelectionStrategy, dryRun bool) (
367+
*txauthor.AuthoredTx, error)
366368

367369
// GetTransactionDetails returns a detailed description of a transaction
368370
// given its transaction hash.

lnwallet/mock.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/btcsuite/btcwallet/wallet/txauthor"
1818
"github.com/btcsuite/btcwallet/wtxmgr"
1919
"github.com/lightningnetwork/lnd/chainntnfs"
20+
"github.com/lightningnetwork/lnd/fn"
2021
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
2122
)
2223

@@ -35,6 +36,10 @@ type mockWalletController struct {
3536
Utxos []*Utxo
3637
}
3738

39+
// A compile time check to ensure that mockWalletController implements the
40+
// WalletController.
41+
var _ WalletController = (*mockWalletController)(nil)
42+
3843
// BackEnd returns "mock" to signify a mock wallet controller.
3944
func (w *mockWalletController) BackEnd() string {
4045
return "mock"
@@ -145,17 +150,17 @@ func (w *mockWalletController) ImportTaprootScript(waddrmgr.KeyScope,
145150
}
146151

147152
// SendOutputs currently returns dummy values.
148-
func (w *mockWalletController) SendOutputs([]*wire.TxOut,
153+
func (w *mockWalletController) SendOutputs(fn.Set[wire.OutPoint], []*wire.TxOut,
149154
chainfee.SatPerKWeight, int32, string,
150155
base.CoinSelectionStrategy) (*wire.MsgTx, error) {
151156

152157
return nil, nil
153158
}
154159

155160
// CreateSimpleTx currently returns dummy values.
156-
func (w *mockWalletController) CreateSimpleTx([]*wire.TxOut,
157-
chainfee.SatPerKWeight, int32, base.CoinSelectionStrategy,
158-
bool) (*txauthor.AuthoredTx, error) {
161+
func (w *mockWalletController) CreateSimpleTx(fn.Set[wire.OutPoint],
162+
[]*wire.TxOut, chainfee.SatPerKWeight, int32,
163+
base.CoinSelectionStrategy, bool) (*txauthor.AuthoredTx, error) {
159164

160165
return nil, nil
161166
}

lnwallet/rpcwallet/rpcwallet.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/btcsuite/btcd/wire"
2323
"github.com/btcsuite/btcwallet/waddrmgr"
2424
basewallet "github.com/btcsuite/btcwallet/wallet"
25+
"github.com/lightningnetwork/lnd/fn"
2526
"github.com/lightningnetwork/lnd/input"
2627
"github.com/lightningnetwork/lnd/keychain"
2728
"github.com/lightningnetwork/lnd/lncfg"
@@ -120,12 +121,13 @@ func (r *RPCKeyRing) NewAddress(addrType lnwallet.AddressType, change bool,
120121
// NOTE: This is a part of the WalletController interface.
121122
//
122123
// NOTE: This method only signs with BIP49/84 keys.
123-
func (r *RPCKeyRing) SendOutputs(outputs []*wire.TxOut,
124-
feeRate chainfee.SatPerKWeight, minConfs int32, label string,
124+
func (r *RPCKeyRing) SendOutputs(inputs fn.Set[wire.OutPoint],
125+
outputs []*wire.TxOut, feeRate chainfee.SatPerKWeight,
126+
minConfs int32, label string,
125127
strategy basewallet.CoinSelectionStrategy) (*wire.MsgTx, error) {
126128

127129
tx, err := r.WalletController.SendOutputs(
128-
outputs, feeRate, minConfs, label, strategy,
130+
inputs, outputs, feeRate, minConfs, label, strategy,
129131
)
130132
if err != nil && err != basewallet.ErrTxUnsigned {
131133
return nil, err

lnwallet/test/test_interface.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ func sendCoins(t *testing.T, miner *rpctest.Harness,
169169
t.Helper()
170170

171171
tx, err := sender.SendOutputs(
172-
[]*wire.TxOut{output}, feeRate, minConf, labels.External,
172+
nil, []*wire.TxOut{output}, feeRate, minConf, labels.External,
173173
sender.Cfg.CoinSelectionStrategy,
174174
)
175175
require.NoError(t, err, "unable to send transaction")
@@ -1193,7 +1193,7 @@ func testListTransactionDetails(miner *rpctest.Harness,
11931193
require.NoError(t, err, "unable to make output script")
11941194
burnOutput := wire.NewTxOut(outputAmt, outputScript)
11951195
burnTX, err := alice.SendOutputs(
1196-
[]*wire.TxOut{burnOutput}, 2500, 1, labels.External,
1196+
nil, []*wire.TxOut{burnOutput}, 2500, 1, labels.External,
11971197
alice.Cfg.CoinSelectionStrategy,
11981198
)
11991199
require.NoError(t, err, "unable to create burn tx")
@@ -1453,7 +1453,7 @@ func testTransactionSubscriptions(miner *rpctest.Harness,
14531453

14541454
burnOutput := wire.NewTxOut(outputAmt, outputScript)
14551455
tx, err := alice.SendOutputs(
1456-
[]*wire.TxOut{burnOutput}, 2500, 1, labels.External,
1456+
nil, []*wire.TxOut{burnOutput}, 2500, 1, labels.External,
14571457
alice.Cfg.CoinSelectionStrategy,
14581458
)
14591459
require.NoError(t, err, "unable to create tx")
@@ -1642,7 +1642,7 @@ func newTx(t *testing.T, r *rpctest.Harness, pubKey *btcec.PublicKey,
16421642
PkScript: keyScript,
16431643
}
16441644
tx, err := alice.SendOutputs(
1645-
[]*wire.TxOut{newOutput}, 2500, 1, labels.External,
1645+
nil, []*wire.TxOut{newOutput}, 2500, 1, labels.External,
16461646
alice.Cfg.CoinSelectionStrategy,
16471647
)
16481648
require.NoError(t, err, "unable to create output")
@@ -1958,7 +1958,7 @@ func testSignOutputUsingTweaks(r *rpctest.Harness,
19581958
PkScript: keyScript,
19591959
}
19601960
tx, err := alice.SendOutputs(
1961-
[]*wire.TxOut{newOutput}, 2500, 1, labels.External,
1961+
nil, []*wire.TxOut{newOutput}, 2500, 1, labels.External,
19621962
alice.Cfg.CoinSelectionStrategy,
19631963
)
19641964
if err != nil {
@@ -2077,7 +2077,7 @@ func testReorgWalletBalance(r *rpctest.Harness, w *lnwallet.LightningWallet,
20772077
PkScript: script,
20782078
}
20792079
tx, err := w.SendOutputs(
2080-
[]*wire.TxOut{output}, 2500, 1, labels.External,
2080+
nil, []*wire.TxOut{output}, 2500, 1, labels.External,
20812081
w.Cfg.CoinSelectionStrategy,
20822082
)
20832083
require.NoError(t, err, "unable to send outputs")
@@ -2302,7 +2302,7 @@ func testSpendUnconfirmed(miner *rpctest.Harness,
23022302
PkScript: alicePkScript,
23032303
}
23042304
_, err = bob.SendOutputs(
2305-
[]*wire.TxOut{output}, txFeeRate, 0, labels.External,
2305+
nil, []*wire.TxOut{output}, txFeeRate, 0, labels.External,
23062306
bob.Cfg.CoinSelectionStrategy,
23072307
)
23082308
if err == nil {
@@ -2329,7 +2329,7 @@ func testSpendUnconfirmed(miner *rpctest.Harness,
23292329
// First, verify that we don't have enough balance to send the coins
23302330
// using confirmed outputs only.
23312331
_, err = bob.SendOutputs(
2332-
[]*wire.TxOut{output}, txFeeRate, 1, labels.External,
2332+
nil, []*wire.TxOut{output}, txFeeRate, 1, labels.External,
23332333
bob.Cfg.CoinSelectionStrategy,
23342334
)
23352335
if err == nil {
@@ -2571,7 +2571,7 @@ func testCreateSimpleTx(r *rpctest.Harness, w *lnwallet.LightningWallet,
25712571

25722572
// Now try creating a tx spending to these outputs.
25732573
createTx, createErr := w.CreateSimpleTx(
2574-
outputs, feeRate, minConfs,
2574+
nil, outputs, feeRate, minConfs,
25752575
w.Cfg.CoinSelectionStrategy, true,
25762576
)
25772577
switch {
@@ -2590,7 +2590,7 @@ func testCreateSimpleTx(r *rpctest.Harness, w *lnwallet.LightningWallet,
25902590
// only difference is that the dry run tx is not signed, and
25912591
// that the change output position might be different.
25922592
tx, sendErr := w.SendOutputs(
2593-
outputs, feeRate, minConfs, labels.External,
2593+
nil, outputs, feeRate, minConfs, labels.External,
25942594
w.Cfg.CoinSelectionStrategy,
25952595
)
25962596
switch {

rpcserver.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ func (r *rpcServer) sendCoinsOnChain(paymentMap map[string]int64,
10771077
// We first do a dry run, to sanity check we won't spend our wallet
10781078
// balance below the reserved amount.
10791079
authoredTx, err := r.server.cc.Wallet.CreateSimpleTx(
1080-
outputs, feeRate, minConfs, strategy, true,
1080+
nil, outputs, feeRate, minConfs, strategy, true,
10811081
)
10821082
if err != nil {
10831083
return nil, err
@@ -1098,7 +1098,7 @@ func (r *rpcServer) sendCoinsOnChain(paymentMap map[string]int64,
10981098
// If that checks out, we're fairly confident that creating sending to
10991099
// these outputs will keep the wallet balance above the reserve.
11001100
tx, err := r.server.cc.Wallet.SendOutputs(
1101-
outputs, feeRate, minConfs, label, strategy,
1101+
nil, outputs, feeRate, minConfs, label, strategy,
11021102
)
11031103
if err != nil {
11041104
return nil, err
@@ -1207,7 +1207,7 @@ func (r *rpcServer) EstimateFee(ctx context.Context,
12071207
wallet := r.server.cc.Wallet
12081208
err = wallet.WithCoinSelectLock(func() error {
12091209
tx, err = wallet.CreateSimpleTx(
1210-
outputs, feePerKw, minConfs, coinSelectionStrategy,
1210+
nil, outputs, feePerKw, minConfs, coinSelectionStrategy,
12111211
true,
12121212
)
12131213
return err

0 commit comments

Comments
 (0)