From 682bd8d33e65f57c4333dce0d22c712f2a85de3a Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 25 Aug 2020 11:35:49 -0700 Subject: [PATCH] wallet: only request spend notification for our outputs We would previously request spend notifications for all transaction outputs, leading to irrelevant transactions being found in the wallet's transaction store. --- wallet/wallet.go | 52 ++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/wallet/wallet.go b/wallet/wallet.go index 4952498..2d1b475 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -3447,7 +3447,35 @@ func (w *Wallet) reliablyPublishTransaction(tx *wire.MsgTx, if err != nil { return nil, err } + + // Along the way, we'll extract our relevant destination addresses from + // the transaction. + var ourAddrs []btcutil.Address err = walletdb.Update(w.db, func(dbTx walletdb.ReadWriteTx) error { + txmgrNs := dbTx.ReadWriteBucket(wtxmgrNamespaceKey) + for _, txOut := range tx.TxOut { + _, addrs, _, err := txscript.ExtractPkScriptAddrs( + txOut.PkScript, w.chainParams, + ) + if err != nil { + // Non-standard outputs can safely be skipped because + // they're not supported by the wallet. + continue + } + for _, addr := range addrs { + // Skip any addresses which are not relevant to + // us. + _, err := w.Manager.Address(txmgrNs, addr) + if waddrmgr.IsError(err, waddrmgr.ErrAddressNotFound) { + continue + } + if err != nil { + return err + } + ourAddrs = append(ourAddrs, addr) + } + } + if err := w.addRelevantTx(dbTx, txRec, nil); err != nil { return err } @@ -3459,7 +3487,6 @@ func (w *Wallet) reliablyPublishTransaction(tx *wire.MsgTx, // If there is a label we should write, get the namespace key // and record it in the tx store. - txmgrNs := dbTx.ReadWriteBucket(wtxmgrNamespaceKey) return w.TxStore.PutTxLabel(txmgrNs, tx.TxHash(), label) }) if err != nil { @@ -3469,27 +3496,8 @@ func (w *Wallet) reliablyPublishTransaction(tx *wire.MsgTx, // We'll also ask to be notified of the transaction once it confirms // on-chain. This is done outside of the database transaction to prevent // backend interaction within it. - // - // NOTE: In some cases, it's possible that the transaction to be - // broadcast is not directly relevant to the user's wallet, e.g., - // multisig. In either case, we'll still ask to be notified of when it - // confirms to maintain consistency. - // - // TODO(wilmer): import script as external if the address does not - // belong to the wallet to handle confs during restarts? - for _, txOut := range tx.TxOut { - _, addrs, _, err := txscript.ExtractPkScriptAddrs( - txOut.PkScript, w.chainParams, - ) - if err != nil { - // Non-standard outputs can safely be skipped because - // they're not supported by the wallet. - continue - } - - if err := chainClient.NotifyReceived(addrs); err != nil { - return nil, err - } + if err := chainClient.NotifyReceived(ourAddrs); err != nil { + return nil, err } return w.publishTransaction(tx)