Merge bitcoin/bitcoin#25648: refactor: Remove all policy globals
ddddd6913bsort after scripted-diff (MacroFake)fac812ca83scripted-diff: Move mempool_args to src/node (MacroFake)66664384a6Remove ::g_max_datacarrier_bytes global (MacroFake)fad0b4fab8Pass datacarrier setting into IsStandard (MacroFake)fa2a6b8516Combine datacarrier globals into one (MacroFake)fa477d32eeRemove ::GetVirtualTransactionSize() alias (MacroFake)fa2f6c1a61Remove ::fIsBareMultisigStd global (MacroFake)fadc14e4f5Remove ::dustRelayFee (MacroFake)fa8a7f01feRemove ::IsStandardTx(tx, reason) alias (MacroFake)fa7a9114e5test: Remove unused cs_main (MacroFake)fa9cba7afbRemove ::incrementalRelayFee and ::minRelayTxFee globals (MacroFake)fa148602e6Remove ::fRequireStandard global (MacroFake)fa468bdfb6Return optional error from ApplyArgsManOptions (MacroFake) Pull request description: This change is good because: * It moves module-specific init-logic out of the bloated init.cpp * It removes a global from validation.cpp and places it into the data structure that needs it (mempool) ACKs for top commit: glozow: re ACKddddd69ryanofsky: Code review ACKddddd6913bariard: Light Code Review ACKddddd69Tree-SHA512: 9de2ce601cfcaa4dfd7d1c92270568895ce8702ccdffb59829fbe9618eab0fd88d738afef33ed66988c66861115e0340e881056bfb71e2aed4af2440bd37eb1e
This commit is contained in:
39 files changed
+269
-229
No files matched your search
@@ -45,6 +45,7 @@ if [ "${RUN_TIDY}" = "true" ]; then
|
|||||||
" src/init"\
|
" src/init"\
|
||||||
" src/kernel"\
|
" src/kernel"\
|
||||||
" src/node/chainstate.cpp"\
|
" src/node/chainstate.cpp"\
|
||||||
|
" src/node/mempool_args.cpp"\
|
||||||
" src/policy/feerate.cpp"\
|
" src/policy/feerate.cpp"\
|
||||||
" src/policy/packages.cpp"\
|
" src/policy/packages.cpp"\
|
||||||
" src/policy/settings.cpp"\
|
" src/policy/settings.cpp"\
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
**Policy** (Mempool or Transaction Relay Policy) is the node's set of validation rules, in addition
|
**Policy** (Mempool or Transaction Relay Policy) is the node's set of validation rules, in addition
|
||||||
to consensus, enforced for unconfirmed transactions before submitting them to the mempool. These
|
to consensus, enforced for unconfirmed transactions before submitting them to the mempool. These
|
||||||
rules are local to the node and configurable (e.g. `-minrelaytxfee`, `-limitancestorsize`,
|
rules are local to the node and configurable (e.g. `-minrelaytxfee`, `-limitancestorsize`,
|
||||||
`-incrementalRelayFee`). Policy may include restrictions on the transaction itself, the transaction
|
`-incrementalrelayfee`). Policy may include restrictions on the transaction itself, the transaction
|
||||||
in relation to the current chain tip, and the transaction in relation to the node's mempool
|
in relation to the current chain tip, and the transaction in relation to the node's mempool
|
||||||
contents. Policy is *not* applied to transactions in blocks.
|
contents. Policy is *not* applied to transactions in blocks.
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ This set of rules is similar but distinct from BIP125.
|
|||||||
Bitcoin Core implementation.
|
Bitcoin Core implementation.
|
||||||
|
|
||||||
* The incremental relay feerate used to calculate the required additional fees is distinct from
|
* The incremental relay feerate used to calculate the required additional fees is distinct from
|
||||||
`minRelayTxFee` and configurable using `-incrementalrelayfee`
|
`-minrelaytxfee` and configurable using `-incrementalrelayfee`
|
||||||
([PR #9380](https://github.com/bitcoin/bitcoin/pull/9380)).
|
([PR #9380](https://github.com/bitcoin/bitcoin/pull/9380)).
|
||||||
|
|
||||||
* RBF enabled by default in the wallet GUI as of **v0.18.1** ([PR
|
* RBF enabled by default in the wallet GUI as of **v0.18.1** ([PR
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ If any transactions in the package are already in the mempool, they are not subm
|
|||||||
("deduplicated") and are thus excluded from this calculation.
|
("deduplicated") and are thus excluded from this calculation.
|
||||||
|
|
||||||
To meet the two feerate requirements of a mempool, i.e., the pre-configured minimum relay feerate
|
To meet the two feerate requirements of a mempool, i.e., the pre-configured minimum relay feerate
|
||||||
(`minRelayTxFee`) and the dynamic mempool minimum feerate, the total package feerate is used instead
|
(`-minrelaytxfee`) and the dynamic mempool minimum feerate, the total package feerate is used instead
|
||||||
of the individual feerate. The individual transactions are allowed to be below the feerate
|
of the individual feerate. The individual transactions are allowed to be below the feerate
|
||||||
requirements if the package meets the feerate requirements. For example, the parent(s) in the
|
requirements if the package meets the feerate requirements. For example, the parent(s) in the
|
||||||
package can pay no fees but be paid for by the child.
|
package can pay no fees but be paid for by the child.
|
||||||
|
|||||||
+8
-8
@@ -139,7 +139,6 @@ BITCOIN_CORE_H = \
|
|||||||
compat/cpuid.h \
|
compat/cpuid.h \
|
||||||
compat/endian.h \
|
compat/endian.h \
|
||||||
compressor.h \
|
compressor.h \
|
||||||
node/connection_types.h \
|
|
||||||
consensus/consensus.h \
|
consensus/consensus.h \
|
||||||
consensus/tx_check.h \
|
consensus/tx_check.h \
|
||||||
consensus/tx_verify.h \
|
consensus/tx_verify.h \
|
||||||
@@ -149,7 +148,6 @@ BITCOIN_CORE_H = \
|
|||||||
dbwrapper.h \
|
dbwrapper.h \
|
||||||
deploymentinfo.h \
|
deploymentinfo.h \
|
||||||
deploymentstatus.h \
|
deploymentstatus.h \
|
||||||
node/eviction.h \
|
|
||||||
external_signer.h \
|
external_signer.h \
|
||||||
flatfile.h \
|
flatfile.h \
|
||||||
fs.h \
|
fs.h \
|
||||||
@@ -184,7 +182,6 @@ BITCOIN_CORE_H = \
|
|||||||
logging.h \
|
logging.h \
|
||||||
logging/timer.h \
|
logging/timer.h \
|
||||||
mapport.h \
|
mapport.h \
|
||||||
mempool_args.h \
|
|
||||||
memusage.h \
|
memusage.h \
|
||||||
merkleblock.h \
|
merkleblock.h \
|
||||||
net.h \
|
net.h \
|
||||||
@@ -199,13 +196,16 @@ BITCOIN_CORE_H = \
|
|||||||
node/caches.h \
|
node/caches.h \
|
||||||
node/chainstate.h \
|
node/chainstate.h \
|
||||||
node/coin.h \
|
node/coin.h \
|
||||||
|
node/connection_types.h \
|
||||||
node/context.h \
|
node/context.h \
|
||||||
|
node/eviction.h \
|
||||||
|
node/interface_ui.h \
|
||||||
|
node/mempool_args.h \
|
||||||
node/mempool_persist_args.h \
|
node/mempool_persist_args.h \
|
||||||
node/miner.h \
|
node/miner.h \
|
||||||
node/minisketchwrapper.h \
|
node/minisketchwrapper.h \
|
||||||
node/psbt.h \
|
node/psbt.h \
|
||||||
node/transaction.h \
|
node/transaction.h \
|
||||||
node/interface_ui.h \
|
|
||||||
node/utxo_snapshot.h \
|
node/utxo_snapshot.h \
|
||||||
noui.h \
|
noui.h \
|
||||||
outputtype.h \
|
outputtype.h \
|
||||||
@@ -372,10 +372,9 @@ libbitcoin_node_a_SOURCES = \
|
|||||||
kernel/context.cpp \
|
kernel/context.cpp \
|
||||||
kernel/mempool_persist.cpp \
|
kernel/mempool_persist.cpp \
|
||||||
mapport.cpp \
|
mapport.cpp \
|
||||||
mempool_args.cpp \
|
|
||||||
net.cpp \
|
net.cpp \
|
||||||
netgroup.cpp \
|
|
||||||
net_processing.cpp \
|
net_processing.cpp \
|
||||||
|
netgroup.cpp \
|
||||||
node/blockstorage.cpp \
|
node/blockstorage.cpp \
|
||||||
node/caches.cpp \
|
node/caches.cpp \
|
||||||
node/chainstate.cpp \
|
node/chainstate.cpp \
|
||||||
@@ -383,13 +382,14 @@ libbitcoin_node_a_SOURCES = \
|
|||||||
node/connection_types.cpp \
|
node/connection_types.cpp \
|
||||||
node/context.cpp \
|
node/context.cpp \
|
||||||
node/eviction.cpp \
|
node/eviction.cpp \
|
||||||
|
node/interface_ui.cpp \
|
||||||
node/interfaces.cpp \
|
node/interfaces.cpp \
|
||||||
|
node/mempool_args.cpp \
|
||||||
node/mempool_persist_args.cpp \
|
node/mempool_persist_args.cpp \
|
||||||
node/miner.cpp \
|
node/miner.cpp \
|
||||||
node/minisketchwrapper.cpp \
|
node/minisketchwrapper.cpp \
|
||||||
node/psbt.cpp \
|
node/psbt.cpp \
|
||||||
node/transaction.cpp \
|
node/transaction.cpp \
|
||||||
node/interface_ui.cpp \
|
|
||||||
noui.cpp \
|
noui.cpp \
|
||||||
policy/fees.cpp \
|
policy/fees.cpp \
|
||||||
policy/fees_args.cpp \
|
policy/fees_args.cpp \
|
||||||
@@ -402,8 +402,8 @@ libbitcoin_node_a_SOURCES = \
|
|||||||
rpc/fees.cpp \
|
rpc/fees.cpp \
|
||||||
rpc/mempool.cpp \
|
rpc/mempool.cpp \
|
||||||
rpc/mining.cpp \
|
rpc/mining.cpp \
|
||||||
rpc/node.cpp \
|
|
||||||
rpc/net.cpp \
|
rpc/net.cpp \
|
||||||
|
rpc/node.cpp \
|
||||||
rpc/output_script.cpp \
|
rpc/output_script.cpp \
|
||||||
rpc/rawtransaction.cpp \
|
rpc/rawtransaction.cpp \
|
||||||
rpc/server.cpp \
|
rpc/server.cpp \
|
||||||
|
|||||||
+4
-43
@@ -31,7 +31,6 @@
|
|||||||
#include <interfaces/init.h>
|
#include <interfaces/init.h>
|
||||||
#include <interfaces/node.h>
|
#include <interfaces/node.h>
|
||||||
#include <mapport.h>
|
#include <mapport.h>
|
||||||
#include <mempool_args.h>
|
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <net_permissions.h>
|
#include <net_permissions.h>
|
||||||
#include <net_processing.h>
|
#include <net_processing.h>
|
||||||
@@ -42,6 +41,7 @@
|
|||||||
#include <node/chainstate.h>
|
#include <node/chainstate.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
#include <node/interface_ui.h>
|
#include <node/interface_ui.h>
|
||||||
|
#include <node/mempool_args.h>
|
||||||
#include <node/mempool_persist_args.h>
|
#include <node/mempool_persist_args.h>
|
||||||
#include <node/miner.h>
|
#include <node/miner.h>
|
||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
@@ -935,16 +935,6 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
|
|||||||
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
|
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
// incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool
|
|
||||||
// and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
|
|
||||||
if (args.IsArgSet("-incrementalrelayfee")) {
|
|
||||||
if (std::optional<CAmount> inc_relay_fee = ParseMoney(args.GetArg("-incrementalrelayfee", ""))) {
|
|
||||||
::incrementalRelayFee = CFeeRate{inc_relay_fee.value()};
|
|
||||||
} else {
|
|
||||||
return InitError(AmountErrMsg("incrementalrelayfee", args.GetArg("-incrementalrelayfee", "")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
|
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
|
||||||
int64_t nPruneArg = args.GetIntArg("-prune", 0);
|
int64_t nPruneArg = args.GetIntArg("-prune", 0);
|
||||||
if (nPruneArg < 0) {
|
if (nPruneArg < 0) {
|
||||||
@@ -973,19 +963,6 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
|
|||||||
return InitError(Untranslated("peertimeout must be a positive integer."));
|
return InitError(Untranslated("peertimeout must be a positive integer."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.IsArgSet("-minrelaytxfee")) {
|
|
||||||
if (std::optional<CAmount> min_relay_fee = ParseMoney(args.GetArg("-minrelaytxfee", ""))) {
|
|
||||||
// High fee check is done afterward in CWallet::Create()
|
|
||||||
::minRelayTxFee = CFeeRate{min_relay_fee.value()};
|
|
||||||
} else {
|
|
||||||
return InitError(AmountErrMsg("minrelaytxfee", args.GetArg("-minrelaytxfee", "")));
|
|
||||||
}
|
|
||||||
} else if (incrementalRelayFee > ::minRelayTxFee) {
|
|
||||||
// Allow only setting incrementalRelayFee to control both
|
|
||||||
::minRelayTxFee = incrementalRelayFee;
|
|
||||||
LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n",::minRelayTxFee.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity check argument for min fee for including tx in block
|
// Sanity check argument for min fee for including tx in block
|
||||||
// TODO: Harmonize which arguments need sanity checking and where that happens
|
// TODO: Harmonize which arguments need sanity checking and where that happens
|
||||||
if (args.IsArgSet("-blockmintxfee")) {
|
if (args.IsArgSet("-blockmintxfee")) {
|
||||||
@@ -994,28 +971,10 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feerate used to define dust. Shouldn't be changed lightly as old
|
|
||||||
// implementations may inadvertently create non-standard transactions
|
|
||||||
if (args.IsArgSet("-dustrelayfee")) {
|
|
||||||
if (std::optional<CAmount> parsed = ParseMoney(args.GetArg("-dustrelayfee", ""))) {
|
|
||||||
dustRelayFee = CFeeRate{parsed.value()};
|
|
||||||
} else {
|
|
||||||
return InitError(AmountErrMsg("dustrelayfee", args.GetArg("-dustrelayfee", "")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fRequireStandard = !args.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
|
|
||||||
if (!chainparams.IsTestChain() && !fRequireStandard) {
|
|
||||||
return InitError(strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString()));
|
|
||||||
}
|
|
||||||
nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
|
nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
|
||||||
|
|
||||||
if (!g_wallet_init_interface.ParameterInteraction()) return false;
|
if (!g_wallet_init_interface.ParameterInteraction()) return false;
|
||||||
|
|
||||||
fIsBareMultisigStd = args.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
|
|
||||||
fAcceptDatacarrier = args.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
|
|
||||||
nMaxDatacarrierBytes = args.GetIntArg("-datacarriersize", nMaxDatacarrierBytes);
|
|
||||||
|
|
||||||
// Option to startup with mocktime set (used for regression testing):
|
// Option to startup with mocktime set (used for regression testing):
|
||||||
SetMockTime(args.GetIntArg("-mocktime", 0)); // SetMockTime(0) is a no-op
|
SetMockTime(args.GetIntArg("-mocktime", 0)); // SetMockTime(0) is a no-op
|
||||||
|
|
||||||
@@ -1418,7 +1377,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
.estimator = node.fee_estimator.get(),
|
.estimator = node.fee_estimator.get(),
|
||||||
.check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
|
.check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
|
||||||
};
|
};
|
||||||
ApplyArgsManOptions(args, mempool_opts);
|
if (const auto err{ApplyArgsManOptions(args, chainparams, mempool_opts)}) {
|
||||||
|
return InitError(*err);
|
||||||
|
}
|
||||||
mempool_opts.check_ratio = std::clamp<int>(mempool_opts.check_ratio, 0, 1'000'000);
|
mempool_opts.check_ratio = std::clamp<int>(mempool_opts.check_ratio, 0, 1'000'000);
|
||||||
|
|
||||||
int64_t descendant_limit_bytes = mempool_opts.limits.descendant_size_vbytes * 40;
|
int64_t descendant_limit_bytes = mempool_opts.limits.descendant_size_vbytes * 40;
|
||||||
|
|||||||
@@ -6,8 +6,13 @@
|
|||||||
|
|
||||||
#include <kernel/mempool_limits.h>
|
#include <kernel/mempool_limits.h>
|
||||||
|
|
||||||
|
#include <policy/feerate.h>
|
||||||
|
#include <policy/policy.h>
|
||||||
|
#include <script/standard.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
class CBlockPolicyEstimator;
|
class CBlockPolicyEstimator;
|
||||||
|
|
||||||
@@ -33,6 +38,20 @@ struct MemPoolOptions {
|
|||||||
int check_ratio{0};
|
int check_ratio{0};
|
||||||
int64_t max_size_bytes{DEFAULT_MAX_MEMPOOL_SIZE_MB * 1'000'000};
|
int64_t max_size_bytes{DEFAULT_MAX_MEMPOOL_SIZE_MB * 1'000'000};
|
||||||
std::chrono::seconds expiry{std::chrono::hours{DEFAULT_MEMPOOL_EXPIRY_HOURS}};
|
std::chrono::seconds expiry{std::chrono::hours{DEFAULT_MEMPOOL_EXPIRY_HOURS}};
|
||||||
|
CFeeRate incremental_relay_feerate{DEFAULT_INCREMENTAL_RELAY_FEE};
|
||||||
|
/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
|
||||||
|
CFeeRate min_relay_feerate{DEFAULT_MIN_RELAY_TX_FEE};
|
||||||
|
CFeeRate dust_relay_feerate{DUST_RELAY_TX_FEE};
|
||||||
|
/**
|
||||||
|
* A data carrying output is an unspendable output containing data. The script
|
||||||
|
* type is designated as TxoutType::NULL_DATA.
|
||||||
|
*
|
||||||
|
* Maximum size of TxoutType::NULL_DATA scripts that this node considers standard.
|
||||||
|
* If nullopt, any size is nonstandard.
|
||||||
|
*/
|
||||||
|
std::optional<unsigned> max_datacarrier_bytes{DEFAULT_ACCEPT_DATACARRIER ? std::optional{MAX_OP_RETURN_RELAY} : std::nullopt};
|
||||||
|
bool permit_bare_multisig{DEFAULT_PERMIT_BAREMULTISIG};
|
||||||
|
bool require_standard{true};
|
||||||
bool full_rbf{DEFAULT_MEMPOOL_FULL_RBF};
|
bool full_rbf{DEFAULT_MEMPOOL_FULL_RBF};
|
||||||
MemPoolLimits limits{};
|
MemPoolLimits limits{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
// Copyright (c) 2022 The Bitcoin Core developers
|
|
||||||
// Distributed under the MIT software license, see the accompanying
|
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
#include <mempool_args.h>
|
|
||||||
|
|
||||||
#include <kernel/mempool_limits.h>
|
|
||||||
#include <kernel/mempool_options.h>
|
|
||||||
|
|
||||||
#include <util/system.h>
|
|
||||||
|
|
||||||
using kernel::MemPoolLimits;
|
|
||||||
using kernel::MemPoolOptions;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
void ApplyArgsManOptions(const ArgsManager& argsman, MemPoolLimits& mempool_limits)
|
|
||||||
{
|
|
||||||
mempool_limits.ancestor_count = argsman.GetIntArg("-limitancestorcount", mempool_limits.ancestor_count);
|
|
||||||
|
|
||||||
if (auto vkb = argsman.GetIntArg("-limitancestorsize")) mempool_limits.ancestor_size_vbytes = *vkb * 1'000;
|
|
||||||
|
|
||||||
mempool_limits.descendant_count = argsman.GetIntArg("-limitdescendantcount", mempool_limits.descendant_count);
|
|
||||||
|
|
||||||
if (auto vkb = argsman.GetIntArg("-limitdescendantsize")) mempool_limits.descendant_size_vbytes = *vkb * 1'000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApplyArgsManOptions(const ArgsManager& argsman, MemPoolOptions& mempool_opts)
|
|
||||||
{
|
|
||||||
mempool_opts.check_ratio = argsman.GetIntArg("-checkmempool", mempool_opts.check_ratio);
|
|
||||||
|
|
||||||
if (auto mb = argsman.GetIntArg("-maxmempool")) mempool_opts.max_size_bytes = *mb * 1'000'000;
|
|
||||||
|
|
||||||
if (auto hours = argsman.GetIntArg("-mempoolexpiry")) mempool_opts.expiry = std::chrono::hours{*hours};
|
|
||||||
|
|
||||||
mempool_opts.full_rbf = argsman.GetBoolArg("-mempoolfullrbf", mempool_opts.full_rbf);
|
|
||||||
|
|
||||||
ApplyArgsManOptions(argsman, mempool_opts.limits);
|
|
||||||
}
|
|
||||||
@@ -4759,8 +4759,8 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi
|
|||||||
}
|
}
|
||||||
if (current_time > peer.m_next_send_feefilter) {
|
if (current_time > peer.m_next_send_feefilter) {
|
||||||
CAmount filterToSend = g_filter_rounder.round(currentFilter);
|
CAmount filterToSend = g_filter_rounder.round(currentFilter);
|
||||||
// We always have a fee filter of at least minRelayTxFee
|
// We always have a fee filter of at least the min relay fee
|
||||||
filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
|
filterToSend = std::max(filterToSend, m_mempool.m_min_relay_feerate.GetFeePerK());
|
||||||
if (filterToSend != peer.m_fee_filter_sent) {
|
if (filterToSend != peer.m_fee_filter_sent) {
|
||||||
m_connman.PushMessage(&pto, CNetMsgMaker(pto.GetCommonVersion()).Make(NetMsgType::FEEFILTER, filterToSend));
|
m_connman.PushMessage(&pto, CNetMsgMaker(pto.GetCommonVersion()).Make(NetMsgType::FEEFILTER, filterToSend));
|
||||||
peer.m_fee_filter_sent = filterToSend;
|
peer.m_fee_filter_sent = filterToSend;
|
||||||
|
|||||||
+20
-4
@@ -301,7 +301,11 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
|
bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
|
||||||
CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
|
CFeeRate getDustRelayFee() override
|
||||||
|
{
|
||||||
|
if (!m_context->mempool) return CFeeRate{DUST_RELAY_TX_FEE};
|
||||||
|
return m_context->mempool->m_dust_relay_feerate;
|
||||||
|
}
|
||||||
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
|
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
|
||||||
{
|
{
|
||||||
JSONRPCRequest req;
|
JSONRPCRequest req;
|
||||||
@@ -676,9 +680,21 @@ public:
|
|||||||
if (!m_node.mempool) return {};
|
if (!m_node.mempool) return {};
|
||||||
return m_node.mempool->GetMinFee();
|
return m_node.mempool->GetMinFee();
|
||||||
}
|
}
|
||||||
CFeeRate relayMinFee() override { return ::minRelayTxFee; }
|
CFeeRate relayMinFee() override
|
||||||
CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
|
{
|
||||||
CFeeRate relayDustFee() override { return ::dustRelayFee; }
|
if (!m_node.mempool) return CFeeRate{DEFAULT_MIN_RELAY_TX_FEE};
|
||||||
|
return m_node.mempool->m_min_relay_feerate;
|
||||||
|
}
|
||||||
|
CFeeRate relayIncrementalFee() override
|
||||||
|
{
|
||||||
|
if (!m_node.mempool) return CFeeRate{DEFAULT_INCREMENTAL_RELAY_FEE};
|
||||||
|
return m_node.mempool->m_incremental_relay_feerate;
|
||||||
|
}
|
||||||
|
CFeeRate relayDustFee() override
|
||||||
|
{
|
||||||
|
if (!m_node.mempool) return CFeeRate{DUST_RELAY_TX_FEE};
|
||||||
|
return m_node.mempool->m_dust_relay_feerate;
|
||||||
|
}
|
||||||
bool havePruned() override
|
bool havePruned() override
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
// Copyright (c) 2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <node/mempool_args.h>
|
||||||
|
|
||||||
|
#include <kernel/mempool_limits.h>
|
||||||
|
#include <kernel/mempool_options.h>
|
||||||
|
|
||||||
|
#include <chainparams.h>
|
||||||
|
#include <consensus/amount.h>
|
||||||
|
#include <logging.h>
|
||||||
|
#include <policy/feerate.h>
|
||||||
|
#include <policy/policy.h>
|
||||||
|
#include <tinyformat.h>
|
||||||
|
#include <util/error.h>
|
||||||
|
#include <util/moneystr.h>
|
||||||
|
#include <util/system.h>
|
||||||
|
#include <util/translation.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
using kernel::MemPoolLimits;
|
||||||
|
using kernel::MemPoolOptions;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void ApplyArgsManOptions(const ArgsManager& argsman, MemPoolLimits& mempool_limits)
|
||||||
|
{
|
||||||
|
mempool_limits.ancestor_count = argsman.GetIntArg("-limitancestorcount", mempool_limits.ancestor_count);
|
||||||
|
|
||||||
|
if (auto vkb = argsman.GetIntArg("-limitancestorsize")) mempool_limits.ancestor_size_vbytes = *vkb * 1'000;
|
||||||
|
|
||||||
|
mempool_limits.descendant_count = argsman.GetIntArg("-limitdescendantcount", mempool_limits.descendant_count);
|
||||||
|
|
||||||
|
if (auto vkb = argsman.GetIntArg("-limitdescendantsize")) mempool_limits.descendant_size_vbytes = *vkb * 1'000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, MemPoolOptions& mempool_opts)
|
||||||
|
{
|
||||||
|
mempool_opts.check_ratio = argsman.GetIntArg("-checkmempool", mempool_opts.check_ratio);
|
||||||
|
|
||||||
|
if (auto mb = argsman.GetIntArg("-maxmempool")) mempool_opts.max_size_bytes = *mb * 1'000'000;
|
||||||
|
|
||||||
|
if (auto hours = argsman.GetIntArg("-mempoolexpiry")) mempool_opts.expiry = std::chrono::hours{*hours};
|
||||||
|
|
||||||
|
// incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool
|
||||||
|
// and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
|
||||||
|
if (argsman.IsArgSet("-incrementalrelayfee")) {
|
||||||
|
if (std::optional<CAmount> inc_relay_fee = ParseMoney(argsman.GetArg("-incrementalrelayfee", ""))) {
|
||||||
|
mempool_opts.incremental_relay_feerate = CFeeRate{inc_relay_fee.value()};
|
||||||
|
} else {
|
||||||
|
return AmountErrMsg("incrementalrelayfee", argsman.GetArg("-incrementalrelayfee", ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argsman.IsArgSet("-minrelaytxfee")) {
|
||||||
|
if (std::optional<CAmount> min_relay_feerate = ParseMoney(argsman.GetArg("-minrelaytxfee", ""))) {
|
||||||
|
// High fee check is done afterward in CWallet::Create()
|
||||||
|
mempool_opts.min_relay_feerate = CFeeRate{min_relay_feerate.value()};
|
||||||
|
} else {
|
||||||
|
return AmountErrMsg("minrelaytxfee", argsman.GetArg("-minrelaytxfee", ""));
|
||||||
|
}
|
||||||
|
} else if (mempool_opts.incremental_relay_feerate > mempool_opts.min_relay_feerate) {
|
||||||
|
// Allow only setting incremental fee to control both
|
||||||
|
mempool_opts.min_relay_feerate = mempool_opts.incremental_relay_feerate;
|
||||||
|
LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n", mempool_opts.min_relay_feerate.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feerate used to define dust. Shouldn't be changed lightly as old
|
||||||
|
// implementations may inadvertently create non-standard transactions
|
||||||
|
if (argsman.IsArgSet("-dustrelayfee")) {
|
||||||
|
if (std::optional<CAmount> parsed = ParseMoney(argsman.GetArg("-dustrelayfee", ""))) {
|
||||||
|
mempool_opts.dust_relay_feerate = CFeeRate{parsed.value()};
|
||||||
|
} else {
|
||||||
|
return AmountErrMsg("dustrelayfee", argsman.GetArg("-dustrelayfee", ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mempool_opts.permit_bare_multisig = argsman.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
|
||||||
|
|
||||||
|
if (argsman.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER)) {
|
||||||
|
mempool_opts.max_datacarrier_bytes = argsman.GetIntArg("-datacarriersize", MAX_OP_RETURN_RELAY);
|
||||||
|
} else {
|
||||||
|
mempool_opts.max_datacarrier_bytes = std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
|
||||||
|
if (!chainparams.IsTestChain() && !mempool_opts.require_standard) {
|
||||||
|
return strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString());
|
||||||
|
}
|
||||||
|
|
||||||
|
mempool_opts.full_rbf = argsman.GetBoolArg("-mempoolfullrbf", mempool_opts.full_rbf);
|
||||||
|
|
||||||
|
ApplyArgsManOptions(argsman, mempool_opts.limits);
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
@@ -2,21 +2,26 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#ifndef BITCOIN_MEMPOOL_ARGS_H
|
#ifndef BITCOIN_NODE_MEMPOOL_ARGS_H
|
||||||
#define BITCOIN_MEMPOOL_ARGS_H
|
#define BITCOIN_NODE_MEMPOOL_ARGS_H
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
class ArgsManager;
|
class ArgsManager;
|
||||||
|
class CChainParams;
|
||||||
|
struct bilingual_str;
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
struct MemPoolOptions;
|
struct MemPoolOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overlay the options set in \p argsman on top of corresponding members in \p mempool_opts.
|
* Overlay the options set in \p argsman on top of corresponding members in \p mempool_opts.
|
||||||
|
* Returns an error if one was encountered.
|
||||||
*
|
*
|
||||||
* @param[in] argsman The ArgsManager in which to check set options.
|
* @param[in] argsman The ArgsManager in which to check set options.
|
||||||
* @param[in,out] mempool_opts The MemPoolOptions to modify according to \p argsman.
|
* @param[in,out] mempool_opts The MemPoolOptions to modify according to \p argsman.
|
||||||
*/
|
*/
|
||||||
void ApplyArgsManOptions(const ArgsManager& argsman, kernel::MemPoolOptions& mempool_opts);
|
[[nodiscard]] std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, kernel::MemPoolOptions& mempool_opts);
|
||||||
|
|
||||||
|
|
||||||
#endif // BITCOIN_MEMPOOL_ARGS_H
|
#endif // BITCOIN_NODE_MEMPOOL_ARGS_H
|
||||||
+1
-1
@@ -137,7 +137,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
|||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
CTransaction ctx = CTransaction(mtx);
|
CTransaction ctx = CTransaction(mtx);
|
||||||
size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
|
size_t size(GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS), ::nBytesPerSigOp));
|
||||||
result.estimated_vsize = size;
|
result.estimated_vsize = size;
|
||||||
// Estimate fee rate
|
// Estimate fee rate
|
||||||
CFeeRate feerate(fee, size);
|
CFeeRate feerate(fee, size);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
|
|||||||
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
|
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
|
bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<unsigned char> > vSolutions;
|
std::vector<std::vector<unsigned char> > vSolutions;
|
||||||
whichType = Solver(scriptPubKey, vSolutions);
|
whichType = Solver(scriptPubKey, vSolutions);
|
||||||
@@ -82,15 +82,16 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
|
|||||||
return false;
|
return false;
|
||||||
if (m < 1 || m > n)
|
if (m < 1 || m > n)
|
||||||
return false;
|
return false;
|
||||||
} else if (whichType == TxoutType::NULL_DATA &&
|
} else if (whichType == TxoutType::NULL_DATA) {
|
||||||
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
|
if (!max_datacarrier_bytes || scriptPubKey.size() > *max_datacarrier_bytes) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
|
bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
|
||||||
{
|
{
|
||||||
if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
|
if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
|
||||||
reason = "version";
|
reason = "version";
|
||||||
@@ -130,7 +131,7 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR
|
|||||||
unsigned int nDataOut = 0;
|
unsigned int nDataOut = 0;
|
||||||
TxoutType whichType;
|
TxoutType whichType;
|
||||||
for (const CTxOut& txout : tx.vout) {
|
for (const CTxOut& txout : tx.vout) {
|
||||||
if (!::IsStandard(txout.scriptPubKey, whichType)) {
|
if (!::IsStandard(txout.scriptPubKey, max_datacarrier_bytes, whichType)) {
|
||||||
reason = "scriptpubkey";
|
reason = "scriptpubkey";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -47,8 +47,8 @@ static constexpr unsigned int MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE{80};
|
|||||||
static constexpr unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE{3600};
|
static constexpr unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE{3600};
|
||||||
/** The maximum size of a standard ScriptSig */
|
/** The maximum size of a standard ScriptSig */
|
||||||
static constexpr unsigned int MAX_STANDARD_SCRIPTSIG_SIZE{1650};
|
static constexpr unsigned int MAX_STANDARD_SCRIPTSIG_SIZE{1650};
|
||||||
/** Min feerate for defining dust. Historically this has been based on the
|
/** Min feerate for defining dust.
|
||||||
* minRelayTxFee, however changing the dust limit changes which transactions are
|
* Changing the dust limit changes which transactions are
|
||||||
* standard and should be done with care and ideally rarely. It makes sense to
|
* standard and should be done with care and ideally rarely. It makes sense to
|
||||||
* only increase the dust limit after prior releases were already not creating
|
* only increase the dust limit after prior releases were already not creating
|
||||||
* outputs below the new threshold */
|
* outputs below the new threshold */
|
||||||
@@ -105,7 +105,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
|
|||||||
|
|
||||||
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
|
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
|
||||||
|
|
||||||
bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType);
|
bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType);
|
||||||
|
|
||||||
|
|
||||||
// Changing the default transaction version requires a two step process: first
|
// Changing the default transaction version requires a two step process: first
|
||||||
@@ -117,7 +117,7 @@ static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{2};
|
|||||||
* Check for standard transaction types
|
* Check for standard transaction types
|
||||||
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
|
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
|
||||||
*/
|
*/
|
||||||
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
|
bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
|
||||||
/**
|
/**
|
||||||
* Check for standard transaction types
|
* Check for standard transaction types
|
||||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||||
|
|||||||
@@ -5,11 +5,6 @@
|
|||||||
|
|
||||||
#include <policy/settings.h>
|
#include <policy/settings.h>
|
||||||
|
|
||||||
#include <policy/feerate.h>
|
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
|
||||||
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
|
||||||
CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
|
|
||||||
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
|
||||||
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
|
|
||||||
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
||||||
@@ -6,35 +6,6 @@
|
|||||||
#ifndef BITCOIN_POLICY_SETTINGS_H
|
#ifndef BITCOIN_POLICY_SETTINGS_H
|
||||||
#define BITCOIN_POLICY_SETTINGS_H
|
#define BITCOIN_POLICY_SETTINGS_H
|
||||||
|
|
||||||
#include <policy/feerate.h>
|
|
||||||
#include <policy/policy.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class CTransaction;
|
|
||||||
|
|
||||||
// Policy settings which are configurable at runtime.
|
|
||||||
extern CFeeRate incrementalRelayFee;
|
|
||||||
extern CFeeRate dustRelayFee;
|
|
||||||
/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
|
|
||||||
extern CFeeRate minRelayTxFee;
|
|
||||||
extern unsigned int nBytesPerSigOp;
|
extern unsigned int nBytesPerSigOp;
|
||||||
extern bool fIsBareMultisigStd;
|
|
||||||
|
|
||||||
static inline bool IsStandardTx(const CTransaction& tx, std::string& reason)
|
|
||||||
{
|
|
||||||
return IsStandardTx(tx, ::fIsBareMultisigStd, ::dustRelayFee, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int64_t GetVirtualTransactionSize(int64_t weight, int64_t sigop_cost)
|
|
||||||
{
|
|
||||||
return GetVirtualTransactionSize(weight, sigop_cost, ::nBytesPerSigOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t sigop_cost)
|
|
||||||
{
|
|
||||||
return GetVirtualTransactionSize(tx, sigop_cost, ::nBytesPerSigOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BITCOIN_POLICY_SETTINGS_H
|
#endif // BITCOIN_POLICY_SETTINGS_H
|
||||||
+1
-2
@@ -6,7 +6,6 @@
|
|||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <policy/settings.h>
|
|
||||||
#include <rpc/protocol.h>
|
#include <rpc/protocol.h>
|
||||||
#include <rpc/request.h>
|
#include <rpc/request.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
@@ -88,7 +87,7 @@ static RPCHelpMan estimatesmartfee()
|
|||||||
CFeeRate feeRate{fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative)};
|
CFeeRate feeRate{fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative)};
|
||||||
if (feeRate != CFeeRate(0)) {
|
if (feeRate != CFeeRate(0)) {
|
||||||
CFeeRate min_mempool_feerate{mempool.GetMinFee()};
|
CFeeRate min_mempool_feerate{mempool.GetMinFee()};
|
||||||
CFeeRate min_relay_feerate{::minRelayTxFee};
|
CFeeRate min_relay_feerate{mempool.m_min_relay_feerate};
|
||||||
feeRate = std::max({feeRate, min_mempool_feerate, min_relay_feerate});
|
feeRate = std::max({feeRate, min_mempool_feerate, min_relay_feerate});
|
||||||
result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
|
result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+3
-3
@@ -666,9 +666,9 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool)
|
|||||||
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
|
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
|
||||||
ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
|
ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
|
||||||
ret.pushKV("maxmempool", pool.m_max_size_bytes);
|
ret.pushKV("maxmempool", pool.m_max_size_bytes);
|
||||||
ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), ::minRelayTxFee).GetFeePerK()));
|
ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), pool.m_min_relay_feerate).GetFeePerK()));
|
||||||
ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
|
ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_min_relay_feerate.GetFeePerK()));
|
||||||
ret.pushKV("incrementalrelayfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
|
ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_incremental_relay_feerate.GetFeePerK()));
|
||||||
ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
|
ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
|
||||||
ret.pushKV("fullrbf", pool.m_full_rbf);
|
ret.pushKV("fullrbf", pool.m_full_rbf);
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
+5
-2
@@ -645,8 +645,11 @@ static RPCHelpMan getnetworkinfo()
|
|||||||
obj.pushKV("connections_out", node.connman->GetNodeCount(ConnectionDirection::Out));
|
obj.pushKV("connections_out", node.connman->GetNodeCount(ConnectionDirection::Out));
|
||||||
}
|
}
|
||||||
obj.pushKV("networks", GetNetworksInfo());
|
obj.pushKV("networks", GetNetworksInfo());
|
||||||
obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
|
if (node.mempool) {
|
||||||
obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
|
// Those fields can be deprecated, to be replaced by the getmempoolinfo fields
|
||||||
|
obj.pushKV("relayfee", ValueFromAmount(node.mempool->m_min_relay_feerate.GetFeePerK()));
|
||||||
|
obj.pushKV("incrementalfee", ValueFromAmount(node.mempool->m_incremental_relay_feerate.GetFeePerK()));
|
||||||
|
}
|
||||||
UniValue localAddresses(UniValue::VARR);
|
UniValue localAddresses(UniValue::VARR);
|
||||||
{
|
{
|
||||||
LOCK(g_maplocalhost_mutex);
|
LOCK(g_maplocalhost_mutex);
|
||||||
|
|||||||
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
typedef std::vector<unsigned char> valtype;
|
typedef std::vector<unsigned char> valtype;
|
||||||
|
|
||||||
bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
|
|
||||||
unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
|
|
||||||
|
|
||||||
CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
|
CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
|
||||||
CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
|
CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
|
||||||
|
|
||||||
|
|||||||
+1
-10
@@ -33,20 +33,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default setting for nMaxDatacarrierBytes. 80 bytes of data, +1 for OP_RETURN,
|
* Default setting for -datacarriersize. 80 bytes of data, +1 for OP_RETURN,
|
||||||
* +2 for the pushdata opcodes.
|
* +2 for the pushdata opcodes.
|
||||||
*/
|
*/
|
||||||
static const unsigned int MAX_OP_RETURN_RELAY = 83;
|
static const unsigned int MAX_OP_RETURN_RELAY = 83;
|
||||||
|
|
||||||
/**
|
|
||||||
* A data carrying output is an unspendable output containing data. The script
|
|
||||||
* type is designated as TxoutType::NULL_DATA.
|
|
||||||
*/
|
|
||||||
extern bool fAcceptDatacarrier;
|
|
||||||
|
|
||||||
/** Maximum size of TxoutType::NULL_DATA scripts that this node considers standard. */
|
|
||||||
extern unsigned nMaxDatacarrierBytes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mandatory script verification flags that all new blocks must comply with for
|
* Mandatory script verification flags that all new blocks must comply with for
|
||||||
* them to be valid. (but old blocks may not comply with) Currently just P2SH,
|
* them to be valid. (but old blocks may not comply with) Currently just P2SH,
|
||||||
|
|||||||
@@ -87,9 +87,6 @@ FUZZ_TARGET_INIT(integer, initialize_integer)
|
|||||||
}
|
}
|
||||||
(void)GetSizeOfCompactSize(u64);
|
(void)GetSizeOfCompactSize(u64);
|
||||||
(void)GetSpecialScriptSize(u32);
|
(void)GetSpecialScriptSize(u32);
|
||||||
if (!MultiplicationOverflow(i64, static_cast<int64_t>(::nBytesPerSigOp)) && !AdditionOverflow(i64 * ::nBytesPerSigOp, static_cast<int64_t>(4))) {
|
|
||||||
(void)GetVirtualTransactionSize(i64, i64);
|
|
||||||
}
|
|
||||||
if (!MultiplicationOverflow(i64, static_cast<int64_t>(u32)) && !AdditionOverflow(i64, static_cast<int64_t>(4)) && !AdditionOverflow(i64 * u32, static_cast<int64_t>(4))) {
|
if (!MultiplicationOverflow(i64, static_cast<int64_t>(u32)) && !AdditionOverflow(i64, static_cast<int64_t>(4)) && !AdditionOverflow(i64 * u32, static_cast<int64_t>(4))) {
|
||||||
(void)GetVirtualTransactionSize(i64, i64, u32);
|
(void)GetVirtualTransactionSize(i64, i64, u32);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,12 +157,12 @@ FUZZ_TARGET_INIT(key, initialize_key)
|
|||||||
assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
|
assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
|
||||||
|
|
||||||
TxoutType which_type_tx_pubkey;
|
TxoutType which_type_tx_pubkey;
|
||||||
const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
|
const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, std::nullopt, which_type_tx_pubkey);
|
||||||
assert(is_standard_tx_pubkey);
|
assert(is_standard_tx_pubkey);
|
||||||
assert(which_type_tx_pubkey == TxoutType::PUBKEY);
|
assert(which_type_tx_pubkey == TxoutType::PUBKEY);
|
||||||
|
|
||||||
TxoutType which_type_tx_multisig;
|
TxoutType which_type_tx_multisig;
|
||||||
const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
|
const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, std::nullopt, which_type_tx_multisig);
|
||||||
assert(is_standard_tx_multisig);
|
assert(is_standard_tx_multisig);
|
||||||
assert(which_type_tx_multisig == TxoutType::MULTISIG);
|
assert(which_type_tx_multisig == TxoutType::MULTISIG);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <mempool_args.h>
|
#include <node/mempool_args.h>
|
||||||
#include <policy/rbf.h>
|
#include <policy/rbf.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ FUZZ_TARGET_INIT(script, initialize_script)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TxoutType which_type;
|
TxoutType which_type;
|
||||||
bool is_standard_ret = IsStandard(script, which_type);
|
bool is_standard_ret = IsStandard(script, std::nullopt, which_type);
|
||||||
if (!is_standard_ret) {
|
if (!is_standard_ret) {
|
||||||
assert(which_type == TxoutType::NONSTANDARD ||
|
assert(which_type == TxoutType::NONSTANDARD ||
|
||||||
which_type == TxoutType::NULL_DATA ||
|
which_type == TxoutType::NULL_DATA ||
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
|
|||||||
|
|
||||||
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
|
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
|
||||||
std::string reason;
|
std::string reason;
|
||||||
const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
|
const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
|
||||||
const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
|
const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
|
||||||
if (is_standard_without_permit_bare_multisig) {
|
if (is_standard_without_permit_bare_multisig) {
|
||||||
assert(is_standard_with_permit_bare_multisig);
|
assert(is_standard_with_permit_bare_multisig);
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,6 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
|
|||||||
(void)GetTransactionWeight(tx);
|
(void)GetTransactionWeight(tx);
|
||||||
(void)GetVirtualTransactionSize(tx);
|
(void)GetVirtualTransactionSize(tx);
|
||||||
(void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
|
(void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
|
||||||
(void)IsStandardTx(tx, reason);
|
|
||||||
(void)RecursiveDynamicUsage(tx);
|
(void)RecursiveDynamicUsage(tx);
|
||||||
(void)SignalsOptInRBF(tx);
|
(void)SignalsOptInRBF(tx);
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <mempool_args.h>
|
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
|
#include <node/mempool_args.h>
|
||||||
#include <node/miner.h>
|
#include <node/miner.h>
|
||||||
#include <test/fuzz/FuzzedDataProvider.h>
|
#include <test/fuzz/FuzzedDataProvider.h>
|
||||||
#include <test/fuzz/fuzz.h>
|
#include <test/fuzz/fuzz.h>
|
||||||
@@ -116,7 +116,7 @@ void MockTime(FuzzedDataProvider& fuzzed_data_provider, const CChainState& chain
|
|||||||
SetMockTime(time);
|
SetMockTime(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTxMemPool MakeMempool(const NodeContext& node)
|
CTxMemPool MakeMempool(FuzzedDataProvider& fuzzed_data_provider, const NodeContext& node)
|
||||||
{
|
{
|
||||||
// Take the default options for tests...
|
// Take the default options for tests...
|
||||||
CTxMemPool::Options mempool_opts{MemPoolOptionsForTest(node)};
|
CTxMemPool::Options mempool_opts{MemPoolOptionsForTest(node)};
|
||||||
@@ -124,6 +124,7 @@ CTxMemPool MakeMempool(const NodeContext& node)
|
|||||||
// ...override specific options for this specific fuzz suite
|
// ...override specific options for this specific fuzz suite
|
||||||
mempool_opts.estimator = nullptr;
|
mempool_opts.estimator = nullptr;
|
||||||
mempool_opts.check_ratio = 1;
|
mempool_opts.check_ratio = 1;
|
||||||
|
mempool_opts.require_standard = fuzzed_data_provider.ConsumeBool();
|
||||||
|
|
||||||
// ...and construct a CTxMemPool from it
|
// ...and construct a CTxMemPool from it
|
||||||
return CTxMemPool{mempool_opts};
|
return CTxMemPool{mempool_opts};
|
||||||
@@ -150,7 +151,7 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
|
|||||||
constexpr CAmount SUPPLY_TOTAL{COINBASE_MATURITY * 50 * COIN};
|
constexpr CAmount SUPPLY_TOTAL{COINBASE_MATURITY * 50 * COIN};
|
||||||
|
|
||||||
SetMempoolConstraints(*node.args, fuzzed_data_provider);
|
SetMempoolConstraints(*node.args, fuzzed_data_provider);
|
||||||
CTxMemPool tx_pool_{MakeMempool(node)};
|
CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
|
||||||
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
|
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
|
||||||
|
|
||||||
chainstate.SetMempool(&tx_pool);
|
chainstate.SetMempool(&tx_pool);
|
||||||
@@ -237,7 +238,6 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
|
|||||||
auto txr = std::make_shared<TransactionsDelta>(removed, added);
|
auto txr = std::make_shared<TransactionsDelta>(removed, added);
|
||||||
RegisterSharedValidationInterface(txr);
|
RegisterSharedValidationInterface(txr);
|
||||||
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
|
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
|
||||||
::fRequireStandard = fuzzed_data_provider.ConsumeBool();
|
|
||||||
|
|
||||||
// Make sure ProcessNewPackage on one transaction works.
|
// Make sure ProcessNewPackage on one transaction works.
|
||||||
// The result is not guaranteed to be the same as what is returned by ATMP.
|
// The result is not guaranteed to be the same as what is returned by ATMP.
|
||||||
@@ -325,7 +325,7 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetMempoolConstraints(*node.args, fuzzed_data_provider);
|
SetMempoolConstraints(*node.args, fuzzed_data_provider);
|
||||||
CTxMemPool tx_pool_{MakeMempool(node)};
|
CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
|
||||||
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
|
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
|
||||||
|
|
||||||
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300)
|
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300)
|
||||||
@@ -348,7 +348,6 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
|
|||||||
|
|
||||||
const auto tx = MakeTransactionRef(mut_tx);
|
const auto tx = MakeTransactionRef(mut_tx);
|
||||||
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
|
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
|
||||||
::fRequireStandard = fuzzed_data_provider.ConsumeBool();
|
|
||||||
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false));
|
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false));
|
||||||
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
|
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
|
||||||
if (accepted) {
|
if (accepted) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <kernel/mempool_persist.h>
|
#include <kernel/mempool_persist.h>
|
||||||
|
|
||||||
#include <chainparamsbase.h>
|
#include <chainparamsbase.h>
|
||||||
#include <mempool_args.h>
|
#include <node/mempool_args.h>
|
||||||
#include <node/mempool_persist_args.h>
|
#include <node/mempool_persist_args.h>
|
||||||
#include <test/fuzz/FuzzedDataProvider.h>
|
#include <test/fuzz/FuzzedDataProvider.h>
|
||||||
#include <test/fuzz/fuzz.h>
|
#include <test/fuzz/fuzz.h>
|
||||||
|
|||||||
@@ -141,23 +141,30 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
|
|||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
key[i].MakeNewKey(true);
|
key[i].MakeNewKey(true);
|
||||||
|
|
||||||
TxoutType whichType;
|
const auto is_standard{[](const CScript& spk) {
|
||||||
|
TxoutType type;
|
||||||
|
bool res{::IsStandard(spk, std::nullopt, type)};
|
||||||
|
if (res) {
|
||||||
|
BOOST_CHECK_EQUAL(type, TxoutType::MULTISIG);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}};
|
||||||
|
|
||||||
CScript a_and_b;
|
CScript a_and_b;
|
||||||
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK(::IsStandard(a_and_b, whichType));
|
BOOST_CHECK(is_standard(a_and_b));
|
||||||
|
|
||||||
CScript a_or_b;
|
CScript a_or_b;
|
||||||
a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK(::IsStandard(a_or_b, whichType));
|
BOOST_CHECK(is_standard(a_or_b));
|
||||||
|
|
||||||
CScript escrow;
|
CScript escrow;
|
||||||
escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
|
escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK(::IsStandard(escrow, whichType));
|
BOOST_CHECK(is_standard(escrow));
|
||||||
|
|
||||||
CScript one_of_four;
|
CScript one_of_four;
|
||||||
one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG;
|
one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK(!::IsStandard(one_of_four, whichType));
|
BOOST_CHECK(!is_standard(one_of_four));
|
||||||
|
|
||||||
CScript malformed[6];
|
CScript malformed[6];
|
||||||
malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
||||||
@@ -167,8 +174,9 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
|
|||||||
malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
|
malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
|
||||||
malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
|
malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++) {
|
||||||
BOOST_CHECK(!::IsStandard(malformed[i], whichType));
|
BOOST_CHECK(!is_standard(malformed[i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(multisig_Sign)
|
BOOST_AUTO_TEST_CASE(multisig_Sign)
|
||||||
|
|||||||
@@ -18,6 +18,11 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
// Helpers:
|
// Helpers:
|
||||||
|
bool IsStandardTx(const CTransaction& tx, std::string& reason)
|
||||||
|
{
|
||||||
|
return IsStandardTx(tx, std::nullopt, DEFAULT_PERMIT_BAREMULTISIG, CFeeRate{DUST_RELAY_TX_FEE}, reason);
|
||||||
|
}
|
||||||
|
|
||||||
static std::vector<unsigned char>
|
static std::vector<unsigned char>
|
||||||
Serialize(const CScript& s)
|
Serialize(const CScript& s)
|
||||||
{
|
{
|
||||||
@@ -49,7 +54,6 @@ BOOST_FIXTURE_TEST_SUITE(script_p2sh_tests, BasicTestingSetup)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(sign)
|
BOOST_AUTO_TEST_CASE(sign)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
|
||||||
// Pay-to-script-hash looks like this:
|
// Pay-to-script-hash looks like this:
|
||||||
// scriptSig: <sig> <sig...> <serialized_script>
|
// scriptSig: <sig> <sig...> <serialized_script>
|
||||||
// scriptPubKey: HASH160 <hash> EQUAL
|
// scriptPubKey: HASH160 <hash> EQUAL
|
||||||
@@ -149,7 +153,6 @@ BOOST_AUTO_TEST_CASE(norecurse)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(set)
|
BOOST_AUTO_TEST_CASE(set)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
|
||||||
// Test the CScript::Set* methods
|
// Test the CScript::Set* methods
|
||||||
FillableSigningProvider keystore;
|
FillableSigningProvider keystore;
|
||||||
CKey key[4];
|
CKey key[4];
|
||||||
@@ -263,7 +266,6 @@ BOOST_AUTO_TEST_CASE(switchover)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
|
||||||
CCoinsView coinsDummy;
|
CCoinsView coinsDummy;
|
||||||
CCoinsViewCache coins(&coinsDummy);
|
CCoinsViewCache coins(&coinsDummy);
|
||||||
FillableSigningProvider keystore;
|
FillableSigningProvider keystore;
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ typedef std::vector<unsigned char> valtype;
|
|||||||
// In script_tests.cpp
|
// In script_tests.cpp
|
||||||
UniValue read_json(const std::string& jsondata);
|
UniValue read_json(const std::string& jsondata);
|
||||||
|
|
||||||
|
static CFeeRate g_dust{DUST_RELAY_TX_FEE};
|
||||||
|
static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
|
||||||
|
|
||||||
static std::map<std::string, unsigned int> mapFlagNames = {
|
static std::map<std::string, unsigned int> mapFlagNames = {
|
||||||
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
|
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
|
||||||
{std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC},
|
{std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC},
|
||||||
@@ -745,7 +748,6 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_IsStandard)
|
BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
|
||||||
FillableSigningProvider keystore;
|
FillableSigningProvider keystore;
|
||||||
CCoinsView coinsDummy;
|
CCoinsView coinsDummy;
|
||||||
CCoinsViewCache coins(&coinsDummy);
|
CCoinsViewCache coins(&coinsDummy);
|
||||||
@@ -765,19 +767,19 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|||||||
|
|
||||||
constexpr auto CheckIsStandard = [](const auto& t) {
|
constexpr auto CheckIsStandard = [](const auto& t) {
|
||||||
std::string reason;
|
std::string reason;
|
||||||
BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
|
BOOST_CHECK(IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_multi, g_dust, reason));
|
||||||
BOOST_CHECK(reason.empty());
|
BOOST_CHECK(reason.empty());
|
||||||
};
|
};
|
||||||
constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in) {
|
constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in) {
|
||||||
std::string reason;
|
std::string reason;
|
||||||
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
|
BOOST_CHECK(!IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_multi, g_dust, reason));
|
||||||
BOOST_CHECK_EQUAL(reason_in, reason);
|
BOOST_CHECK_EQUAL(reason_in, reason);
|
||||||
};
|
};
|
||||||
|
|
||||||
CheckIsStandard(t);
|
CheckIsStandard(t);
|
||||||
|
|
||||||
// Check dust with default relay fee:
|
// Check dust with default relay fee:
|
||||||
CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK() / 1000;
|
CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;
|
||||||
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
||||||
// dust:
|
// dust:
|
||||||
t.vout[0].nValue = nDustThreshold - 1;
|
t.vout[0].nValue = nDustThreshold - 1;
|
||||||
@@ -805,14 +807,14 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|||||||
|
|
||||||
// Check dust with odd relay fee to verify rounding:
|
// Check dust with odd relay fee to verify rounding:
|
||||||
// nDustThreshold = 182 * 3702 / 1000
|
// nDustThreshold = 182 * 3702 / 1000
|
||||||
dustRelayFee = CFeeRate(3702);
|
g_dust = CFeeRate(3702);
|
||||||
// dust:
|
// dust:
|
||||||
t.vout[0].nValue = 674 - 1;
|
t.vout[0].nValue = 674 - 1;
|
||||||
CheckIsNotStandard(t, "dust");
|
CheckIsNotStandard(t, "dust");
|
||||||
// not dust:
|
// not dust:
|
||||||
t.vout[0].nValue = 674;
|
t.vout[0].nValue = 674;
|
||||||
CheckIsStandard(t);
|
CheckIsStandard(t);
|
||||||
dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
g_dust = CFeeRate{DUST_RELAY_TX_FEE};
|
||||||
|
|
||||||
t.vout[0].scriptPubKey = CScript() << OP_1;
|
t.vout[0].scriptPubKey = CScript() << OP_1;
|
||||||
CheckIsNotStandard(t, "scriptpubkey");
|
CheckIsNotStandard(t, "scriptpubkey");
|
||||||
@@ -924,16 +926,16 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|||||||
BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
|
BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
|
||||||
CheckIsNotStandard(t, "tx-size");
|
CheckIsNotStandard(t, "tx-size");
|
||||||
|
|
||||||
// Check bare multisig (standard if policy flag fIsBareMultisigStd is set)
|
// Check bare multisig (standard if policy flag g_bare_multi is set)
|
||||||
fIsBareMultisigStd = true;
|
g_bare_multi = true;
|
||||||
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
|
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
|
||||||
t.vin.resize(1);
|
t.vin.resize(1);
|
||||||
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
|
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
|
||||||
CheckIsStandard(t);
|
CheckIsStandard(t);
|
||||||
|
|
||||||
fIsBareMultisigStd = false;
|
g_bare_multi = false;
|
||||||
CheckIsNotStandard(t, "bare-multisig");
|
CheckIsNotStandard(t, "bare-multisig");
|
||||||
fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;
|
||||||
|
|
||||||
// Check P2WPKH outputs dust threshold
|
// Check P2WPKH outputs dust threshold
|
||||||
t.vout[0].scriptPubKey = CScript() << OP_0 << ParseHex("ffffffffffffffffffffffffffffffffffffffff");
|
t.vout[0].scriptPubKey = CScript() << OP_0 << ParseHex("ffffffffffffffffffffffffffffffffffffffff");
|
||||||
|
|||||||
@@ -14,12 +14,12 @@
|
|||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <init/common.h>
|
#include <init/common.h>
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
#include <mempool_args.h>
|
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <net_processing.h>
|
#include <net_processing.h>
|
||||||
#include <node/blockstorage.h>
|
#include <node/blockstorage.h>
|
||||||
#include <node/chainstate.h>
|
#include <node/chainstate.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
|
#include <node/mempool_args.h>
|
||||||
#include <node/miner.h>
|
#include <node/miner.h>
|
||||||
#include <noui.h>
|
#include <noui.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
@@ -160,7 +160,8 @@ CTxMemPool::Options MemPoolOptionsForTest(const NodeContext& node)
|
|||||||
// chainparams.DefaultConsistencyChecks for tests
|
// chainparams.DefaultConsistencyChecks for tests
|
||||||
.check_ratio = 1,
|
.check_ratio = 1,
|
||||||
};
|
};
|
||||||
ApplyArgsManOptions(*node.args, mempool_opts);
|
const auto err{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)};
|
||||||
|
Assert(!err);
|
||||||
return mempool_opts;
|
return mempool_opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-4
@@ -106,7 +106,7 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
|
|||||||
|
|
||||||
size_t CTxMemPoolEntry::GetTxSize() const
|
size_t CTxMemPoolEntry::GetTxSize() const
|
||||||
{
|
{
|
||||||
return GetVirtualTransactionSize(nTxWeight, sigOpCost);
|
return GetVirtualTransactionSize(nTxWeight, sigOpCost, ::nBytesPerSigOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendants,
|
void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendants,
|
||||||
@@ -458,6 +458,12 @@ CTxMemPool::CTxMemPool(const Options& opts)
|
|||||||
minerPolicyEstimator{opts.estimator},
|
minerPolicyEstimator{opts.estimator},
|
||||||
m_max_size_bytes{opts.max_size_bytes},
|
m_max_size_bytes{opts.max_size_bytes},
|
||||||
m_expiry{opts.expiry},
|
m_expiry{opts.expiry},
|
||||||
|
m_incremental_relay_feerate{opts.incremental_relay_feerate},
|
||||||
|
m_min_relay_feerate{opts.min_relay_feerate},
|
||||||
|
m_dust_relay_feerate{opts.dust_relay_feerate},
|
||||||
|
m_permit_bare_multisig{opts.permit_bare_multisig},
|
||||||
|
m_max_datacarrier_bytes{opts.max_datacarrier_bytes},
|
||||||
|
m_require_standard{opts.require_standard},
|
||||||
m_full_rbf{opts.full_rbf},
|
m_full_rbf{opts.full_rbf},
|
||||||
m_limits{opts.limits}
|
m_limits{opts.limits}
|
||||||
{
|
{
|
||||||
@@ -1117,12 +1123,12 @@ CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
|
|||||||
rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
|
rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
|
||||||
lastRollingFeeUpdate = time;
|
lastRollingFeeUpdate = time;
|
||||||
|
|
||||||
if (rollingMinimumFeeRate < (double)incrementalRelayFee.GetFeePerK() / 2) {
|
if (rollingMinimumFeeRate < (double)m_incremental_relay_feerate.GetFeePerK() / 2) {
|
||||||
rollingMinimumFeeRate = 0;
|
rollingMinimumFeeRate = 0;
|
||||||
return CFeeRate(0);
|
return CFeeRate(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::max(CFeeRate(llround(rollingMinimumFeeRate)), incrementalRelayFee);
|
return std::max(CFeeRate(llround(rollingMinimumFeeRate)), m_incremental_relay_feerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxMemPool::trackPackageRemoved(const CFeeRate& rate) {
|
void CTxMemPool::trackPackageRemoved(const CFeeRate& rate) {
|
||||||
@@ -1146,7 +1152,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpends
|
|||||||
// to have 0 fee). This way, we don't allow txn to enter mempool with feerate
|
// to have 0 fee). This way, we don't allow txn to enter mempool with feerate
|
||||||
// equal to txn which were removed with no block in between.
|
// equal to txn which were removed with no block in between.
|
||||||
CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
|
CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
|
||||||
removed += incrementalRelayFee;
|
removed += m_incremental_relay_feerate;
|
||||||
trackPackageRemoved(removed);
|
trackPackageRemoved(removed);
|
||||||
maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
|
maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
|
||||||
|
|
||||||
|
|||||||
+11
-5
@@ -568,6 +568,12 @@ public:
|
|||||||
|
|
||||||
const int64_t m_max_size_bytes;
|
const int64_t m_max_size_bytes;
|
||||||
const std::chrono::seconds m_expiry;
|
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;
|
||||||
|
const bool m_require_standard;
|
||||||
const bool m_full_rbf;
|
const bool m_full_rbf;
|
||||||
|
|
||||||
using Limits = kernel::MemPoolLimits;
|
using Limits = kernel::MemPoolLimits;
|
||||||
@@ -702,11 +708,11 @@ public:
|
|||||||
void CalculateDescendants(txiter it, setEntries& setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
void CalculateDescendants(txiter it, setEntries& setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
/** The minimum fee to get into the mempool, which may itself not be enough
|
/** The minimum fee to get into the mempool, which may itself not be enough
|
||||||
* for larger-sized transactions.
|
* for larger-sized transactions.
|
||||||
* The incrementalRelayFee policy variable is used to bound the time it
|
* The m_incremental_relay_feerate policy variable is used to bound the time it
|
||||||
* takes the fee rate to go back down all the way to 0. When the feerate
|
* takes the fee rate to go back down all the way to 0. When the feerate
|
||||||
* would otherwise be half of this, it is set to 0 instead.
|
* would otherwise be half of this, it is set to 0 instead.
|
||||||
*/
|
*/
|
||||||
CFeeRate GetMinFee() const {
|
CFeeRate GetMinFee() const {
|
||||||
return GetMinFee(m_max_size_bytes);
|
return GetMinFee(m_max_size_bytes);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-8
@@ -124,7 +124,6 @@ GlobalMutex g_best_block_mutex;
|
|||||||
std::condition_variable g_best_block_cv;
|
std::condition_variable g_best_block_cv;
|
||||||
uint256 g_best_block;
|
uint256 g_best_block;
|
||||||
bool g_parallel_script_checks{false};
|
bool g_parallel_script_checks{false};
|
||||||
bool fRequireStandard = true;
|
|
||||||
bool fCheckBlockIndex = false;
|
bool fCheckBlockIndex = false;
|
||||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
||||||
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
||||||
@@ -647,8 +646,9 @@ private:
|
|||||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
|
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (package_fee < ::minRelayTxFee.GetFee(package_size)) {
|
if (package_fee < m_pool.m_min_relay_feerate.GetFee(package_size)) {
|
||||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met", strprintf("%d < %d", package_fee, ::minRelayTxFee.GetFee(package_size)));
|
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
|
||||||
|
strprintf("%d < %d", package_fee, m_pool.m_min_relay_feerate.GetFee(package_size)));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -700,8 +700,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|||||||
|
|
||||||
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
||||||
std::string reason;
|
std::string reason;
|
||||||
if (fRequireStandard && !IsStandardTx(tx, reason))
|
if (m_pool.m_require_standard && !IsStandardTx(tx, m_pool.m_max_datacarrier_bytes, m_pool.m_permit_bare_multisig, m_pool.m_dust_relay_feerate, reason)) {
|
||||||
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
|
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
|
||||||
|
}
|
||||||
|
|
||||||
// Do not work on transactions that are too small.
|
// Do not work on transactions that are too small.
|
||||||
// A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes.
|
// A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes.
|
||||||
@@ -807,13 +808,14 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|||||||
return false; // state filled in by CheckTxInputs
|
return false; // state filled in by CheckTxInputs
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fRequireStandard && !AreInputsStandard(tx, m_view)) {
|
if (m_pool.m_require_standard && !AreInputsStandard(tx, m_view)) {
|
||||||
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
|
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for non-standard witnesses.
|
// Check for non-standard witnesses.
|
||||||
if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, m_view))
|
if (tx.HasWitness() && m_pool.m_require_standard && !IsWitnessStandard(tx, m_view)) {
|
||||||
return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");
|
return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");
|
||||||
|
}
|
||||||
|
|
||||||
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
|
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
|
||||||
|
|
||||||
@@ -840,7 +842,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|||||||
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
||||||
strprintf("%d", nSigOpsCost));
|
strprintf("%d", nSigOpsCost));
|
||||||
|
|
||||||
// No individual transactions are allowed below minRelayTxFee and mempool min fee except from
|
// No individual transactions are allowed below the min relay feerate and mempool min feerate except from
|
||||||
// disconnected blocks and transactions in a package. Package transactions will be checked using
|
// disconnected blocks and transactions in a package. Package transactions will be checked using
|
||||||
// package feerate later.
|
// package feerate later.
|
||||||
if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state)) return false;
|
if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state)) return false;
|
||||||
@@ -958,7 +960,7 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
|||||||
ws.m_conflicting_size += it->GetTxSize();
|
ws.m_conflicting_size += it->GetTxSize();
|
||||||
}
|
}
|
||||||
if (const auto err_string{PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
|
if (const auto err_string{PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
|
||||||
::incrementalRelayFee, hash)}) {
|
m_pool.m_incremental_relay_feerate, hash)}) {
|
||||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
|
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ extern uint256 g_best_block;
|
|||||||
* False indicates all script checking is done on the main threadMessageHandler thread.
|
* False indicates all script checking is done on the main threadMessageHandler thread.
|
||||||
*/
|
*/
|
||||||
extern bool g_parallel_script_checks;
|
extern bool g_parallel_script_checks;
|
||||||
extern bool fRequireStandard;
|
|
||||||
extern bool fCheckBlockIndex;
|
extern bool fCheckBlockIndex;
|
||||||
extern bool fCheckpointsEnabled;
|
extern bool fCheckpointsEnabled;
|
||||||
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
|
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
|
||||||
|
|||||||
+1
-1
@@ -87,7 +87,7 @@ CFeeRate GetDiscardRate(const CWallet& wallet)
|
|||||||
CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, false /* conservative */);
|
CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, false /* conservative */);
|
||||||
// Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate
|
// Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate
|
||||||
discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate);
|
discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate);
|
||||||
// Discard rate must be at least dustRelayFee
|
// Discard rate must be at least dust relay feerate
|
||||||
discard_rate = std::max(discard_rate, wallet.chain().relayDustFee());
|
discard_rate = std::max(discard_rate, wallet.chain().relayDustFee());
|
||||||
return discard_rate;
|
return discard_rate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||||||
self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
|
self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
|
||||||
# self.old_node sets only NODE_NETWORK
|
# self.old_node sets only NODE_NETWORK
|
||||||
self.old_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK)
|
self.old_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK)
|
||||||
# self.std_node is for testing node1 (fRequireStandard=true)
|
# self.std_node is for testing node1 (requires standard txs)
|
||||||
self.std_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
|
self.std_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
|
||||||
# self.std_wtx_node is for testing node1 with wtxid relay
|
# self.std_wtx_node is for testing node1 with wtxid relay
|
||||||
self.std_wtx_node = self.nodes[1].add_p2p_connection(TestP2PConn(wtxidrelay=True), services=P2P_SERVICES)
|
self.std_wtx_node = self.nodes[1].add_p2p_connection(TestP2PConn(wtxidrelay=True), services=P2P_SERVICES)
|
||||||
@@ -1382,7 +1382,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||||||
tx3.vout.append(CTxOut(total_value - 1000, script_pubkey))
|
tx3.vout.append(CTxOut(total_value - 1000, script_pubkey))
|
||||||
tx3.rehash()
|
tx3.rehash()
|
||||||
|
|
||||||
# First we test this transaction against fRequireStandard=true node
|
# First we test this transaction against std_node
|
||||||
# making sure the txid is added to the reject filter
|
# making sure the txid is added to the reject filter
|
||||||
self.std_node.announce_tx_and_wait_for_getdata(tx3)
|
self.std_node.announce_tx_and_wait_for_getdata(tx3)
|
||||||
test_transaction_acceptance(self.nodes[1], self.std_node, tx3, with_witness=True, accepted=False, reason="bad-txns-nonstandard-inputs")
|
test_transaction_acceptance(self.nodes[1], self.std_node, tx3, with_witness=True, accepted=False, reason="bad-txns-nonstandard-inputs")
|
||||||
@@ -1390,7 +1390,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||||||
self.std_node.announce_tx_and_wait_for_getdata(tx3, success=False)
|
self.std_node.announce_tx_and_wait_for_getdata(tx3, success=False)
|
||||||
|
|
||||||
# Spending a higher version witness output is not allowed by policy,
|
# Spending a higher version witness output is not allowed by policy,
|
||||||
# even with fRequireStandard=false.
|
# even with the node that accepts non-standard txs.
|
||||||
test_transaction_acceptance(self.nodes[0], self.test_node, tx3, with_witness=True, accepted=False, reason="reserved for soft-fork upgrades")
|
test_transaction_acceptance(self.nodes[0], self.test_node, tx3, with_witness=True, accepted=False, reason="reserved for soft-fork upgrades")
|
||||||
|
|
||||||
# Building a block with the transaction must be valid, however.
|
# Building a block with the transaction must be valid, however.
|
||||||
|
|||||||
Reference in new issue
Block a user