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. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
src/qt/test/wallettests.cpp
CHANGED
|
@@ -26,6 +26,7 @@
|
|
| 26 |
#include <qt/walletmodel.h>
|
| 27 |
#include <script/solver.h>
|
| 28 |
#include <test/util/setup_common.h>
|
|
|
|
| 29 |
#include <validation.h>
|
| 30 |
#include <wallet/test/util.h>
|
| 31 |
#include <wallet/wallet.h>
|
|
@@ -76,7 +77,7 @@ void ConfirmSend(QString* text = nullptr, QMessageBox::StandardButton confirm_ty
|
|
| 76 |
|
| 77 |
//! Send coins to address and return txid.
|
| 78 |
Txid SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount, bool rbf,
|
| 79 |
-
QMessageBox::StandardButton confirm_type = QMessageBox::Yes)
|
| 80 |
{
|
| 81 |
QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
|
| 82 |
SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
|
|
@@ -90,7 +91,7 @@ Txid SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDesti
|
|
| 90 |
boost::signals2::scoped_connection c(wallet.NotifyTransactionChanged.connect([&txid](const Txid& hash, ChangeType status) {
|
| 91 |
if (status == CT_NEW) txid = hash;
|
| 92 |
}));
|
| 93 |
-
ConfirmSend(/*text=*/nullptr, confirm_type);
|
| 94 |
bool invoked = QMetaObject::invokeMethod(&sendCoinsDialog, "sendButtonClicked", Q_ARG(bool, false));
|
| 95 |
assert(invoked);
|
| 96 |
return txid;
|
|
@@ -265,6 +266,8 @@ public:
|
|
| 265 |
// QT_QPA_PLATFORM=cocoa build/bin/test_bitcoin-qt # macOS
|
| 266 |
void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
| 267 |
{
|
|
|
|
|
|
|
| 268 |
// Create widgets for sending coins and listing transactions.
|
| 269 |
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
|
| 270 |
MiniGUI mini_gui(node, platformStyle.get());
|
|
@@ -284,19 +287,42 @@ void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
|
| 284 |
// Send two transactions, and verify they are added to transaction list.
|
| 285 |
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
|
| 286 |
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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
// Transaction table model updates on a QueuedConnection, so process events to ensure it's updated.
|
| 290 |
qApp->processEvents();
|
| 291 |
-
QCOMPARE(transactionTableModel->rowCount({}), 107);
|
| 292 |
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
|
| 293 |
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
|
|
|
|
| 294 |
|
| 295 |
// Call bumpfee. Test canceled fullrbf bump, canceled bip-125-rbf bump, passing bump, and then failing bump.
|
| 296 |
BumpFee(transactionView, txid1, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
|
| 297 |
BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
|
| 298 |
BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/false);
|
| 299 |
BumpFee(transactionView, txid2, /*expectDisabled=*/true, /*expectError=*/"already bumped", /*cancel=*/false);
|
|
|
|
| 300 |
|
| 301 |
// Check current balance on OverviewPage
|
| 302 |
OverviewPage overviewPage(platformStyle.get());
|
|
@@ -435,6 +461,34 @@ void TestGUIWatchOnly(interfaces::Node& node, TestChain100Setup& test)
|
|
| 435 |
PartiallySignedTransaction psbt;
|
| 436 |
std::string err;
|
| 437 |
QVERIFY(DecodeRawPSBT(psbt, MakeByteSpan(*decoded_psbt), err));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
}
|
| 439 |
|
| 440 |
void TestGUI(interfaces::Node& node)
|
|
|
|
| 26 |
#include <qt/walletmodel.h>
|
| 27 |
#include <script/solver.h>
|
| 28 |
#include <test/util/setup_common.h>
|
| 29 |
+
#include <util/rbf.h>
|
| 30 |
#include <validation.h>
|
| 31 |
#include <wallet/test/util.h>
|
| 32 |
#include <wallet/wallet.h>
|
|
|
|
| 77 |
|
| 78 |
//! Send coins to address and return txid.
|
| 79 |
Txid SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount, bool rbf,
|
| 80 |
+
QMessageBox::StandardButton confirm_type = QMessageBox::Yes, QString* confirmation_text = nullptr)
|
| 81 |
{
|
| 82 |
QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
|
| 83 |
SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
|
|
|
|
| 91 |
boost::signals2::scoped_connection c(wallet.NotifyTransactionChanged.connect([&txid](const Txid& hash, ChangeType status) {
|
| 92 |
if (status == CT_NEW) txid = hash;
|
| 93 |
}));
|
| 94 |
+
ConfirmSend(confirmation_text, confirm_type);
|
| 95 |
bool invoked = QMetaObject::invokeMethod(&sendCoinsDialog, "sendButtonClicked", Q_ARG(bool, false));
|
| 96 |
assert(invoked);
|
| 97 |
return txid;
|
|
|
|
| 266 |
// QT_QPA_PLATFORM=cocoa build/bin/test_bitcoin-qt # macOS
|
| 267 |
void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
| 268 |
{
|
| 269 |
+
wallet->m_signal_rbf = false;
|
| 270 |
+
|
| 271 |
// Create widgets for sending coins and listing transactions.
|
| 272 |
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
|
| 273 |
MiniGUI mini_gui(node, platformStyle.get());
|
|
|
|
| 287 |
// Send two transactions, and verify they are added to transaction list.
|
| 288 |
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
|
| 289 |
QCOMPARE(transactionTableModel->rowCount({}), 105);
|
| 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."));
|
| 313 |
// Transaction table model updates on a QueuedConnection, so process events to ensure it's updated.
|
| 314 |
qApp->processEvents();
|
| 315 |
+
QCOMPARE(transactionTableModel->rowCount({}), 108);
|
| 316 |
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
|
| 317 |
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
|
| 318 |
+
QVERIFY(FindTx(*transactionTableModel, txid3).isValid());
|
| 319 |
|
| 320 |
// Call bumpfee. Test canceled fullrbf bump, canceled bip-125-rbf bump, passing bump, and then failing bump.
|
| 321 |
BumpFee(transactionView, txid1, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
|
| 322 |
BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
|
| 323 |
BumpFee(transactionView, txid2, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/false);
|
| 324 |
BumpFee(transactionView, txid2, /*expectDisabled=*/true, /*expectError=*/"already bumped", /*cancel=*/false);
|
| 325 |
+
BumpFee(transactionView, txid3, /*expectDisabled=*/false, /*expectError=*/{}, /*cancel=*/true);
|
| 326 |
|
| 327 |
// Check current balance on OverviewPage
|
| 328 |
OverviewPage overviewPage(platformStyle.get());
|
|
|
|
| 461 |
PartiallySignedTransaction psbt;
|
| 462 |
std::string err;
|
| 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}));
|
| 492 |
}
|
| 493 |
|
| 494 |
void TestGUI(interfaces::Node& node)
|