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