From 8f35612364dc8180f41128bcd8c32f6f99fd6ded Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 8 Aug 2024 21:58:13 +0800 Subject: [PATCH 1/9] mod: update `btcwallet` version --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0e628d18b0..5abb53852f 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ 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.20240718224643-db3a4a2543bd + github.com/btcsuite/btcwallet v0.16.10-0.20240809133323-7d3434c65ae2 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.2 diff --git a/go.sum b/go.sum index d556042dd3..e77306ddb8 100644 --- a/go.sum +++ b/go.sum @@ -92,8 +92,8 @@ 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.20240718224643-db3a4a2543bd h1:QDb8foTCRoXrfoZVEzSYgSde16MJh4gCtCin8OCS0kI= -github.com/btcsuite/btcwallet v0.16.10-0.20240718224643-db3a4a2543bd/go.mod h1:X2xDre+j1QphTRo54y2TikUzeSvreL1t1aMXrD8Kc5A= +github.com/btcsuite/btcwallet v0.16.10-0.20240809133323-7d3434c65ae2 h1:qa4Avm7p97JroZZyMJADbEb9u853pjleJYSeitENvLc= +github.com/btcsuite/btcwallet v0.16.10-0.20240809133323-7d3434c65ae2/go.mod h1:X2xDre+j1QphTRo54y2TikUzeSvreL1t1aMXrD8Kc5A= 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= From 9801ee036b09d3a4688adc245317f01578ac742a Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 8 Aug 2024 15:01:53 +0800 Subject: [PATCH 2/9] lnwallet+lntest: add `FetchOutpointInfo` and `FetchDerivationInfo` --- lntest/mock/walletcontroller.go | 23 +++++++++++++++++ lnwallet/btcwallet/signer.go | 44 +++++++++++++++++++++++++++++++++ lnwallet/interface.go | 16 +++++++++--- lnwallet/mock.go | 24 ++++++++++++++++++ 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/lntest/mock/walletcontroller.go b/lntest/mock/walletcontroller.go index 7af22e0383..e8d65570b4 100644 --- a/lntest/mock/walletcontroller.go +++ b/lntest/mock/walletcontroller.go @@ -58,6 +58,21 @@ func (w *WalletController) FetchInputInfo( return utxo, nil } +// FetchOutpointInfo will be called to get info about the inputs to the funding +// transaction. +func (w *WalletController) FetchOutpointInfo( + prevOut *wire.OutPoint) (*lnwallet.Utxo, error) { + + utxo := &lnwallet.Utxo{ + AddressType: lnwallet.WitnessPubKey, + Value: 10 * btcutil.SatoshiPerBitcoin, + PkScript: []byte("dummy"), + Confirmations: 1, + OutPoint: *prevOut, + } + return utxo, nil +} + // ScriptForOutput returns the address, witness program and redeem script for a // given UTXO. An error is returned if the UTXO does not belong to our wallet or // it is not a managed pubKey address. @@ -292,3 +307,11 @@ func (w *WalletController) RemoveDescendants(*wire.MsgTx) error { func (w *WalletController) CheckMempoolAcceptance(tx *wire.MsgTx) error { return nil } + +// FetchDerivationInfo queries for the wallet's knowledge of the passed +// pkScript and constructs the derivation info and returns it. +func (w *WalletController) FetchDerivationInfo( + pkScript []byte) (*psbt.Bip32Derivation, error) { + + return nil, nil +} diff --git a/lnwallet/btcwallet/signer.go b/lnwallet/btcwallet/signer.go index 9864164769..e6021f12ad 100644 --- a/lnwallet/btcwallet/signer.go +++ b/lnwallet/btcwallet/signer.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/hdkeychain" + "github.com/btcsuite/btcd/btcutil/psbt" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -56,6 +57,49 @@ func (b *BtcWallet) FetchInputInfo(prevOut *wire.OutPoint) (*lnwallet.Utxo, }, nil } +// FetchOutpointInfo queries for the WalletController's knowledge of the passed +// outpoint. If the base wallet determines this output is under its control, +// then the original txout should be returned. Otherwise, a non-nil error value +// of ErrNotMine should be returned instead. +// +// This is a part of the WalletController interface. +func (b *BtcWallet) FetchOutpointInfo(prevOut *wire.OutPoint) (*lnwallet.Utxo, + error) { + + prevTx, txOut, confirmations, err := b.wallet.FetchOutpointInfo(prevOut) + if err != nil { + return nil, err + } + + // Then, we'll populate all of the information required by the struct. + addressType := lnwallet.UnknownAddressType + switch { + case txscript.IsPayToWitnessPubKeyHash(txOut.PkScript): + addressType = lnwallet.WitnessPubKey + case txscript.IsPayToScriptHash(txOut.PkScript): + addressType = lnwallet.NestedWitnessPubKey + case txscript.IsPayToTaproot(txOut.PkScript): + addressType = lnwallet.TaprootPubkey + } + + return &lnwallet.Utxo{ + AddressType: addressType, + Value: btcutil.Amount(txOut.Value), + PkScript: txOut.PkScript, + Confirmations: confirmations, + OutPoint: *prevOut, + PrevTx: prevTx, + }, nil +} + +// FetchDerivationInfo queries for the wallet's knowledge of the passed +// pkScript and constructs the derivation info and returns it. +func (b *BtcWallet) FetchDerivationInfo( + pkScript []byte) (*psbt.Bip32Derivation, error) { + + return b.wallet.FetchDerivationInfo(pkScript) +} + // ScriptForOutput returns the address, witness program and redeem script for a // given UTXO. An error is returned if the UTXO does not belong to our wallet or // it is not a managed pubKey address. diff --git a/lnwallet/interface.go b/lnwallet/interface.go index af5955d8e6..37568cfa67 100644 --- a/lnwallet/interface.go +++ b/lnwallet/interface.go @@ -228,11 +228,21 @@ type TransactionSubscription interface { // across all concrete implementations. type WalletController interface { // FetchInputInfo queries for the WalletController's knowledge of the - // passed outpoint. If the base wallet determines this output is under - // its control, then the original txout should be returned. Otherwise, - // a non-nil error value of ErrNotMine should be returned instead. + // passed outpoint. It returns the same info as `FetchOutpointInfo` + // plus the Bip32Derivation info. FetchInputInfo(prevOut *wire.OutPoint) (*Utxo, error) + // FetchOutpointInfo queries for the WalletController's knowledge of + // the passed outpoint. If the base wallet determines this output is + // under its control, then the original txout should be returned. + // Otherwise, a non-nil error value of ErrNotMine should be returned + // instead. + FetchOutpointInfo(prevOut *wire.OutPoint) (*Utxo, error) + + // FetchDerivationInfo queries for the wallet's knowledge of the passed + // pkScript and constructs the derivation info and returns it. + FetchDerivationInfo(pkScript []byte) (*psbt.Bip32Derivation, error) + // ScriptForOutput returns the address, witness program and redeem // script for a given UTXO. An error is returned if the UTXO does not // belong to our wallet or it is not a managed pubKey address. diff --git a/lnwallet/mock.go b/lnwallet/mock.go index e6bd0b2e41..62efd6145c 100644 --- a/lnwallet/mock.go +++ b/lnwallet/mock.go @@ -61,6 +61,22 @@ func (w *mockWalletController) FetchInputInfo( return utxo, nil } +// FetchOutpointInfo will be called to get info about the inputs to the funding +// transaction. +func (w *mockWalletController) FetchOutpointInfo( + prevOut *wire.OutPoint) (*Utxo, error) { + + utxo := &Utxo{ + AddressType: WitnessPubKey, + Value: 10 * btcutil.SatoshiPerBitcoin, + PkScript: []byte("dummy"), + Confirmations: 1, + OutPoint: *prevOut, + } + + return utxo, nil +} + // ScriptForOutput returns the address, witness program and redeem script for a // given UTXO. An error is returned if the UTXO does not belong to our wallet or // it is not a managed pubKey address. @@ -300,6 +316,14 @@ func (w *mockWalletController) RemoveDescendants(*wire.MsgTx) error { return nil } +// FetchDerivationInfo queries for the wallet's knowledge of the passed +// pkScript and constructs the derivation info and returns it. +func (w *mockWalletController) FetchDerivationInfo( + pkScript []byte) (*psbt.Bip32Derivation, error) { + + return nil, nil +} + func (w *mockWalletController) CheckMempoolAcceptance(tx *wire.MsgTx) error { return nil } From aba8507b2a52f4222d3bb2c6873a36c94511569c Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 8 Aug 2024 21:53:27 +0800 Subject: [PATCH 3/9] lnrpc+lnwallet: replace `FetchInputInfo` with new methods This commit replaces the usage of `FetchInputInfo` with `FetchOutpointInfo` and `FetchDerivationInfo` to remove unncessary fetching of the derivation path. --- lnrpc/walletrpc/walletkit_server.go | 2 +- lnwallet/rpcwallet/rpcwallet.go | 25 +++++++++++++++++++------ lnwallet/wallet.go | 6 +++--- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index e70a1a7712..f72c6986a3 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -1142,7 +1142,7 @@ func (w *WalletKit) sweepNewInput(op *wire.OutPoint, currentHeight uint32, // // We'll gather all of the information required by the UtxoSweeper in // order to sweep the output. - utxo, err := w.cfg.Wallet.FetchInputInfo(op) + utxo, err := w.cfg.Wallet.FetchOutpointInfo(op) if err != nil { return err } diff --git a/lnwallet/rpcwallet/rpcwallet.go b/lnwallet/rpcwallet/rpcwallet.go index c702174163..bf6aa61df3 100644 --- a/lnwallet/rpcwallet/rpcwallet.go +++ b/lnwallet/rpcwallet/rpcwallet.go @@ -154,7 +154,7 @@ func (r *RPCKeyRing) SendOutputs(inputs fn.Set[wire.OutPoint], // watch-only wallet if it can map this outpoint into a coin we // own. If not, then we can't continue because our wallet state // is out of sync. - info, err := r.WalletController.FetchInputInfo( + info, err := r.WalletController.FetchOutpointInfo( &txIn.PreviousOutPoint, ) if err != nil { @@ -289,7 +289,7 @@ func (r *RPCKeyRing) FinalizePsbt(packet *psbt.Packet, _ string) error { // We can only sign this input if it's ours, so we try to map it // to a coin we own. If we can't, then we'll continue as it // isn't our input. - utxo, err := r.FetchInputInfo(&txIn.PreviousOutPoint) + utxo, err := r.FetchOutpointInfo(&txIn.PreviousOutPoint) if err != nil { continue } @@ -906,7 +906,7 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor, } txIn := tx.TxIn[idx] - info, err := r.WalletController.FetchInputInfo( + info, err := r.WalletController.FetchOutpointInfo( &txIn.PreviousOutPoint, ) if err != nil { @@ -1015,19 +1015,32 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor, signDesc.KeyDesc.PubKey = fullDesc.PubKey } + var derivation *psbt.Bip32Derivation + // Make sure we actually know about the input. We either have been // watching the UTXO on-chain or we have been given all the required // info in the sign descriptor. - info, err := r.WalletController.FetchInputInfo(&txIn.PreviousOutPoint) + info, err := r.WalletController.FetchOutpointInfo( + &txIn.PreviousOutPoint, + ) + + // If the wallet is aware of this outpoint, we go ahead and fetch the + // derivation info. + if err == nil { + derivation, err = r.WalletController.FetchDerivationInfo( + info.PkScript, + ) + } + switch { - // No error, we do have the full UTXO and derivation info available. + // No error, we do have the full UTXO info available. case err == nil: in.WitnessUtxo = &wire.TxOut{ Value: int64(info.Value), PkScript: info.PkScript, } in.NonWitnessUtxo = info.PrevTx - in.Bip32Derivation = []*psbt.Bip32Derivation{info.Derivation} + in.Bip32Derivation = []*psbt.Bip32Derivation{derivation} // The wallet doesn't know about this UTXO, so it's probably a TX that // we haven't published yet (e.g. a channel funding TX). So we need to diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 90a0bea2d3..6925446a3e 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -1646,7 +1646,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) { []*input.Script, 0, len(ourContribution.Inputs), ) for _, txIn := range fundingTx.TxIn { - _, err := l.FetchInputInfo(&txIn.PreviousOutPoint) + _, err := l.FetchOutpointInfo(&txIn.PreviousOutPoint) if err != nil { continue } @@ -2592,7 +2592,7 @@ func (c *CoinSource) ListCoins(minConfs int32, // 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) (*wallet.Coin, error) { - inputInfo, err := c.wallet.FetchInputInfo(&op) + inputInfo, err := c.wallet.FetchOutpointInfo(&op) if err != nil { return nil, err } @@ -2689,7 +2689,7 @@ func NewWalletPrevOutputFetcher(wc WalletController) *WalletPrevOutputFetcher { // passed outpoint. A nil value will be returned if the passed outpoint doesn't // exist. func (w *WalletPrevOutputFetcher) FetchPrevOutput(op wire.OutPoint) *wire.TxOut { - utxo, err := w.wc.FetchInputInfo(&op) + utxo, err := w.wc.FetchOutpointInfo(&op) if err != nil { return nil } From d7381ce3fe300283901c595e12c10307496116d8 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 1 Aug 2024 03:08:56 +0800 Subject: [PATCH 4/9] rpcserver: remove redundant call to `FetchInputInfo` --- rpcserver.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 7fef873266..005bc38fc9 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3488,14 +3488,7 @@ func (r *rpcServer) WalletBalance(ctx context.Context, return nil, err } for _, leasedOutput := range leases { - utxoInfo, err := r.server.cc.Wallet.FetchInputInfo( - &leasedOutput.Outpoint, - ) - if err != nil { - return nil, err - } - - lockedBalance += utxoInfo.Value + lockedBalance += btcutil.Amount(leasedOutput.Value) } // Get the current number of non-private anchor channels. From b17db4a32ac370684f6c8a8e58ec89149cb2b3a9 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 8 Aug 2024 21:55:10 +0800 Subject: [PATCH 5/9] lntest+lnwallet: remove the method `FetchInputInfo` This method is no longer used. In addition, the `Derivation` field on the `Utxo` is also removed to avoid nil dereference. --- lntest/mock/walletcontroller.go | 15 ------------- lnwallet/btcwallet/signer.go | 38 --------------------------------- lnwallet/interface.go | 8 +------ lnwallet/mock.go | 16 -------------- 4 files changed, 1 insertion(+), 76 deletions(-) diff --git a/lntest/mock/walletcontroller.go b/lntest/mock/walletcontroller.go index e8d65570b4..bfef14ee01 100644 --- a/lntest/mock/walletcontroller.go +++ b/lntest/mock/walletcontroller.go @@ -43,21 +43,6 @@ func (w *WalletController) BackEnd() string { return "mock" } -// FetchInputInfo will be called to get info about the inputs to the funding -// transaction. -func (w *WalletController) FetchInputInfo( - prevOut *wire.OutPoint) (*lnwallet.Utxo, error) { - - utxo := &lnwallet.Utxo{ - AddressType: lnwallet.WitnessPubKey, - Value: 10 * btcutil.SatoshiPerBitcoin, - PkScript: []byte("dummy"), - Confirmations: 1, - OutPoint: *prevOut, - } - return utxo, nil -} - // FetchOutpointInfo will be called to get info about the inputs to the funding // transaction. func (w *WalletController) FetchOutpointInfo( diff --git a/lnwallet/btcwallet/signer.go b/lnwallet/btcwallet/signer.go index e6021f12ad..97832a7890 100644 --- a/lnwallet/btcwallet/signer.go +++ b/lnwallet/btcwallet/signer.go @@ -19,44 +19,6 @@ import ( "github.com/lightningnetwork/lnd/lnwallet" ) -// FetchInputInfo queries for the WalletController's knowledge of the passed -// outpoint. If the base wallet determines this output is under its control, -// then the original txout should be returned. Otherwise, a non-nil error value -// of ErrNotMine should be returned instead. -// -// This is a part of the WalletController interface. -func (b *BtcWallet) FetchInputInfo(prevOut *wire.OutPoint) (*lnwallet.Utxo, - error) { - - prevTx, txOut, bip32, confirmations, err := b.wallet.FetchInputInfo( - prevOut, - ) - if err != nil { - return nil, err - } - - // Then, we'll populate all of the information required by the struct. - addressType := lnwallet.UnknownAddressType - switch { - case txscript.IsPayToWitnessPubKeyHash(txOut.PkScript): - addressType = lnwallet.WitnessPubKey - case txscript.IsPayToScriptHash(txOut.PkScript): - addressType = lnwallet.NestedWitnessPubKey - case txscript.IsPayToTaproot(txOut.PkScript): - addressType = lnwallet.TaprootPubkey - } - - return &lnwallet.Utxo{ - AddressType: addressType, - Value: btcutil.Amount(txOut.Value), - PkScript: txOut.PkScript, - Confirmations: confirmations, - OutPoint: *prevOut, - Derivation: bip32, - PrevTx: prevTx, - }, nil -} - // FetchOutpointInfo queries for the WalletController's knowledge of the passed // outpoint. If the base wallet determines this output is under its control, // then the original txout should be returned. Otherwise, a non-nil error value diff --git a/lnwallet/interface.go b/lnwallet/interface.go index 37568cfa67..94478f1110 100644 --- a/lnwallet/interface.go +++ b/lnwallet/interface.go @@ -126,8 +126,7 @@ type Utxo struct { Confirmations int64 PkScript []byte wire.OutPoint - Derivation *psbt.Bip32Derivation - PrevTx *wire.MsgTx + PrevTx *wire.MsgTx } // OutputDetail contains additional information on a destination address. @@ -227,11 +226,6 @@ type TransactionSubscription interface { // behavior of all interface methods in order to ensure identical behavior // across all concrete implementations. type WalletController interface { - // FetchInputInfo queries for the WalletController's knowledge of the - // passed outpoint. It returns the same info as `FetchOutpointInfo` - // plus the Bip32Derivation info. - FetchInputInfo(prevOut *wire.OutPoint) (*Utxo, error) - // FetchOutpointInfo queries for the WalletController's knowledge of // the passed outpoint. If the base wallet determines this output is // under its control, then the original txout should be returned. diff --git a/lnwallet/mock.go b/lnwallet/mock.go index 62efd6145c..5016fa0d67 100644 --- a/lnwallet/mock.go +++ b/lnwallet/mock.go @@ -45,22 +45,6 @@ func (w *mockWalletController) BackEnd() string { return "mock" } -// FetchInputInfo will be called to get info about the inputs to the funding -// transaction. -func (w *mockWalletController) FetchInputInfo( - prevOut *wire.OutPoint) (*Utxo, error) { - - utxo := &Utxo{ - AddressType: WitnessPubKey, - Value: 10 * btcutil.SatoshiPerBitcoin, - PkScript: []byte("dummy"), - Confirmations: 1, - OutPoint: *prevOut, - } - - return utxo, nil -} - // FetchOutpointInfo will be called to get info about the inputs to the funding // transaction. func (w *mockWalletController) FetchOutpointInfo( From f70c9191648eb33ac38caeac5eb6e037a82293d9 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 1 Aug 2024 02:44:48 +0800 Subject: [PATCH 6/9] lnrpc: fetch utxo info in `lockInputs` This commit prepares the following commit where we change the `LeaseOutput` to be more efficient. --- lnrpc/walletrpc/psbt.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lnrpc/walletrpc/psbt.go b/lnrpc/walletrpc/psbt.go index 19b1024733..4d3e8641a2 100644 --- a/lnrpc/walletrpc/psbt.go +++ b/lnrpc/walletrpc/psbt.go @@ -56,7 +56,13 @@ func lockInputs(w lnwallet.WalletController, }, } - expiration, pkScript, value, err := w.LeaseOutput( + // Get the details about this outpoint. + utxo, err := w.FetchOutpointInfo(&lock.Outpoint) + if err != nil { + return nil, fmt.Errorf("fetch outpoint info: %w", err) + } + + expiration, _, _, err := w.LeaseOutput( lock.LockID, lock.Outpoint, chanfunding.DefaultLockDuration, ) @@ -80,8 +86,8 @@ func lockInputs(w lnwallet.WalletController, } lock.Expiration = expiration - lock.PkScript = pkScript - lock.Value = int64(value) + lock.PkScript = utxo.PkScript + lock.Value = int64(utxo.Value) locks[idx] = lock } From 3e36adf476c6ece37fce084083f0ab855af9794e Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 1 Aug 2024 03:01:54 +0800 Subject: [PATCH 7/9] mulit: remove `ListLeasedOutputs` in `LeaseOutput` This commit removes the call toe `ListLeasedOutputs` in `LeaseOutput` - the returned info from `ListLeasedOutputs` can easily be accessed via `FetchInputInfo` and this info is only used at one callsite. `ListLeasedOutputs` then becomes unnecessary here, plus it's very slow and needs to be refactored in `btcwallet` instead. --- lnrpc/walletrpc/psbt.go | 2 +- lnrpc/walletrpc/walletkit_server.go | 2 +- lntest/mock/walletcontroller.go | 4 ++-- lnwallet/btcwallet/btcwallet.go | 24 ++++-------------------- lnwallet/chanfunding/assembler.go | 2 +- lnwallet/chanfunding/wallet_assembler.go | 2 +- lnwallet/interface.go | 3 +-- lnwallet/mock.go | 4 ++-- sweep/walletsweep.go | 4 ++-- sweep/walletsweep_test.go | 4 ++-- 10 files changed, 17 insertions(+), 34 deletions(-) diff --git a/lnrpc/walletrpc/psbt.go b/lnrpc/walletrpc/psbt.go index 4d3e8641a2..0577519647 100644 --- a/lnrpc/walletrpc/psbt.go +++ b/lnrpc/walletrpc/psbt.go @@ -62,7 +62,7 @@ func lockInputs(w lnwallet.WalletController, return nil, fmt.Errorf("fetch outpoint info: %w", err) } - expiration, _, _, err := w.LeaseOutput( + expiration, err := w.LeaseOutput( lock.LockID, lock.Outpoint, chanfunding.DefaultLockDuration, ) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index f72c6986a3..cc836e809f 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -490,7 +490,7 @@ func (w *WalletKit) LeaseOutput(ctx context.Context, // other concurrent processes attempting to lease the same UTXO. var expiration time.Time err = w.cfg.CoinSelectionLocker.WithCoinSelectLock(func() error { - expiration, _, _, err = w.cfg.Wallet.LeaseOutput( + expiration, err = w.cfg.Wallet.LeaseOutput( lockID, *op, duration, ) return err diff --git a/lntest/mock/walletcontroller.go b/lntest/mock/walletcontroller.go index bfef14ee01..cb7e387010 100644 --- a/lntest/mock/walletcontroller.go +++ b/lntest/mock/walletcontroller.go @@ -195,9 +195,9 @@ func (w *WalletController) ListTransactionDetails(int32, int32, // LeaseOutput returns the current time and a nil error. func (w *WalletController) LeaseOutput(wtxmgr.LockID, wire.OutPoint, - time.Duration) (time.Time, []byte, btcutil.Amount, error) { + time.Duration) (time.Time, error) { - return time.Now(), nil, 0, nil + return time.Now(), nil } // ReleaseOutput currently does nothing. diff --git a/lnwallet/btcwallet/btcwallet.go b/lnwallet/btcwallet/btcwallet.go index b3f9b4f9b1..22204dea39 100644 --- a/lnwallet/btcwallet/btcwallet.go +++ b/lnwallet/btcwallet/btcwallet.go @@ -1079,36 +1079,20 @@ func (b *BtcWallet) CreateSimpleTx(inputs fn.Set[wire.OutPoint], // // NOTE: This method requires the global coin selection lock to be held. func (b *BtcWallet) LeaseOutput(id wtxmgr.LockID, op wire.OutPoint, - duration time.Duration) (time.Time, []byte, btcutil.Amount, error) { + duration time.Duration) (time.Time, error) { // Make sure we don't attempt to double lock an output that's been // locked by the in-memory implementation. if b.wallet.LockedOutpoint(op) { - return time.Time{}, nil, 0, wtxmgr.ErrOutputAlreadyLocked + return time.Time{}, wtxmgr.ErrOutputAlreadyLocked } lockedUntil, err := b.wallet.LeaseOutput(id, op, duration) if err != nil { - return time.Time{}, nil, 0, err + return time.Time{}, err } - // Get the pkScript and value for this lock from the list of all leased - // outputs. - allLeases, err := b.wallet.ListLeasedOutputs() - if err != nil { - return time.Time{}, nil, 0, err - } - - for _, lease := range allLeases { - if lease.Outpoint == op { - return lockedUntil, lease.PkScript, - btcutil.Amount(lease.Value), nil - } - } - - // We MUST find the leased output in the loop above, otherwise something - // is seriously wrong. - return time.Time{}, nil, 0, wtxmgr.ErrUnknownOutput + return lockedUntil, nil } // ListLeasedOutputs returns a list of all currently locked outputs. diff --git a/lnwallet/chanfunding/assembler.go b/lnwallet/chanfunding/assembler.go index a694d2a2c4..2fdb87b32d 100644 --- a/lnwallet/chanfunding/assembler.go +++ b/lnwallet/chanfunding/assembler.go @@ -44,7 +44,7 @@ type OutputLeaser interface { // LeaseOutput leases a target output, rendering it unusable for coin // selection. LeaseOutput(i wtxmgr.LockID, o wire.OutPoint, d time.Duration) ( - time.Time, []byte, btcutil.Amount, error) + time.Time, error) // ReleaseOutput releases a target output, allowing it to be used for // coin selection once again. diff --git a/lnwallet/chanfunding/wallet_assembler.go b/lnwallet/chanfunding/wallet_assembler.go index 4f2aa759b2..f824210e13 100644 --- a/lnwallet/chanfunding/wallet_assembler.go +++ b/lnwallet/chanfunding/wallet_assembler.go @@ -525,7 +525,7 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) { for _, coin := range selectedCoins { outpoint := coin.OutPoint - _, _, _, err = w.cfg.CoinLeaser.LeaseOutput( + _, err = w.cfg.CoinLeaser.LeaseOutput( LndInternalLockID, outpoint, DefaultReservationTimeout, ) diff --git a/lnwallet/interface.go b/lnwallet/interface.go index 94478f1110..d3b123509b 100644 --- a/lnwallet/interface.go +++ b/lnwallet/interface.go @@ -413,8 +413,7 @@ type WalletController interface { // // NOTE: This method requires the global coin selection lock to be held. LeaseOutput(id wtxmgr.LockID, op wire.OutPoint, - duration time.Duration) (time.Time, []byte, btcutil.Amount, - error) + duration time.Duration) (time.Time, error) // ReleaseOutput unlocks an output, allowing it to be available for coin // selection if it remains unspent. The ID should match the one used to diff --git a/lnwallet/mock.go b/lnwallet/mock.go index 5016fa0d67..faac5fa678 100644 --- a/lnwallet/mock.go +++ b/lnwallet/mock.go @@ -201,9 +201,9 @@ func (w *mockWalletController) ListTransactionDetails(int32, int32, // LeaseOutput returns the current time and a nil error. func (w *mockWalletController) LeaseOutput(wtxmgr.LockID, wire.OutPoint, - time.Duration) (time.Time, []byte, btcutil.Amount, error) { + time.Duration) (time.Time, error) { - return time.Now(), nil, 0, nil + return time.Now(), nil } // ReleaseOutput currently does nothing. diff --git a/sweep/walletsweep.go b/sweep/walletsweep.go index 919e5f1d51..da5e56dee0 100644 --- a/sweep/walletsweep.go +++ b/sweep/walletsweep.go @@ -179,7 +179,7 @@ type OutputLeaser interface { // LeaseOutput leases a target output, rendering it unusable for coin // selection. LeaseOutput(i wtxmgr.LockID, o wire.OutPoint, d time.Duration) ( - time.Time, []byte, btcutil.Amount, error) + time.Time, error) // ReleaseOutput releases a target output, allowing it to be used for // coin selection once again. @@ -284,7 +284,7 @@ func CraftSweepAllTx(feeRate, maxFeeRate chainfee.SatPerKWeight, log.Tracef("[WithCoinSelectLock] leasing utxo: %v", utxo.OutPoint) - _, _, _, err = outputLeaser.LeaseOutput( + _, err = outputLeaser.LeaseOutput( chanfunding.LndInternalLockID, utxo.OutPoint, chanfunding.DefaultLockDuration, ) diff --git a/sweep/walletsweep_test.go b/sweep/walletsweep_test.go index f5ed0283e7..968d9cb4fb 100644 --- a/sweep/walletsweep_test.go +++ b/sweep/walletsweep_test.go @@ -199,11 +199,11 @@ func newMockOutputLeaser() *mockOutputLeaser { } func (m *mockOutputLeaser) LeaseOutput(_ wtxmgr.LockID, o wire.OutPoint, - t time.Duration) (time.Time, []byte, btcutil.Amount, error) { + t time.Duration) (time.Time, error) { m.leasedOutputs[o] = struct{}{} - return time.Now().Add(t), nil, 0, nil + return time.Now().Add(t), nil } func (m *mockOutputLeaser) ReleaseOutput(_ wtxmgr.LockID, From 8259e0fb5fafbce26544dec5a0146a05de9bfc42 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 1 Aug 2024 03:10:42 +0800 Subject: [PATCH 8/9] itest: remove redundant call to `ht.WaitForBlockchainSync` This check has already been done when mining blocks. --- itest/lnd_hold_invoice_force_test.go | 8 -------- itest/lnd_psbt_test.go | 1 - itest/lnd_route_blinding_test.go | 4 ---- 3 files changed, 13 deletions(-) diff --git a/itest/lnd_hold_invoice_force_test.go b/itest/lnd_hold_invoice_force_test.go index 2b251b3cb9..7c616e7a50 100644 --- a/itest/lnd_hold_invoice_force_test.go +++ b/itest/lnd_hold_invoice_force_test.go @@ -95,10 +95,6 @@ func testHoldInvoiceForceClose(ht *lntest.HarnessTest) { // We first mine enough blocks to trigger an invoice cancelation. ht.MineBlocks(int(blocksTillCancel)) - // Wait for the nodes to be synced. - ht.WaitForBlockchainSync(alice) - ht.WaitForBlockchainSync(bob) - // Check that the invoice is canceled by Bob. err := wait.NoError(func() error { inv := bob.RPC.LookupInvoice(payHash[:]) @@ -135,10 +131,6 @@ func testHoldInvoiceForceClose(ht *lntest.HarnessTest) { // invoice cancelation message was received by Alice. ht.MineBlocks(int(blocksTillForce - blocksTillCancel)) - // Wait for the nodes to be synced. - ht.WaitForBlockchainSync(alice) - ht.WaitForBlockchainSync(bob) - // Check that Alice has not closed the channel because there are no // outgoing HTLCs in her channel as the only HTLC has already been // canceled. diff --git a/itest/lnd_psbt_test.go b/itest/lnd_psbt_test.go index 91d67ba376..ac39bb4971 100644 --- a/itest/lnd_psbt_test.go +++ b/itest/lnd_psbt_test.go @@ -1578,7 +1578,6 @@ func sendAllCoinsToAddrType(ht *lntest.HarnessTest, }) ht.MineBlocksAndAssertNumTxes(1, 1) - ht.WaitForBlockchainSync(hn) } // testPsbtChanFundingFailFlow tests the failing of a funding flow by the diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index 44d5879f99..fbfca0f275 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -852,10 +852,6 @@ func testErrorHandlingOnChainFailure(ht *lntest.HarnessTest) { ht.AssertNumPendingSweeps(ht.Bob, 0) ht.MineBlocksAndAssertNumTxes(1, 1) - // Assert that the HTLC has cleared. - ht.WaitForBlockchainSync(ht.Bob) - ht.WaitForBlockchainSync(ht.Alice) - ht.AssertHTLCNotActive(ht.Bob, testCase.channels[0], hash[:]) ht.AssertHTLCNotActive(ht.Alice, testCase.channels[0], hash[:]) From 363e529f9b6e1276b940071fb95e5d5808ad2cfb Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 1 Aug 2024 03:59:55 +0800 Subject: [PATCH 9/9] docs: update release notes --- docs/release-notes/release-notes-0.18.3.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/release-notes/release-notes-0.18.3.md b/docs/release-notes/release-notes-0.18.3.md index 8ba9eefadf..d60b069ff4 100644 --- a/docs/release-notes/release-notes-0.18.3.md +++ b/docs/release-notes/release-notes-0.18.3.md @@ -151,6 +151,11 @@ commitment when the channel was force closed. * [Allow](https://github.com/lightningnetwork/lnd/pull/8845) multiple etcd hosts to be specified in db.etcd.host. +* Improved the internal [`LeaseOutput` + method](https://github.com/lightningnetwork/lnd/pull/8961) to be more + efficient, which improves the performance of related RPC calls such as + `LeaseOutput`, `SendCoins`, and PSBT funding process. + ## RPC Updates * [`xImportMissionControl`](https://github.com/lightningnetwork/lnd/pull/8779)