v30.3-roots.1 · Commit 16: [PATCH 16/68] feat(qt): add per-send RBF override
src/qt/test/wallettests.cpp
Before: src/qt/test/wallettests.cpp · After: src/qt/test/wallettests.cpp
File metadata
index 5e65dcca318d978d10c58605669197dee236daaa..a477110f9ae62f0d0b236850d143289323e9ba75 100644
Download original patch · Release notes
Diff rows 1–110 of 110. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
src/qt/test/wallettests.cpp
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
#include <qt/walletmodel.h>
|
|
27
27
|
#include <script/solver.h>
|
|
28
28
|
#include <test/util/setup_common.h>
|
|
29
|
+
#include <util/rbf.h>
|
|
29
30
|
#include <validation.h>
|
|
30
31
|
#include <wallet/test/util.h>
|
|
31
32
|
#include <wallet/wallet.h>
|
|
@@ -76,7 +77,7 @@ void ConfirmSend(QString* text = nullptr, QMessageBox::StandardButton confirm_ty
|
|
|
76
77
|
|
|
77
78
|
//! Send coins to address and return txid.
|
|
78
79
|
Txid SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount, bool rbf,
|
|
79
|
-
QMessageBox::StandardButton confirm_type = QMessageBox::Yes)
|
|
80
|
+
QMessageBox::StandardButton confirm_type = QMessageBox::Yes, QString* confirmation_text = nullptr)
|
|
80
81
|
{
|
|
81
82
|
QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
|
|
82
83
|
SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
|
|
@@ -90,7 +91,7 @@ Txid SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDesti
|
|
|
90
91
|
boost::signals2::scoped_connection c(wallet.NotifyTransactionChanged.connect([&txid](const Txid& hash, ChangeType status) {
|
|
91
92
|
if (status == CT_NEW) txid = hash;
|
|
92
93
|
}));
|
|
93
|
-
ConfirmSend(/*text=*/nullptr, confirm_type);
|
|
94
|
+
ConfirmSend(confirmation_text, confirm_type);
|
|
94
95
|
bool invoked = QMetaObject::invokeMethod(&sendCoinsDialog, "sendButtonClicked", Q_ARG(bool, false));
|
|
95
96
|
assert(invoked);
|
|
96
97
|
return txid;
|
|
@@ -265,6 +266,8 @@ public:
|
|
|
265
266
|
// QT_QPA_PLATFORM=cocoa build/bin/test_bitcoin-qt # macOS
|
|
266
267
|
void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
|
267
268
|
{
|
|
269
|
+
wallet->m_signal_rbf = false;
|
|
270
|
+
|
|
268
271
|
// Create widgets for sending coins and listing transactions.
|
|
269
272
|
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
|
|
270
273
|
MiniGUI mini_gui(node, platformStyle.get());
|
|
@@ -284,19 +287,42 @@ void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
|
|
284
287
|
// Send two transactions, and verify they are added to transaction list.
|
|
285
288
|
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
|
|
286
289
|
QCOMPARE(transactionTableModel->rowCount({}), 105);
|
|
287
|
-
Txid txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, /*rbf=*/false);
|
|
288
|
-
Txid txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN, /*rbf=*/true);
|
|
290
|
+
QCheckBox* rbf_checkbox = sendCoinsDialog.findChild<QCheckBox*>("optInRBF");
|
|
291
|
+
QVERIFY(rbf_checkbox);
|
|
292
|
+
QCOMPARE(rbf_checkbox->text(), "Enable Replace-By-Fee");
|
|
293
|
+
QVERIFY(rbf_checkbox->focusPolicy() != Qt::NoFocus);
|
|
294
|
+
QVERIFY(!rbf_checkbox->isChecked());
|
|
295
|
+
|
|
296
|
+
QString no_rbf_confirmation;
|
|
297
|
+
Txid txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, /*rbf=*/false, QMessageBox::Yes, &no_rbf_confirmation);
|
|
298
|
+
QString rbf_confirmation;
|
|
299
|
+
Txid txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN, /*rbf=*/true, QMessageBox::Yes, &rbf_confirmation);
|
|
300
|
+
QVERIFY(!SignalsOptInRBF(*wallet->mapWallet.at(txid1).tx));
|
|
301
|
+
QVERIFY(SignalsOptInRBF(*wallet->mapWallet.at(txid2).tx));
|
|
302
|
+
QVERIFY(no_rbf_confirmation.contains("Not signalling Replace-By-Fee, BIP-125."));
|
|
303
|
+
QVERIFY(rbf_confirmation.contains("signals Replace-By-Fee (BIP-125)"));
|
|
304
|
+
|
|
305
|
+
wallet->m_signal_rbf = true;
|
|
306
|
+
SendCoinsDialog default_rbf_dialog(platformStyle.get());
|
|
307
|
+
default_rbf_dialog.setModel(&walletModel);
|
|
308
|
+
QVERIFY(default_rbf_dialog.findChild<QCheckBox*>("optInRBF")->isChecked());
|
|
309
|
+
QString default_on_override_confirmation;
|
|
310
|
+
Txid txid3 = SendCoins(*wallet.get(), default_rbf_dialog, PKHash(), COIN, /*rbf=*/false, QMessageBox::Yes, &default_on_override_confirmation);
|
|
311
|
+
QVERIFY(!SignalsOptInRBF(*wallet->mapWallet.at(txid3).tx));
|
|
312
|
+
QVERIFY(default_on_override_confirmation.contains("Not signalling Replace-By-Fee, BIP-125."));
|
|
289
313
|
// Transaction table model updates on a QueuedConnection, so process events to ensure it's updated.
|
|
290
314
|
qApp->processEvents();
|
|
291
|
-
QCOMPARE(transactionTableModel->rowCount({}), 107);
|
|
315
|
+
QCOMPARE(transactionTableModel->rowCount({}), 108);
|
|
292
316
|
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
|
|
293
317
|
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
|
|
318
|
+
QVERIFY(FindTx(*transactionTableModel, txid3).isValid());
|
|
294
319
|
|
|
295
320
|
// Call bumpfee. Test canceled fullrbf bump, canceled bip-125-rbf bump, passing bump, and then failing bump.
|
|
296
321
|
BumpFee(transactionView, txid1, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
|
|
297
322
|
BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
|
|
298
323
|
BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/false);
|
|
299
324
|
BumpFee(transactionView, txid2, /*expectDisabled=*/true, /*expectError=*/"already bumped", /*cancel=*/false);
|
|
325
|
+
BumpFee(transactionView, txid3, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
|
|
300
326
|
|
|
301
327
|
// Check current balance on OverviewPage
|
|
302
328
|
OverviewPage overviewPage(platformStyle.get());
|
|
@@ -435,6 +461,34 @@ void TestGUIWatchOnly(interfaces::Node& node, TestChain100Setup& test)
|
|
|
435
461
|
PartiallySignedTransaction psbt;
|
|
436
462
|
std::string err;
|
|
437
463
|
QVERIFY(DecodeRawPSBT(psbt, MakeByteSpan(*decoded_psbt), err));
|
|
464
|
+
QVERIFY(!SignalsOptInRBF(CTransaction{*psbt.tx}));
|
|
465
|
+
|
|
466
|
+
SendCoinsDialog rbf_psbt_dialog(platformStyle.get());
|
|
467
|
+
rbf_psbt_dialog.setModel(&walletModel);
|
|
468
|
+
rbf_psbt_dialog.getCoinControl()->destChange = PKHash{test.coinbaseKey.GetPubKey()};
|
|
469
|
+
QTimer rbf_timer;
|
|
470
|
+
rbf_timer.setInterval(500);
|
|
471
|
+
QObject::connect(&rbf_timer, &QTimer::timeout, [&](){
|
|
472
|
+
for (QWidget* widget : QApplication::topLevelWidgets()) {
|
|
473
|
+
if (widget->inherits("QMessageBox") && widget->objectName().compare("psbt_copied_message") == 0) {
|
|
474
|
+
QMessageBox* dialog = qobject_cast<QMessageBox*>(widget);
|
|
475
|
+
QAbstractButton* button = dialog->button(QMessageBox::Discard);
|
|
476
|
+
button->setEnabled(true);
|
|
477
|
+
button->click();
|
|
478
|
+
rbf_timer.stop();
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
rbf_timer.start(500);
|
|
484
|
+
|
|
485
|
+
SendCoins(*wallet.get(), rbf_psbt_dialog, PKHash(), 5 * COIN, /*rbf=*/true, QMessageBox::Save);
|
|
486
|
+
decoded_psbt = DecodeBase64(QApplication::clipboard()->text().toStdString());
|
|
487
|
+
QVERIFY(decoded_psbt);
|
|
488
|
+
psbt = {};
|
|
489
|
+
err.clear();
|
|
490
|
+
QVERIFY(DecodeRawPSBT(psbt, MakeByteSpan(*decoded_psbt), err));
|
|
491
|
+
QVERIFY(SignalsOptInRBF(CTransaction{*psbt.tx}));
|
|
438
492
|
}
|
|
439
493
|
|
|
440
494
|
void TestGUI(interfaces::Node& node)
|