Merge acceptnonstddatacarrier-28+knots

This commit is contained in:
Luke Dashjr 2025-03-05 03:27:08 +00:00
commit 48c848e044
9 changed files with 64 additions and 38 deletions

View File

@ -669,6 +669,10 @@ void SetupServerArgs(ArgsManager& argsman)
SetupChainParamsBaseOptions(argsman); SetupChainParamsBaseOptions(argsman);
argsman.AddArg("-acceptnonstddatacarrier",
strprintf("Relay and mine non-OP_RETURN datacarrier injection (default: %u)",
DEFAULT_ACCEPT_NON_STD_DATACARRIER),
ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (default: %u)", DEFAULT_ACCEPT_NON_STD_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (default: %u)", DEFAULT_ACCEPT_NON_STD_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define cost of relay, used for mempool limiting and replacement policy. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY); argsman.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define cost of relay, used for mempool limiting and replacement policy. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);

View File

@ -32,6 +32,8 @@ static constexpr RBFPolicy DEFAULT_MEMPOOL_RBF_POLICY{RBFPolicy::Always};
static constexpr TRUCPolicy DEFAULT_MEMPOOL_TRUC_POLICY{TRUCPolicy::Enforce}; static constexpr TRUCPolicy DEFAULT_MEMPOOL_TRUC_POLICY{TRUCPolicy::Enforce};
/** Whether to fall back to legacy V1 serialization when writing mempool.dat */ /** Whether to fall back to legacy V1 serialization when writing mempool.dat */
static constexpr bool DEFAULT_PERSIST_V1_DAT{false}; static constexpr bool DEFAULT_PERSIST_V1_DAT{false};
/** Default for -acceptnonstddatacarrier */
static constexpr bool DEFAULT_ACCEPT_NON_STD_DATACARRIER{true};
/** Default for -acceptnonstdtxn */ /** Default for -acceptnonstdtxn */
static constexpr bool DEFAULT_ACCEPT_NON_STD_TXN{false}; static constexpr bool DEFAULT_ACCEPT_NON_STD_TXN{false};
@ -71,6 +73,7 @@ struct MemPoolOptions {
bool datacarrier_fullcount{DEFAULT_DATACARRIER_FULLCOUNT}; bool datacarrier_fullcount{DEFAULT_DATACARRIER_FULLCOUNT};
bool permit_bare_pubkey{DEFAULT_PERMIT_BAREPUBKEY}; bool permit_bare_pubkey{DEFAULT_PERMIT_BAREPUBKEY};
bool permit_bare_multisig{DEFAULT_PERMIT_BAREMULTISIG}; bool permit_bare_multisig{DEFAULT_PERMIT_BAREMULTISIG};
bool accept_non_std_datacarrier{DEFAULT_ACCEPT_NON_STD_DATACARRIER};
bool require_standard{true}; bool require_standard{true};
RBFPolicy rbf_policy{DEFAULT_MEMPOOL_RBF_POLICY}; RBFPolicy rbf_policy{DEFAULT_MEMPOOL_RBF_POLICY};
TRUCPolicy truc_policy{DEFAULT_MEMPOOL_TRUC_POLICY}; TRUCPolicy truc_policy{DEFAULT_MEMPOOL_TRUC_POLICY};

View File

@ -152,6 +152,7 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& argsman, const CChainP
mempool_opts.max_datacarrier_bytes = std::nullopt; mempool_opts.max_datacarrier_bytes = std::nullopt;
} }
mempool_opts.datacarrier_fullcount = argsman.GetBoolArg("-datacarrierfullcount", DEFAULT_DATACARRIER_FULLCOUNT); mempool_opts.datacarrier_fullcount = argsman.GetBoolArg("-datacarrierfullcount", DEFAULT_DATACARRIER_FULLCOUNT);
mempool_opts.accept_non_std_datacarrier = argsman.GetBoolArg("-acceptnonstddatacarrier", DEFAULT_ACCEPT_NON_STD_DATACARRIER);
mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", DEFAULT_ACCEPT_NON_STD_TXN); mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", DEFAULT_ACCEPT_NON_STD_TXN);

View File

@ -22,6 +22,7 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <utility>
#include <vector> #include <vector>
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
@ -420,17 +421,21 @@ std::pair<CScript, unsigned int> GetScriptForTransactionInput(CScript prevScript
return std::make_pair(CScript(), 0); return std::make_pair(CScript(), 0);
} }
size_t DatacarrierBytes(const CTransaction& tx, const CCoinsViewCache& view) std::pair<size_t, size_t> DatacarrierBytes(const CTransaction& tx, const CCoinsViewCache& view)
{ {
size_t ret{0}; std::pair<size_t, size_t> ret{0, 0};
for (const CTxIn& txin : tx.vin) { for (const CTxIn& txin : tx.vin) {
const CTxOut &utxo = view.AccessCoin(txin.prevout).out; const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin); auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
ret += script.DatacarrierBytes(); const auto dcb = script.DatacarrierBytes();
ret.first += dcb.first;
ret.second += dcb.second;
} }
for (const CTxOut& txout : tx.vout) { for (const CTxOut& txout : tx.vout) {
ret += txout.scriptPubKey.DatacarrierBytes(); const auto dcb = txout.scriptPubKey.DatacarrierBytes();
ret.first += dcb.first;
ret.second += dcb.second;
} }
return ret; return ret;
@ -446,12 +451,14 @@ int32_t CalculateExtraTxWeight(const CTransaction& tx, const CCoinsViewCache& vi
const CTxOut &utxo = view.AccessCoin(txin.prevout).out; const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin); auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
if (weight_per_data_byte > consensus_weight_per_byte) { if (weight_per_data_byte > consensus_weight_per_byte) {
mod_weight += script.DatacarrierBytes() * (weight_per_data_byte - consensus_weight_per_byte); const auto dcb = script.DatacarrierBytes();
mod_weight += (dcb.first + dcb.second) * (weight_per_data_byte - consensus_weight_per_byte);
} }
} }
if (weight_per_data_byte > WITNESS_SCALE_FACTOR) { if (weight_per_data_byte > WITNESS_SCALE_FACTOR) {
for (const CTxOut& txout : tx.vout) { for (const CTxOut& txout : tx.vout) {
mod_weight += txout.scriptPubKey.DatacarrierBytes() * (weight_per_data_byte - WITNESS_SCALE_FACTOR); const auto dcb = txout.scriptPubKey.DatacarrierBytes();
mod_weight += (dcb.first + dcb.second) * (weight_per_data_byte - WITNESS_SCALE_FACTOR);
} }
} }
} }

View File

@ -201,7 +201,7 @@ static inline int64_t GetVirtualTransactionInputSize(const CTxIn& tx)
std::pair<CScript, unsigned int> GetScriptForTransactionInput(CScript prevScript, const CTxIn&); std::pair<CScript, unsigned int> GetScriptForTransactionInput(CScript prevScript, const CTxIn&);
size_t DatacarrierBytes(const CTransaction& tx, const CCoinsViewCache& view); std::pair<size_t, size_t> DatacarrierBytes(const CTransaction& tx, const CCoinsViewCache& view);
int32_t CalculateExtraTxWeight(const CTransaction& tx, const CCoinsViewCache& view, const unsigned int weight_per_data_byte); int32_t CalculateExtraTxWeight(const CTransaction& tx, const CCoinsViewCache& view, const unsigned int weight_per_data_byte);

View File

@ -303,7 +303,7 @@ bool CScript::HasValidOps() const
return true; return true;
} }
size_t CScript::DatacarrierBytes() const std::pair<size_t, size_t> CScript::DatacarrierBytes() const
{ {
size_t counted{0}; size_t counted{0};
opcodetype opcode, last_opcode{OP_INVALIDOPCODE}; opcodetype opcode, last_opcode{OP_INVALIDOPCODE};
@ -314,17 +314,17 @@ size_t CScript::DatacarrierBytes() const
opcode_it = it; opcode_it = it;
if (!GetOp(it, opcode, push_data)) { if (!GetOp(it, opcode, push_data)) {
// Invalid scripts are necessarily all data // Invalid scripts are necessarily all data
return size(); return {0, size()};
} }
if (opcode == OP_IF || opcode == OP_NOTIF) { if (opcode == OP_IF || opcode == OP_NOTIF) {
++inside_conditional; ++inside_conditional;
} else if (opcode == OP_ENDIF) { } else if (opcode == OP_ENDIF) {
if (!inside_conditional) return size(); // invalid if (!inside_conditional) return {0, size()}; // invalid
--inside_conditional; --inside_conditional;
} else if (opcode == OP_RETURN && !inside_conditional) { } else if (opcode == OP_RETURN && !inside_conditional) {
// unconditional OP_RETURN is unspendable // unconditional OP_RETURN is unspendable
return size(); return {size(), 0};
} }
// Match OP_FALSE OP_IF // Match OP_FALSE OP_IF
@ -350,7 +350,7 @@ size_t CScript::DatacarrierBytes() const
counted += it - data_began; counted += it - data_began;
} }
} }
return counted; return {0, counted};
} }
bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet) bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)

View File

@ -562,7 +562,7 @@ public:
return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE); return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE);
} }
size_t DatacarrierBytes() const; std::pair<size_t, size_t> DatacarrierBytes() const;
void clear() void clear()
{ {

View File

@ -1505,28 +1505,33 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps)
BOOST_CHECK(!script.HasValidOps()); BOOST_CHECK(!script.HasValidOps());
} }
static std::string DatacarrierBytesStr(const CScript &script) {
auto dcb = script.DatacarrierBytes();
return strprintf("%s+%s", dcb.first, dcb.second);
}
BOOST_AUTO_TEST_CASE(script_DataCarrierBytes) BOOST_AUTO_TEST_CASE(script_DataCarrierBytes)
{ {
using zeros = std::vector<unsigned char>; using zeros = std::vector<unsigned char>;
// empty script // empty script
BOOST_CHECK_EQUAL(0, (CScript()).DatacarrierBytes()); BOOST_CHECK_EQUAL("0+0", DatacarrierBytesStr(CScript()));
// series of pushes are not data // series of pushes are not data
BOOST_CHECK_EQUAL(0, (CScript() << OP_0 << OP_0 << OP_0).DatacarrierBytes()); BOOST_CHECK_EQUAL("0+0", DatacarrierBytesStr(CScript() << OP_0 << OP_0 << OP_0));
// unspendable if first op is OP_RETURN, then length(1), zeros(11) // unspendable if first op is OP_RETURN, then length(1), zeros(11)
BOOST_CHECK_EQUAL(13, (CScript() << OP_RETURN << zeros(11)).DatacarrierBytes()); BOOST_CHECK_EQUAL("13+0", DatacarrierBytesStr(CScript() << OP_RETURN << zeros(11)));
// invalid script (no data following PUSHDATA) makes it all data // invalid script (no data following PUSHDATA) makes it all data
BOOST_CHECK_EQUAL(2, (CScript() << OP_0 << OP_PUSHDATA4).DatacarrierBytes()); BOOST_CHECK_EQUAL("0+2", DatacarrierBytesStr(CScript() << OP_0 << OP_PUSHDATA4));
// no data here // no data here
BOOST_CHECK_EQUAL(0, (CScript() << OP_TRUE << OP_IF << OP_ENDIF).DatacarrierBytes()); BOOST_CHECK_EQUAL("0+0", DatacarrierBytesStr(CScript() << OP_TRUE << OP_IF << OP_ENDIF));
// specific data pattern, entire script is data // specific data pattern, entire script is data
BOOST_CHECK_EQUAL(4, (CScript() << OP_FALSE << OP_IF << OP_7 << OP_ENDIF).DatacarrierBytes()); BOOST_CHECK_EQUAL("0+4", DatacarrierBytesStr(CScript() << OP_FALSE << OP_IF << OP_7 << OP_ENDIF));
// consecutive data // consecutive data
BOOST_CHECK_EQUAL(6, (CScript() << OP_FALSE << OP_IF << OP_ENDIF << OP_FALSE << OP_IF << OP_ENDIF).DatacarrierBytes()); BOOST_CHECK_EQUAL("0+6", DatacarrierBytesStr(CScript() << OP_FALSE << OP_IF << OP_ENDIF << OP_FALSE << OP_IF << OP_ENDIF));
// nested data (all is data) // nested data (all is data)
BOOST_CHECK_EQUAL(6, (CScript() << OP_FALSE << OP_IF << OP_TRUE << OP_IF << OP_ENDIF << OP_ENDIF).DatacarrierBytes()); BOOST_CHECK_EQUAL("0+6", DatacarrierBytesStr(CScript() << OP_FALSE << OP_IF << OP_TRUE << OP_IF << OP_ENDIF << OP_ENDIF));
// pushing then immediately dropping is data: length(1), zero(11), OP_DROP // pushing then immediately dropping is data: length(1), zero(11), OP_DROP
BOOST_CHECK_EQUAL(13, (CScript() << zeros(11) << OP_DROP).DatacarrierBytes()); BOOST_CHECK_EQUAL("0+13", DatacarrierBytesStr(CScript() << zeros(11) << OP_DROP));
} }
BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput) BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
@ -1541,7 +1546,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in); auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in);
BOOST_CHECK(ret_script == tx_in.scriptSig); BOOST_CHECK(ret_script == tx_in.scriptSig);
BOOST_CHECK_EQUAL(scale, WITNESS_SCALE_FACTOR); BOOST_CHECK_EQUAL(scale, WITNESS_SCALE_FACTOR);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2PKH - no datacarrier bytes { // P2PKH - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1552,7 +1557,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in); auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in);
BOOST_CHECK(ret_script == tx_in.scriptSig); BOOST_CHECK(ret_script == tx_in.scriptSig);
BOOST_CHECK_EQUAL(scale, WITNESS_SCALE_FACTOR); BOOST_CHECK_EQUAL(scale, WITNESS_SCALE_FACTOR);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2SH - no datacarrier bytes { // P2SH - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1565,7 +1570,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in); auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in);
BOOST_CHECK(ret_script == redeem_script); BOOST_CHECK(ret_script == redeem_script);
BOOST_CHECK_EQUAL(scale, WITNESS_SCALE_FACTOR); BOOST_CHECK_EQUAL(scale, WITNESS_SCALE_FACTOR);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2SH - with datacarrier bytes { // P2SH - with datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1580,7 +1585,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
BOOST_CHECK(ret_script == redeem_script); BOOST_CHECK(ret_script == redeem_script);
BOOST_CHECK_EQUAL(scale, WITNESS_SCALE_FACTOR); BOOST_CHECK_EQUAL(scale, WITNESS_SCALE_FACTOR);
// OP_RETURN(1), length(1), zeros(27) = 29 // OP_RETURN(1), length(1), zeros(27) = 29
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 29); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "29+0");
} }
{ // P2WPKH - no datacarrier bytes { // P2WPKH - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1596,7 +1601,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
// should have no script at all since it's wrapped P2WPKH // should have no script at all since it's wrapped P2WPKH
BOOST_CHECK(ret_script == CScript()); BOOST_CHECK(ret_script == CScript());
BOOST_CHECK_EQUAL(scale, 0); BOOST_CHECK_EQUAL(scale, 0);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2WSH - no datacarrier bytes { // P2WSH - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1612,7 +1617,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in); auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in);
BOOST_CHECK(ret_script == redeem_script); BOOST_CHECK(ret_script == redeem_script);
BOOST_CHECK_EQUAL(scale, 1); BOOST_CHECK_EQUAL(scale, 1);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2WSH - some datacarrier bytes { // P2WSH - some datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1629,7 +1634,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
BOOST_CHECK(ret_script == redeem_script); BOOST_CHECK(ret_script == redeem_script);
BOOST_CHECK_EQUAL(scale, 1); BOOST_CHECK_EQUAL(scale, 1);
// OP_FALSE(1), OP_IF(1), length(1), zeros(10), OP_ENDIF(1) // OP_FALSE(1), OP_IF(1), length(1), zeros(10), OP_ENDIF(1)
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 14); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+14");
} }
{ // P2SH-P2WPKH - no datacarrier bytes { // P2SH-P2WPKH - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1644,7 +1649,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
BOOST_CHECK(ret_script == CScript()); BOOST_CHECK(ret_script == CScript());
// data bytes in the witness get discounted (*1 instead of *4) // data bytes in the witness get discounted (*1 instead of *4)
BOOST_CHECK_EQUAL(scale, 0); BOOST_CHECK_EQUAL(scale, 0);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2SH-P2WSH - no datacarrier bytes { // P2SH-P2WSH - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1668,7 +1673,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
BOOST_CHECK(ret_script == witness_redeem_script); BOOST_CHECK(ret_script == witness_redeem_script);
// data bytes in the witness get discounted (*1 instead of *4) // data bytes in the witness get discounted (*1 instead of *4)
BOOST_CHECK_EQUAL(scale, 1); BOOST_CHECK_EQUAL(scale, 1);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2SH-P2WSH - some datacarrier bytes { // P2SH-P2WSH - some datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1693,7 +1698,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
// data bytes in the witness get discounted (*1 instead of *4) // data bytes in the witness get discounted (*1 instead of *4)
BOOST_CHECK_EQUAL(scale, 1); BOOST_CHECK_EQUAL(scale, 1);
// OP_FALSE(1), OP_IF(1), length(1), zeros(10), OP_ENDIF(1) = 14 // OP_FALSE(1), OP_IF(1), length(1), zeros(10), OP_ENDIF(1) = 14
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 14); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+14");
} }
{ // P2TR keypath - no datacarrier bytes { // P2TR keypath - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1705,7 +1710,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in); auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in);
BOOST_CHECK(ret_script == CScript()); BOOST_CHECK(ret_script == CScript());
BOOST_CHECK_EQUAL(scale, 0); BOOST_CHECK_EQUAL(scale, 0);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2TR keypath - annex but no script - no datacarrier bytes { // P2TR keypath - annex but no script - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1719,7 +1724,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in); auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in);
BOOST_CHECK(ret_script == CScript()); BOOST_CHECK(ret_script == CScript());
BOOST_CHECK_EQUAL(scale, 0); BOOST_CHECK_EQUAL(scale, 0);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2TR scriptpath - no datacarrier bytes { // P2TR scriptpath - no datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1738,7 +1743,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in); auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in);
BOOST_CHECK(ret_script == script); BOOST_CHECK(ret_script == script);
BOOST_CHECK_EQUAL(scale, 1); BOOST_CHECK_EQUAL(scale, 1);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 0); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "0+0");
} }
{ // P2TR scriptpath - some datacarrier bytes { // P2TR scriptpath - some datacarrier bytes
CScript prev_script; // scriptPubKey CScript prev_script; // scriptPubKey
@ -1756,7 +1761,7 @@ BOOST_AUTO_TEST_CASE(script_GetScriptForTransactionInput)
auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in); auto [ret_script, scale] = GetScriptForTransactionInput(prev_script, tx_in);
BOOST_CHECK(ret_script == script); BOOST_CHECK(ret_script == script);
BOOST_CHECK_EQUAL(scale, 1); BOOST_CHECK_EQUAL(scale, 1);
BOOST_CHECK_EQUAL(ret_script.DatacarrierBytes(), 3); BOOST_CHECK_EQUAL(DatacarrierBytesStr(ret_script), "3+0");
} }
} }

View File

@ -1014,8 +1014,14 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, reason); return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, reason);
} }
if (m_pool.m_opts.datacarrier_fullcount && (!ignore_rejects.count("txn-datacarrier-exceeded")) && DatacarrierBytes(tx, m_view) > m_pool.m_opts.max_datacarrier_bytes.value_or(0)) { if (m_pool.m_opts.datacarrier_fullcount || !m_pool.m_opts.accept_non_std_datacarrier) {
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-exceeded"); const auto dcb = DatacarrierBytes(tx, m_view);
if (dcb.second > 0 && !(m_pool.m_opts.accept_non_std_datacarrier || ignore_rejects.count("txn-datacarrier-nonstandard"))) {
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-nonstandard");
}
if (m_pool.m_opts.datacarrier_fullcount && (!ignore_rejects.count("txn-datacarrier-exceeded")) && dcb.first + dcb.second > m_pool.m_opts.max_datacarrier_bytes.value_or(0)) {
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-exceeded");
}
} }
// Check for non-standard witnesses. // Check for non-standard witnesses.