Merge bitcoin/bitcoin#25648: refactor: Remove all policy globals
ddddd6913b1bdee1cad89a32d363306ea1f7b8d7 sort after scripted-diff (MacroFake)
fac812ca835e0d843aba1d4db0e49d183018a29e scripted-diff: Move mempool_args to src/node (MacroFake)
66664384a6fec39ecb4d8d06db66a4f193a06e33 Remove ::g_max_datacarrier_bytes global (MacroFake)
fad0b4fab849eb5f1f0aa54ebc290f85a473ec91 Pass datacarrier setting into IsStandard (MacroFake)
fa2a6b8516b24d7e9ca11926a49cf2b07f661e81 Combine datacarrier globals into one (MacroFake)
fa477d32eefcc3dd2f06b452066290d9936d8c5d Remove ::GetVirtualTransactionSize() alias (MacroFake)
fa2f6c1a611dffe5a3f63fe1b453f1dd420371b1 Remove ::fIsBareMultisigStd global (MacroFake)
fadc14e4f514e7167723285e0ac3d4a7149bbee6 Remove ::dustRelayFee (MacroFake)
fa8a7f01fe1b6db98097021276ed5d929faadbec Remove ::IsStandardTx(tx, reason) alias (MacroFake)
fa7a9114e59b81b50584311a4ab2b3e9a8d956bd test: Remove unused cs_main (MacroFake)
fa9cba7afb73c01bd2c8fefd662dfc80dd98c5e8 Remove ::incrementalRelayFee and ::minRelayTxFee globals (MacroFake)
fa148602e67fe035b1b21eff6c0b656919ac2d45 Remove ::fRequireStandard global (MacroFake)
fa468bdfb62dec286cb977db78d3e47b64dafeba Return 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 ACK ddddd69
ryanofsky:
Code review ACK ddddd6913b1bdee1cad89a32d363306ea1f7b8d7
ariard:
Light Code Review ACK ddddd69
Tree-SHA512: 9de2ce601cfcaa4dfd7d1c92270568895ce8702ccdffb59829fbe9618eab0fd88d738afef33ed66988c66861115e0340e881056bfb71e2aed4af2440bd37eb1e
This commit is contained in:
commit
f6fdedf850
@ -45,6 +45,7 @@ if [ "${RUN_TIDY}" = "true" ]; then
|
||||
" src/init"\
|
||||
" src/kernel"\
|
||||
" src/node/chainstate.cpp"\
|
||||
" src/node/mempool_args.cpp"\
|
||||
" src/policy/feerate.cpp"\
|
||||
" src/policy/packages.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
|
||||
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`,
|
||||
`-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
|
||||
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.
|
||||
|
||||
* 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)).
|
||||
|
||||
* 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.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
@ -139,7 +139,6 @@ BITCOIN_CORE_H = \
|
||||
compat/cpuid.h \
|
||||
compat/endian.h \
|
||||
compressor.h \
|
||||
node/connection_types.h \
|
||||
consensus/consensus.h \
|
||||
consensus/tx_check.h \
|
||||
consensus/tx_verify.h \
|
||||
@ -149,7 +148,6 @@ BITCOIN_CORE_H = \
|
||||
dbwrapper.h \
|
||||
deploymentinfo.h \
|
||||
deploymentstatus.h \
|
||||
node/eviction.h \
|
||||
external_signer.h \
|
||||
flatfile.h \
|
||||
fs.h \
|
||||
@ -184,7 +182,6 @@ BITCOIN_CORE_H = \
|
||||
logging.h \
|
||||
logging/timer.h \
|
||||
mapport.h \
|
||||
mempool_args.h \
|
||||
memusage.h \
|
||||
merkleblock.h \
|
||||
net.h \
|
||||
@ -199,13 +196,16 @@ BITCOIN_CORE_H = \
|
||||
node/caches.h \
|
||||
node/chainstate.h \
|
||||
node/coin.h \
|
||||
node/connection_types.h \
|
||||
node/context.h \
|
||||
node/eviction.h \
|
||||
node/interface_ui.h \
|
||||
node/mempool_args.h \
|
||||
node/mempool_persist_args.h \
|
||||
node/miner.h \
|
||||
node/minisketchwrapper.h \
|
||||
node/psbt.h \
|
||||
node/transaction.h \
|
||||
node/interface_ui.h \
|
||||
node/utxo_snapshot.h \
|
||||
noui.h \
|
||||
outputtype.h \
|
||||
@ -372,10 +372,9 @@ libbitcoin_node_a_SOURCES = \
|
||||
kernel/context.cpp \
|
||||
kernel/mempool_persist.cpp \
|
||||
mapport.cpp \
|
||||
mempool_args.cpp \
|
||||
net.cpp \
|
||||
netgroup.cpp \
|
||||
net_processing.cpp \
|
||||
netgroup.cpp \
|
||||
node/blockstorage.cpp \
|
||||
node/caches.cpp \
|
||||
node/chainstate.cpp \
|
||||
@ -383,13 +382,14 @@ libbitcoin_node_a_SOURCES = \
|
||||
node/connection_types.cpp \
|
||||
node/context.cpp \
|
||||
node/eviction.cpp \
|
||||
node/interface_ui.cpp \
|
||||
node/interfaces.cpp \
|
||||
node/mempool_args.cpp \
|
||||
node/mempool_persist_args.cpp \
|
||||
node/miner.cpp \
|
||||
node/minisketchwrapper.cpp \
|
||||
node/psbt.cpp \
|
||||
node/transaction.cpp \
|
||||
node/interface_ui.cpp \
|
||||
noui.cpp \
|
||||
policy/fees.cpp \
|
||||
policy/fees_args.cpp \
|
||||
@ -402,8 +402,8 @@ libbitcoin_node_a_SOURCES = \
|
||||
rpc/fees.cpp \
|
||||
rpc/mempool.cpp \
|
||||
rpc/mining.cpp \
|
||||
rpc/node.cpp \
|
||||
rpc/net.cpp \
|
||||
rpc/node.cpp \
|
||||
rpc/output_script.cpp \
|
||||
rpc/rawtransaction.cpp \
|
||||
rpc/server.cpp \
|
||||
|
||||
47
src/init.cpp
47
src/init.cpp
@ -31,7 +31,6 @@
|
||||
#include <interfaces/init.h>
|
||||
#include <interfaces/node.h>
|
||||
#include <mapport.h>
|
||||
#include <mempool_args.h>
|
||||
#include <net.h>
|
||||
#include <net_permissions.h>
|
||||
#include <net_processing.h>
|
||||
@ -42,6 +41,7 @@
|
||||
#include <node/chainstate.h>
|
||||
#include <node/context.h>
|
||||
#include <node/interface_ui.h>
|
||||
#include <node/mempool_args.h>
|
||||
#include <node/mempool_persist_args.h>
|
||||
#include <node/miner.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());
|
||||
}
|
||||
|
||||
// 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
|
||||
int64_t nPruneArg = args.GetIntArg("-prune", 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."));
|
||||
}
|
||||
|
||||
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
|
||||
// TODO: Harmonize which arguments need sanity checking and where that happens
|
||||
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);
|
||||
|
||||
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):
|
||||
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(),
|
||||
.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);
|
||||
|
||||
int64_t descendant_limit_bytes = mempool_opts.limits.descendant_size_vbytes * 40;
|
||||
|
||||
@ -6,8 +6,13 @@
|
||||
|
||||
#include <kernel/mempool_limits.h>
|
||||
|
||||
#include <policy/feerate.h>
|
||||
#include <policy/policy.h>
|
||||
#include <script/standard.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
class CBlockPolicyEstimator;
|
||||
|
||||
@ -33,6 +38,20 @@ struct MemPoolOptions {
|
||||
int check_ratio{0};
|
||||
int64_t max_size_bytes{DEFAULT_MAX_MEMPOOL_SIZE_MB * 1'000'000};
|
||||
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};
|
||||
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) {
|
||||
CAmount filterToSend = g_filter_rounder.round(currentFilter);
|
||||
// We always have a fee filter of at least minRelayTxFee
|
||||
filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
|
||||
// We always have a fee filter of at least the min relay fee
|
||||
filterToSend = std::max(filterToSend, m_mempool.m_min_relay_feerate.GetFeePerK());
|
||||
if (filterToSend != peer.m_fee_filter_sent) {
|
||||
m_connman.PushMessage(&pto, CNetMsgMaker(pto.GetCommonVersion()).Make(NetMsgType::FEEFILTER, filterToSend));
|
||||
peer.m_fee_filter_sent = filterToSend;
|
||||
|
||||
@ -301,7 +301,11 @@ public:
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
JSONRPCRequest req;
|
||||
@ -676,9 +680,21 @@ public:
|
||||
if (!m_node.mempool) return {};
|
||||
return m_node.mempool->GetMinFee();
|
||||
}
|
||||
CFeeRate relayMinFee() override { return ::minRelayTxFee; }
|
||||
CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
|
||||
CFeeRate relayDustFee() override { return ::dustRelayFee; }
|
||||
CFeeRate relayMinFee() override
|
||||
{
|
||||
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
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
|
||||
99
src/node/mempool_args.cpp
Normal file
99
src/node/mempool_args.cpp
Normal file
@ -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
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_MEMPOOL_ARGS_H
|
||||
#define BITCOIN_MEMPOOL_ARGS_H
|
||||
#ifndef BITCOIN_NODE_MEMPOOL_ARGS_H
|
||||
#define BITCOIN_NODE_MEMPOOL_ARGS_H
|
||||
|
||||
#include <optional>
|
||||
|
||||
class ArgsManager;
|
||||
class CChainParams;
|
||||
struct bilingual_str;
|
||||
namespace kernel {
|
||||
struct MemPoolOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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,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
|
||||
@ -137,7 +137,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
||||
|
||||
if (success) {
|
||||
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;
|
||||
// Estimate fee rate
|
||||
CFeeRate feerate(fee, size);
|
||||
|
||||
@ -67,7 +67,7 @@ bool IsDust(const CTxOut& txout, const CFeeRate& 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;
|
||||
whichType = Solver(scriptPubKey, vSolutions);
|
||||
@ -82,15 +82,16 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
|
||||
return false;
|
||||
if (m < 1 || m > n)
|
||||
return false;
|
||||
} else if (whichType == TxoutType::NULL_DATA &&
|
||||
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
|
||||
return false;
|
||||
} else if (whichType == TxoutType::NULL_DATA) {
|
||||
if (!max_datacarrier_bytes || scriptPubKey.size() > *max_datacarrier_bytes) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
reason = "version";
|
||||
@ -130,7 +131,7 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR
|
||||
unsigned int nDataOut = 0;
|
||||
TxoutType whichType;
|
||||
for (const CTxOut& txout : tx.vout) {
|
||||
if (!::IsStandard(txout.scriptPubKey, whichType)) {
|
||||
if (!::IsStandard(txout.scriptPubKey, max_datacarrier_bytes, whichType)) {
|
||||
reason = "scriptpubkey";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -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};
|
||||
/** The maximum size of a standard ScriptSig */
|
||||
static constexpr unsigned int MAX_STANDARD_SCRIPTSIG_SIZE{1650};
|
||||
/** Min feerate for defining dust. Historically this has been based on the
|
||||
* minRelayTxFee, however changing the dust limit changes which transactions are
|
||||
/** Min feerate for defining dust.
|
||||
* Changing the dust limit changes which transactions are
|
||||
* 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
|
||||
* 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 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
|
||||
@ -117,7 +117,7 @@ static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{2};
|
||||
* Check for standard transaction types
|
||||
* @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
|
||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
|
||||
@ -5,11 +5,6 @@
|
||||
|
||||
#include <policy/settings.h>
|
||||
|
||||
#include <policy/feerate.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;
|
||||
|
||||
@ -6,35 +6,6 @@
|
||||
#ifndef 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 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
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include <core_io.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <policy/fees.h>
|
||||
#include <policy/settings.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <rpc/request.h>
|
||||
#include <rpc/server.h>
|
||||
@ -88,7 +87,7 @@ static RPCHelpMan estimatesmartfee()
|
||||
CFeeRate feeRate{fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative)};
|
||||
if (feeRate != CFeeRate(0)) {
|
||||
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});
|
||||
result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
|
||||
} else {
|
||||
|
||||
@ -666,9 +666,9 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool)
|
||||
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
|
||||
ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
|
||||
ret.pushKV("maxmempool", pool.m_max_size_bytes);
|
||||
ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), ::minRelayTxFee).GetFeePerK()));
|
||||
ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
|
||||
ret.pushKV("incrementalrelayfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
|
||||
ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), pool.m_min_relay_feerate).GetFeePerK()));
|
||||
ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_min_relay_feerate.GetFeePerK()));
|
||||
ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_incremental_relay_feerate.GetFeePerK()));
|
||||
ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
|
||||
ret.pushKV("fullrbf", pool.m_full_rbf);
|
||||
return ret;
|
||||
|
||||
@ -645,8 +645,11 @@ static RPCHelpMan getnetworkinfo()
|
||||
obj.pushKV("connections_out", node.connman->GetNodeCount(ConnectionDirection::Out));
|
||||
}
|
||||
obj.pushKV("networks", GetNetworksInfo());
|
||||
obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
|
||||
obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
|
||||
if (node.mempool) {
|
||||
// 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);
|
||||
{
|
||||
LOCK(g_maplocalhost_mutex);
|
||||
|
||||
@ -16,9 +16,6 @@
|
||||
|
||||
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 ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
|
||||
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
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
|
||||
* 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)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))) {
|
||||
(void)GetVirtualTransactionSize(i64, i64, u32);
|
||||
}
|
||||
|
||||
@ -157,12 +157,12 @@ FUZZ_TARGET_INIT(key, initialize_key)
|
||||
assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
|
||||
|
||||
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(which_type_tx_pubkey == TxoutType::PUBKEY);
|
||||
|
||||
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(which_type_tx_multisig == TxoutType::MULTISIG);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// 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 <node/mempool_args.h>
|
||||
#include <policy/rbf.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <sync.h>
|
||||
|
||||
@ -55,7 +55,7 @@ FUZZ_TARGET_INIT(script, initialize_script)
|
||||
}
|
||||
|
||||
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) {
|
||||
assert(which_type == TxoutType::NONSTANDARD ||
|
||||
which_type == TxoutType::NULL_DATA ||
|
||||
|
||||
@ -69,8 +69,8 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
|
||||
|
||||
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
|
||||
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_without_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ false, 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, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
|
||||
if (is_standard_without_permit_bare_multisig) {
|
||||
assert(is_standard_with_permit_bare_multisig);
|
||||
}
|
||||
@ -92,7 +92,6 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
|
||||
(void)GetTransactionWeight(tx);
|
||||
(void)GetVirtualTransactionSize(tx);
|
||||
(void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
|
||||
(void)IsStandardTx(tx, reason);
|
||||
(void)RecursiveDynamicUsage(tx);
|
||||
(void)SignalsOptInRBF(tx);
|
||||
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <consensus/validation.h>
|
||||
#include <mempool_args.h>
|
||||
#include <node/context.h>
|
||||
#include <node/mempool_args.h>
|
||||
#include <node/miner.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
@ -116,7 +116,7 @@ void MockTime(FuzzedDataProvider& fuzzed_data_provider, const CChainState& chain
|
||||
SetMockTime(time);
|
||||
}
|
||||
|
||||
CTxMemPool MakeMempool(const NodeContext& node)
|
||||
CTxMemPool MakeMempool(FuzzedDataProvider& fuzzed_data_provider, const NodeContext& node)
|
||||
{
|
||||
// Take the default options for tests...
|
||||
CTxMemPool::Options mempool_opts{MemPoolOptionsForTest(node)};
|
||||
@ -124,6 +124,7 @@ CTxMemPool MakeMempool(const NodeContext& node)
|
||||
// ...override specific options for this specific fuzz suite
|
||||
mempool_opts.estimator = nullptr;
|
||||
mempool_opts.check_ratio = 1;
|
||||
mempool_opts.require_standard = fuzzed_data_provider.ConsumeBool();
|
||||
|
||||
// ...and construct a CTxMemPool from it
|
||||
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};
|
||||
|
||||
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_);
|
||||
|
||||
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);
|
||||
RegisterSharedValidationInterface(txr);
|
||||
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
|
||||
::fRequireStandard = fuzzed_data_provider.ConsumeBool();
|
||||
|
||||
// Make sure ProcessNewPackage on one transaction works.
|
||||
// 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);
|
||||
CTxMemPool tx_pool_{MakeMempool(node)};
|
||||
CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
|
||||
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
|
||||
|
||||
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 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 bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
|
||||
if (accepted) {
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <kernel/mempool_persist.h>
|
||||
|
||||
#include <chainparamsbase.h>
|
||||
#include <mempool_args.h>
|
||||
#include <node/mempool_args.h>
|
||||
#include <node/mempool_persist_args.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
|
||||
@ -141,23 +141,30 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
|
||||
for (int i = 0; i < 4; i++)
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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];
|
||||
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[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
BOOST_CHECK(!::IsStandard(malformed[i], whichType));
|
||||
for (int i = 0; i < 6; i++) {
|
||||
BOOST_CHECK(!is_standard(malformed[i]));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multisig_Sign)
|
||||
|
||||
@ -18,6 +18,11 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
// 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>
|
||||
Serialize(const CScript& s)
|
||||
{
|
||||
@ -49,7 +54,6 @@ BOOST_FIXTURE_TEST_SUITE(script_p2sh_tests, BasicTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sign)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
// Pay-to-script-hash looks like this:
|
||||
// scriptSig: <sig> <sig...> <serialized_script>
|
||||
// scriptPubKey: HASH160 <hash> EQUAL
|
||||
@ -149,7 +153,6 @@ BOOST_AUTO_TEST_CASE(norecurse)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(set)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
// Test the CScript::Set* methods
|
||||
FillableSigningProvider keystore;
|
||||
CKey key[4];
|
||||
@ -263,7 +266,6 @@ BOOST_AUTO_TEST_CASE(switchover)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CCoinsView coinsDummy;
|
||||
CCoinsViewCache coins(&coinsDummy);
|
||||
FillableSigningProvider keystore;
|
||||
|
||||
@ -40,6 +40,9 @@ typedef std::vector<unsigned char> valtype;
|
||||
// In script_tests.cpp
|
||||
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 = {
|
||||
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
|
||||
{std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC},
|
||||
@ -745,7 +748,6 @@ BOOST_AUTO_TEST_CASE(test_witness)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
FillableSigningProvider keystore;
|
||||
CCoinsView coinsDummy;
|
||||
CCoinsViewCache coins(&coinsDummy);
|
||||
@ -765,19 +767,19 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||
|
||||
constexpr auto CheckIsStandard = [](const auto& t) {
|
||||
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());
|
||||
};
|
||||
constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in) {
|
||||
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);
|
||||
};
|
||||
|
||||
CheckIsStandard(t);
|
||||
|
||||
// Check dust with default relay fee:
|
||||
CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK() / 1000;
|
||||
CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;
|
||||
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
||||
// dust:
|
||||
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:
|
||||
// nDustThreshold = 182 * 3702 / 1000
|
||||
dustRelayFee = CFeeRate(3702);
|
||||
g_dust = CFeeRate(3702);
|
||||
// dust:
|
||||
t.vout[0].nValue = 674 - 1;
|
||||
CheckIsNotStandard(t, "dust");
|
||||
// not dust:
|
||||
t.vout[0].nValue = 674;
|
||||
CheckIsStandard(t);
|
||||
dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
||||
g_dust = CFeeRate{DUST_RELAY_TX_FEE};
|
||||
|
||||
t.vout[0].scriptPubKey = CScript() << OP_1;
|
||||
CheckIsNotStandard(t, "scriptpubkey");
|
||||
@ -924,16 +926,16 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||
BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
|
||||
CheckIsNotStandard(t, "tx-size");
|
||||
|
||||
// Check bare multisig (standard if policy flag fIsBareMultisigStd is set)
|
||||
fIsBareMultisigStd = true;
|
||||
// Check bare multisig (standard if policy flag g_bare_multi is set)
|
||||
g_bare_multi = true;
|
||||
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
|
||||
t.vin.resize(1);
|
||||
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
|
||||
CheckIsStandard(t);
|
||||
|
||||
fIsBareMultisigStd = false;
|
||||
g_bare_multi = false;
|
||||
CheckIsNotStandard(t, "bare-multisig");
|
||||
fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
||||
g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;
|
||||
|
||||
// Check P2WPKH outputs dust threshold
|
||||
t.vout[0].scriptPubKey = CScript() << OP_0 << ParseHex("ffffffffffffffffffffffffffffffffffffffff");
|
||||
|
||||
@ -14,12 +14,12 @@
|
||||
#include <init.h>
|
||||
#include <init/common.h>
|
||||
#include <interfaces/chain.h>
|
||||
#include <mempool_args.h>
|
||||
#include <net.h>
|
||||
#include <net_processing.h>
|
||||
#include <node/blockstorage.h>
|
||||
#include <node/chainstate.h>
|
||||
#include <node/context.h>
|
||||
#include <node/mempool_args.h>
|
||||
#include <node/miner.h>
|
||||
#include <noui.h>
|
||||
#include <policy/fees.h>
|
||||
@ -160,7 +160,8 @@ CTxMemPool::Options MemPoolOptionsForTest(const NodeContext& node)
|
||||
// chainparams.DefaultConsistencyChecks for tests
|
||||
.check_ratio = 1,
|
||||
};
|
||||
ApplyArgsManOptions(*node.args, mempool_opts);
|
||||
const auto err{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)};
|
||||
Assert(!err);
|
||||
return mempool_opts;
|
||||
}
|
||||
|
||||
|
||||
@ -106,7 +106,7 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
|
||||
|
||||
size_t CTxMemPoolEntry::GetTxSize() const
|
||||
{
|
||||
return GetVirtualTransactionSize(nTxWeight, sigOpCost);
|
||||
return GetVirtualTransactionSize(nTxWeight, sigOpCost, ::nBytesPerSigOp);
|
||||
}
|
||||
|
||||
void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendants,
|
||||
@ -458,6 +458,12 @@ CTxMemPool::CTxMemPool(const Options& opts)
|
||||
minerPolicyEstimator{opts.estimator},
|
||||
m_max_size_bytes{opts.max_size_bytes},
|
||||
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_limits{opts.limits}
|
||||
{
|
||||
@ -1117,12 +1123,12 @@ CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
|
||||
rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
|
||||
lastRollingFeeUpdate = time;
|
||||
|
||||
if (rollingMinimumFeeRate < (double)incrementalRelayFee.GetFeePerK() / 2) {
|
||||
if (rollingMinimumFeeRate < (double)m_incremental_relay_feerate.GetFeePerK() / 2) {
|
||||
rollingMinimumFeeRate = 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) {
|
||||
@ -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
|
||||
// equal to txn which were removed with no block in between.
|
||||
CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
|
||||
removed += incrementalRelayFee;
|
||||
removed += m_incremental_relay_feerate;
|
||||
trackPackageRemoved(removed);
|
||||
maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
|
||||
|
||||
|
||||
@ -568,6 +568,12 @@ public:
|
||||
|
||||
const int64_t m_max_size_bytes;
|
||||
const std::chrono::seconds m_expiry;
|
||||
const CFeeRate m_incremental_relay_feerate;
|
||||
const CFeeRate m_min_relay_feerate;
|
||||
const CFeeRate m_dust_relay_feerate;
|
||||
const bool m_permit_bare_multisig;
|
||||
const std::optional<unsigned> m_max_datacarrier_bytes;
|
||||
const bool m_require_standard;
|
||||
const bool m_full_rbf;
|
||||
|
||||
using Limits = kernel::MemPoolLimits;
|
||||
@ -702,11 +708,11 @@ public:
|
||||
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
|
||||
* for larger-sized transactions.
|
||||
* The incrementalRelayFee 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
|
||||
* would otherwise be half of this, it is set to 0 instead.
|
||||
*/
|
||||
* for larger-sized transactions.
|
||||
* 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
|
||||
* would otherwise be half of this, it is set to 0 instead.
|
||||
*/
|
||||
CFeeRate GetMinFee() const {
|
||||
return GetMinFee(m_max_size_bytes);
|
||||
}
|
||||
|
||||
@ -124,7 +124,6 @@ GlobalMutex g_best_block_mutex;
|
||||
std::condition_variable g_best_block_cv;
|
||||
uint256 g_best_block;
|
||||
bool g_parallel_script_checks{false};
|
||||
bool fRequireStandard = true;
|
||||
bool fCheckBlockIndex = false;
|
||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
||||
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));
|
||||
}
|
||||
|
||||
if (package_fee < ::minRelayTxFee.GetFee(package_size)) {
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met", strprintf("%d < %d", 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, m_pool.m_min_relay_feerate.GetFee(package_size)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -700,8 +700,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
|
||||
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
||||
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);
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -807,13 +808,14 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
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");
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
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",
|
||||
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
|
||||
// package feerate later.
|
||||
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();
|
||||
}
|
||||
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 true;
|
||||
|
||||
@ -100,7 +100,6 @@ extern uint256 g_best_block;
|
||||
* False indicates all script checking is done on the main threadMessageHandler thread.
|
||||
*/
|
||||
extern bool g_parallel_script_checks;
|
||||
extern bool fRequireStandard;
|
||||
extern bool fCheckBlockIndex;
|
||||
extern bool fCheckpointsEnabled;
|
||||
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
|
||||
|
||||
@ -87,7 +87,7 @@ CFeeRate GetDiscardRate(const CWallet& wallet)
|
||||
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
|
||||
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());
|
||||
return discard_rate;
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||
self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
|
||||
# self.old_node sets only 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_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)
|
||||
@ -1382,7 +1382,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||
tx3.vout.append(CTxOut(total_value - 1000, script_pubkey))
|
||||
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
|
||||
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")
|
||||
@ -1390,7 +1390,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||
self.std_node.announce_tx_and_wait_for_getdata(tx3, success=False)
|
||||
|
||||
# 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")
|
||||
|
||||
# Building a block with the transaction must be valid, however.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user