Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
wallettests.cpp
Go to the documentation of this file.
1// Copyright (c) 2015-present 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>
7
9#include <interfaces/chain.h>
10#include <interfaces/node.h>
11#include <key_io.h>
13#include <qt/bitcoinunits.h>
14#include <qt/clientmodel.h>
15#include <qt/optionsmodel.h>
16#include <qt/overviewpage.h>
17#include <qt/platformstyle.h>
22#include <qt/sendcoinsdialog.h>
23#include <qt/sendcoinsentry.h>
25#include <qt/transactionview.h>
26#include <qt/walletmodel.h>
27#include <script/solver.h>
29#include <validation.h>
30#include <wallet/test/util.h>
31#include <wallet/scan.h>
32#include <wallet/wallet.h>
33
34#include <chrono>
35#include <memory>
36
37#include <QAbstractButton>
38#include <QAction>
39#include <QApplication>
40#include <QCheckBox>
41#include <QClipboard>
42#include <QObject>
43#include <QPushButton>
44#include <QTimer>
45#include <QVBoxLayout>
46#include <QTextEdit>
47#include <QListView>
48#include <QDialogButtonBox>
49
51using wallet::CWallet;
59
60namespace
61{
63void ConfirmSend(QString* text = nullptr, QMessageBox::StandardButton confirm_type = QMessageBox::Yes)
64{
65 QTimer::singleShot(0, [text, confirm_type]() {
66 for (QWidget* widget : QApplication::topLevelWidgets()) {
67 if (widget->inherits("SendConfirmationDialog")) {
69 if (text) *text = dialog->text();
71 button->setEnabled(true);
72 button->click();
73 }
74 }
75 });
76}
77
79Txid SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount,
80 QMessageBox::StandardButton confirm_type = QMessageBox::Yes)
81{
82 QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
83 SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
84 entry->findChild<QValidatedLineEdit*>("payTo")->setText(QString::fromStdString(EncodeDestination(address)));
85 entry->findChild<BitcoinAmountField*>("payAmount")->setValue(amount);
86 Txid txid;
87 btcsignals::scoped_connection c(wallet.NotifyTransactionChanged.connect([&txid](const Txid& hash, ChangeType status) {
88 if (status == CT_NEW) txid = hash;
89 }));
90 ConfirmSend(/*text=*/nullptr, confirm_type);
91 bool invoked = QMetaObject::invokeMethod(&sendCoinsDialog, "sendButtonClicked", Q_ARG(bool, false));
93 return txid;
94}
95
97QModelIndex FindTx(const QAbstractItemModel& model, const Txid& txid)
98{
99 QString hash = QString::fromStdString(txid.ToString());
100 int rows = model.rowCount({});
101 for (int row = 0; row < rows; ++row) {
102 QModelIndex index = model.index(row, 0, {});
103 if (model.data(index, TransactionTableModel::TxHashRole) == hash) {
104 return index;
105 }
106 }
107 return {};
108}
109
111void BumpFee(TransactionView& view, const Txid& txid, bool expectDisabled, std::string expectError, bool cancel)
112{
113 QTableView* table = view.findChild<QTableView*>("transactionView");
114 QModelIndex index = FindTx(*table->selectionModel()->model(), txid);
115 QVERIFY2(index.isValid(), "Could not find BumpFee txid");
116
117 // Select row in table, invoke context menu, and make sure bumpfee action is
118 // enabled or disabled as expected.
119 QAction* action = view.findChild<QAction*>("bumpFeeAction");
120 table->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
121 action->setEnabled(expectDisabled);
122 table->customContextMenuRequested({});
123 QCOMPARE(action->isEnabled(), !expectDisabled);
124
125 action->setEnabled(true);
126 QString text;
127 if (expectError.empty()) {
128 ConfirmSend(&text, cancel ? QMessageBox::Cancel : QMessageBox::Yes);
129 } else {
130 ConfirmMessage(&text, 0ms);
131 }
132 action->trigger();
133 QVERIFY(text.indexOf(QString::fromStdString(expectError)) != -1);
134}
135
137{
138 BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit();
141}
142
143// Verify the 'useAvailableBalance' functionality. With and without manually selected coins.
144// Case 1: No coin control selected coins.
145// 'useAvailableBalance' should fill the amount edit box with the total available balance
146// Case 2: With coin control selected coins.
147// 'useAvailableBalance' should fill the amount edit box with the sum of the selected coins values.
148void VerifyUseAvailableBalance(SendCoinsDialog& sendCoinsDialog, const WalletModel& walletModel)
149{
150 // Verify first entry amount and "useAvailableBalance" button
151 QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
152 QVERIFY(entries->count() == 1); // only one entry
153 SendCoinsEntry* send_entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
154 QVERIFY(send_entry->getValue().amount == 0);
155 // Now click "useAvailableBalance", check updated balance (the entire wallet balance should be set)
156 Q_EMIT send_entry->useAvailableBalance(send_entry);
157 QVERIFY(send_entry->getValue().amount == walletModel.getCachedBalance().balance);
158
159 // Now manually select two coins and click on "useAvailableBalance". Then check updated balance
160 // (only the sum of the selected coins should be set).
161 int COINS_TO_SELECT = 2;
162 auto coins = walletModel.wallet().listCoins();
164 int selected = 0;
165 QVERIFY(coins.size() == 1); // context check, coins received only on one destination
166 for (const auto& [outpoint, tx_out] : coins.begin()->second) {
167 sendCoinsDialog.getCoinControl()->Select(outpoint);
168 sum_selected_coins += tx_out.txout.nValue;
169 if (++selected == COINS_TO_SELECT) break;
170 }
172
173 // Now that we have 2 coins selected, "useAvailableBalance" should update the balance label only with
174 // the sum of them.
175 Q_EMIT send_entry->useAvailableBalance(send_entry);
176 QVERIFY(send_entry->getValue().amount == sum_selected_coins);
177}
178
179void SyncUpWallet(const std::shared_ptr<CWallet>& wallet, interfaces::Node& node)
180{
182 reserver.reserve();
183 wallet::ScanResult result = wallet->Scanner().Scan(Params().GetConsensus().hashGenesisBlock, /*start_height=*/0, /*max_height=*/{}, reserver, /*save_progress=*/false);
185 QCOMPARE(result.last_scanned_block, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash()));
187}
188
189std::shared_ptr<CWallet> SetupDescriptorsWallet(interfaces::Node& node, TestChain100Setup& test, bool watch_only = false)
190{
191 std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockableWalletDatabase());
192 LOCK(wallet->cs_wallet);
193 wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
194 if (watch_only) {
195 wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
196 } else {
197 wallet->SetupDescriptorScriptPubKeyMans();
198 }
199
200 // Add the coinbase key
202 std::string error;
203 std::string key_str;
204 if (watch_only) {
206 } else {
208 }
209 auto descs = Parse("combo(" + key_str + ")", provider, error, /* require_checksum=*/ false);
210 assert(!descs.empty());
211 assert(descs.size() == 1);
212 auto& desc = descs.at(0);
213 WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
214 Assert(wallet->AddWalletDescriptor(w_desc, provider, "", false));
215 const PKHash dest{test.coinbaseKey.GetPubKey()};
216 wallet->SetAddressBook(dest, "", wallet::AddressPurpose::RECEIVE);
217 wallet->SetLastBlockProcessed(105, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash()));
219 wallet->SetBroadcastTransactions(true);
220 return wallet;
221}
222
223struct MiniGUI {
224public:
225 SendCoinsDialog sendCoinsDialog;
226 TransactionView transactionView;
227 OptionsModel optionsModel;
228 std::unique_ptr<ClientModel> clientModel;
229 std::unique_ptr<WalletModel> walletModel;
230
231 MiniGUI(interfaces::Node& node, const PlatformStyle* platformStyle) : sendCoinsDialog(platformStyle), transactionView(platformStyle), optionsModel(node) {
232 bilingual_str error;
233 QVERIFY(optionsModel.Init(error));
234 clientModel = std::make_unique<ClientModel>(node, &optionsModel);
235 }
236
237 void initModelForWallet(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet, const PlatformStyle* platformStyle)
238 {
239 WalletContext& context = *node.walletLoader().context();
241 walletModel = std::make_unique<WalletModel>(interfaces::MakeWallet(context, wallet), *clientModel, platformStyle);
242 RemoveWallet(context, wallet, /* load_on_start= */ std::nullopt);
243 sendCoinsDialog.setModel(walletModel.get());
244 transactionView.setModel(walletModel.get());
245 }
246
247};
248
250//
251// Test widgets can be debugged interactively calling show() on them and
252// manually running the event loop, e.g.:
253//
254// sendCoinsDialog.show();
255// QEventLoop().exec();
256//
257// This also requires overriding the default minimal Qt platform:
258//
259// QT_QPA_PLATFORM=xcb build/bin/test_bitcoin-qt # Linux
260// QT_QPA_PLATFORM=windows build/bin/test_bitcoin-qt # Windows
261// QT_QPA_PLATFORM=cocoa build/bin/test_bitcoin-qt # macOS
262void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
263{
264 // Create widgets for sending coins and listing transactions.
265 std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
266 MiniGUI mini_gui(node, platformStyle.get());
267 mini_gui.initModelForWallet(node, wallet, platformStyle.get());
268 WalletModel& walletModel = *mini_gui.walletModel;
269 SendCoinsDialog& sendCoinsDialog = mini_gui.sendCoinsDialog;
270 TransactionView& transactionView = mini_gui.transactionView;
271
272 // Update walletModel cached balance which will trigger an update for the 'labelBalance' QLabel.
273 walletModel.pollBalanceChanged();
274 // Check balance in send dialog
275 CompareBalance(walletModel, walletModel.wallet().getBalance(), sendCoinsDialog.findChild<QLabel*>("labelBalance"));
276
277 // Check 'UseAvailableBalance' functionality
278 VerifyUseAvailableBalance(sendCoinsDialog, walletModel);
279
280 // Send two transactions, and verify they are added to transaction list.
281 TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
282 QCOMPARE(transactionTableModel->rowCount({}), 105);
283 Txid txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN);
284 Txid txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN);
285 // Transaction table model updates on a QueuedConnection, so process events to ensure it's updated.
286 qApp->processEvents();
287 QCOMPARE(transactionTableModel->rowCount({}), 107);
288 QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
289 QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
290
291 // Call bumpfee. Test canceled fullrbf bump, canceled bip-125-rbf bump, passing bump, and then failing bump.
292 BumpFee(transactionView, txid1, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
293 BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
294 BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/false);
295 BumpFee(transactionView, txid2, /*expectDisabled=*/true, /*expectError=*/"already bumped", /*cancel=*/false);
296
297 // Check current balance on OverviewPage
298 OverviewPage overviewPage(platformStyle.get());
299 overviewPage.setWalletModel(&walletModel);
300 walletModel.pollBalanceChanged(); // Manual balance polling update
301 CompareBalance(walletModel, walletModel.wallet().getBalance(), overviewPage.findChild<QLabel*>("labelBalance"));
302
303 // Check Request Payment button
304 ReceiveCoinsDialog receiveCoinsDialog(platformStyle.get());
305 receiveCoinsDialog.setModel(&walletModel);
307
308 // Label input
309 QLineEdit* labelInput = receiveCoinsDialog.findChild<QLineEdit*>("reqLabel");
310 labelInput->setText("TEST_LABEL_1");
311
312 // Amount input
315
316 // Message input
317 QLineEdit* messageInput = receiveCoinsDialog.findChild<QLineEdit*>("reqMessage");
318 messageInput->setText("TEST_MESSAGE_1");
319 int initialRowCount = requestTableModel->rowCount({});
320 QPushButton* requestPaymentButton = receiveCoinsDialog.findChild<QPushButton*>("receiveButton");
321 requestPaymentButton->click();
322 QString address;
323 for (QWidget* widget : QApplication::topLevelWidgets()) {
324 if (widget->inherits("ReceiveRequestDialog")) {
326 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("payment_header")->text(), QString("Payment information"));
327 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("uri_tag")->text(), QString("URI:"));
328 QString uri = receiveRequestDialog->QObject::findChild<QLabel*>("uri_content")->text();
329 QCOMPARE(uri.count("bitcoin:"), 2);
330 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("address_tag")->text(), QString("Address:"));
331 QVERIFY(address.isEmpty());
332 address = receiveRequestDialog->QObject::findChild<QLabel*>("address_content")->text();
333 QVERIFY(!address.isEmpty());
334
335 QCOMPARE(uri.count("amount=0.00000001"), 2);
336 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("amount_tag")->text(), QString("Amount:"));
337 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("amount_content")->text(), QString::fromStdString("0.00000001 " + CURRENCY_UNIT));
338
339 QCOMPARE(uri.count("label=TEST_LABEL_1"), 2);
340 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("label_tag")->text(), QString("Label:"));
341 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("label_content")->text(), QString("TEST_LABEL_1"));
342
343 QCOMPARE(uri.count("message=TEST_MESSAGE_1"), 2);
344 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("message_tag")->text(), QString("Message:"));
345 QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("message_content")->text(), QString("TEST_MESSAGE_1"));
346 }
347 }
348
349 // Clear button
350 QPushButton* clearButton = receiveCoinsDialog.findChild<QPushButton*>("clearButton");
351 clearButton->click();
352 QCOMPARE(labelInput->text(), QString(""));
353 QCOMPARE(amountInput->value(), CAmount(0));
354 QCOMPARE(messageInput->text(), QString(""));
355
356 // Check addition to history
357 int currentRowCount = requestTableModel->rowCount({});
359
360 // Check addition to wallet
361 std::vector<std::string> requests = walletModel.wallet().getAddressReceiveRequests();
362 QCOMPARE(requests.size(), size_t{1});
363 RecentRequestEntry entry;
364 SpanReader{MakeByteSpan(requests[0])} >> entry;
365 QCOMPARE(entry.nVersion, int{1});
366 QCOMPARE(entry.id, int64_t{1});
367 QVERIFY(entry.date.isValid());
368 QCOMPARE(entry.recipient.address, address);
369 QCOMPARE(entry.recipient.label, QString{"TEST_LABEL_1"});
370 QCOMPARE(entry.recipient.amount, CAmount{1});
371 QCOMPARE(entry.recipient.message, QString{"TEST_MESSAGE_1"});
372 QCOMPARE(entry.recipient.sPaymentRequest, std::string{});
374
375 // Check Remove button
376 QTableView* table = receiveCoinsDialog.findChild<QTableView*>("recentRequestsView");
377 table->selectRow(currentRowCount-1);
378 QPushButton* removeRequestButton = receiveCoinsDialog.findChild<QPushButton*>("removeRequestButton");
379 removeRequestButton->click();
381
382 // Check removal from wallet
383 QCOMPARE(walletModel.wallet().getAddressReceiveRequests().size(), size_t{0});
384}
385
387{
388 const std::shared_ptr<CWallet>& wallet = SetupDescriptorsWallet(node, test, /*watch_only=*/true);
389
390 // Create widgets and init models
391 std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
392 MiniGUI mini_gui(node, platformStyle.get());
393 mini_gui.initModelForWallet(node, wallet, platformStyle.get());
394 WalletModel& walletModel = *mini_gui.walletModel;
395 SendCoinsDialog& sendCoinsDialog = mini_gui.sendCoinsDialog;
396
397 // Update walletModel cached balance which will trigger an update for the 'labelBalance' QLabel.
398 walletModel.pollBalanceChanged();
399 // Check balance in send dialog
400 CompareBalance(walletModel, walletModel.wallet().getBalances().balance,
401 sendCoinsDialog.findChild<QLabel*>("labelBalance"));
402
403 // Set change address
404 sendCoinsDialog.getCoinControl()->destChange = PKHash{test.coinbaseKey.GetPubKey()};
405
406 // Time to reject "save" PSBT dialog ('SendCoins' locks the main thread until the dialog receives the event).
407 QTimer timer;
408 timer.setInterval(500);
409 QObject::connect(&timer, &QTimer::timeout, [&](){
410 for (QWidget* widget : QApplication::topLevelWidgets()) {
411 if (widget->inherits("QMessageBox") && widget->objectName().compare("psbt_copied_message") == 0) {
413 QAbstractButton* button = dialog->button(QMessageBox::Discard);
414 button->setEnabled(true);
415 button->click();
416 timer.stop();
417 break;
418 }
419 }
420 });
421 timer.start(500);
422
423 // Send tx and verify PSBT copied to the clipboard.
424 SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, QMessageBox::Save);
425 const std::string& psbt_string = QApplication::clipboard()->text().toStdString();
426 QVERIFY(!psbt_string.empty());
427
428 // Decode psbt
429 std::optional<std::vector<unsigned char>> decoded_psbt = DecodeBase64(psbt_string);
432 QVERIFY(psbt);
433}
434
436{
437 // Set up wallet and chain with 105 blocks (5 mature blocks for spending).
439 for (int i = 0; i < 5; ++i) {
441 }
442 auto wallet_loader = interfaces::MakeWalletLoader(*test.m_node.chain, *Assert(test.m_node.args));
443 test.m_node.wallet_loader = wallet_loader.get();
444 node.setContext(&test.m_node);
445
446 // "Full" GUI tests, use descriptor wallet
447 const std::shared_ptr<CWallet>& desc_wallet = SetupDescriptorsWallet(node, test);
449
450 // Legacy watch-only wallet test
451 // Verify PSBT creation.
452 TestGUIWatchOnly(node, test);
453}
454
455} // namespace
456
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
int64_t CAmount
Amount in satoshis (Can be negative)
Definition amount.h:12
constexpr CAmount COIN
The amount of satoshis in one BTC.
Definition amount.h:15
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
Definition check.h:119
Widget for entering bitcoin amounts.
void setValue(const CAmount &value)
static QString formatWithUnit(Unit unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
Unit
Bitcoin units.
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition key.cpp:184
Interface from Qt to configuration data structure for Bitcoin client.
bool Init(bilingual_str &error)
BitcoinUnit getDisplayUnit() const
Overview ("home") page widget.
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.
Dialog for requesting payment of bitcoins.
int64_t id
SendCoinsRecipient recipient
int nVersion
QDateTime date
Model for list of recently generated payment requests / bitcoin: URIs.
Dialog for sending bitcoins.
void setModel(WalletModel *model)
wallet::CCoinControl * getCoinControl()
A single entry in the dialog for sending bitcoins.
Minimal stream for reading from an existing byte array by std::span.
Definition streams.h:83
UI model for the transaction table of a wallet.
@ TxHashRole
Transaction hash.
int rowCount(const QModelIndex &parent) const override
Widget showing the transaction list for a wallet, including a filter row.
void setModel(WalletModel *model)
QTableView * transactionView
Interface to Bitcoin wallet from Qt view code.
Definition walletmodel.h:49
RecentRequestsTableModel * getRecentRequestsTableModel() const
void pollBalanceChanged()
TransactionTableModel * getTransactionTableModel() const
interfaces::Wallet & wallet() const
OptionsModel * getOptionsModel() const
interfaces::WalletBalances getCachedBalance() const
void walletTests()
interfaces::Node & m_node
Definition wallettests.h:19
constexpr bool IsNull() const
Definition uint256.h:50
Top-level interface for a bitcoin node (bitcoind process).
Definition node.h:66
virtual CoinsList listCoins()=0
virtual CAmount getBalance()=0
Get balance.
virtual WalletBalances getBalances()=0
Get balances.
virtual std::vector< std::string > getAddressReceiveRequests()=0
Get receive requests.
PreselectedInput & Select(const COutPoint &outpoint)
Lock-in the given output for spending.
CTxDestination destChange
Custom change destination, if not set an address is generated.
Definition coincontrol.h:86
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition wallet.h:318
Descriptor with some wallet metadata.
Definition walletutil.h:86
RAII object to check and reserve a wallet rescan.
Definition scan.h:37
static UniValue Parse(std::string_view raw, ParamFormat format=ParamFormat::JSON)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition client.cpp:411
const std::string CURRENCY_UNIT
Definition feerate.h:19
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition hex_base.cpp:30
std::string EncodeSecret(const CKey &key)
Definition key_io.cpp:233
std::string EncodeDestination(const CTxDestination &dest)
Definition key_io.cpp:292
std::unique_ptr< WalletLoader > MakeWalletLoader(Chain &chain, ArgsManager &args)
Return implementation of ChainClient interface for a wallet loader.
std::unique_ptr< Wallet > MakeWallet(wallet::WalletContext &context, const std::shared_ptr< wallet::CWallet > &wallet)
Return implementation of Wallet interface.
std::unique_ptr< WalletDatabase > CreateMockableWalletDatabase()
Definition util.cpp:126
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Definition wallet.cpp:163
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition walletutil.h:53
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition walletutil.h:30
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition wallet.cpp:175
util::Result< PartiallySignedTransaction > DecodeRawPSBT(std::span< const std::byte > tx_data)
Decode a raw (binary blob) PSBT into a PartiallySignedTransaction.
Definition psbt.cpp:871
void ConfirmMessage(QString *text, std::chrono::milliseconds msec)
Press "Ok" button in message box dialog.
Definition util.cpp:16
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition solver.cpp:213
auto MakeByteSpan(const V &v) noexcept
Definition span.h:84
node::NodeContext m_node
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
CBlock CreateAndProcessBlock(const std::vector< CMutableTransaction > &txns, const CScript &scriptPubKey, bool sync=true)
Create a new block with just the given transactions, coinbase paying to scriptPubKey,...
Bilingual messages:
Definition translation.h:24
ArgsManager * args
Definition context.h:76
interfaces::WalletLoader * wallet_loader
Definition context.h:81
std::unique_ptr< interfaces::Chain > chain
Definition context.h:78
Result of a wallet scan.
Definition scan.h:19
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
Definition scan.h:25
enum wallet::ScanResult::@19 status
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
Definition scan.h:32
WalletContext struct containing references to state shared between CWallet instances,...
Definition context.h:36
#define LOCK(cs)
Definition sync.h:268
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition sync.h:299
FuzzedDataProvider provider
ChangeType
General change type (added, updated, removed).
std::optional< std::vector< unsigned char > > DecodeBase64(std::string_view str)
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82
assert(!tx.IsCoinBase())
WalletContext context