mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-06-03 16:02:34 +02:00
Merge rwconf_policy-27+knots
This commit is contained in:
commit
a0e633d350
24
src/init.cpp
24
src/init.cpp
@ -136,6 +136,7 @@ using node::ShouldPersistMempool;
|
||||
using node::ImportBlocks;
|
||||
using node::VerifyLoadedChainstate;
|
||||
|
||||
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};
|
||||
@ -482,6 +483,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: %u)", 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);
|
||||
@ -672,8 +674,8 @@ void SetupServerArgs(ArgsManager& argsman)
|
||||
ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-maxscriptsize", strprintf("Maximum size of scripts we relay and mine, in bytes (default: %s)", DEFAULT_SCRIPT_SIZE_POLICY_LIMIT), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-mempoolfullrbf", strprintf("Accept transaction replace-by-fee without requiring replaceability signaling (default: %u)", (DEFAULT_MEMPOOL_RBF_POLICY == RBFPolicy::Always)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-mempoolreplacement", strprintf("Set to 0 to disable RBF entirely, \"fee,optin\" to honour RBF opt-out signal, or \"fee,-optin\" to always RBF aka full RBF (default: %s)", "fee,optin"), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-mempooltruc", strprintf("Behaviour for transactions requesting TRUC limits: \"reject\" the transactions entirely, \"accept\" them just like any other, or \"enforce\" to impose their requested restrictions (default: %s)", "reject"), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-mempoolreplacement", strprintf("Set to 0 to disable RBF entirely, \"fee,optin\" to honour RBF opt-out signal, or \"fee,-optin\" to always RBF aka full RBF (default: %s)", "fee,-optin"), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-mempooltruc", strprintf("Behaviour for transactions requesting TRUC limits: \"reject\" the transactions entirely, \"accept\" them just like any other, or \"enforce\" to impose their requested restrictions (default: %s)", "accept"), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-permitbarepubkey", strprintf("Relay legacy pubkey outputs (default: %u)", DEFAULT_PERMIT_BAREPUBKEY), ArgsManager::ALLOW_ANY,
|
||||
OptionsCategory::NODE_RELAY);
|
||||
argsman.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY,
|
||||
@ -773,6 +775,24 @@ static bool AppInitServers(NodeContext& node)
|
||||
// Parameter interaction based on rules
|
||||
void InitParameterInteraction(ArgsManager& args)
|
||||
{
|
||||
if (args.GetBoolArg("-corepolicy", DEFAULT_COREPOLICY)) {
|
||||
args.SoftSetArg("-acceptnonstddatacarrier", "1");
|
||||
args.SoftSetArg("-bytespersigopstrict", "0");
|
||||
args.SoftSetArg("-permitbarepubkey", "1");
|
||||
args.SoftSetArg("-permitbaremultisig", "1");
|
||||
args.SoftSetArg("-rejectparasites", "0");
|
||||
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("-mempooltruc", args.GetBoolArg("-acceptnonstdtxn", DEFAULT_ACCEPT_NON_STD_TXN) ? "enforce" : "reject");
|
||||
args.SoftSetArg("-spkreuse", "allow");
|
||||
args.SoftSetArg("-blockprioritysize", "0");
|
||||
args.SoftSetArg("-blockmaxsize", "4000000");
|
||||
args.SoftSetArg("-blockmaxweight", "3996000");
|
||||
}
|
||||
|
||||
if (args.GetBoolArg("-acceptnonstdtxn", DEFAULT_ACCEPT_NON_STD_TXN) && (!args.IsArgSet("-mempooltruc")) && DEFAULT_MEMPOOL_TRUC_POLICY == TRUCPolicy::Reject) {
|
||||
args.SoftSetArg("-mempooltruc", "enforce");
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
class BanMan;
|
||||
class CFeeRate;
|
||||
class CNodeStats;
|
||||
class CTxMemPool;
|
||||
class Coin;
|
||||
class RPCTimerInterface;
|
||||
class UniValue;
|
||||
@ -157,6 +158,8 @@ public:
|
||||
//! Get total bytes sent.
|
||||
virtual int64_t getTotalBytesSent() = 0;
|
||||
|
||||
virtual CTxMemPool& mempool() = 0;
|
||||
|
||||
//! Get mempool size.
|
||||
virtual size_t getMempoolSize() = 0;
|
||||
|
||||
|
@ -26,13 +26,13 @@ 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};
|
||||
/** Default for -mempooltruc; must update docs in init.cpp manually */
|
||||
static constexpr TRUCPolicy DEFAULT_MEMPOOL_TRUC_POLICY{TRUCPolicy::Reject};
|
||||
static constexpr TRUCPolicy DEFAULT_MEMPOOL_TRUC_POLICY{TRUCPolicy::Accept};
|
||||
/** Whether to fall back to legacy V1 serialization when writing mempool.dat */
|
||||
static constexpr bool DEFAULT_PERSIST_V1_DAT{false};
|
||||
/** Default for -acceptnonstddatacarrier */
|
||||
static constexpr bool DEFAULT_ACCEPT_NON_STD_DATACARRIER{true};
|
||||
static constexpr bool DEFAULT_ACCEPT_NON_STD_DATACARRIER{false};
|
||||
/** Default for -acceptnonstdtxn */
|
||||
static constexpr bool DEFAULT_ACCEPT_NON_STD_TXN{false};
|
||||
|
||||
|
@ -512,6 +512,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_opts.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);
|
||||
@ -1782,6 +1783,13 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
|
||||
return true;
|
||||
}
|
||||
|
||||
void PeerManagerImpl::LimitOrphanTxSize(unsigned int nMaxOrphans)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
LOCK(NetEventsInterface::g_msgproc_mutex);
|
||||
m_orphanage.LimitOrphans(nMaxOrphans, m_rng);
|
||||
}
|
||||
|
||||
int PeerManagerImpl::GetNumberOfPeersWithValidatedDownloads() const
|
||||
{
|
||||
AssertLockHeld(m_chainman.GetMutex());
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define BITCOIN_NET_PROCESSING_H
|
||||
|
||||
#include <net.h>
|
||||
#include <threadsafety.h>
|
||||
#include <validationinterface.h>
|
||||
|
||||
class AddrMan;
|
||||
@ -84,6 +85,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;
|
||||
|
@ -416,6 +416,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};
|
||||
};
|
||||
|
||||
|
@ -60,8 +60,8 @@ void RegenerateCommitments(CBlock& block, ChainstateManager& chainman)
|
||||
BlockAssembler::Options BlockAssembler::Options::Clamped() const
|
||||
{
|
||||
BlockAssembler::Options options = *this;
|
||||
// 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);
|
||||
return options;
|
||||
|
@ -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{DEFAULT_BLOCK_MAX_SIZE * WITNESS_SCALE_FACTOR};
|
||||
/** 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,21 +42,21 @@ 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 -rejecttokens */
|
||||
static constexpr bool DEFAULT_REJECT_TOKENS{false};
|
||||
/** Default for -permitbarepubkey */
|
||||
static constexpr bool DEFAULT_PERMIT_BAREPUBKEY{true};
|
||||
static constexpr bool DEFAULT_PERMIT_BAREPUBKEY{false};
|
||||
/** Default for -permitbaremultisig */
|
||||
static constexpr bool DEFAULT_PERMIT_BAREMULTISIG{true};
|
||||
static constexpr bool DEFAULT_PERMIT_BAREMULTISIG{false};
|
||||
/** Default for -rejectparasites */
|
||||
static constexpr bool DEFAULT_REJECT_PARASITES{false};
|
||||
static constexpr bool DEFAULT_REJECT_PARASITES{true};
|
||||
/** 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 */
|
||||
@ -89,12 +89,12 @@ static constexpr unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT_KVB{101};
|
||||
/** Default for -datacarrier */
|
||||
static const bool DEFAULT_ACCEPT_DATACARRIER = true;
|
||||
/**
|
||||
* 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};
|
||||
/**
|
||||
* An extra transaction can be added to a package, as long as it only has one
|
||||
* ancestor and is no larger than this. Not really any reason to make this
|
||||
|
@ -9,31 +9,111 @@
|
||||
#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 <common/args.h>
|
||||
#include <common/system.h>
|
||||
#include <consensus/consensus.h> // for MAX_BLOCK_SERIALIZED_SIZE
|
||||
#include <interfaces/node.h>
|
||||
#include <node/chainstatemanager_args.h>
|
||||
#include <netbase.h>
|
||||
#include <node/mempool_args.h> // for ParseDustDynamicOpt
|
||||
#include <outputtype.h>
|
||||
#include <primitives/transaction.h> // for WITNESS_SCALE_FACTOR
|
||||
#include <txdb.h>
|
||||
#include <txmempool.h> // for maxmempoolMinimum
|
||||
#include <util/check.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <utility>
|
||||
|
||||
#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 <QRadioButton>
|
||||
#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, QLayout *horizontalLayout)
|
||||
{
|
||||
QWidget * const parent = o->parentWidget();
|
||||
const QStringList text_parts = text.split("%s");
|
||||
|
||||
if (!horizontalLayout) horizontalLayout = new QHBoxLayout();
|
||||
|
||||
if (!text_parts[0].isEmpty()) {
|
||||
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);
|
||||
|
||||
o->setProperty("L", QVariant::fromValue((QLayout*)horizontalLayout));
|
||||
|
||||
FixTabOrder(o);
|
||||
}
|
||||
|
||||
static void setSiblingsEnabled(QWidget * const o, const bool state)
|
||||
{
|
||||
auto layout = o->property("L").value<QLayout*>();
|
||||
Assert(layout);
|
||||
// NOTE: QLayout::children does not do what we need here
|
||||
for (int i = layout->count(); i-- > 0; ) {
|
||||
QLayoutItem * const layoutitem = layout->itemAt(i);
|
||||
QWidget * const childwidget = layoutitem->widget();
|
||||
if (!childwidget) continue;
|
||||
childwidget->setEnabled(state);
|
||||
}
|
||||
}
|
||||
|
||||
int setFontChoice(QComboBox* cb, const OptionsModel::FontChoice& fc)
|
||||
{
|
||||
@ -139,6 +219,282 @@ 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"));
|
||||
|
||||
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 kvB higher than transactions they are replacing."));
|
||||
|
||||
rejectspkreuse = new QCheckBox(tabMempool);
|
||||
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_Mempool->addWidget(rejectspkreuse);
|
||||
FixTabOrder(rejectspkreuse);
|
||||
|
||||
mempooltruc = new QValueComboBox(tabMempool);
|
||||
mempooltruc->addItem(QString("do not relay or mine at all"), QVariant("reject"));
|
||||
mempooltruc->addItem(QString("handle the same as other transactions"), QVariant("accept"));
|
||||
mempooltruc->addItem(QString("impose stricter limits requested (DRAFT)"), QVariant("enforce"));
|
||||
mempooltruc->setToolTip(tr("Some transactions signal a request to limit both themselves and other related transactions to more restrictive expectations. Specifically, this would disallow more than 1 unconfirmed predecessor or spending transaction, as well as smaller size limits (see BIP 431 for details), regardless of what policy you have configured."));
|
||||
CreateOptionUI(verticalLayout_Mempool, mempooltruc, tr("Transactions requesting more restrictive policy limits (TRUC): %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"));
|
||||
|
||||
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"));
|
||||
|
||||
verticalLayout_Mempool->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||
|
||||
/* Filters tab */
|
||||
|
||||
QWidget * const tabFilters = new QWidget();
|
||||
auto& groupBox_Spamfiltering = tabFilters;
|
||||
ui->tabWidget->insertTab(ui->tabWidget->indexOf(ui->tabWindow), tabFilters, 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);
|
||||
|
||||
rejectparasites = new QCheckBox(groupBox_Spamfiltering);
|
||||
rejectparasites->setText(tr("Reject parasite transactions"));
|
||||
rejectparasites->setToolTip(tr("With this option enabled, transactions related to parasitic overlay protocols will be ignored. Parasites are transactions using Bitcoin as a technical infrastructure to animate other protocols, unrelated to ordinary money transfers."));
|
||||
verticalLayout_Spamfiltering->addWidget(rejectparasites);
|
||||
FixTabOrder(rejectparasites);
|
||||
|
||||
rejecttokens = new QCheckBox(groupBox_Spamfiltering);
|
||||
rejecttokens->setText(tr("Ignore transactions involving non-bitcoin token/asset overlay protocols"));
|
||||
rejecttokens->setToolTip(tr("With this option enabled, transactions involving non-bitcoin tokens/assets will not be relayed or mined by your node. Due to not having value, and some technical design flaws, token mints and transfers are often spammy and can bog down the network."));
|
||||
verticalLayout_Spamfiltering->addWidget(rejecttokens);
|
||||
FixTabOrder(rejecttokens);
|
||||
|
||||
minrelaytxfee = new BitcoinAmountField(groupBox_Spamfiltering);
|
||||
CreateOptionUI(verticalLayout_Spamfiltering, minrelaytxfee, tr("Ignore transactions offering miners less than %s per kvB in transaction fees."));
|
||||
|
||||
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."));
|
||||
|
||||
rejectbarepubkey = new QCheckBox(groupBox_Spamfiltering);
|
||||
rejectbarepubkey->setText(tr("Ignore bare/exposed public keys (pay-to-IP)"));
|
||||
rejectbarepubkey->setToolTip(tr("Spam is sometimes disguised to appear as if it is a deprecated pay-to-IP (bare pubkey) transaction, where the \"key\" is actually arbitrary data (not a real key) instead. Support for pay-to-IP was only ever supported by Satoshi's early Bitcoin wallet, which has been abandoned since 2011."));
|
||||
verticalLayout_Spamfiltering->addWidget(rejectbarepubkey);
|
||||
FixTabOrder(rejectbarepubkey);
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
rejectnonstddatacarrier = new QCheckBox(groupBox_Spamfiltering);
|
||||
rejectnonstddatacarrier->setText(tr("Ignore data embedded with non-standard formats"));
|
||||
rejectnonstddatacarrier->setToolTip(tr("Some attempts to spam Bitcoin intentionally use non-standard formats in an attempt to bypass the datacarrier limits. Without this option, %1 will attempt to detect these and enforce the intended limits. By enabling this option, your node will ignore these transactions entirely (when detected) even if they fall within the configured limits otherwise."));
|
||||
verticalLayout_Spamfiltering->addWidget(rejectnonstddatacarrier);
|
||||
FixTabOrder(rejectnonstddatacarrier);
|
||||
|
||||
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 kvB (\"dust\")."));
|
||||
|
||||
|
||||
auto hlayout = new QHBoxLayout();
|
||||
dustdynamic_enable = new QCheckBox(groupBox_Spamfiltering);
|
||||
dustdynamic_enable->setText(tr("Automatically adjust the dust limit upward to"));
|
||||
hlayout->addWidget(dustdynamic_enable);
|
||||
dustdynamic_multiplier = new QDoubleSpinBox(groupBox_Spamfiltering);
|
||||
dustdynamic_multiplier->setDecimals(3);
|
||||
dustdynamic_multiplier->setStepType(QAbstractSpinBox::DefaultStepType);
|
||||
dustdynamic_multiplier->setSingleStep(1);
|
||||
dustdynamic_multiplier->setMinimum(0.001);
|
||||
dustdynamic_multiplier->setMaximum(65);
|
||||
dustdynamic_multiplier->setValue(DEFAULT_DUST_RELAY_MULTIPLIER / 1000.0);
|
||||
CreateOptionUI(verticalLayout_Spamfiltering, dustdynamic_multiplier, tr("%s times:"), hlayout);
|
||||
|
||||
QStyleOptionButton styleoptbtn;
|
||||
const auto checkbox_indent = dustdynamic_enable->style()->subElementRect(QStyle::SE_CheckBoxIndicator, &styleoptbtn, dustdynamic_enable).width();
|
||||
|
||||
hlayout = new QHBoxLayout();
|
||||
hlayout->addSpacing(checkbox_indent);
|
||||
dustdynamic_target = new QRadioButton(groupBox_Spamfiltering);
|
||||
hlayout->addWidget(dustdynamic_target);
|
||||
dustdynamic_target_blocks = new QSpinBox(groupBox_Spamfiltering);
|
||||
dustdynamic_target_blocks->setMinimum(2);
|
||||
dustdynamic_target_blocks->setMaximum(1008); // FIXME: Get this from the fee estimator
|
||||
dustdynamic_target_blocks->setValue(1008);
|
||||
CreateOptionUI(verticalLayout_Spamfiltering, dustdynamic_target_blocks, tr("fee estimate for %s blocks."), hlayout);
|
||||
// FIXME: Make it possible to click labels to select + focus spinbox
|
||||
|
||||
hlayout = new QHBoxLayout();
|
||||
hlayout->addSpacing(checkbox_indent);
|
||||
dustdynamic_mempool = new QRadioButton(groupBox_Spamfiltering);
|
||||
hlayout->addWidget(dustdynamic_mempool);
|
||||
dustdynamic_mempool_kvB = new QSpinBox(groupBox_Spamfiltering);
|
||||
dustdynamic_mempool_kvB->setMinimum(1);
|
||||
dustdynamic_mempool_kvB->setMaximum(std::numeric_limits<int32_t>::max());
|
||||
dustdynamic_mempool_kvB->setValue(3024000);
|
||||
CreateOptionUI(verticalLayout_Spamfiltering, dustdynamic_mempool_kvB, tr("the lowest fee of the best known %s kvB of unconfirmed transactions."), hlayout);
|
||||
|
||||
const auto dustdynamic_enable_toggled = [this](const bool state){
|
||||
dustdynamic_multiplier->setEnabled(state);
|
||||
setSiblingsEnabled(dustdynamic_target_blocks, state);
|
||||
setSiblingsEnabled(dustdynamic_mempool_kvB, state);
|
||||
if (state) {
|
||||
if (!dustdynamic_mempool->isChecked()) dustdynamic_target->setChecked(true);
|
||||
dustdynamic_target_blocks->setEnabled(dustdynamic_target->isChecked());
|
||||
dustdynamic_mempool_kvB->setEnabled(dustdynamic_mempool->isChecked());
|
||||
}
|
||||
};
|
||||
connect(dustdynamic_enable, &QAbstractButton::toggled, dustdynamic_enable_toggled);
|
||||
dustdynamic_enable_toggled(dustdynamic_enable->isChecked());
|
||||
connect(dustdynamic_target, &QAbstractButton::toggled, [this](const bool state){
|
||||
dustdynamic_target_blocks->setEnabled(state);
|
||||
});
|
||||
connect(dustdynamic_mempool, &QAbstractButton::toggled, [this](const bool state){
|
||||
dustdynamic_mempool_kvB->setEnabled(state);
|
||||
});
|
||||
|
||||
|
||||
connect(rejectunknownscripts, &QAbstractButton::toggled, [this, dustdynamic_enable_toggled](const bool state){
|
||||
rejectbarepubkey->setEnabled(state);
|
||||
rejectbaremultisig->setEnabled(state);
|
||||
rejectparasites->setEnabled(state);
|
||||
rejecttokens->setEnabled(state);
|
||||
setSiblingsEnabled(dustrelayfee, state);
|
||||
setSiblingsEnabled(maxscriptsize, state);
|
||||
setSiblingsEnabled(dustdynamic_multiplier, state);
|
||||
dustdynamic_enable_toggled(state && dustdynamic_enable->isChecked());
|
||||
});
|
||||
|
||||
|
||||
verticalLayout_Spamfiltering->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 kvB."));
|
||||
|
||||
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 */
|
||||
@ -295,6 +651,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(); });
|
||||
@ -325,6 +683,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);
|
||||
@ -364,6 +723,75 @@ 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);
|
||||
|
||||
QVariant current_mempooltruc = model->data(model->index(OptionsModel::mempooltruc, 0), Qt::EditRole);
|
||||
int current_mempooltruc_index = mempooltruc->findData(current_mempooltruc);
|
||||
if (current_mempooltruc_index == -1) {
|
||||
mempooltruc->addItem(current_mempooltruc.toString(), current_mempooltruc);
|
||||
current_mempooltruc_index = mempooltruc->count() - 1;
|
||||
}
|
||||
mempooltruc->setCurrentIndex(current_mempooltruc_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(rejectparasites, OptionsModel::rejectparasites);
|
||||
mapper->addMapping(rejecttokens, OptionsModel::rejecttokens);
|
||||
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(rejectbarepubkey, OptionsModel::rejectbarepubkey);
|
||||
mapper->addMapping(rejectbaremultisig, OptionsModel::rejectbaremultisig);
|
||||
mapper->addMapping(maxscriptsize, OptionsModel::maxscriptsize);
|
||||
mapper->addMapping(datacarriercost, OptionsModel::datacarriercost);
|
||||
mapper->addMapping(datacarriersize, OptionsModel::datacarriersize);
|
||||
mapper->addMapping(rejectnonstddatacarrier, OptionsModel::rejectnonstddatacarrier);
|
||||
mapper->addMapping(dustrelayfee, OptionsModel::dustrelayfee);
|
||||
|
||||
QVariant current_dustdynamic = model->data(model->index(OptionsModel::dustdynamic, 0), Qt::EditRole);
|
||||
const util::Result<std::pair<int32_t, int>> parsed_dustdynamic = ParseDustDynamicOpt(current_dustdynamic.toString().toStdString(), std::numeric_limits<unsigned int>::max());
|
||||
if (parsed_dustdynamic) {
|
||||
if (parsed_dustdynamic->first == 0) {
|
||||
dustdynamic_enable->setChecked(false);
|
||||
} else {
|
||||
dustdynamic_multiplier->setValue(parsed_dustdynamic->second / 1000.0);
|
||||
if (parsed_dustdynamic->first < 0) {
|
||||
dustdynamic_target->setChecked(true);
|
||||
dustdynamic_target_blocks->setValue(-parsed_dustdynamic->first);
|
||||
} else {
|
||||
dustdynamic_mempool->setChecked(true);
|
||||
dustdynamic_mempool_kvB->setValue(parsed_dustdynamic->first);
|
||||
}
|
||||
dustdynamic_enable->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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()) {
|
||||
@ -396,6 +824,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) {
|
||||
@ -411,14 +875,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();
|
||||
}
|
||||
@ -480,6 +955,19 @@ void OptionsDialog::on_okButton_clicked()
|
||||
model->setData(model->index(OptionsModel::maxuploadtarget, 0), 0);
|
||||
}
|
||||
|
||||
model->setData(model->index(OptionsModel::mempoolreplacement, 0), mempoolreplacement->itemData(mempoolreplacement->currentIndex()));
|
||||
model->setData(model->index(OptionsModel::mempooltruc, 0), mempooltruc->itemData(mempooltruc->currentIndex()));
|
||||
|
||||
if (dustdynamic_enable->isChecked()) {
|
||||
if (dustdynamic_target->isChecked()) {
|
||||
model->setData(model->index(OptionsModel::dustdynamic, 0), QStringLiteral("%2*target:%1").arg(dustdynamic_target_blocks->value()).arg(dustdynamic_multiplier->value()));
|
||||
} else if (dustdynamic_mempool->isChecked()) {
|
||||
model->setData(model->index(OptionsModel::dustdynamic, 0), QStringLiteral("%2*mempool:%1").arg(dustdynamic_mempool_kvB->value()).arg(dustdynamic_multiplier->value()));
|
||||
}
|
||||
} else {
|
||||
model->setData(model->index(OptionsModel::dustdynamic, 0), "off");
|
||||
}
|
||||
|
||||
mapper->submit();
|
||||
accept();
|
||||
updateDefaultProxyNets();
|
||||
|
@ -8,12 +8,22 @@
|
||||
#include <QDialog>
|
||||
#include <QValidator>
|
||||
|
||||
class BitcoinAmountField;
|
||||
class ClientModel;
|
||||
class OptionsModel;
|
||||
class QValidatedLineEdit;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QBoxLayout;
|
||||
class QCheckBox;
|
||||
class QDataWidgetMapper;
|
||||
class QDoubleSpinBox;
|
||||
class QLayout;
|
||||
class QRadioButton;
|
||||
class QSpinBox;
|
||||
class QString;
|
||||
class QValueComboBox;
|
||||
class QWidget;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Ui {
|
||||
@ -69,6 +79,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 +93,48 @@ 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, QLayout *horizontalLayout = nullptr);
|
||||
|
||||
QCheckBox *walletrbf;
|
||||
|
||||
QSpinBox *blockreconstructionextratxn;
|
||||
|
||||
QValueComboBox *mempoolreplacement;
|
||||
QValueComboBox *mempooltruc;
|
||||
QSpinBox *maxorphantx;
|
||||
BitcoinAmountField *incrementalrelayfee;
|
||||
QSpinBox *maxmempool;
|
||||
QSpinBox *mempoolexpiry;
|
||||
|
||||
QCheckBox *rejectunknownscripts;
|
||||
QCheckBox *rejectparasites;
|
||||
QCheckBox *rejecttokens;
|
||||
QCheckBox *rejectspkreuse;
|
||||
BitcoinAmountField *minrelaytxfee;
|
||||
QSpinBox *bytespersigop, *bytespersigopstrict;
|
||||
QSpinBox *limitancestorcount;
|
||||
QSpinBox *limitancestorsize;
|
||||
QSpinBox *limitdescendantcount;
|
||||
QSpinBox *limitdescendantsize;
|
||||
QCheckBox *rejectbarepubkey;
|
||||
QCheckBox *rejectbaremultisig;
|
||||
QSpinBox *maxscriptsize;
|
||||
QSpinBox *datacarriersize;
|
||||
QDoubleSpinBox *datacarriercost;
|
||||
QCheckBox *rejectnonstddatacarrier;
|
||||
BitcoinAmountField *dustrelayfee;
|
||||
QCheckBox *dustdynamic_enable;
|
||||
QDoubleSpinBox *dustdynamic_multiplier;
|
||||
QRadioButton *dustdynamic_target;
|
||||
QSpinBox *dustdynamic_target_blocks;
|
||||
QRadioButton *dustdynamic_mempool;
|
||||
QSpinBox *dustdynamic_mempool_kvB;
|
||||
|
||||
BitcoinAmountField *blockmintxfee;
|
||||
QSpinBox *blockmaxsize, *blockprioritysize, *blockmaxweight;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_OPTIONSDIALOG_H
|
||||
|
@ -14,16 +14,22 @@
|
||||
|
||||
#include <chainparams.h>
|
||||
#include <common/args.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/chainstatemanager_args.h>
|
||||
#include <node/context.h>
|
||||
#include <node/mempool_args.h> // for ParseDustDynamicOpt
|
||||
#include <outputtype.h>
|
||||
#include <policy/settings.h>
|
||||
#include <txdb.h> // for -dbcache defaults
|
||||
#include <util/moneystr.h> // for FormatMoney
|
||||
#include <util/string.h>
|
||||
#include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS
|
||||
#include <wallet/wallet.h> // For DEFAULT_SPEND_ZEROCONF_CHANGE
|
||||
@ -32,8 +38,10 @@
|
||||
#include <interfaces/wallet.h>
|
||||
#endif
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLatin1Char>
|
||||
@ -59,6 +67,7 @@ static const char* SettingName(OptionsModel::OptionID option)
|
||||
case OptionsModel::MapPortNatpmp: return "natpmp";
|
||||
case OptionsModel::Listen: return "listen";
|
||||
case OptionsModel::Server: return "server";
|
||||
case OptionsModel::walletrbf: return "walletrbf";
|
||||
case OptionsModel::addresstype: return "addresstype";
|
||||
case OptionsModel::PruneSizeMiB: return "prune";
|
||||
case OptionsModel::PruneTristate: return "prune";
|
||||
@ -72,6 +81,36 @@ static const char* SettingName(OptionsModel::OptionID option)
|
||||
case OptionsModel::maxuploadtarget: return "maxuploadtarget";
|
||||
case OptionsModel::peerbloomfilters: return "peerbloomfilters";
|
||||
case OptionsModel::peerblockfilters: return "peerblockfilters";
|
||||
case OptionsModel::mempoolreplacement: return "mempoolreplacement";
|
||||
case OptionsModel::mempooltruc: return "mempooltruc";
|
||||
case OptionsModel::maxorphantx: return "maxorphantx";
|
||||
case OptionsModel::maxmempool: return "maxmempool";
|
||||
case OptionsModel::incrementalrelayfee: return "incrementalrelayfee";
|
||||
case OptionsModel::mempoolexpiry: return "mempoolexpiry";
|
||||
case OptionsModel::rejectunknownscripts: return "rejectunknownscripts";
|
||||
case OptionsModel::rejectparasites: return "rejectparasites";
|
||||
case OptionsModel::rejecttokens: return "rejecttokens";
|
||||
case OptionsModel::rejectspkreuse: return "rejectspkreuse";
|
||||
case OptionsModel::minrelaytxfee: return "minrelaytxfee";
|
||||
case OptionsModel::bytespersigop: return "bytespersigop";
|
||||
case OptionsModel::bytespersigopstrict: return "bytespersigopstrict";
|
||||
case OptionsModel::limitancestorcount: return "limitancestorcount";
|
||||
case OptionsModel::limitancestorsize: return "limitancestorsize";
|
||||
case OptionsModel::limitdescendantcount: return "limitdescendantcount";
|
||||
case OptionsModel::limitdescendantsize: return "limitdescendantsize";
|
||||
case OptionsModel::rejectbarepubkey: return "rejectbarepubkey";
|
||||
case OptionsModel::rejectbaremultisig: return "rejectbaremultisig";
|
||||
case OptionsModel::maxscriptsize: return "maxscriptsize";
|
||||
case OptionsModel::datacarriercost: return "datacarriercost";
|
||||
case OptionsModel::datacarriersize: return "datacarriersize";
|
||||
case OptionsModel::rejectnonstddatacarrier: return "rejectnonstddatacarrier";
|
||||
case OptionsModel::dustrelayfee: return "dustrelayfee";
|
||||
case OptionsModel::dustdynamic: return "dustdynamic";
|
||||
case OptionsModel::blockmintxfee: return "blockmintxfee";
|
||||
case OptionsModel::blockmaxsize: return "blockmaxsize";
|
||||
case OptionsModel::blockprioritysize: return "blockprioritysize";
|
||||
case OptionsModel::blockmaxweight: return "blockmaxweight";
|
||||
case OptionsModel::blockreconstructionextratxn: return "blockreconstructionextratxn";
|
||||
default: throw std::logic_error(strprintf("GUI option %i has no corresponding node setting.", option));
|
||||
}
|
||||
}
|
||||
@ -205,6 +244,26 @@ 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);
|
||||
}
|
||||
|
||||
static QString CanonicalMempoolTRUC(const OptionsModel& model)
|
||||
{
|
||||
switch (model.node().mempool().m_truc_policy) {
|
||||
case TRUCPolicy::Reject: return "reject";
|
||||
case TRUCPolicy::Accept: return "accept";
|
||||
case TRUCPolicy::Enforce: return "enforce";
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
OptionsModel::OptionsModel(interfaces::Node& node, QObject *parent) :
|
||||
QAbstractListModel(parent), m_node{node}
|
||||
{
|
||||
@ -337,7 +396,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")) {
|
||||
@ -592,6 +653,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:
|
||||
@ -618,6 +683,70 @@ 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 mempooltruc:
|
||||
return CanonicalMempoolTRUC(*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 rejectparasites:
|
||||
return node().mempool().m_reject_parasites;
|
||||
case rejecttokens:
|
||||
return node().mempool().m_reject_tokens;
|
||||
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 rejectbarepubkey:
|
||||
return !node().mempool().m_permit_bare_pubkey;
|
||||
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 rejectnonstddatacarrier:
|
||||
return !node().mempool().m_accept_non_std_datacarrier;
|
||||
case dustrelayfee:
|
||||
return qlonglong(node().mempool().m_dust_relay_feerate_floor.GetFeePerK());
|
||||
case dustdynamic:
|
||||
return QString::fromStdString(SettingToString(setting(), DEFAULT_DUST_DYNAMIC));
|
||||
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();
|
||||
}
|
||||
@ -832,6 +961,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);
|
||||
@ -920,6 +1067,308 @@ 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 mempooltruc:
|
||||
{
|
||||
if (changed()) {
|
||||
QString nv = value.toString();
|
||||
if (nv == "reject") {
|
||||
node().mempool().m_truc_policy = TRUCPolicy::Reject;
|
||||
} else if (nv == "accept") {
|
||||
node().mempool().m_truc_policy = TRUCPolicy::Accept;
|
||||
} else if (nv == "enforce") {
|
||||
node().mempool().m_truc_policy = TRUCPolicy::Enforce;
|
||||
}
|
||||
node().updateRwSetting("mempooltruc", 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 rejectparasites:
|
||||
{
|
||||
if (changed()) {
|
||||
const bool nv = value.toBool();
|
||||
node().mempool().m_reject_parasites = nv;
|
||||
node().updateRwSetting("rejectparasites", nv);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rejecttokens:
|
||||
{
|
||||
if (changed()) {
|
||||
const bool nv = value.toBool();
|
||||
node().mempool().m_reject_tokens = nv;
|
||||
node().updateRwSetting("rejecttokens", nv);
|
||||
}
|
||||
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 rejectbarepubkey:
|
||||
if (changed()) {
|
||||
// The config and internal option is inverted
|
||||
const bool nv = ! value.toBool();
|
||||
node().mempool().m_permit_bare_pubkey = nv;
|
||||
node().updateRwSetting("permitbaremultisig", nv);
|
||||
}
|
||||
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 rejectnonstddatacarrier:
|
||||
if (changed()) {
|
||||
// This option is inverted
|
||||
const bool new_value = ! value.toBool();
|
||||
node().updateRwSetting("acceptnonstddatacarrier" + suffix, new_value);
|
||||
node().mempool().m_accept_non_std_datacarrier = new_value;
|
||||
}
|
||||
break;
|
||||
case dustrelayfee:
|
||||
if (changed()) {
|
||||
CAmount nNv = value.toLongLong();
|
||||
gArgs.ModifyRWConfigFile("dustrelayfee", FormatMoney(nNv));
|
||||
CFeeRate feerate{nNv};
|
||||
node().mempool().m_dust_relay_feerate_floor = feerate;
|
||||
if (node().mempool().m_dust_relay_feerate < feerate || !node().mempool().m_dust_relay_target) {
|
||||
node().mempool().m_dust_relay_feerate = feerate;
|
||||
} else {
|
||||
node().mempool().UpdateDynamicDustFeerate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case dustdynamic:
|
||||
if (changed()) {
|
||||
const std::string newvalue_str = value.toString().toStdString();
|
||||
const util::Result<std::pair<int32_t, int>> parsed = ParseDustDynamicOpt(newvalue_str, 1008 /* FIXME: get from estimator */);
|
||||
assert(parsed); // FIXME: what to do if it fails to parse?
|
||||
// FIXME: save -prev-<type> for each type
|
||||
update(newvalue_str);
|
||||
node().mempool().m_dust_relay_target = parsed->first;
|
||||
node().mempool().m_dust_relay_multiplier = parsed->second;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
FontForMoney, // FontChoice
|
||||
FontForQRCodes, // FontChoice
|
||||
PeersTabAlternatingRowColors, // bool
|
||||
walletrbf, // bool
|
||||
CoinControlFeatures, // bool
|
||||
SubFeeFromAmount, // bool
|
||||
ThreadsScriptVerif, // int
|
||||
@ -80,6 +81,37 @@ public:
|
||||
maxuploadtarget,
|
||||
peerbloomfilters, // bool
|
||||
peerblockfilters, // bool
|
||||
mempoolreplacement,
|
||||
mempooltruc,
|
||||
maxorphantx,
|
||||
maxmempool,
|
||||
incrementalrelayfee,
|
||||
mempoolexpiry,
|
||||
rejectunknownscripts, // bool
|
||||
rejectparasites, // bool
|
||||
rejecttokens, // bool
|
||||
rejectspkreuse, // bool
|
||||
minrelaytxfee,
|
||||
bytespersigop,
|
||||
bytespersigopstrict,
|
||||
limitancestorcount,
|
||||
limitancestorsize,
|
||||
limitdescendantcount,
|
||||
limitdescendantsize,
|
||||
rejectbarepubkey, // bool
|
||||
rejectbaremultisig, // bool
|
||||
maxscriptsize,
|
||||
datacarriercost, // double
|
||||
datacarriersize,
|
||||
rejectnonstddatacarrier, // bool
|
||||
dustrelayfee,
|
||||
dustdynamic, // QString
|
||||
blockmintxfee,
|
||||
blockmaxsize,
|
||||
blockprioritysize,
|
||||
blockmaxweight,
|
||||
blockreconstructionextratxn,
|
||||
corepolicy,
|
||||
OptionIDRowCount,
|
||||
};
|
||||
|
||||
@ -156,6 +188,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);
|
||||
|
@ -28,6 +28,7 @@ void initialize_miner()
|
||||
for (uint32_t i = 0; i < uint32_t{100}; ++i) {
|
||||
g_available_coins.emplace_back(Txid::FromUint256(uint256::ZERO), i);
|
||||
}
|
||||
g_setup->m_node.args->ForceSetArg("-blockprioritysize", "0");
|
||||
}
|
||||
|
||||
// Test that the MiniMiner can run with various outpoints and feerates.
|
||||
|
@ -603,6 +603,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;
|
||||
|
@ -20,13 +20,13 @@
|
||||
// Helpers:
|
||||
static bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, std::string& reason)
|
||||
{
|
||||
return IsStandardTx(tx, std::nullopt, DEFAULT_PERMIT_BAREPUBKEY, permit_bare_multisig, /*reject_parasites=*/ false, /*reject_tokens=*/false, CFeeRate{DUST_RELAY_TX_FEE}, reason);
|
||||
return IsStandardTx(tx, std::nullopt, /*permit_bare_pubkey=*/ true, permit_bare_multisig, /*reject_parasites=*/ false, /*reject_tokens=*/false, CFeeRate{DUST_RELAY_TX_FEE}, reason);
|
||||
}
|
||||
|
||||
static bool IsStandardTx(const CTransaction& tx, std::string& reason)
|
||||
{
|
||||
return IsStandardTx(tx, std::nullopt, DEFAULT_PERMIT_BAREPUBKEY, /*permit_bare_multisig=*/true, /*reject_parasites=*/ false, /*reject_tokens=*/false, CFeeRate{DUST_RELAY_TX_FEE}, reason) &&
|
||||
IsStandardTx(tx, std::nullopt, DEFAULT_PERMIT_BAREPUBKEY, /*permit_bare_multisig=*/false, /*reject_parasites=*/ false, /*reject_tokens=*/false, CFeeRate{DUST_RELAY_TX_FEE}, reason);
|
||||
return IsStandardTx(tx, std::nullopt, /*permit_bare_pubkey=*/ true, /*permit_bare_multisig=*/true, /*reject_parasites=*/ false, /*reject_tokens=*/false, CFeeRate{DUST_RELAY_TX_FEE}, reason) &&
|
||||
IsStandardTx(tx, std::nullopt, /*permit_bare_pubkey=*/ true, /*permit_bare_multisig=*/false, /*reject_parasites=*/ false, /*reject_tokens=*/false, CFeeRate{DUST_RELAY_TX_FEE}, reason);
|
||||
}
|
||||
|
||||
static std::vector<unsigned char> Serialize(const CScript& s)
|
||||
|
@ -41,7 +41,6 @@
|
||||
typedef std::vector<unsigned char> valtype;
|
||||
|
||||
static CFeeRate g_dust{DUST_RELAY_TX_FEE};
|
||||
static bool g_bare_pubkey{DEFAULT_PERMIT_BAREPUBKEY};
|
||||
static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
|
||||
|
||||
static std::map<std::string, unsigned int> mapFlagNames = {
|
||||
@ -761,12 +760,12 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||
|
||||
const auto CheckIsStandard = [&](const auto& t) {
|
||||
std::string reason;
|
||||
BOOST_CHECK(IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_pubkey, g_bare_multi, /*reject_parasites=*/ reject_parasites, /*reject_tokens=*/reject_tokens, g_dust, reason));
|
||||
BOOST_CHECK(IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, /*permit_bare_pubkey=*/ true, g_bare_multi, /*reject_parasites=*/ reject_parasites, /*reject_tokens=*/reject_tokens, g_dust, reason));
|
||||
BOOST_CHECK(reason.empty());
|
||||
};
|
||||
const auto CheckIsNotStandard = [&](const auto& t, const std::string& reason_in) {
|
||||
std::string reason;
|
||||
BOOST_CHECK(!IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_pubkey, g_bare_multi, /*reject_parasites=*/ reject_parasites, /*reject_tokens=*/reject_tokens, g_dust, reason));
|
||||
BOOST_CHECK(!IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, /*permit_bare_pubkey=*/ true, g_bare_multi, /*reject_parasites=*/ reject_parasites, /*reject_tokens=*/reject_tokens, g_dust, reason));
|
||||
BOOST_CHECK_EQUAL(reason_in, reason);
|
||||
};
|
||||
|
||||
@ -834,12 +833,15 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||
reject_tokens = false;
|
||||
|
||||
// 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");
|
||||
|
||||
|
@ -52,7 +52,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
|
||||
spends[i].vin[0].prevout.n = 0;
|
||||
spends[i].vout.resize(1);
|
||||
spends[i].vout[0].nValue = 11*CENT;
|
||||
spends[i].vout[0].scriptPubKey = scriptPubKey;
|
||||
spends[i].vout[0].scriptPubKey = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));
|
||||
|
||||
// Sign:
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
@ -22,6 +22,7 @@ CTxMemPool::Options MemPoolOptionsForTest(const NodeContext& node)
|
||||
// Default to always checking mempool regardless of
|
||||
// chainparams.DefaultConsistencyChecks for tests
|
||||
.check_ratio = 1,
|
||||
.truc_policy = TRUCPolicy::Enforce,
|
||||
};
|
||||
const auto result{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)};
|
||||
Assert(result);
|
||||
|
@ -452,26 +452,26 @@ 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;
|
||||
std::chrono::seconds m_expiry;
|
||||
CFeeRate m_incremental_relay_feerate;
|
||||
CFeeRate m_min_relay_feerate;
|
||||
CFeeRate m_dust_relay_feerate;
|
||||
CFeeRate m_dust_relay_feerate_floor;
|
||||
int32_t m_dust_relay_target;
|
||||
int m_dust_relay_multiplier;
|
||||
const bool m_permit_bare_pubkey;
|
||||
const bool m_permit_bare_multisig;
|
||||
bool m_permit_bare_pubkey;
|
||||
bool m_permit_bare_multisig;
|
||||
bool m_reject_parasites;
|
||||
bool m_reject_tokens;
|
||||
const std::optional<unsigned> m_max_datacarrier_bytes;
|
||||
std::optional<unsigned> m_max_datacarrier_bytes;
|
||||
bool m_datacarrier_fullcount;
|
||||
bool m_accept_non_std_datacarrier;
|
||||
const bool m_require_standard;
|
||||
const RBFPolicy m_rbf_policy;
|
||||
const TRUCPolicy m_truc_policy;
|
||||
bool m_require_standard;
|
||||
RBFPolicy m_rbf_policy;
|
||||
TRUCPolicy m_truc_policy;
|
||||
const bool m_persist_v1_dat;
|
||||
|
||||
const Limits m_limits;
|
||||
Limits m_limits;
|
||||
|
||||
/** Create a new CTxMemPool.
|
||||
* Sanity checks will be off by default for performance, because otherwise
|
||||
|
@ -828,7 +828,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
|
||||
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
|
||||
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||
auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
|
||||
auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey, GetScriptForDestination(PKHash(key.GetPubKey())));
|
||||
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
|
||||
|
||||
|
||||
@ -870,7 +870,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
|
||||
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||
block_tx = TestSimpleSpend(*m_coinbase_txns[2], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
|
||||
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
|
||||
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForDestination(PKHash(key.GetPubKey())));
|
||||
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
|
||||
SyncWithValidationInterfaceQueue();
|
||||
});
|
||||
|
@ -122,6 +122,7 @@ class TestNode():
|
||||
|
||||
if self.version is None:
|
||||
self.args += [
|
||||
"-corepolicy",
|
||||
"-softwareexpiry=0",
|
||||
"-walletimplicitsegwit",
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user