Merge rwconf_policy-25+knots

This commit is contained in:
Luke Dashjr 2023-11-15 23:49:11 +00:00
commit e3ba2d1e08
18 changed files with 787 additions and 28 deletions

View File

@ -129,6 +129,7 @@ using node::ThreadImport;
using node::VerifyLoadedChainstate;
using node::fReindex;
static constexpr bool DEFAULT_COREPOLICY{false};
static constexpr bool DEFAULT_PROXYRANDOMIZE{true};
static constexpr bool DEFAULT_REST_ENABLE{false};
static constexpr bool DEFAULT_I2P_ACCEPT_INCOMING{true};
@ -443,6 +444,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-coinstatsindex", strprintf("Maintain coinstats index used by the gettxoutsetinfo RPC (default: %u)", DEFAULT_COINSTATSINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-conf=<file>", strprintf("Specify path to read-only configuration file. Relative paths will be prefixed by datadir location (only useable from command line, not configuration file) (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-confrw=<file>", strprintf("Specify read/write configuration file. Relative paths will be prefixed by the network-specific datadir location (default: %s)", BITCOIN_RW_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-corepolicy", strprintf("Use Bitcoin Core policy defaults (default: %s)", DEFAULT_COREPOLICY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (%d to %d, default: %d). In addition, unused mempool memory is shared for this cache (see -maxmempool).", nMinDbCache, nMaxDbCache, nDefaultDbCache), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@ -712,6 +714,20 @@ static bool AppInitServers(NodeContext& node)
// Parameter interaction based on rules
void InitParameterInteraction(ArgsManager& args)
{
if (args.GetBoolArg("-corepolicy", DEFAULT_COREPOLICY)) {
args.SoftSetArg("-bytespersigopstrict", "0");
args.SoftSetArg("-permitbaremultisig", "1");
args.SoftSetArg("-datacarriercost", "0.25");
args.SoftSetArg("-datacarrierfullcount", "0");
args.SoftSetArg("-datacarriersize", "83");
args.SoftSetArg("-maxscriptsize", strprintf("%s", std::numeric_limits<unsigned int>::max()));
args.SoftSetArg("-mempoolreplacement", args.GetBoolArg("-mempoolfullrbf", false) ? "fee,-optin" : "fee,optin");
args.SoftSetArg("-spkreuse", "allow");
args.SoftSetArg("-blockprioritysize", "0");
args.SoftSetArg("-blockmaxsize", "4000000");
args.SoftSetArg("-blockmaxweight", "3996000");
}
// when specifying an explicit binding address, you want to listen on it
// even when -connect or -proxy is specified
if (args.IsArgSet("-bind")) {

View File

@ -27,6 +27,7 @@ class BanMan;
class CFeeRate;
class CNetAddr;
class CNodeStats;
class CTxMemPool;
class Coin;
class RPCTimerInterface;
class UniValue;
@ -161,6 +162,8 @@ public:
//! Get total bytes sent.
virtual int64_t getTotalBytesSent() = 0;
virtual CTxMemPool& mempool() = 0;
//! Get mempool size.
virtual size_t getMempoolSize() = 0;

View File

@ -25,7 +25,7 @@ static constexpr unsigned int DEFAULT_BLOCKSONLY_MAX_MEMPOOL_SIZE_MB{5};
/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
static constexpr unsigned int DEFAULT_MEMPOOL_EXPIRY_HOURS{336};
/** Default for -mempoolreplacement; must update docs in init.cpp manually */
static constexpr RBFPolicy DEFAULT_MEMPOOL_RBF_POLICY{RBFPolicy::OptIn};
static constexpr RBFPolicy DEFAULT_MEMPOOL_RBF_POLICY{RBFPolicy::Always};
namespace kernel {
/**

View File

@ -517,6 +517,7 @@ public:
std::optional<std::string> 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);

View File

@ -7,6 +7,7 @@
#define BITCOIN_NET_PROCESSING_H
#include <net.h>
#include <threadsafety.h>
#include <validationinterface.h>
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;

View File

@ -409,6 +409,7 @@ public:
}
ArgsManager& args() { return *Assert(Assert(m_context)->args); }
ChainstateManager& chainman() { return *Assert(m_context->chainman); }
CTxMemPool& mempool() override { return *Assert(m_context->mempool); }
NodeContext* m_context{nullptr};
};

View File

@ -58,8 +58,8 @@ void RegenerateCommitments(CBlock& block, ChainstateManager& chainman)
static BlockAssembler::Options ClampOptions(BlockAssembler::Options options)
{
// Limit weight to between 4K and DEFAULT_BLOCK_MAX_WEIGHT for sanity:
options.nBlockMaxWeight = std::clamp<size_t>(options.nBlockMaxWeight, 4000, DEFAULT_BLOCK_MAX_WEIGHT);
// Limit weight to between 4K and MAX_BLOCK_WEIGHT-4k for sanity:
options.nBlockMaxWeight = std::clamp<size_t>(options.nBlockMaxWeight, 4000, MAX_BLOCK_WEIGHT - 4000);
// Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity:
options.nBlockMaxSize = std::clamp<size_t>(options.nBlockMaxSize, 1000, MAX_BLOCK_SERIALIZED_SIZE - 1000);
// Whether we need to account for byte usage (in addition to weight usage)

View File

@ -22,13 +22,13 @@ class CFeeRate;
class CScript;
/** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = MAX_BLOCK_SERIALIZED_SIZE;
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 300000;
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0;
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 100000;
/** Minimum priority for transactions to be accepted into the priority area **/
static const double MINIMUM_TX_PRIORITY = COIN * 144 / 250;
/** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/
static constexpr unsigned int DEFAULT_BLOCK_MAX_WEIGHT{MAX_BLOCK_WEIGHT - 4000};
static constexpr unsigned int DEFAULT_BLOCK_MAX_WEIGHT{1500000};
/** Default for -blockmintxfee, which sets the minimum feerate for a transaction in blocks created by mining code **/
static constexpr unsigned int DEFAULT_BLOCK_MIN_TX_FEE{1000};
/** The maximum weight for transactions we're willing to relay/mine */
@ -42,15 +42,15 @@ static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/
/** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/
static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000};
/** Default for -maxscriptsize */
static constexpr unsigned int DEFAULT_SCRIPT_SIZE_POLICY_LIMIT{std::numeric_limits<unsigned int>::max()};
static constexpr unsigned int DEFAULT_SCRIPT_SIZE_POLICY_LIMIT{1650};
/** Default for -bytespersigop */
static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20};
/** Default for -bytespersigopstrict */
static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP_STRICT{20};
/** Default for -datacarriercost (multiplied by WITNESS_SCALE_FACTOR) */
static constexpr unsigned int DEFAULT_WEIGHT_PER_DATA_BYTE{1};
static constexpr unsigned int DEFAULT_WEIGHT_PER_DATA_BYTE{4};
/** Default for -permitbaremultisig */
static constexpr bool DEFAULT_PERMIT_BAREMULTISIG{true};
static constexpr bool DEFAULT_PERMIT_BAREMULTISIG{false};
/** The maximum number of witness stack items in a standard P2WSH script */
static constexpr unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS{100};
/** The maximum size in bytes of each witness stack item in a standard P2WSH script */

View File

@ -9,30 +9,89 @@
#include <qt/optionsdialog.h>
#include <qt/forms/ui_optionsdialog.h>
#include <qt/bitcoinamountfield.h>
#include <qt/bitcoinunits.h>
#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
#include <consensus/consensus.h> // for MAX_BLOCK_SERIALIZED_SIZE
#include <interfaces/node.h>
#include <validation.h> // for DEFAULT_SCRIPTCHECK_THREADS and MAX_SCRIPTCHECK_THREADS
#include <netbase.h>
#include <outputtype.h>
#include <primitives/transaction.h> // for WITNESS_SCALE_FACTOR
#include <txdb.h> // for -dbcache defaults
#include <util/system.h>
#include <txmempool.h> // for maxmempoolMinimum
#include <chrono>
#include <QApplication>
#include <QBoxLayout>
#include <QDataWidgetMapper>
#include <QDir>
#include <QDoubleSpinBox>
#include <QFontDialog>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QIntValidator>
#include <QLabel>
#include <QLocale>
#include <QMessageBox>
#include <QSpacerItem>
#include <QString>
#include <QStringList>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QVBoxLayout>
#include <QWidget>
void OptionsDialog::FixTabOrder(QWidget * const o)
{
BitcoinAmountField * const af = qobject_cast<BitcoinAmountField *>(o);
if (af) {
af->setupTabChain(prevwidget);
} else {
setTabOrder(prevwidget, o);
}
prevwidget = o;
}
void OptionsDialog::CreateOptionUI(QBoxLayout * const layout, QWidget * const o, const QString& text)
{
QWidget * const parent = o->parentWidget();
const QStringList text_parts = text.split("%s");
QHBoxLayout * const horizontalLayout = new QHBoxLayout();
QLabel * const labelBefore = new QLabel(parent);
labelBefore->setText(text_parts[0]);
labelBefore->setTextFormat(Qt::PlainText);
labelBefore->setBuddy(o);
labelBefore->setToolTip(o->toolTip());
horizontalLayout->addWidget(labelBefore);
horizontalLayout->addWidget(o);
QLabel * const labelAfter = new QLabel(parent);
labelAfter->setText(text_parts[1]);
labelAfter->setTextFormat(Qt::PlainText);
labelAfter->setBuddy(o);
labelAfter->setToolTip(o->toolTip());
horizontalLayout->addWidget(labelAfter);
QSpacerItem * const horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer);
layout->addLayout(horizontalLayout);
FixTabOrder(o);
}
int setFontChoice(QComboBox* cb, const OptionsModel::FontChoice& fc)
{
@ -136,6 +195,178 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
ui->maxuploadtarget->setMaximum(std::numeric_limits<int>::max());
connect(ui->maxuploadtargetCheckbox, SIGNAL(toggled(bool)), ui->maxuploadtarget, SLOT(setEnabled(bool)));
prevwidget = ui->tabWidget;
walletrbf = new QCheckBox(ui->tabWallet);
walletrbf->setText(tr("Request Replace-By-Fee"));
walletrbf->setToolTip(tr("Indicates that the sender may wish to replace this transaction with a new one paying higher fees (prior to being confirmed). Can be overridden per send."));
ui->verticalLayout_Wallet->insertWidget(0, walletrbf);
FixTabOrder(walletrbf);
/* Network tab */
QLayoutItem *spacer = ui->verticalLayout_Network->takeAt(ui->verticalLayout_Network->count() - 1);
prevwidget = dynamic_cast<QWidgetItem*>(ui->verticalLayout_Network->itemAt(ui->verticalLayout_Network->count() - 1))->widget();
blockreconstructionextratxn = new QSpinBox(ui->tabNetwork);
blockreconstructionextratxn->setMinimum(0);
blockreconstructionextratxn->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(ui->verticalLayout_Network, blockreconstructionextratxn, tr("Keep at most %s extra transactions in memory for compact block reconstruction"));
ui->verticalLayout_Network->addItem(spacer);
prevwidget = ui->peerbloomfilters;
/* Mempool tab */
QWidget * const tabMempool = new QWidget();
QVBoxLayout * const verticalLayout_Mempool = new QVBoxLayout(tabMempool);
ui->tabWidget->insertTab(ui->tabWidget->indexOf(ui->tabWindow), tabMempool, tr("Mem&pool"));
mempoolreplacement = new QValueComboBox(tabMempool);
mempoolreplacement->addItem(QString("never"), QVariant("never"));
mempoolreplacement->addItem(QString("with a higher mining fee, and opt-in"), QVariant("fee,optin"));
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<int>::max());
CreateOptionUI(verticalLayout_Mempool, maxorphantx, tr("Keep at most %s unconnected transactions in memory"));
maxmempool = new QSpinBox(tabMempool);
const int64_t nMempoolSizeMinMB = maxmempoolMinimumBytes(gArgs.GetIntArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT_KVB) * 1'000) / 1'000'000;
maxmempool->setMinimum(nMempoolSizeMinMB);
maxmempool->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(verticalLayout_Mempool, maxmempool, tr("Keep the transaction memory pool below %s MB"));
incrementalrelayfee = new BitcoinAmountField(tabMempool);
connect(incrementalrelayfee, SIGNAL(valueChanged()), this, SLOT(incrementalrelayfee_changed()));
CreateOptionUI(verticalLayout_Mempool, incrementalrelayfee, tr("Require transaction fees to be at least %s per kB higher than transactions they are replacing."));
mempoolexpiry = new QSpinBox(tabMempool);
mempoolexpiry->setMinimum(1);
mempoolexpiry->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(verticalLayout_Mempool, mempoolexpiry, tr("Do not keep transactions in memory more than %s hours"));
QGroupBox * const groupBox_Spamfiltering = new QGroupBox(tabMempool);
groupBox_Spamfiltering->setTitle(tr("Spam filtering"));
QVBoxLayout * const verticalLayout_Spamfiltering = new QVBoxLayout(groupBox_Spamfiltering);
rejectunknownscripts = new QCheckBox(groupBox_Spamfiltering);
rejectunknownscripts->setText(tr("Ignore unrecognised receiver scripts"));
rejectunknownscripts->setToolTip(tr("With this option enabled, unrecognised receiver (\"pubkey\") scripts will be ignored. Unrecognisable scripts could be used to bypass further spam filters. If your software is outdated, they may also be used to trick you into thinking you were sent bitcoins that will never confirm."));
verticalLayout_Spamfiltering->addWidget(rejectunknownscripts);
FixTabOrder(rejectunknownscripts);
rejectspkreuse = new QCheckBox(groupBox_Spamfiltering);
rejectspkreuse->setText(tr("Disallow most address reuse"));
rejectspkreuse->setToolTip(tr("With this option enabled, your memory pool will only allow each unique payment destination to be used once, effectively deprioritising address reuse. Address reuse is not technically supported, and harms the privacy of all Bitcoin users. It also has limited real-world utility, and has been known to be common with spam."));
verticalLayout_Spamfiltering->addWidget(rejectspkreuse);
FixTabOrder(rejectspkreuse);
minrelaytxfee = new BitcoinAmountField(groupBox_Spamfiltering);
CreateOptionUI(verticalLayout_Spamfiltering, minrelaytxfee, tr("Consider transaction fees less than %s per kB relayed to be worthless."));
bytespersigop = new QSpinBox(groupBox_Spamfiltering);
bytespersigop->setMinimum(1);
bytespersigop->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(verticalLayout_Spamfiltering, bytespersigop, tr("Treat each consensus-counted sigop as at least %s bytes."));
bytespersigopstrict = new QSpinBox(groupBox_Spamfiltering);
bytespersigopstrict->setMinimum(1);
bytespersigopstrict->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(verticalLayout_Spamfiltering, bytespersigopstrict, tr("Ignore transactions with fewer than %s bytes per potentially-executed sigop."));
limitancestorcount = new QSpinBox(groupBox_Spamfiltering);
limitancestorcount->setMinimum(1);
limitancestorcount->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(verticalLayout_Spamfiltering, limitancestorcount, tr("Ignore transactions with %s or more unconfirmed ancestors."));
limitancestorsize = new QSpinBox(groupBox_Spamfiltering);
limitancestorsize->setMinimum(1);
limitancestorsize->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(verticalLayout_Spamfiltering, limitancestorsize, tr("Ignore transactions whose size with all unconfirmed ancestors exceeds %s kilobytes."));
limitdescendantcount = new QSpinBox(groupBox_Spamfiltering);
limitdescendantcount->setMinimum(1);
limitdescendantcount->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(verticalLayout_Spamfiltering, limitdescendantcount, tr("Ignore transactions if any ancestor would have %s or more unconfirmed descendants."));
limitdescendantsize = new QSpinBox(groupBox_Spamfiltering);
limitdescendantsize->setMinimum(1);
limitdescendantsize->setMaximum(std::numeric_limits<int>::max());
CreateOptionUI(verticalLayout_Spamfiltering, limitdescendantsize, tr("Ignore transactions if any ancestor would have more than %s kilobytes of unconfirmed descendants."));
rejectbaremultisig = new QCheckBox(groupBox_Spamfiltering);
rejectbaremultisig->setText(tr("Ignore bare/exposed \"multisig\" scripts"));
rejectbaremultisig->setToolTip(tr("Spam is sometimes disguised to appear as if it is an old-style N-of-M multi-party transaction, where most of the keys are really bogus. At the same time, legitimate multi-party transactions typically have always used P2SH format (which is not filtered by this option), which is more secure."));
verticalLayout_Spamfiltering->addWidget(rejectbaremultisig);
FixTabOrder(rejectbaremultisig);
maxscriptsize = new QSpinBox(groupBox_Spamfiltering);
maxscriptsize->setMinimum(0);
maxscriptsize->setMaximum(std::numeric_limits<int>::max());
maxscriptsize->setToolTip(tr("There may be rare smart contracts that require a large amount of code, but more often a larger code segment is actually just spam finding new ways to try to evade filtering. 1650 bytes is sometimes considered the high end of what might be normal, usually for N-of-20 multisig."));
CreateOptionUI(verticalLayout_Spamfiltering, maxscriptsize, tr("Ignore transactions with smart contract code larger than %s bytes."));
datacarriersize = new QSpinBox(groupBox_Spamfiltering);
datacarriersize->setMinimum(0);
datacarriersize->setMaximum(std::numeric_limits<int>::max());
datacarriersize->setToolTip(tr("While Bitcoin itself does not support attaching arbitrary data to transactions, despite that various methods for disguising it have been devised over the years. Since it is sometimes impractical to detect small spam disguised as ordinary transactions, it is sometimes considered beneficial to tolerate certain kinds of less harmful data attachments."));
CreateOptionUI(verticalLayout_Spamfiltering, datacarriersize, tr("Ignore transactions with additional data larger than %s bytes."));
datacarriercost = new QDoubleSpinBox(groupBox_Spamfiltering);
datacarriercost->setDecimals(2);
datacarriercost->setStepType(QAbstractSpinBox::DefaultStepType);
datacarriercost->setSingleStep(0.25);
datacarriercost->setMinimum(0.25);
datacarriercost->setMaximum(MAX_BLOCK_SERIALIZED_SIZE);
datacarriercost->setToolTip(tr("As an alternative to, or in addition to, limiting the size of disguised data, you can also configure how it is accounted for in comparison to legitimate transaction data. For example, 1 vbyte per actual byte would count it as equivalent to ordinary transaction data; 0.25 vB/B would allow it to benefit from the so-called \"segwit discount\"; or 2 vB/B would establish a bias toward legitimate transactions."));
CreateOptionUI(verticalLayout_Spamfiltering, datacarriercost, tr("Weigh embedded data as %s virtual bytes per actual byte."));
connect(datacarriercost, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [=](double d){
const double w = d * 4;
const double wf = floor(w);
if (w != wf) datacarriercost->setValue(wf / 4);
});
dustrelayfee = new BitcoinAmountField(groupBox_Spamfiltering);
CreateOptionUI(verticalLayout_Spamfiltering, dustrelayfee, tr("Ignore transactions with values that would cost more to spend at a fee rate of %s per kB."));
verticalLayout_Mempool->addWidget(groupBox_Spamfiltering);
verticalLayout_Mempool->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
/* Mining tab */
QWidget * const tabMining = new QWidget();
QVBoxLayout * const verticalLayout_Mining = new QVBoxLayout(tabMining);
ui->tabWidget->insertTab(ui->tabWidget->indexOf(ui->tabWindow), tabMining, tr("M&ining"));
verticalLayout_Mining->addWidget(new QLabel(tr("<strong>Note that mining is heavily influenced by the settings on the Mempool tab.</strong>")));
blockmintxfee = new BitcoinAmountField(tabMining);
CreateOptionUI(verticalLayout_Mining, blockmintxfee, tr("Only mine transactions paying a fee of at least %s per kB."));
blockmaxsize = new QSpinBox(tabMining);
blockmaxsize->setMinimum(1);
blockmaxsize->setMaximum((MAX_BLOCK_SERIALIZED_SIZE - 1000) / 1000);
connect(blockmaxsize, SIGNAL(valueChanged(int)), this, SLOT(blockmaxsize_changed(int)));
CreateOptionUI(verticalLayout_Mining, blockmaxsize, tr("Never mine a block larger than %s kB."));
blockprioritysize = new QSpinBox(tabMining);
blockprioritysize->setMinimum(0);
blockprioritysize->setMaximum(blockmaxsize->maximum());
connect(blockprioritysize, SIGNAL(valueChanged(int)), this, SLOT(blockmaxsize_increase(int)));
CreateOptionUI(verticalLayout_Mining, blockprioritysize, tr("Mine first %s kB of transactions sorted by coin-age priority."));
blockmaxweight = new QSpinBox(tabMining);
blockmaxweight->setMinimum(1);
blockmaxweight->setMaximum((MAX_BLOCK_WEIGHT-4000) / 1000);
connect(blockmaxweight, SIGNAL(valueChanged(int)), this, SLOT(blockmaxweight_changed(int)));
CreateOptionUI(verticalLayout_Mining, blockmaxweight, tr("Never mine a block weighing more than %s kWU."));
verticalLayout_Mining->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
/* Window elements init */
#ifdef Q_OS_MACOS
/* remove Window tab on Mac */
@ -292,6 +523,8 @@ void OptionsDialog::setModel(OptionsModel *_model)
connect(ui->connectSocksTor, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
connect(ui->peerbloomfilters, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
connect(ui->peerblockfilters, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
/* Mempool */
connect(rejectspkreuse, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
/* Display */
connect(ui->lang, qOverload<>(&QValueComboBox::valueChanged), [this]{ showRestartWarning(); });
connect(ui->thirdPartyTxUrls, &QLineEdit::textChanged, [this]{ showRestartWarning(); });
@ -321,6 +554,7 @@ void OptionsDialog::setMapper()
mapper->addMapping(ui->pruneSizeMiB, OptionsModel::PruneSizeMiB);
/* Wallet */
mapper->addMapping(walletrbf, OptionsModel::walletrbf);
mapper->addMapping(ui->addressType, OptionsModel::addresstype);
mapper->addMapping(ui->spendZeroConfChange, OptionsModel::SpendZeroConfChange);
mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures);
@ -360,6 +594,45 @@ void OptionsDialog::setMapper()
mapper->addMapping(ui->peerbloomfilters, OptionsModel::peerbloomfilters);
mapper->addMapping(ui->peerblockfilters, OptionsModel::peerblockfilters);
mapper->addMapping(blockreconstructionextratxn, OptionsModel::blockreconstructionextratxn);
/* Mempool tab */
QVariant current_mempoolreplacement = model->data(model->index(OptionsModel::mempoolreplacement, 0), Qt::EditRole);
int current_mempoolreplacement_index = mempoolreplacement->findData(current_mempoolreplacement);
if (current_mempoolreplacement_index == -1) {
mempoolreplacement->addItem(current_mempoolreplacement.toString(), current_mempoolreplacement);
current_mempoolreplacement_index = mempoolreplacement->count() - 1;
}
mempoolreplacement->setCurrentIndex(current_mempoolreplacement_index);
mapper->addMapping(maxorphantx, OptionsModel::maxorphantx);
mapper->addMapping(maxmempool, OptionsModel::maxmempool);
mapper->addMapping(incrementalrelayfee, OptionsModel::incrementalrelayfee);
mapper->addMapping(mempoolexpiry, OptionsModel::mempoolexpiry);
mapper->addMapping(rejectunknownscripts, OptionsModel::rejectunknownscripts);
mapper->addMapping(rejectspkreuse, OptionsModel::rejectspkreuse);
mapper->addMapping(minrelaytxfee, OptionsModel::minrelaytxfee);
mapper->addMapping(bytespersigop, OptionsModel::bytespersigop);
mapper->addMapping(bytespersigopstrict, OptionsModel::bytespersigopstrict);
mapper->addMapping(limitancestorcount, OptionsModel::limitancestorcount);
mapper->addMapping(limitancestorsize, OptionsModel::limitancestorsize);
mapper->addMapping(limitdescendantcount, OptionsModel::limitdescendantcount);
mapper->addMapping(limitdescendantsize, OptionsModel::limitdescendantsize);
mapper->addMapping(rejectbaremultisig, OptionsModel::rejectbaremultisig);
mapper->addMapping(maxscriptsize, OptionsModel::maxscriptsize);
mapper->addMapping(datacarriercost, OptionsModel::datacarriercost);
mapper->addMapping(datacarriersize, OptionsModel::datacarriersize);
mapper->addMapping(dustrelayfee, OptionsModel::dustrelayfee);
/* Mining tab */
mapper->addMapping(blockmintxfee, OptionsModel::blockmintxfee);
mapper->addMapping(blockmaxsize, OptionsModel::blockmaxsize);
mapper->addMapping(blockprioritysize, OptionsModel::blockprioritysize);
mapper->addMapping(blockmaxweight, OptionsModel::blockmaxweight);
/* Window */
#ifndef Q_OS_MACOS
if (QSystemTrayIcon::isSystemTrayAvailable()) {
@ -392,6 +665,42 @@ void OptionsDialog::setOkButtonState(bool fState)
ui->okButton->setEnabled(fState);
}
void OptionsDialog::incrementalrelayfee_changed()
{
if (incrementalrelayfee->value() > minrelaytxfee->value()) {
minrelaytxfee->setValue(incrementalrelayfee->value());
}
}
void OptionsDialog::blockmaxsize_changed(int i)
{
if (blockprioritysize->value() > i) {
blockprioritysize->setValue(i);
}
if (blockmaxweight->value() < i) {
blockmaxweight->setValue(i);
} else if (blockmaxweight->value() > i * WITNESS_SCALE_FACTOR) {
blockmaxweight->setValue(i * WITNESS_SCALE_FACTOR);
}
}
void OptionsDialog::blockmaxsize_increase(int i)
{
if (blockmaxsize->value() < i) {
blockmaxsize->setValue(i);
}
}
void OptionsDialog::blockmaxweight_changed(int i)
{
if (blockmaxsize->value() < i / WITNESS_SCALE_FACTOR) {
blockmaxsize->setValue(i / WITNESS_SCALE_FACTOR);
} else if (blockmaxsize->value() > i) {
blockmaxsize->setValue(i);
}
}
void OptionsDialog::on_resetButton_clicked()
{
if (model) {
@ -407,14 +716,25 @@ void OptionsDialog::on_resetButton_clicked()
with a client shutdown. */
reset_dialog_text.append(tr("Client will be shut down. Do you want to proceed?"));
//: Window title text of pop-up window shown when the user has chosen to reset options.
QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm options reset"),
reset_dialog_text, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
QStringList items;
QString strPrefix = tr("Use policy defaults for %1");
items << strPrefix.arg(tr(PACKAGE_NAME));
items << strPrefix.arg(tr("Bitcoin Core")+" ");
if (btnRetVal == QMessageBox::Cancel)
QInputDialog dialog(this);
dialog.setWindowTitle(tr("Confirm options reset"));
dialog.setLabelText(reset_dialog_text);
dialog.setComboBoxItems(items);
dialog.setTextValue(items[0]);
dialog.setComboBoxEditable(false);
if (!dialog.exec()) {
return;
}
/* reset all options and close GUI */
model->Reset();
model->setData(model->index(OptionsModel::corepolicy, 0), items.indexOf(dialog.textValue()));
close();
Q_EMIT quitOnReset();
}
@ -474,6 +794,8 @@ void OptionsDialog::on_okButton_clicked()
model->setData(model->index(OptionsModel::maxuploadtarget, 0), 0);
}
model->setData(model->index(OptionsModel::mempoolreplacement, 0), mempoolreplacement->itemData(mempoolreplacement->currentIndex()));
mapper->submit();
accept();
updateDefaultProxyNets();

View File

@ -8,12 +8,20 @@
#include <QDialog>
#include <QValidator>
class BitcoinAmountField;
class ClientModel;
class OptionsModel;
class QValidatedLineEdit;
QT_BEGIN_NAMESPACE
class QBoxLayout;
class QCheckBox;
class QDataWidgetMapper;
class QDoubleSpinBox;
class QSpinBox;
class QString;
class QValueComboBox;
class QWidget;
QT_END_NAMESPACE
namespace Ui {
@ -69,6 +77,11 @@ private Q_SLOTS:
void updateDefaultProxyNets();
void checkLineEdit();
void incrementalrelayfee_changed();
void blockmaxsize_changed(int);
void blockmaxsize_increase(int);
void blockmaxweight_changed(int);
Q_SIGNALS:
void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, uint16_t nProxyPort);
void quitOnReset();
@ -78,6 +91,37 @@ private:
ClientModel* m_client_model{nullptr};
OptionsModel* model{nullptr};
QDataWidgetMapper* mapper{nullptr};
QWidget *prevwidget{nullptr};
void FixTabOrder(QWidget *);
void CreateOptionUI(QBoxLayout *, QWidget *, const QString& text);
QCheckBox *walletrbf;
QSpinBox *blockreconstructionextratxn;
QValueComboBox *mempoolreplacement;
QSpinBox *maxorphantx;
BitcoinAmountField *incrementalrelayfee;
QSpinBox *maxmempool;
QSpinBox *mempoolexpiry;
QCheckBox *rejectunknownscripts;
QCheckBox *rejectspkreuse;
BitcoinAmountField *minrelaytxfee;
QSpinBox *bytespersigop, *bytespersigopstrict;
QSpinBox *limitancestorcount;
QSpinBox *limitancestorsize;
QSpinBox *limitdescendantcount;
QSpinBox *limitdescendantsize;
QCheckBox *rejectbaremultisig;
QSpinBox *maxscriptsize;
QSpinBox *datacarriersize;
QDoubleSpinBox *datacarriercost;
BitcoinAmountField *dustrelayfee;
BitcoinAmountField *blockmintxfee;
QSpinBox *blockmaxsize, *blockprioritysize, *blockmaxweight;
};
#endif // BITCOIN_QT_OPTIONSDIALOG_H

View File

@ -13,15 +13,20 @@
#include <qt/guiutil.h>
#include <chainparams.h>
#include <consensus/consensus.h>
#include <index/blockfilterindex.h>
#include <interfaces/node.h>
#include <kernel/mempool_options.h> // for DEFAULT_MAX_MEMPOOL_SIZE_MB, DEFAULT_MEMPOOL_EXPIRY_HOURS
#include <mapport.h>
#include <policy/settings.h>
#include <net.h>
#include <net_processing.h>
#include <netbase.h>
#include <node/context.h>
#include <outputtype.h>
#include <policy/settings.h>
#include <txdb.h> // for -dbcache defaults
#include <util/moneystr.h> // for FormatMoney
#include <util/string.h>
#include <util/system.h>
#include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS
@ -31,6 +36,8 @@
#include <interfaces/wallet.h>
#endif
#include <chrono>
#include <QDebug>
#include <QLatin1Char>
#include <QSettings>
@ -64,6 +71,7 @@ static const char* SettingName(OptionsModel::OptionID option)
case OptionsModel::ProxyPortTor: return "onion";
case OptionsModel::ProxyUseTor: return "onion";
case OptionsModel::Language: return "lang";
case OptionsModel::datacarriercost: return "datacarriercost";
default: throw std::logic_error(strprintf("GUI option %i has no corresponding node setting.", option));
}
}
@ -197,6 +205,16 @@ OptionsModel::FontChoice OptionsModel::FontChoiceFromString(const QString& s)
}
}
static QString CanonicalMempoolReplacement(const OptionsModel& model)
{
switch (model.node().mempool().m_rbf_policy) {
case RBFPolicy::Never: return "never";
case RBFPolicy::OptIn: return "fee,optin";
case RBFPolicy::Always: return "fee,-optin";
}
assert(0);
}
OptionsModel::OptionsModel(interfaces::Node& node, QObject *parent) :
QAbstractListModel(parent), m_node{node}
{
@ -277,6 +295,7 @@ bool OptionsModel::Init(bilingual_str& error)
// These are shared with the core or have a command-line parameter
// and we want command-line parameters to overwrite the GUI settings.
for (OptionID option : {DatabaseCache, ThreadsScriptVerif, SpendZeroConfChange, ExternalSignerPath, MapPortUPnP,
datacarriercost,
MapPortNatpmp, Listen, Server, PruneTristate, ProxyUse, ProxyUseTor, Language}) {
// isSettingIgnored will have a false positive here during first-run prune changes
if (option == PruneTristate && m_prune_forced_by_gui) continue;
@ -315,7 +334,9 @@ bool OptionsModel::Init(bilingual_str& error)
addOverriddenOption("-port");
// rwconf settings that require a restart
// Caution: This is before general initialisation occurs!
f_peerbloomfilters = gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS);
f_rejectspkreuse = !(gArgs.GetArg("-spkreuse", DEFAULT_SPKREUSE) == "allow" || gArgs.GetBoolArg("-spkreuse", false));
// Display
if (settings.contains("FontForMoney")) {
@ -570,6 +591,10 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con
return QVariant::fromValue(m_font_qrcodes);
case PeersTabAlternatingRowColors:
return m_peers_tab_alternating_row_colors;
#ifdef ENABLE_WALLET
case walletrbf:
return gArgs.GetBoolArg("-walletrbf", wallet::DEFAULT_WALLET_RBF);
#endif
case CoinControlFeatures:
return fCoinControlFeatures;
case EnablePSBTControls:
@ -596,6 +621,58 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con
return f_peerbloomfilters;
case peerblockfilters:
return gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS);
case mempoolreplacement:
return CanonicalMempoolReplacement(*this);
case maxorphantx:
return qlonglong(gArgs.GetIntArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
case maxmempool:
return qlonglong(node().mempool().m_max_size_bytes / 1'000'000);
case incrementalrelayfee:
return qlonglong(node().mempool().m_incremental_relay_feerate.GetFeePerK());
case mempoolexpiry:
return qlonglong(std::chrono::duration_cast<std::chrono::hours>(node().mempool().m_expiry).count());
case rejectunknownscripts:
return node().mempool().m_require_standard;
case rejectspkreuse:
return f_rejectspkreuse;
case minrelaytxfee:
return qlonglong(node().mempool().m_min_relay_feerate.GetFeePerK());
case bytespersigop:
return nBytesPerSigOp;
case bytespersigopstrict:
return nBytesPerSigOpStrict;
case limitancestorcount:
return qlonglong(node().mempool().m_limits.ancestor_count);
case limitancestorsize:
return qlonglong(node().mempool().m_limits.ancestor_size_vbytes / 1'000);
case limitdescendantcount:
return qlonglong(node().mempool().m_limits.descendant_count);
case limitdescendantsize:
return qlonglong(node().mempool().m_limits.descendant_size_vbytes / 1'000);
case rejectbaremultisig:
return !node().mempool().m_permit_bare_multisig;
case maxscriptsize:
return ::g_script_size_policy_limit;
case datacarriercost:
return double(::g_weight_per_data_byte) / WITNESS_SCALE_FACTOR;
case datacarriersize:
return qlonglong(node().mempool().m_max_datacarrier_bytes.value_or(0));
case dustrelayfee:
return qlonglong(node().mempool().m_dust_relay_feerate.GetFeePerK());
case blockmintxfee:
if (gArgs.IsArgSet("-blockmintxfee")) {
return qlonglong(ParseMoney(gArgs.GetArg("-blockmintxfee", "")).value_or(0));
} else {
return qlonglong(DEFAULT_BLOCK_MIN_TX_FEE);
}
case blockmaxsize:
return qlonglong(gArgs.GetIntArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE) / 1000);
case blockprioritysize:
return qlonglong(gArgs.GetIntArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE) / 1000);
case blockmaxweight:
return qlonglong(gArgs.GetIntArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT) / 1000);
case blockreconstructionextratxn:
return qlonglong(gArgs.GetIntArg("-blockreconstructionextratxn", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
default:
return QVariant();
}
@ -810,6 +887,24 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std::
settings.setValue("PeersTabAlternatingRowColors", m_peers_tab_alternating_row_colors);
Q_EMIT peersTabAlternatingRowColorsChanged(m_peers_tab_alternating_row_colors);
break;
#ifdef ENABLE_WALLET
case walletrbf:
if (changed()) {
const bool fNewValue = value.toBool();
const std::string newvalue_str = strprintf("%d", fNewValue);
gArgs.ModifyRWConfigFile("walletrbf", newvalue_str);
gArgs.ForceSetArg("-walletrbf", newvalue_str);
for (auto& wallet_interface : m_node.walletLoader().getWallets()) {
wallet::CWallet *wallet;
if (wallet_interface && (wallet = wallet_interface->wallet())) {
wallet->m_signal_rbf = fNewValue;
} else {
setRestartRequired(true);
}
}
}
break;
#endif
case CoinControlFeatures:
fCoinControlFeatures = value.toBool();
settings.setValue("fCoinControlFeatures", fCoinControlFeatures);
@ -898,6 +993,242 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std::
}
break;
}
case mempoolreplacement:
{
if (changed()) {
QString nv = value.toString();
if (nv == "never") {
node().mempool().m_rbf_policy = RBFPolicy::Never;
node().updateRwSetting("mempoolfullrbf", "0");
} else if (nv == "fee,optin") {
node().mempool().m_rbf_policy = RBFPolicy::OptIn;
node().updateRwSetting("mempoolfullrbf", "0");
} else { // "fee,-optin"
node().mempool().m_rbf_policy = RBFPolicy::Always;
node().updateRwSetting("mempoolfullrbf", "1");
}
gArgs.ModifyRWConfigFile("mempoolreplacement", nv.toStdString());
}
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;
}
case maxmempool:
{
if (changed()) {
long long nOldValue = node().mempool().m_max_size_bytes;
long long nNv = value.toLongLong();
std::string strNv = value.toString().toStdString();
node().mempool().m_max_size_bytes = nNv * 1'000'000;
gArgs.ForceSetArg("-maxmempool", strNv);
gArgs.ModifyRWConfigFile("maxmempool", strNv);
if (nNv < nOldValue) {
LOCK(cs_main);
auto node_ctx = node().context();
assert(node_ctx && node_ctx->mempool && node_ctx->chainman);
auto& active_chainstate = node_ctx->chainman->ActiveChainstate();
LimitMempoolSize(*node_ctx->mempool, active_chainstate.CoinsTip());
}
}
break;
}
case incrementalrelayfee:
if (changed()) {
CAmount nNv = value.toLongLong();
gArgs.ModifyRWConfigFile("incrementalrelayfee", FormatMoney(nNv));
node().mempool().m_incremental_relay_feerate = CFeeRate(nNv);
}
break;
case mempoolexpiry:
{
if (changed()) {
const auto old_value = node().mempool().m_expiry;
const std::chrono::hours new_value{value.toLongLong()};
std::string strNv = value.toString().toStdString();
node().mempool().m_expiry = new_value;
gArgs.ForceSetArg("-mempoolexpiry", strNv);
gArgs.ModifyRWConfigFile("mempoolexpiry", strNv);
if (new_value < old_value) {
LOCK(cs_main);
auto node_ctx = node().context();
assert(node_ctx && node_ctx->mempool && node_ctx->chainman);
auto& active_chainstate = node_ctx->chainman->ActiveChainstate();
LimitMempoolSize(*node_ctx->mempool, active_chainstate.CoinsTip());
}
}
break;
}
case rejectunknownscripts:
{
if (changed()) {
const bool fNewValue = value.toBool();
node().mempool().m_require_standard = fNewValue;
// This option is inverted in the config:
gArgs.ModifyRWConfigFile("acceptnonstdtxn", strprintf("%d", ! fNewValue));
}
break;
}
case rejectspkreuse:
if (changed()) {
const bool fNewValue = value.toBool();
gArgs.ModifyRWConfigFile("spkreuse", fNewValue ? "conflict" : "allow");
f_rejectspkreuse = fNewValue;
setRestartRequired(true);
}
break;
case minrelaytxfee:
if (changed()) {
CAmount nNv = value.toLongLong();
gArgs.ModifyRWConfigFile("minrelaytxfee", FormatMoney(nNv));
node().mempool().m_min_relay_feerate = CFeeRate(nNv);
}
break;
case bytespersigop:
if (changed()) {
gArgs.ModifyRWConfigFile("bytespersigop", value.toString().toStdString());
nBytesPerSigOp = value.toLongLong();
}
break;
case bytespersigopstrict:
if (changed()) {
gArgs.ModifyRWConfigFile("bytespersigopstrict", value.toString().toStdString());
nBytesPerSigOpStrict = value.toLongLong();
}
break;
case limitancestorcount:
if (changed()) {
long long nNv = value.toLongLong();
std::string strNv = value.toString().toStdString();
node().mempool().m_limits.ancestor_count = nNv;
gArgs.ForceSetArg("-limitancestorcount", strNv);
gArgs.ModifyRWConfigFile("limitancestorcount", strNv);
}
break;
case limitancestorsize:
if (changed()) {
long long nNv = value.toLongLong();
std::string strNv = value.toString().toStdString();
node().mempool().m_limits.ancestor_size_vbytes = nNv * 1'000;
gArgs.ForceSetArg("-limitancestorsize", strNv);
gArgs.ModifyRWConfigFile("limitancestorsize", strNv);
}
break;
case limitdescendantcount:
if (changed()) {
long long nNv = value.toLongLong();
std::string strNv = value.toString().toStdString();
node().mempool().m_limits.descendant_count = nNv;
gArgs.ForceSetArg("-limitdescendantcount", strNv);
gArgs.ModifyRWConfigFile("limitdescendantcount", strNv);
}
break;
case limitdescendantsize:
if (changed()) {
long long nNv = value.toLongLong();
std::string strNv = value.toString().toStdString();
node().mempool().m_limits.descendant_size_vbytes = nNv * 1'000;
gArgs.ForceSetArg("-limitdescendantsize", strNv);
gArgs.ModifyRWConfigFile("limitdescendantsize", strNv);
}
break;
case rejectbaremultisig:
if (changed()) {
// The config and internal option is inverted
const bool fNewValue = ! value.toBool();
node().mempool().m_permit_bare_multisig = fNewValue;
gArgs.ModifyRWConfigFile("permitbaremultisig", strprintf("%d", fNewValue));
}
break;
case maxscriptsize:
if (changed()) {
const auto nv = value.toLongLong();
update(nv);
::g_script_size_policy_limit = nv;
}
break;
case datacarriercost:
if (changed()) {
const double nNewSize = value.toDouble();
update(nNewSize);
::g_weight_per_data_byte = nNewSize * WITNESS_SCALE_FACTOR;
}
break;
case datacarriersize:
if (changed()) {
const int nNewSize = value.toInt();
const bool fNewEn = (nNewSize > 0);
if (fNewEn) {
if (!node().mempool().m_max_datacarrier_bytes.has_value()) {
gArgs.ModifyRWConfigFile("datacarrier", strprintf("%d", fNewEn));
}
gArgs.ModifyRWConfigFile("datacarriersize", value.toString().toStdString());
node().mempool().m_max_datacarrier_bytes = nNewSize;
} else {
gArgs.ModifyRWConfigFile("datacarrier", "0");
node().mempool().m_max_datacarrier_bytes = std::nullopt;
}
}
break;
case dustrelayfee:
if (changed()) {
CAmount nNv = value.toLongLong();
gArgs.ModifyRWConfigFile("dustrelayfee", FormatMoney(nNv));
node().mempool().m_dust_relay_feerate = CFeeRate(nNv);
}
break;
case blockmintxfee:
if (changed()) {
std::string strNv = FormatMoney(value.toLongLong());
gArgs.ForceSetArg("-blockmintxfee", strNv);
gArgs.ModifyRWConfigFile("blockmintxfee", strNv);
}
break;
case blockmaxsize:
case blockprioritysize:
case blockmaxweight:
if (changed()) {
const int nNewValue_kB = value.toInt();
std::string strNv = strprintf("%d000", nNewValue_kB);
std::string strKey;
switch (option) {
case blockmaxsize:
strKey = "blockmaxsize";
break;
case blockprioritysize:
strKey = "blockprioritysize";
break;
case blockmaxweight:
strKey = "blockmaxweight";
break;
default: assert(0);
}
gArgs.ForceSetArg("-" + strKey, strNv);
gArgs.ModifyRWConfigFile(strKey, strNv);
}
break;
case blockreconstructionextratxn:
if (changed()) {
std::string strNv = value.toString().toStdString();
gArgs.ForceSetArg("-blockreconstructionextratxn", strNv);
gArgs.ModifyRWConfigFile("blockreconstructionextratxn", strNv);
}
break;
case corepolicy:
gArgs.ModifyRWConfigFile("corepolicy", value.toString().toStdString());
break;
default:
break;
}

View File

@ -64,6 +64,7 @@ public:
FontForMoney, // FontChoice
FontForQRCodes, // FontChoice
PeersTabAlternatingRowColors, // bool
walletrbf, // bool
CoinControlFeatures, // bool
SubFeeFromAmount, // bool
ThreadsScriptVerif, // int
@ -80,6 +81,31 @@ public:
maxuploadtarget,
peerbloomfilters, // bool
peerblockfilters, // bool
mempoolreplacement,
maxorphantx,
maxmempool,
incrementalrelayfee,
mempoolexpiry,
rejectunknownscripts, // bool
rejectspkreuse, // bool
minrelaytxfee,
bytespersigop,
bytespersigopstrict,
limitancestorcount,
limitancestorsize,
limitdescendantcount,
limitdescendantsize,
rejectbaremultisig, // bool
maxscriptsize,
datacarriercost, // double
datacarriersize,
dustrelayfee,
blockmintxfee,
blockmaxsize,
blockprioritysize,
blockmaxweight,
blockreconstructionextratxn,
corepolicy,
OptionIDRowCount,
};
@ -156,6 +182,7 @@ private:
/* rwconf settings that require a restart */
bool f_peerbloomfilters;
bool f_rejectspkreuse;
// Add option to list of GUI options overridden through command line/config file
void addOverriddenOption(const std::string &option);

View File

@ -33,12 +33,12 @@ public:
};
/**
* Default setting for -datacarriersize. 80 bytes of data, +1 for OP_RETURN,
* +2 for the pushdata opcodes.
* Default setting for -datacarriersize. 40 bytes of data, +1 for OP_RETURN,
* +1 for the pushdata opcode.
*/
static const unsigned int MAX_OP_RETURN_RELAY = 83;
static constexpr unsigned int MAX_OP_RETURN_RELAY{42};
/** Default for -datacarrierfullcount */
static constexpr bool DEFAULT_DATACARRIER_FULLCOUNT{false};
static constexpr bool DEFAULT_DATACARRIER_FULLCOUNT{true};
/**
* Mandatory script verification flags that all new blocks must comply with for

View File

@ -604,6 +604,8 @@ void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
gArgs.ForceSetArg("-blockprioritysize", "0");
// Note that by default, these tests run with size accounting enabled.
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
std::unique_ptr<CBlockTemplate> pblocktemplate;

View File

@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(set)
txTo[i].vin[0].prevout.n = i;
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
txTo[i].vout[0].nValue = 1*CENT;
txTo[i].vout[0].scriptPubKey = inner[i];
txTo[i].vout[0].scriptPubKey = outer[i];
}
for (int i = 0; i < 4; i++)
{

View File

@ -819,12 +819,15 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
CheckIsNotStandard(t, "scriptpubkey");
// MAX_OP_RETURN_RELAY-byte TxoutType::NULL_DATA (standard)
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
while (t.vout[0].scriptPubKey.size() < MAX_OP_RETURN_RELAY) {
t.vout[0].scriptPubKey << OP_0;
}
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
CheckIsStandard(t);
// MAX_OP_RETURN_RELAY+1-byte TxoutType::NULL_DATA (non-standard)
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
t.vout[0].scriptPubKey << OP_0;
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
CheckIsNotStandard(t, "scriptpubkey");

View File

@ -463,17 +463,17 @@ public:
using Options = kernel::MemPoolOptions;
int64_t m_max_size_bytes;
const std::chrono::seconds m_expiry;
const CFeeRate m_incremental_relay_feerate;
const CFeeRate m_min_relay_feerate;
const CFeeRate m_dust_relay_feerate;
const bool m_permit_bare_multisig;
const std::optional<unsigned> m_max_datacarrier_bytes;
std::chrono::seconds m_expiry;
CFeeRate m_incremental_relay_feerate;
CFeeRate m_min_relay_feerate;
CFeeRate m_dust_relay_feerate;
bool m_permit_bare_multisig;
std::optional<unsigned> m_max_datacarrier_bytes;
bool m_datacarrier_fullcount;
const bool m_require_standard;
const RBFPolicy m_rbf_policy;
bool m_require_standard;
RBFPolicy m_rbf_policy;
const Limits m_limits;
Limits m_limits;
/** Create a new CTxMemPool.
* Sanity checks will be off by default for performance, because otherwise

View File

@ -120,6 +120,7 @@ class TestNode():
if self.version is None:
self.args += [
"-corepolicy",
"-softwareexpiry=0",
"-walletimplicitsegwit",
]