diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 167c8095b6..7dba8344db 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -517,6 +517,7 @@ public: std::optional FetchBlock(NodeId peer_id, const uint256& hash, const CBlockIndex* block_index) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); + void LimitOrphanTxSize(unsigned int nMaxOrphans) override; bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; } void SendPings() override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); void RelayTransaction(const uint256& txid, const uint256& wtxid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); @@ -1673,6 +1674,12 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c return true; } +void PeerManagerImpl::LimitOrphanTxSize(unsigned int nMaxOrphans) +{ + LOCK(cs_main); + m_orphanage.LimitOrphans(nMaxOrphans); +} + int PeerManagerImpl::GetNumberOfPeersWithValidatedDownloads() { AssertLockHeld(cs_main); diff --git a/src/net_processing.h b/src/net_processing.h index 92ab812a9f..690634553f 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -7,6 +7,7 @@ #define BITCOIN_NET_PROCESSING_H #include +#include #include class AddrMan; @@ -63,6 +64,7 @@ public: /** Get statistics from node state */ virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const = 0; + virtual void LimitOrphanTxSize(unsigned int nMaxOrphans) = 0; /** Whether this node ignores txs received over p2p. */ virtual bool IgnoresIncomingTxs() = 0; diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 20bcc5a6f0..b0636d2b44 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -198,6 +198,11 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet) mempoolreplacement->addItem(QString("with a higher mining fee (no opt-out)"), QVariant("fee,-optin")); CreateOptionUI(verticalLayout_Mempool, mempoolreplacement, tr("Transaction &replacement: %s")); + maxorphantx = new QSpinBox(tabMempool); + maxorphantx->setMinimum(0); + maxorphantx->setMaximum(std::numeric_limits::max()); + CreateOptionUI(verticalLayout_Mempool, maxorphantx, tr("Keep at most %s unconnected transactions in memory")); + QGroupBox * const groupBox_Spamfiltering = new QGroupBox(tabMempool); groupBox_Spamfiltering->setTitle(tr("Spam filtering")); QVBoxLayout * const verticalLayout_Spamfiltering = new QVBoxLayout(groupBox_Spamfiltering); @@ -442,6 +447,8 @@ void OptionsDialog::setMapper() } mempoolreplacement->setCurrentIndex(current_mempoolreplacement_index); + mapper->addMapping(maxorphantx, OptionsModel::maxorphantx); + /* Window */ #ifndef Q_OS_MACOS if (QSystemTrayIcon::isSystemTrayAvailable()) { diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 5811844404..aaa8f9a316 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -15,6 +15,7 @@ class QValidatedLineEdit; QT_BEGIN_NAMESPACE class QBoxLayout; class QDataWidgetMapper; +class QSpinBox; class QString; class QValueComboBox; class QWidget; @@ -88,6 +89,7 @@ private: void CreateOptionUI(QBoxLayout *, QWidget *, const QString& text); QValueComboBox *mempoolreplacement; + QSpinBox *maxorphantx; }; #endif // BITCOIN_QT_OPTIONSDIALOG_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 33fa232839..e8b1280840 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -609,6 +609,8 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con return gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS); case mempoolreplacement: return CanonicalMempoolReplacement(*this); + case maxorphantx: + return qlonglong(gArgs.GetIntArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); default: return QVariant(); } @@ -926,6 +928,21 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std:: } break; } + case maxorphantx: + { + if (changed()) { + unsigned int nMaxOrphanTx = gArgs.GetIntArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS); + unsigned int nNv = value.toLongLong(); + std::string strNv = value.toString().toStdString(); + gArgs.ForceSetArg("-maxorphantx", strNv); + gArgs.ModifyRWConfigFile("maxorphantx", strNv); + if (nNv < nMaxOrphanTx) { + assert(node().context() && node().context()->peerman); + node().context()->peerman->LimitOrphanTxSize(nNv); + } + } + break; + } default: break; } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 2297c23fa2..38a984331a 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -81,6 +81,7 @@ public: peerbloomfilters, // bool peerblockfilters, // bool mempoolreplacement, + maxorphantx, OptionIDRowCount, };