Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2017-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <qt/test/addressbooktests.h>6#include <qt/test/util.h>7#include <test/util/setup_common.h>9#include <interfaces/chain.h>10#include <interfaces/node.h>11#include <qt/addressbookpage.h>12#include <qt/clientmodel.h>13#include <qt/editaddressdialog.h>14#include <qt/optionsmodel.h>15#include <qt/platformstyle.h>16#include <qt/qvalidatedlineedit.h>17#include <qt/walletmodel.h>19#include <key.h>20#include <key_io.h>21#include <wallet/wallet.h>22#include <wallet/test/util.h>23#include <walletinitinterface.h>25#include <chrono>27#include <QApplication>28#include <QLineEdit>29#include <QMessageBox>30#include <QTableView>31#include <QTimer>33using wallet::AddWallet;34using wallet::CWallet;35using wallet::CreateMockableWalletDatabase;36using wallet::RemoveWallet;37using wallet::WALLET_FLAG_DESCRIPTORS;38using wallet::WalletContext;40namespace41{43/**44* Fill the edit address dialog box with data, submit it, and ensure that45* the resulting message meets expectations.46*/47void EditAddressAndSubmit(48EditAddressDialog* dialog,49const QString& label, const QString& address, QString expected_msg)50{51QString warning_text;53dialog->findChild<QLineEdit*>("labelEdit")->setText(label);54dialog->findChild<QValidatedLineEdit*>("addressEdit")->setText(address);56ConfirmMessage(&warning_text, 5ms);57dialog->accept();58QCOMPARE(warning_text, expected_msg);59}61/**62* Test adding various send addresses to the address book.63*64* There are three cases tested:65*66* - new_address: a new address which should add as a send address successfully.67* - existing_s_address: an existing sending address which won't add successfully.68* - existing_r_address: an existing receiving address which won't add successfully.69*70* In each case, verify the resulting state of the address book and optionally71* the warning message presented to the user.72*/73void TestAddAddressesToSendBook(interfaces::Node& node)74{75TestChain100Setup test;76auto wallet_loader = interfaces::MakeWalletLoader(*test.m_node.chain, *Assert(test.m_node.args));77test.m_node.wallet_loader = wallet_loader.get();78node.setContext(&test.m_node);79const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockableWalletDatabase());80wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);81{82LOCK(wallet->cs_wallet);83wallet->SetupDescriptorScriptPubKeyMans();84}86auto build_address{[]() {87const WitnessV0KeyHash dest{GenerateRandomKey().GetPubKey()};88return std::make_pair(dest, QString::fromStdString(EncodeDestination(dest)));89}};91CTxDestination r_key_dest, s_key_dest;93// Add a preexisting "receive" entry in the address book.94QString preexisting_r_address;95QString r_label("already here (r)");97// Add a preexisting "send" entry in the address book.98QString preexisting_s_address;99QString s_label("already here (s)");101// Define a new address (which should add to the address book successfully).102QString new_address_a;103QString new_address_b;105std::tie(r_key_dest, preexisting_r_address) = build_address();106std::tie(s_key_dest, preexisting_s_address) = build_address();107std::tie(std::ignore, new_address_a) = build_address();108std::tie(std::ignore, new_address_b) = build_address();110{111LOCK(wallet->cs_wallet);112wallet->SetAddressBook(r_key_dest, r_label.toStdString(), wallet::AddressPurpose::RECEIVE);113wallet->SetAddressBook(s_key_dest, s_label.toStdString(), wallet::AddressPurpose::SEND);114}116auto check_addbook_size = [&wallet](int expected_size) {117LOCK(wallet->cs_wallet);118QCOMPARE(static_cast<int>(wallet->m_address_book.size()), expected_size);119};121// We should start with the two addresses we added earlier and nothing else.122check_addbook_size(2);124// Initialize relevant QT models.125std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));126OptionsModel optionsModel(node);127bilingual_str error;128QVERIFY(optionsModel.Init(error));129ClientModel clientModel(node, &optionsModel);130WalletContext& context = *node.walletLoader().context();131AddWallet(context, wallet);132WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel, platformStyle.get());133RemoveWallet(context, wallet, /* load_on_start= */ std::nullopt);134EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);135editAddressDialog.setModel(walletModel.getAddressTableModel());137AddressBookPage address_book{platformStyle.get(), AddressBookPage::ForEditing, AddressBookPage::SendingTab};138address_book.setModel(walletModel.getAddressTableModel());139auto table_view = address_book.findChild<QTableView*>("tableView");140QCOMPARE(table_view->model()->rowCount(), 1);142EditAddressAndSubmit(143&editAddressDialog, QString("uhoh"), preexisting_r_address,144QString(145"Address \"%1\" already exists as a receiving address with label "146"\"%2\" and so cannot be added as a sending address."147).arg(preexisting_r_address).arg(r_label));148check_addbook_size(2);149QCOMPARE(table_view->model()->rowCount(), 1);151EditAddressAndSubmit(152&editAddressDialog, QString("uhoh, different"), preexisting_s_address,153QString(154"The entered address \"%1\" is already in the address book with "155"label \"%2\"."156).arg(preexisting_s_address).arg(s_label));157check_addbook_size(2);158QCOMPARE(table_view->model()->rowCount(), 1);160// Submit a new address which should add successfully - we expect the161// warning message to be blank.162EditAddressAndSubmit(163&editAddressDialog, QString("io - new A"), new_address_a, QString(""));164check_addbook_size(3);165QCOMPARE(table_view->model()->rowCount(), 2);167EditAddressAndSubmit(168&editAddressDialog, QString("io - new B"), new_address_b, QString(""));169check_addbook_size(4);170QCOMPARE(table_view->model()->rowCount(), 3);172auto search_line = address_book.findChild<QLineEdit*>("searchLineEdit");174search_line->setText(r_label);175QCOMPARE(table_view->model()->rowCount(), 0);177search_line->setText(s_label);178QCOMPARE(table_view->model()->rowCount(), 1);180search_line->setText("io");181QCOMPARE(table_view->model()->rowCount(), 2);183// Check wildcard "?".184search_line->setText("io?new");185QCOMPARE(table_view->model()->rowCount(), 0);186search_line->setText("io???new");187QCOMPARE(table_view->model()->rowCount(), 2);189// Check wildcard "*".190search_line->setText("io*new");191QCOMPARE(table_view->model()->rowCount(), 2);192search_line->setText("*");193QCOMPARE(table_view->model()->rowCount(), 3);195search_line->setText(preexisting_r_address);196QCOMPARE(table_view->model()->rowCount(), 0);198search_line->setText(preexisting_s_address);199QCOMPARE(table_view->model()->rowCount(), 1);201search_line->setText(new_address_a);202QCOMPARE(table_view->model()->rowCount(), 1);204search_line->setText(new_address_b);205QCOMPARE(table_view->model()->rowCount(), 1);207search_line->setText("");208QCOMPARE(table_view->model()->rowCount(), 3);209}211} // namespace213void AddressBookTests::addressBookTests()214{215TestAddAddressesToSendBook(m_node);216}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.