From 596d9698812d0cc38e9c5c86f91a7da73a801ee7 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 16 Jul 2025 18:01:05 +0800 Subject: [PATCH 1/4] btcwallet: fix duplicate import The `wallet` has already imported using `base`. --- lnwallet/btcwallet/btcwallet.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lnwallet/btcwallet/btcwallet.go b/lnwallet/btcwallet/btcwallet.go index 455d79ee0..32497a5ca 100644 --- a/lnwallet/btcwallet/btcwallet.go +++ b/lnwallet/btcwallet/btcwallet.go @@ -19,7 +19,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/chain" "github.com/btcsuite/btcwallet/waddrmgr" - "github.com/btcsuite/btcwallet/wallet" base "github.com/btcsuite/btcwallet/wallet" "github.com/btcsuite/btcwallet/wallet/txauthor" "github.com/btcsuite/btcwallet/wallet/txrules" @@ -981,11 +980,11 @@ func (b *BtcWallet) CreateSimpleTx(inputs fn.Set[wire.OutPoint], } // Add the optional inputs to the transaction. - optFunc := wallet.WithCustomSelectUtxos(inputs.ToSlice()) + optFunc := base.WithCustomSelectUtxos(inputs.ToSlice()) return b.wallet.CreateSimpleTx( nil, defaultAccount, outputs, minConfs, feeSatPerKB, - strategy, dryRun, []wallet.TxCreateOption{optFunc}..., + strategy, dryRun, []base.TxCreateOption{optFunc}..., ) } From 24033134431a70c53f3a728ffa1f538ece2a3f3e Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Mon, 11 Aug 2025 17:47:23 +0800 Subject: [PATCH 2/4] gomod: update btcwallet --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c321cf977..7dc8cc2fd 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog v0.0.0-20241003133417-09c4e92e319c github.com/btcsuite/btclog/v2 v2.0.1-0.20250728225537-6090e87c6c5b - github.com/btcsuite/btcwallet v0.16.15-0.20250805011126-a3632ae48ab3 + github.com/btcsuite/btcwallet v0.16.15-0.20250811092146-05b3a40651e6 github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5 github.com/btcsuite/btcwallet/wallet/txrules v1.2.2 github.com/btcsuite/btcwallet/walletdb v1.5.1 diff --git a/go.sum b/go.sum index 2ef822fbe..4f9d613bb 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,8 @@ github.com/btcsuite/btclog v0.0.0-20241003133417-09c4e92e319c/go.mod h1:w7xnGOhw github.com/btcsuite/btclog/v2 v2.0.1-0.20250728225537-6090e87c6c5b h1:MQ+Q6sDy37V1wP1Yu79A5KqJutolqUGwA99UZWQDWZM= github.com/btcsuite/btclog/v2 v2.0.1-0.20250728225537-6090e87c6c5b/go.mod h1:XItGUfVOxotJL8kkuk2Hj3EVow5KCugXl3wWfQ6K0AE= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.16.15-0.20250805011126-a3632ae48ab3 h1:MAjNRpj3XhCOrhchq4wq0qI34TIBX/DCnT6OLWejx68= -github.com/btcsuite/btcwallet v0.16.15-0.20250805011126-a3632ae48ab3/go.mod h1:H6dfoZcWPonM2wbVsR2ZBY0PKNZKdQyLAmnX8vL9JFA= +github.com/btcsuite/btcwallet v0.16.15-0.20250811092146-05b3a40651e6 h1:s6NCipDdvDK5rBrC4dIlni1iHsuDOKdfwpL32I3b6Tw= +github.com/btcsuite/btcwallet v0.16.15-0.20250811092146-05b3a40651e6/go.mod h1:H6dfoZcWPonM2wbVsR2ZBY0PKNZKdQyLAmnX8vL9JFA= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5 h1:Rr0njWI3r341nhSPesKQ2JF+ugDSzdPoeckS75SeDZk= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5/go.mod h1:+tXJ3Ym0nlQc/iHSwW1qzjmPs3ev+UVWMbGgfV1OZqU= github.com/btcsuite/btcwallet/wallet/txrules v1.2.2 h1:YEO+Lx1ZJJAtdRrjuhXjWrYsmAk26wLTlNzxt2q0lhk= From b10aca5c1bf15803221abaaf9edf50dab9a62e88 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 6 Aug 2025 23:06:31 +0800 Subject: [PATCH 3/4] lnwallet: use the wallet interface --- keychain/btcwallet.go | 16 ++++++++++------ lnwallet/btcwallet/btcwallet.go | 26 ++++++++++++++------------ lnwallet/btcwallet/signer_test.go | 2 +- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/keychain/btcwallet.go b/keychain/btcwallet.go index 677de20da..cdacef53b 100644 --- a/keychain/btcwallet.go +++ b/keychain/btcwallet.go @@ -48,7 +48,7 @@ type BtcWalletKeyRing struct { // wallet is a pointer to the active instance of the btcwallet core. // This is required as we'll need to manually open database // transactions in order to derive addresses and lookup relevant keys - wallet *wallet.Wallet + wallet wallet.Interface // chainKeyScope defines the purpose and coin type to be used when generating // keys for this keyring. @@ -64,7 +64,7 @@ type BtcWalletKeyRing struct { // // NOTE: The passed waddrmgr.Manager MUST be unlocked in order for the keychain // to function. -func NewBtcWalletKeyRing(w *wallet.Wallet, coinType uint32) SecretKeyRing { +func NewBtcWalletKeyRing(w wallet.Interface, coinType uint32) SecretKeyRing { // Construct the key scope that will be used within the waddrmgr to // create an HD chain for deriving all of our required keys. A different // scope is used for each specific coin type. @@ -92,14 +92,18 @@ func (b *BtcWalletKeyRing) keyScope() (*waddrmgr.ScopedKeyManager, error) { // Otherwise, we'll first do a check to ensure that the root manager // isn't locked, as otherwise we won't be able to *use* the scope. - if !b.wallet.Manager.WatchOnly() && b.wallet.Manager.IsLocked() { + if !b.wallet.AddrManager().WatchOnly() && + b.wallet.AddrManager().IsLocked() { + return nil, fmt.Errorf("cannot create BtcWalletKeyRing with " + "locked waddrmgr.Manager") } // If the manager is indeed unlocked, then we'll fetch the scope, cache // it, and return to the caller. - lnScope, err := b.wallet.Manager.FetchScopedKeyManager(b.chainKeyScope) + lnScope, err := b.wallet.AddrManager().FetchScopedKeyManager( + b.chainKeyScope, + ) if err != nil { return nil, err } @@ -218,7 +222,7 @@ func (b *BtcWalletKeyRing) DeriveKey(keyLoc KeyLocator) (KeyDescriptor, error) { // require. We skip this if we're using a remote signer in which // case we _need_ to create all accounts when creating the // wallet, so it must exist now. - if !b.wallet.Manager.WatchOnly() { + if !b.wallet.AddrManager().WatchOnly() { err = b.createAccountIfNotExists( addrmgrNs, keyLoc.Family, scope, ) @@ -288,7 +292,7 @@ func (b *BtcWalletKeyRing) DerivePrivKey(keyDesc KeyDescriptor) ( // require. We skip this if we're using a remote signer in which // case we _need_ to create all accounts when creating the // wallet, so it must exist now. - if !b.wallet.Manager.WatchOnly() { + if !b.wallet.AddrManager().WatchOnly() { err = b.createAccountIfNotExists( addrmgrNs, keyDesc.Family, scope, ) diff --git a/lnwallet/btcwallet/btcwallet.go b/lnwallet/btcwallet/btcwallet.go index 32497a5ca..682908cd0 100644 --- a/lnwallet/btcwallet/btcwallet.go +++ b/lnwallet/btcwallet/btcwallet.go @@ -84,7 +84,7 @@ var ( // operate. type BtcWallet struct { // wallet is an active instance of btcwallet. - wallet *base.Wallet + wallet base.Interface chain chain.Interface @@ -288,7 +288,7 @@ func (b *BtcWallet) BackEnd() string { // InternalWallet returns a pointer to the internal base wallet which is the // core of btcwallet. -func (b *BtcWallet) InternalWallet() *base.Wallet { +func (b *BtcWallet) InternalWallet() base.Interface { return b.wallet } @@ -299,7 +299,7 @@ func (b *BtcWallet) InternalWallet() *base.Wallet { func (b *BtcWallet) Start() error { // Is the wallet (according to its database) currently watch-only // already? If it is, we won't need to convert it later. - walletIsWatchOnly := b.wallet.Manager.WatchOnly() + walletIsWatchOnly := b.wallet.AddrManager().WatchOnly() // If the wallet is watch-only, but we don't expect it to be, then we // are in an unexpected state and cannot continue. @@ -335,7 +335,7 @@ func (b *BtcWallet) Start() error { // created correctly for new wallets. Existing wallets don't // automatically add them, we need to do that manually now. for _, scope := range LndDefaultKeyScopes { - _, err := b.wallet.Manager.FetchScopedKeyManager(scope) + _, err := b.wallet.AddrManager().FetchScopedKeyManager(scope) if waddrmgr.IsError(err, waddrmgr.ErrScopeNotFound) { // The default scope wasn't found, that probably means // it was added recently and older wallets don't know it @@ -348,7 +348,9 @@ func (b *BtcWallet) Start() error { } } - scope, err := b.wallet.Manager.FetchScopedKeyManager(b.chainKeyScope) + scope, err := b.wallet.AddrManager().FetchScopedKeyManager( + b.chainKeyScope, + ) if err != nil { // If the scope hasn't yet been created (it wouldn't been // loaded by default if it was), then we'll manually create the @@ -1291,7 +1293,7 @@ func (b *BtcWallet) GetTransactionDetails( // Grab the best block the wallet knows of, we'll use this to calculate // # of confirmations shortly below. - bestBlock := b.wallet.Manager.SyncedTo() + bestBlock := b.wallet.SyncedTo() currentHeight := bestBlock.Height tx, err := b.wallet.GetTransaction(*txHash) if err != nil { @@ -1481,7 +1483,7 @@ func (b *BtcWallet) ListTransactionDetails(startHeight, endHeight int32, // Grab the best block the wallet knows of, we'll use this to calculate // # of confirmations shortly below. - bestBlock := b.wallet.Manager.SyncedTo() + bestBlock := b.wallet.SyncedTo() currentHeight := bestBlock.Height // We'll attempt to find all transactions from start to end height. @@ -1554,7 +1556,7 @@ type txSubscriptionClient struct { confirmed chan *lnwallet.TransactionDetail unconfirmed chan *lnwallet.TransactionDetail - w *base.Wallet + w base.Interface wg sync.WaitGroup quit chan struct{} @@ -1597,7 +1599,7 @@ out: select { case txNtfn := <-t.txClient.C: // TODO(roasbeef): handle detached blocks - currentHeight := t.w.Manager.SyncedTo().Height + currentHeight := t.w.SyncedTo().Height // Launch a goroutine to re-package and send // notifications for any newly confirmed transactions. @@ -1653,7 +1655,7 @@ out: // // This is a part of the WalletController interface. func (b *BtcWallet) SubscribeTransactions() (lnwallet.TransactionSubscription, error) { - walletClient := b.wallet.NtfnServer.TransactionNotifications() + walletClient := b.wallet.NotificationServer().TransactionNotifications() txClient := &txSubscriptionClient{ txClient: walletClient, @@ -1674,7 +1676,7 @@ func (b *BtcWallet) SubscribeTransactions() (lnwallet.TransactionSubscription, e // This is a part of the WalletController interface. func (b *BtcWallet) IsSynced() (bool, int64, error) { // Grab the best chain state the wallet is currently aware of. - syncState := b.wallet.Manager.SyncedTo() + syncState := b.wallet.SyncedTo() // We'll also extract the current best wallet timestamp so the caller // can get an idea of where we are in the sync timeline. @@ -1752,7 +1754,7 @@ func (b *BtcWallet) GetRecoveryInfo() (bool, float64, error) { } // Grab the best chain state the wallet is currently aware of. - syncState := b.wallet.Manager.SyncedTo() + syncState := b.wallet.SyncedTo() // Next, query the chain backend to grab the info about the tip of the // main chain. diff --git a/lnwallet/btcwallet/signer_test.go b/lnwallet/btcwallet/signer_test.go index a0e4bba6d..e45211d82 100644 --- a/lnwallet/btcwallet/signer_test.go +++ b/lnwallet/btcwallet/signer_test.go @@ -220,7 +220,7 @@ func TestScriptImport(t *testing.T) { require.Equal(t, firstAddressTaproot, firstDerivedAddr.String()) scope := waddrmgr.KeyScopeBIP0086 - _, err = w.InternalWallet().Manager.FetchScopedKeyManager(scope) + _, err = w.InternalWallet().AddrManager().FetchScopedKeyManager(scope) require.NoError(t, err) // Let's create a taproot script output now. This is a hash lock with a From 48f88248b8e140391e38ca1f7e8da36f3ce53fd9 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 8 Aug 2025 19:03:31 +0800 Subject: [PATCH 4/4] docs: update release notes --- docs/release-notes/release-notes-0.20.0.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/release-notes/release-notes-0.20.0.md b/docs/release-notes/release-notes-0.20.0.md index 1b106d1a1..dd732698e 100644 --- a/docs/release-notes/release-notes-0.20.0.md +++ b/docs/release-notes/release-notes-0.20.0.md @@ -174,6 +174,9 @@ reader of a payment request. - [Refactored](https://github.com/lightningnetwork/lnd/pull/10018) `channelLink` to improve readability and maintainability of the code. +- [Introduced](https://github.com/lightningnetwork/lnd/pull/10136) a wallet + interface to decouple the relationship between `lnd` and `btcwallet`. + ## Breaking Changes ## Performance Improvements