What changed, and why it matters
This commit removes the on/off checkbox in the Bitcoin Core desktop wallet that let users choose whether a transaction should signal 'Replace-By-Fee' (RBF). After the change, the GUI simply follows the wallet's configuration setting instead. It is a user-interface simplification, not a fix for a software vulnerability.
No security action required. Treat as a normal UI/UX change. Wallet operators who relied on the GUI checkbox to disable RBF per transaction should now use the -walletrbf=0 configuration option if they wish to disable RBF globally.
Security signals we found
No memory-safety, cryptographic, or consensus changes
No input validation, parsing, or network code modified
Change is confined to Qt GUI and wallet test code
Behavioral change: GUI no longer lets users opt out of RBF per transaction; defaults to wallet setting
Evidence from the diff
The patch deletes the ‘Enable Replace-By-Fee’ QCheckBox from the SendCoinsDialog form and disconnects its state from CCoinControl::m_signal_bip125_rbf. The GUI no longer overrides the wallet’s RBF policy; it falls back to the existing -walletrbf CLI option (default true). Tests are updated to remove the now-obsolete rbf parameter. A hard-coded coin_control.m_signal_bip125_rbf = true in bumpFee is also removed, relying on the wallet’s default RBF behavior instead.
Changed components
src/qt/forms/sendcoinsdialog.uisrc/qt/sendcoinsdialog.cppsrc/qt/test/wallettests.cppsrc/qt/walletmodel.cppInspect captured patch +8 / −39
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index 1ca92440..db59fccb 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -1049,16 +1049,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</item>
</layout>
</item>
- <item>
- <widget class="QCheckBox" name="optInRBF">
- <property name="text">
- <string>Enable Replace-By-Fee</string>
- </property>
- <property name="toolTip">
- <string>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</string>
- </property>
- </widget>
- </item>
</layout>
</widget>
</item>
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 74b93417..7c8c0436 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -179,13 +179,6 @@ void SendCoinsDialog::setModel(WalletModel *_model)
connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::coinControlUpdateLabels);
connect(ui->customFee, &BitcoinAmountField::valueChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
-#if (QT_VERSION >= QT_VERSION_CHECK(6, 7, 0))
- connect(ui->optInRBF, &QCheckBox::checkStateChanged, this, &SendCoinsDialog::updateSmartFeeLabel);
- connect(ui->optInRBF, &QCheckBox::checkStateChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
-#else
- connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::updateSmartFeeLabel);
- connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
-#endif
CAmount requiredFee = model->wallet().getRequiredFee(1000);
ui->customFee->SetMinValue(requiredFee);
if (ui->customFee->value() < requiredFee) {
@@ -195,9 +188,6 @@ void SendCoinsDialog::setModel(WalletModel *_model)
updateFeeSectionControls();
updateSmartFeeLabel();
- // set default rbf checkbox state
- ui->optInRBF->setCheckState(Qt::Checked);
-
if (model->wallet().hasExternalSigner()) {
//: "device" usually means a hardware wallet.
ui->sendButton->setText(tr("Sign on device"));
@@ -360,17 +350,12 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa
question_string.append("<span style='color:#aa0000; font-weight:bold;'>");
question_string.append(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee));
question_string.append("</span><br />");
-
- // append RBF message according to transaction's signalling
- question_string.append("<span style='font-size:10pt; font-weight:normal;'>");
- if (ui->optInRBF->isChecked()) {
- question_string.append(tr("You can increase the fee later (signals Replace-By-Fee, BIP-125)."));
- } else {
- question_string.append(tr("Not signalling Replace-By-Fee, BIP-125."));
- }
- question_string.append("</span>");
}
+ // append RBF message
+ question_string.append("<span style='font-size:10pt; font-weight:normal;'>");
+ question_string.append(tr("You can increase the fee later."));
+
// add total amount in all subdivision units
question_string.append("<hr />");
CAmount totalAmount = m_current_transaction->getTotalTransactionAmount() + txFee;
@@ -834,7 +819,6 @@ void SendCoinsDialog::updateCoinControlState()
// Avoid using global defaults when sending money from the GUI
// Either custom fee will be used or if not selected, the confirmation target from dropdown box
m_coin_control->m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex());
- m_coin_control->m_signal_bip125_rbf = ui->optInRBF->isChecked();
}
void SendCoinsDialog::updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state) {
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index bb9e0618..556a6cb6 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -75,17 +75,13 @@ void ConfirmSend(QString* text = nullptr, QMessageBox::StandardButton confirm_ty
}
//! Send coins to address and return txid.
-Txid SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount, bool rbf,
+Txid SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount,
QMessageBox::StandardButton confirm_type = QMessageBox::Yes)
{
QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
entry->findChild<QValidatedLineEdit*>("payTo")->setText(QString::fromStdString(EncodeDestination(address)));
entry->findChild<BitcoinAmountField*>("payAmount")->setValue(amount);
- sendCoinsDialog.findChild<QFrame*>("frameFee")
- ->findChild<QFrame*>("frameFeeSelection")
- ->findChild<QCheckBox*>("optInRBF")
- ->setCheckState(rbf ? Qt::Checked : Qt::Unchecked);
Txid txid;
btcsignals::scoped_connection c(wallet.NotifyTransactionChanged.connect([&txid](const Txid& hash, ChangeType status) {
if (status == CT_NEW) txid = hash;
@@ -283,8 +279,8 @@ void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
// Send two transactions, and verify they are added to transaction list.
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
QCOMPARE(transactionTableModel->rowCount({}), 105);
- Txid txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, /*rbf=*/false);
- Txid txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN, /*rbf=*/true);
+ Txid txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN);
+ Txid txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN);
// Transaction table model updates on a QueuedConnection, so process events to ensure it's updated.
qApp->processEvents();
QCOMPARE(transactionTableModel->rowCount({}), 107);
@@ -424,7 +420,7 @@ void TestGUIWatchOnly(interfaces::Node& node, TestChain100Setup& test)
timer.start(500);
// Send tx and verify PSBT copied to the clipboard.
- SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, /*rbf=*/false, QMessageBox::Save);
+ SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, QMessageBox::Save);
const std::string& psbt_string = QApplication::clipboard()->text().toStdString();
QVERIFY(!psbt_string.empty());
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 67a420f5..a9142b93 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -464,7 +464,6 @@ WalletModel::UnlockContext::~UnlockContext()
bool WalletModel::bumpFee(Txid hash, Txid& new_hash)
{
CCoinControl coin_control;
- coin_control.m_signal_bip125_rbf = true;
std::vector<bilingual_str> errors;
CAmount old_fee;
CAmount new_fee;
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.