diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bench/wallet_create_tx.cpp | 4 | ||||
-rw-r--r-- | src/qt/sendcoinsdialog.cpp | 9 | ||||
-rw-r--r-- | src/qt/sendcoinsdialog.h | 3 | ||||
-rw-r--r-- | src/qt/test/wallettests.cpp | 258 | ||||
-rw-r--r-- | src/qt/walletmodel.cpp | 14 | ||||
-rw-r--r-- | src/wallet/interfaces.cpp | 20 | ||||
-rw-r--r-- | src/wallet/spend.cpp | 6 | ||||
-rw-r--r-- | src/wallet/spend.h | 2 | ||||
-rw-r--r-- | src/wallet/test/wallet_tests.cpp | 2 |
9 files changed, 248 insertions, 70 deletions
diff --git a/src/bench/wallet_create_tx.cpp b/src/bench/wallet_create_tx.cpp index 80d23d1e51..cb31421598 100644 --- a/src/bench/wallet_create_tx.cpp +++ b/src/bench/wallet_create_tx.cpp @@ -102,7 +102,7 @@ static void WalletCreateTx(benchmark::Bench& bench, const OutputType output_type } // Check available balance - auto bal = wallet::GetAvailableBalance(wallet); // Cache + auto bal = WITH_LOCK(wallet.cs_wallet, return wallet::AvailableCoins(wallet).GetTotalAmount()); // Cache assert(bal == 50 * COIN * (chain_size - COINBASE_MATURITY)); wallet::CCoinControl coin_control; @@ -161,7 +161,7 @@ static void AvailableCoins(benchmark::Bench& bench, const std::vector<OutputType } // Check available balance - auto bal = wallet::GetAvailableBalance(wallet); // Cache + auto bal = WITH_LOCK(wallet.cs_wallet, return wallet::AvailableCoins(wallet).GetTotalAmount()); // Cache assert(bal == 50 * COIN * (chain_size - COINBASE_MATURITY)); bench.epochIterations(2).run([&] { diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index e3fa4058a6..48f7fb6ad1 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -403,7 +403,7 @@ void SendCoinsDialog::presentPSBT(PartiallySignedTransaction& psbtx) CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << psbtx; GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str()); - QMessageBox msgBox; + QMessageBox msgBox(this); //: Caption of "PSBT has been copied" messagebox msgBox.setText(tr("Unsigned Transaction", "PSBT copied")); msgBox.setInformativeText(tr("The PSBT has been copied to the clipboard. You can also save it.")); @@ -791,8 +791,13 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry) // Include watch-only for wallets without private key m_coin_control->fAllowWatchOnly = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner(); + // Same behavior as send: if we have selected coins, only obtain their available balance. + // Copy to avoid modifying the member's data. + CCoinControl coin_control = *m_coin_control; + coin_control.m_allow_other_inputs = !coin_control.HasSelected(); + // Calculate available amount to send. - CAmount amount = model->getAvailableBalance(m_coin_control.get()); + CAmount amount = model->getAvailableBalance(&coin_control); for (int i = 0; i < ui->entries->count(); ++i) { SendCoinsEntry* e = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget()); if (e && !e->isHidden() && e != entry) { diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 2fcdf5b32a..ac05cd98e5 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -49,6 +49,9 @@ public: void pasteEntry(const SendCoinsRecipient &rv); bool handlePaymentRequest(const SendCoinsRecipient &recipient); + // Only used for testing-purposes + wallet::CCoinControl* getCoinControl() { return m_coin_control.get(); } + public Q_SLOTS: void clear(); void reject() override; diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index be5bcbbd54..eb7bf33a32 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -5,6 +5,7 @@ #include <qt/test/wallettests.h> #include <qt/test/util.h> +#include <wallet/coincontrol.h> #include <interfaces/chain.h> #include <interfaces/node.h> #include <key_io.h> @@ -34,6 +35,8 @@ #include <QAction> #include <QApplication> #include <QCheckBox> +#include <QClipboard> +#include <QObject> #include <QPushButton> #include <QTimer> #include <QVBoxLayout> @@ -46,6 +49,7 @@ using wallet::CWallet; using wallet::CreateMockWalletDatabase; using wallet::RemoveWallet; using wallet::WALLET_FLAG_DESCRIPTORS; +using wallet::WALLET_FLAG_DISABLE_PRIVATE_KEYS; using wallet::WalletContext; using wallet::WalletDescriptor; using wallet::WalletRescanReserver; @@ -53,14 +57,14 @@ using wallet::WalletRescanReserver; namespace { //! Press "Yes" or "Cancel" buttons in modal send confirmation dialog. -void ConfirmSend(QString* text = nullptr, bool cancel = false) +void ConfirmSend(QString* text = nullptr, QMessageBox::StandardButton confirm_type = QMessageBox::Yes) { - QTimer::singleShot(0, [text, cancel]() { + QTimer::singleShot(0, [text, confirm_type]() { for (QWidget* widget : QApplication::topLevelWidgets()) { if (widget->inherits("SendConfirmationDialog")) { SendConfirmationDialog* dialog = qobject_cast<SendConfirmationDialog*>(widget); if (text) *text = dialog->text(); - QAbstractButton* button = dialog->button(cancel ? QMessageBox::Cancel : QMessageBox::Yes); + QAbstractButton* button = dialog->button(confirm_type); button->setEnabled(true); button->click(); } @@ -69,7 +73,8 @@ void ConfirmSend(QString* text = nullptr, bool cancel = false) } //! Send coins to address and return txid. -uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount, bool rbf) +uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount, bool rbf, + QMessageBox::StandardButton confirm_type = QMessageBox::Yes) { QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries"); SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget()); @@ -83,7 +88,7 @@ uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDe boost::signals2::scoped_connection c(wallet.NotifyTransactionChanged.connect([&txid](const uint256& hash, ChangeType status) { if (status == CT_NEW) txid = hash; })); - ConfirmSend(); + ConfirmSend(/*text=*/nullptr, confirm_type); bool invoked = QMetaObject::invokeMethod(&sendCoinsDialog, "sendButtonClicked", Q_ARG(bool, false)); assert(invoked); return txid; @@ -121,7 +126,7 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st action->setEnabled(true); QString text; if (expectError.empty()) { - ConfirmSend(&text, cancel); + ConfirmSend(&text, cancel ? QMessageBox::Cancel : QMessageBox::Yes); } else { ConfirmMessage(&text, 0ms); } @@ -136,6 +141,119 @@ void CompareBalance(WalletModel& walletModel, CAmount expected_balance, QLabel* QCOMPARE(balance_label_to_check->text().trimmed(), balanceComparison); } +// Verify the 'useAvailableBalance' functionality. With and without manually selected coins. +// Case 1: No coin control selected coins. +// 'useAvailableBalance' should fill the amount edit box with the total available balance +// Case 2: With coin control selected coins. +// 'useAvailableBalance' should fill the amount edit box with the sum of the selected coins values. +void VerifyUseAvailableBalance(SendCoinsDialog& sendCoinsDialog, const WalletModel& walletModel) +{ + // Verify first entry amount and "useAvailableBalance" button + QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries"); + QVERIFY(entries->count() == 1); // only one entry + SendCoinsEntry* send_entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget()); + QVERIFY(send_entry->getValue().amount == 0); + // Now click "useAvailableBalance", check updated balance (the entire wallet balance should be set) + Q_EMIT send_entry->useAvailableBalance(send_entry); + QVERIFY(send_entry->getValue().amount == walletModel.getCachedBalance().balance); + + // Now manually select two coins and click on "useAvailableBalance". Then check updated balance + // (only the sum of the selected coins should be set). + int COINS_TO_SELECT = 2; + auto coins = walletModel.wallet().listCoins(); + CAmount sum_selected_coins = 0; + int selected = 0; + QVERIFY(coins.size() == 1); // context check, coins received only on one destination + for (const auto& [outpoint, tx_out] : coins.begin()->second) { + sendCoinsDialog.getCoinControl()->Select(outpoint); + sum_selected_coins += tx_out.txout.nValue; + if (++selected == COINS_TO_SELECT) break; + } + QVERIFY(selected == COINS_TO_SELECT); + + // Now that we have 2 coins selected, "useAvailableBalance" should update the balance label only with + // the sum of them. + Q_EMIT send_entry->useAvailableBalance(send_entry); + QVERIFY(send_entry->getValue().amount == sum_selected_coins); +} + +void SyncUpWallet(const std::shared_ptr<CWallet>& wallet, interfaces::Node& node) +{ + WalletRescanReserver reserver(*wallet); + reserver.reserve(); + CWallet::ScanResult result = wallet->ScanForWalletTransactions(Params().GetConsensus().hashGenesisBlock, /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/false); + QCOMPARE(result.status, CWallet::ScanResult::SUCCESS); + QCOMPARE(result.last_scanned_block, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash())); + QVERIFY(result.last_failed_block.IsNull()); +} + +std::shared_ptr<CWallet> SetupLegacyWatchOnlyWallet(interfaces::Node& node, TestChain100Setup& test) +{ + std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockWalletDatabase()); + wallet->LoadWallet(); + { + LOCK(wallet->cs_wallet); + wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS); + wallet->SetupLegacyScriptPubKeyMan(); + // Add watched key + CPubKey pubKey = test.coinbaseKey.GetPubKey(); + bool import_keys = wallet->ImportPubKeys({pubKey.GetID()}, {{pubKey.GetID(), pubKey}} , /*key_origins=*/{}, /*add_keypool=*/false, /*internal=*/false, /*timestamp=*/1); + assert(import_keys); + wallet->SetLastBlockProcessed(105, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash())); + } + SyncUpWallet(wallet, node); + return wallet; +} + +std::shared_ptr<CWallet> SetupDescriptorsWallet(interfaces::Node& node, TestChain100Setup& test) +{ + std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockWalletDatabase()); + wallet->LoadWallet(); + LOCK(wallet->cs_wallet); + wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); + wallet->SetupDescriptorScriptPubKeyMans(); + + // Add the coinbase key + FlatSigningProvider provider; + std::string error; + std::unique_ptr<Descriptor> desc = Parse("combo(" + EncodeSecret(test.coinbaseKey) + ")", provider, error, /* require_checksum=*/ false); + assert(desc); + WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1); + if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false); + CTxDestination dest = GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type); + wallet->SetAddressBook(dest, "", "receive"); + wallet->SetLastBlockProcessed(105, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash())); + SyncUpWallet(wallet, node); + wallet->SetBroadcastTransactions(true); + return wallet; +} + +struct MiniGUI { +public: + SendCoinsDialog sendCoinsDialog; + TransactionView transactionView; + OptionsModel optionsModel; + std::unique_ptr<ClientModel> clientModel; + std::unique_ptr<WalletModel> walletModel; + + MiniGUI(interfaces::Node& node, const PlatformStyle* platformStyle) : sendCoinsDialog(platformStyle), transactionView(platformStyle), optionsModel(node) { + bilingual_str error; + QVERIFY(optionsModel.Init(error)); + clientModel = std::make_unique<ClientModel>(node, &optionsModel); + } + + void initModelForWallet(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet, const PlatformStyle* platformStyle) + { + WalletContext& context = *node.walletLoader().context(); + AddWallet(context, wallet); + walletModel = std::make_unique<WalletModel>(interfaces::MakeWallet(context, wallet), *clientModel, platformStyle); + RemoveWallet(context, wallet, /* load_on_start= */ std::nullopt); + sendCoinsDialog.setModel(walletModel.get()); + transactionView.setModel(walletModel.get()); + } + +}; + //! Simple qt wallet tests. // // Test widgets can be debugged interactively calling show() on them and @@ -149,64 +267,24 @@ void CompareBalance(WalletModel& walletModel, CAmount expected_balance, QLabel* // QT_QPA_PLATFORM=xcb src/qt/test/test_bitcoin-qt # Linux // QT_QPA_PLATFORM=windows src/qt/test/test_bitcoin-qt # Windows // QT_QPA_PLATFORM=cocoa src/qt/test/test_bitcoin-qt # macOS -void TestGUI(interfaces::Node& node) +void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet) { - // Set up wallet and chain with 105 blocks (5 mature blocks for spending). - TestChain100Setup test; - for (int i = 0; i < 5; ++i) { - test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); - } - auto wallet_loader = interfaces::MakeWalletLoader(*test.m_node.chain, *Assert(test.m_node.args)); - test.m_node.wallet_loader = wallet_loader.get(); - node.setContext(&test.m_node); - const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockWalletDatabase()); - wallet->LoadWallet(); - wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); - { - LOCK(wallet->cs_wallet); - wallet->SetupDescriptorScriptPubKeyMans(); - - // Add the coinbase key - FlatSigningProvider provider; - std::string error; - std::unique_ptr<Descriptor> desc = Parse("combo(" + EncodeSecret(test.coinbaseKey) + ")", provider, error, /* require_checksum=*/ false); - assert(desc); - WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1); - if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false); - CTxDestination dest = GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type); - wallet->SetAddressBook(dest, "", "receive"); - wallet->SetLastBlockProcessed(105, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash())); - } - { - WalletRescanReserver reserver(*wallet); - reserver.reserve(); - CWallet::ScanResult result = wallet->ScanForWalletTransactions(Params().GetConsensus().hashGenesisBlock, /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/false); - QCOMPARE(result.status, CWallet::ScanResult::SUCCESS); - QCOMPARE(result.last_scanned_block, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash())); - QVERIFY(result.last_failed_block.IsNull()); - } - wallet->SetBroadcastTransactions(true); - // Create widgets for sending coins and listing transactions. std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other")); - SendCoinsDialog sendCoinsDialog(platformStyle.get()); - TransactionView transactionView(platformStyle.get()); - OptionsModel optionsModel(node); - bilingual_str error; - QVERIFY(optionsModel.Init(error)); - ClientModel clientModel(node, &optionsModel); - WalletContext& context = *node.walletLoader().context(); - AddWallet(context, wallet); - WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel, platformStyle.get()); - RemoveWallet(context, wallet, /* load_on_start= */ std::nullopt); - sendCoinsDialog.setModel(&walletModel); - transactionView.setModel(&walletModel); + MiniGUI mini_gui(node, platformStyle.get()); + mini_gui.initModelForWallet(node, wallet, platformStyle.get()); + WalletModel& walletModel = *mini_gui.walletModel; + SendCoinsDialog& sendCoinsDialog = mini_gui.sendCoinsDialog; + TransactionView& transactionView = mini_gui.transactionView; // Update walletModel cached balance which will trigger an update for the 'labelBalance' QLabel. walletModel.pollBalanceChanged(); // Check balance in send dialog CompareBalance(walletModel, walletModel.wallet().getBalance(), sendCoinsDialog.findChild<QLabel*>("labelBalance")); + // Check 'UseAvailableBalance' functionality + VerifyUseAvailableBalance(sendCoinsDialog, walletModel); + // Send two transactions, and verify they are added to transaction list. TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel(); QCOMPARE(transactionTableModel->rowCount({}), 105); @@ -313,6 +391,76 @@ void TestGUI(interfaces::Node& node) QCOMPARE(walletModel.wallet().getAddressReceiveRequests().size(), size_t{0}); } +void TestGUIWatchOnly(interfaces::Node& node, TestChain100Setup& test) +{ + const std::shared_ptr<CWallet>& wallet = SetupLegacyWatchOnlyWallet(node, test); + + // Create widgets and init models + std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other")); + MiniGUI mini_gui(node, platformStyle.get()); + mini_gui.initModelForWallet(node, wallet, platformStyle.get()); + WalletModel& walletModel = *mini_gui.walletModel; + SendCoinsDialog& sendCoinsDialog = mini_gui.sendCoinsDialog; + + // Update walletModel cached balance which will trigger an update for the 'labelBalance' QLabel. + walletModel.pollBalanceChanged(); + // Check balance in send dialog + CompareBalance(walletModel, walletModel.wallet().getBalances().watch_only_balance, + sendCoinsDialog.findChild<QLabel*>("labelBalance")); + + // Set change address + sendCoinsDialog.getCoinControl()->destChange = GetDestinationForKey(test.coinbaseKey.GetPubKey(), OutputType::LEGACY); + + // Time to reject "save" PSBT dialog ('SendCoins' locks the main thread until the dialog receives the event). + QTimer timer; + timer.setInterval(500); + QObject::connect(&timer, &QTimer::timeout, [&](){ + for (QWidget* widget : QApplication::topLevelWidgets()) { + if (widget->inherits("QMessageBox")) { + QMessageBox* dialog = qobject_cast<QMessageBox*>(widget); + QAbstractButton* button = dialog->button(QMessageBox::Discard); + button->setEnabled(true); + button->click(); + timer.stop(); + break; + } + } + }); + timer.start(500); + + // Send tx and verify PSBT copied to the clipboard. + SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, /*rbf=*/false, QMessageBox::Save); + const std::string& psbt_string = QApplication::clipboard()->text().toStdString(); + QVERIFY(!psbt_string.empty()); + + // Decode psbt + std::optional<std::vector<unsigned char>> decoded_psbt = DecodeBase64(psbt_string); + QVERIFY(decoded_psbt); + PartiallySignedTransaction psbt; + std::string err; + QVERIFY(DecodeRawPSBT(psbt, MakeByteSpan(*decoded_psbt), err)); +} + +void TestGUI(interfaces::Node& node) +{ + // Set up wallet and chain with 105 blocks (5 mature blocks for spending). + TestChain100Setup test; + for (int i = 0; i < 5; ++i) { + test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); + } + auto wallet_loader = interfaces::MakeWalletLoader(*test.m_node.chain, *Assert(test.m_node.args)); + test.m_node.wallet_loader = wallet_loader.get(); + node.setContext(&test.m_node); + + // "Full" GUI tests, use descriptor wallet + const std::shared_ptr<CWallet>& desc_wallet = SetupDescriptorsWallet(node, test); + TestGUI(node, desc_wallet); + + // Legacy watch-only wallet test + // Verify PSBT creation. + TestGUIWatchOnly(node, test); +} + } // namespace void WalletTests::walletTests() diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 61172d1625..565b732bf0 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -613,5 +613,17 @@ uint256 WalletModel::getLastBlockProcessed() const CAmount WalletModel::getAvailableBalance(const CCoinControl* control) { - return control && control->HasSelected() ? wallet().getAvailableBalance(*control) : getCachedBalance().balance; + // No selected coins, return the cached balance + if (!control || !control->HasSelected()) { + const interfaces::WalletBalances& balances = getCachedBalance(); + CAmount available_balance = balances.balance; + // if wallet private keys are disabled, this is a watch-only wallet + // so, let's include the watch-only balance. + if (balances.have_watch_only && m_wallet->privateKeysDisabled()) { + available_balance += balances.watch_only_balance; + } + return available_balance; + } + // Fetch balance from the wallet, taking into account the selected coins + return wallet().getAvailableBalance(*control); } diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 1a76e46c54..df1eb19a33 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -18,6 +18,7 @@ #include <util/system.h> #include <util/translation.h> #include <util/ui_change_type.h> +#include <wallet/coincontrol.h> #include <wallet/context.h> #include <wallet/feebumper.h> #include <wallet/fees.h> @@ -403,7 +404,24 @@ public: CAmount getBalance() override { return GetBalance(*m_wallet).m_mine_trusted; } CAmount getAvailableBalance(const CCoinControl& coin_control) override { - return GetAvailableBalance(*m_wallet, &coin_control); + LOCK(m_wallet->cs_wallet); + CAmount total_amount = 0; + // Fetch selected coins total amount + if (coin_control.HasSelected()) { + FastRandomContext rng{}; + CoinSelectionParams params(rng); + // Note: for now, swallow any error. + if (auto res = FetchSelectedInputs(*m_wallet, coin_control, params)) { + total_amount += res->total_amount; + } + } + + // And fetch the wallet available coins + if (coin_control.m_allow_other_inputs) { + total_amount += AvailableCoins(*m_wallet, &coin_control).GetTotalAmount(); + } + + return total_amount; } isminetype txinIsMine(const CTxIn& txin) override { diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 4548d5f813..57f3785a3a 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -356,12 +356,6 @@ CoinsResult AvailableCoinsListUnspent(const CWallet& wallet, const CCoinControl* return AvailableCoins(wallet, coinControl, /*feerate=*/ std::nullopt, params); } -CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinControl) -{ - LOCK(wallet.cs_wallet); - return AvailableCoins(wallet, coinControl).GetTotalAmount(); -} - const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint& outpoint) { AssertLockHeld(wallet.cs_wallet); diff --git a/src/wallet/spend.h b/src/wallet/spend.h index 78c2c5f22b..cc9ccf3011 100644 --- a/src/wallet/spend.h +++ b/src/wallet/spend.h @@ -94,8 +94,6 @@ CoinsResult AvailableCoins(const CWallet& wallet, */ CoinsResult AvailableCoinsListUnspent(const CWallet& wallet, const CCoinControl* coinControl = nullptr, CoinFilterParams params = {}) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); -CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinControl = nullptr); - /** * Find non-change parent output. */ diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 2e95a14807..edcfaa24e5 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -581,7 +581,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup) BOOST_CHECK_EQUAL(list.begin()->second.size(), 1U); // Check initial balance from one mature coinbase transaction. - BOOST_CHECK_EQUAL(50 * COIN, GetAvailableBalance(*wallet)); + BOOST_CHECK_EQUAL(50 * COIN, WITH_LOCK(wallet->cs_wallet, return AvailableCoins(*wallet).GetTotalAmount())); // Add a transaction creating a change address, and confirm ListCoins still // returns the coin associated with the change address underneath the |