Bitcoin Core 22.99.0
P2P Digital Currency
addressbooktests.cpp
Go to the documentation of this file.
1// Copyright (c) 2017-2020 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6#include <qt/test/util.h>
8
9#include <interfaces/chain.h>
10#include <interfaces/node.h>
11#include <qt/clientmodel.h>
13#include <qt/optionsmodel.h>
14#include <qt/platformstyle.h>
16#include <qt/walletmodel.h>
17
18#include <key.h>
19#include <key_io.h>
20#include <wallet/wallet.h>
21#include <walletinitinterface.h>
22
23#include <QApplication>
24#include <QTimer>
25#include <QMessageBox>
26
27namespace
28{
29
34void EditAddressAndSubmit(
35 EditAddressDialog* dialog,
36 const QString& label, const QString& address, QString expected_msg)
37{
38 QString warning_text;
39
40 dialog->findChild<QLineEdit*>("labelEdit")->setText(label);
41 dialog->findChild<QValidatedLineEdit*>("addressEdit")->setText(address);
42
43 ConfirmMessage(&warning_text, 5);
44 dialog->accept();
45 QCOMPARE(warning_text, expected_msg);
46}
47
60void TestAddAddressesToSendBook(interfaces::Node& node)
61{
63 auto wallet_client = interfaces::MakeWalletClient(*test.m_node.chain, *Assert(test.m_node.args));
64 test.m_node.wallet_client = wallet_client.get();
65 node.setContext(&test.m_node);
66 const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockWalletDatabase());
67 wallet->LoadWallet();
68 wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
69 {
70 LOCK(wallet->cs_wallet);
71 wallet->SetupDescriptorScriptPubKeyMans();
72 }
73
74 auto build_address = [&wallet]() {
75 CKey key;
76 key.MakeNewKey(true);
78 key.GetPubKey(), wallet->m_default_address_type));
79
80 return std::make_pair(dest, QString::fromStdString(EncodeDestination(dest)));
81 };
82
83 CTxDestination r_key_dest, s_key_dest;
84
85 // Add a preexisting "receive" entry in the address book.
86 QString preexisting_r_address;
87 QString r_label("already here (r)");
88
89 // Add a preexisting "send" entry in the address book.
90 QString preexisting_s_address;
91 QString s_label("already here (s)");
92
93 // Define a new address (which should add to the address book successfully).
94 QString new_address;
95
96 std::tie(r_key_dest, preexisting_r_address) = build_address();
97 std::tie(s_key_dest, preexisting_s_address) = build_address();
98 std::tie(std::ignore, new_address) = build_address();
99
100 {
101 LOCK(wallet->cs_wallet);
102 wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive");
103 wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send");
104 }
105
106 auto check_addbook_size = [&wallet](int expected_size) {
107 LOCK(wallet->cs_wallet);
108 QCOMPARE(static_cast<int>(wallet->m_address_book.size()), expected_size);
109 };
110
111 // We should start with the two addresses we added earlier and nothing else.
112 check_addbook_size(2);
113
114 // Initialize relevant QT models.
115 std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
116 OptionsModel optionsModel;
117 ClientModel clientModel(node, &optionsModel);
118 WalletContext& context = *node.walletClient().context();
119 AddWallet(context, wallet);
120 WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel, platformStyle.get());
121 RemoveWallet(context, wallet, /* load_on_start= */ std::nullopt);
123 editAddressDialog.setModel(walletModel.getAddressTableModel());
124
125 EditAddressAndSubmit(
126 &editAddressDialog, QString("uhoh"), preexisting_r_address,
127 QString(
128 "Address \"%1\" already exists as a receiving address with label "
129 "\"%2\" and so cannot be added as a sending address."
130 ).arg(preexisting_r_address).arg(r_label));
131
132 check_addbook_size(2);
133
134 EditAddressAndSubmit(
135 &editAddressDialog, QString("uhoh, different"), preexisting_s_address,
136 QString(
137 "The entered address \"%1\" is already in the address book with "
138 "label \"%2\"."
139 ).arg(preexisting_s_address).arg(s_label));
140
141 check_addbook_size(2);
142
143 // Submit a new address which should add successfully - we expect the
144 // warning message to be blank.
145 EditAddressAndSubmit(
146 &editAddressDialog, QString("new"), new_address, QString(""));
147
148 check_addbook_size(3);
149}
150
151} // namespace
152
154{
155#ifdef Q_OS_MAC
156 if (QApplication::platformName() == "minimal") {
157 // Disable for mac on "minimal" platform to avoid crashes inside the Qt
158 // framework when it tries to look up unimplemented cocoa functions,
159 // and fails to handle returned nulls
160 // (https://bugreports.qt.io/browse/QTBUG-49686).
161 QWARN("Skipping AddressBookTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke "
162 "with 'QT_QPA_PLATFORM=cocoa test_bitcoin-qt' on mac, or else use a linux or windows build.");
163 return;
164 }
165#endif
166 TestAddAddressesToSendBook(m_node);
167}
#define Assert(val)
Identity function.
Definition: check.h:57
interfaces::Node & m_node
An encapsulated private key.
Definition: key.h:27
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:160
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:187
Model for Bitcoin network client.
Definition: clientmodel.h:48
Dialog for editing an address and associated information.
void accept() override
Interface from Qt to configuration data structure for Bitcoin client.
Definition: optionsmodel.h:39
static const PlatformStyle * instantiate(const QString &platformId)
Get style associated with provided platform name, or 0 if not known.
Line edit that can be marked as "invalid" to show input validation feedback.
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:52
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:55
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:256
std::unique_ptr< Wallet > MakeWallet(const std::shared_ptr< CWallet > &wallet)
Definition: dummywallet.cpp:62
std::unique_ptr< WalletClient > MakeWalletClient(Chain &chain, ArgsManager &args)
Return implementation of ChainClient interface for a wallet client.
Definition: dummywallet.cpp:67
CTxDestination GetDestinationForKey(const CPubKey &key, OutputType type)
Get a destination of the requested type (if possible) to the specified key.
Definition: outputtype.cpp:49
void ConfirmMessage(QString *text, int msec)
Press "Ok" button in message box dialog.
Definition: util.cpp:12
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
NodeContext m_node
Definition: setup_common.h:78
std::unique_ptr< interfaces::Chain > chain
Definition: context.h:50
ArgsManager * args
Definition: context.h:49
interfaces::WalletClient * wallet_client
Reference to chain client that should used to load or create wallets opened by the gui.
Definition: context.h:55
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
Definition: setup_common.h:116
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:34
#define LOCK(cs)
Definition: sync.h:226
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:117
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition: wallet.cpp:105
std::unique_ptr< WalletDatabase > CreateMockWalletDatabase()
Return object for accessing temporary in-memory database.
Definition: walletdb.cpp:1189
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:65