Merge maxscriptsize-28+knots

This commit is contained in:
Luke Dashjr 2025-03-05 03:27:08 +00:00
commit 574d3ab59c
4 changed files with 26 additions and 3 deletions

View File

@ -690,6 +690,7 @@ void SetupServerArgs(ArgsManager& argsman)
strprintf("Maximum size of data in data carrier transactions we relay and mine, in bytes (default: %u)", strprintf("Maximum size of data in data carrier transactions we relay and mine, in bytes (default: %u)",
MAX_OP_RETURN_RELAY), MAX_OP_RETURN_RELAY),
ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-maxscriptsize", strprintf("Maximum size of scripts we relay and mine, in bytes (default: %s)", DEFAULT_SCRIPT_SIZE_POLICY_LIMIT), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-mempoolfullrbf", strprintf("Accept transaction replace-by-fee without requiring replaceability signaling (default: %u)", (DEFAULT_MEMPOOL_RBF_POLICY == RBFPolicy::Always)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-mempoolfullrbf", strprintf("Accept transaction replace-by-fee without requiring replaceability signaling (default: %u)", (DEFAULT_MEMPOOL_RBF_POLICY == RBFPolicy::Always)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-mempoolreplacement", strprintf("Set to 0 to disable RBF entirely, \"fee,optin\" to honour RBF opt-out signal, or \"fee,-optin\" to always RBF aka full RBF (default: %s)", "fee,-optin"), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-mempoolreplacement", strprintf("Set to 0 to disable RBF entirely, \"fee,optin\" to honour RBF opt-out signal, or \"fee,-optin\" to always RBF aka full RBF (default: %s)", "fee,-optin"), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-mempooltruc", strprintf("Behaviour for transactions requesting TRUC limits: \"reject\" the transactions entirely, \"accept\" them just like any other, or \"enforce\" to impose their requested restrictions (default: %s)", "enforce"), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-mempooltruc", strprintf("Behaviour for transactions requesting TRUC limits: \"reject\" the transactions entirely, \"accept\" them just like any other, or \"enforce\" to impose their requested restrictions (default: %s)", "enforce"), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
@ -1101,6 +1102,8 @@ bool AppInitParameterInteraction(const ArgsManager& args)
g_weight_per_data_byte = ((*parsed * WITNESS_SCALE_FACTOR) + 99) / 100; g_weight_per_data_byte = ((*parsed * WITNESS_SCALE_FACTOR) + 99) / 100;
} }
g_script_size_policy_limit = args.GetIntArg("-maxscriptsize", g_script_size_policy_limit);
nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp); nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
nBytesPerSigOpStrict = args.GetIntArg("-bytespersigopstrict", nBytesPerSigOpStrict); nBytesPerSigOpStrict = args.GetIntArg("-bytespersigopstrict", nBytesPerSigOpStrict);

View File

@ -13,6 +13,7 @@
#include <consensus/validation.h> #include <consensus/validation.h>
#include <kernel/mempool_options.h> #include <kernel/mempool_options.h>
#include <policy/feerate.h> #include <policy/feerate.h>
#include <policy/settings.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <script/interpreter.h> #include <script/interpreter.h>
#include <script/script.h> #include <script/script.h>
@ -25,6 +26,8 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
unsigned int g_script_size_policy_limit{DEFAULT_SCRIPT_SIZE_POLICY_LIMIT};
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
{ {
// "Dust" is defined in terms of dustRelayFee, // "Dust" is defined in terms of dustRelayFee,
@ -143,7 +146,7 @@ bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, st
// some minor future-proofing. That's also enough to spend a // some minor future-proofing. That's also enough to spend a
// 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey // 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey
// is not considered standard. // is not considered standard.
if (txin.scriptSig.size() > MAX_STANDARD_SCRIPTSIG_SIZE) { if (txin.scriptSig.size() > std::min(MAX_STANDARD_SCRIPTSIG_SIZE, g_script_size_policy_limit)) {
MaybeReject("scriptsig-size"); MaybeReject("scriptsig-size");
} }
if (!txin.scriptSig.IsPushOnly()) { if (!txin.scriptSig.IsPushOnly()) {
@ -154,6 +157,10 @@ bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, st
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 (txout.scriptPubKey.size() > g_script_size_policy_limit) {
MaybeReject("scriptpubkey-size");
}
if (!::IsStandard(txout.scriptPubKey, opts.max_datacarrier_bytes, whichType)) { if (!::IsStandard(txout.scriptPubKey, opts.max_datacarrier_bytes, whichType)) {
if (whichType == TxoutType::WITNESS_UNKNOWN) { if (whichType == TxoutType::WITNESS_UNKNOWN) {
MaybeReject("scriptpubkey-unknown-witnessversion"); MaybeReject("scriptpubkey-unknown-witnessversion");
@ -215,6 +222,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
for (unsigned int i = 0; i < tx.vin.size(); i++) { for (unsigned int i = 0; i < tx.vin.size(); i++) {
const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out; const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
if (prev.scriptPubKey.size() > g_script_size_policy_limit) {
MaybeReject("script-size");
}
std::vector<std::vector<unsigned char> > vSolutions; std::vector<std::vector<unsigned char> > vSolutions;
TxoutType whichType = Solver(prev.scriptPubKey, vSolutions); TxoutType whichType = Solver(prev.scriptPubKey, vSolutions);
if (whichType == TxoutType::NONSTANDARD) { if (whichType == TxoutType::NONSTANDARD) {
@ -247,6 +258,9 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
return false; return false;
} }
CScript subscript(stack.back().begin(), stack.back().end()); CScript subscript(stack.back().begin(), stack.back().end());
if (subscript.size() > g_script_size_policy_limit) {
MaybeReject("scriptcheck-size");
}
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) { if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
MaybeReject("scriptcheck-sigops"); MaybeReject("scriptcheck-sigops");
} }
@ -310,7 +324,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
// Check P2WSH standard limits // Check P2WSH standard limits
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) { if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
if (tx.vin[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE) if (tx.vin[i].scriptWitness.stack.back().size() > std::min(MAX_STANDARD_P2WSH_SCRIPT_SIZE, g_script_size_policy_limit))
MaybeReject("script-size"); MaybeReject("script-size");
size_t sizeWitnessStack = tx.vin[i].scriptWitness.stack.size() - 1; size_t sizeWitnessStack = tx.vin[i].scriptWitness.stack.size() - 1;
if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS) if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS)
@ -336,12 +350,15 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
if (stack.size() >= 2) { if (stack.size() >= 2) {
// Script path spend (2 or more stack elements after removing optional annex) // Script path spend (2 or more stack elements after removing optional annex)
const auto& control_block = SpanPopBack(stack); const auto& control_block = SpanPopBack(stack);
SpanPopBack(stack); // Ignore script const auto& tapscript = SpanPopBack(stack);
if (control_block.empty()) { if (control_block.empty()) {
// Empty control block is invalid // Empty control block is invalid
out_reason = reason_prefix + "taproot-control-missing"; out_reason = reason_prefix + "taproot-control-missing";
return false; return false;
} }
if (tapscript.size() > g_script_size_policy_limit) {
MaybeReject("script-size");
}
if ((control_block[0] & TAPROOT_LEAF_MASK) == TAPROOT_LEAF_TAPSCRIPT) { if ((control_block[0] & TAPROOT_LEAF_MASK) == TAPROOT_LEAF_TAPSCRIPT) {
// Leaf version 0xc0 (aka Tapscript, see BIP 342) // Leaf version 0xc0 (aka Tapscript, see BIP 342)
if (!ignore_rejects.count(reason_prefix + "taproot-stackitem-size")) { if (!ignore_rejects.count(reason_prefix + "taproot-stackitem-size")) {

View File

@ -44,6 +44,8 @@ static constexpr unsigned int MAX_P2SH_SIGOPS{15};
static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5}; static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5};
/** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/ /** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/
static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000}; static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000};
/** Default for -maxscriptsize */
static constexpr unsigned int DEFAULT_SCRIPT_SIZE_POLICY_LIMIT{std::numeric_limits<unsigned int>::max()};
/** Default for -bytespersigop */ /** Default for -bytespersigop */
static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20}; static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20};
/** Default for -bytespersigopstrict */ /** Default for -bytespersigopstrict */

View File

@ -6,6 +6,7 @@
#ifndef BITCOIN_POLICY_SETTINGS_H #ifndef BITCOIN_POLICY_SETTINGS_H
#define BITCOIN_POLICY_SETTINGS_H #define BITCOIN_POLICY_SETTINGS_H
extern unsigned int g_script_size_policy_limit;
extern unsigned int nBytesPerSigOp; extern unsigned int nBytesPerSigOp;
extern unsigned int nBytesPerSigOpStrict; extern unsigned int nBytesPerSigOpStrict;
extern unsigned int g_weight_per_data_byte; extern unsigned int g_weight_per_data_byte;