Skip to content

Commit 734576e

Browse files
committed
refactor: policy: Pass kernel::MemPoolOptions to IsStandard[Tx] rather than long list of individual options
Github-Pull: bitcoin#30232 Rebased-From: d4c3c2e
1 parent bfaf703 commit 734576e

File tree

9 files changed

+44
-29
lines changed

9 files changed

+44
-29
lines changed

src/policy/policy.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <consensus/amount.h>
1212
#include <consensus/consensus.h>
1313
#include <consensus/validation.h>
14+
#include <kernel/mempool_options.h>
1415
#include <policy/feerate.h>
1516
#include <primitives/transaction.h>
1617
#include <script/interpreter.h>
@@ -71,7 +72,7 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
7172
* Note this must assign whichType even if returning false, in case
7273
* IsStandardTx ignores the "scriptpubkey" rejection.
7374
*/
74-
bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType)
75+
bool IsStandard(const CScript& scriptPubKey, const kernel::MemPoolOptions& opts, TxoutType& whichType)
7576
{
7677
std::vector<std::vector<unsigned char> > vSolutions;
7778
whichType = Solver(scriptPubKey, vSolutions);
@@ -87,7 +88,7 @@ bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_
8788
if (m < 1 || m > n)
8889
return false;
8990
} else if (whichType == TxoutType::NULL_DATA) {
90-
if (!max_datacarrier_bytes || scriptPubKey.size() > *max_datacarrier_bytes) {
91+
if (!opts.max_datacarrier_bytes || scriptPubKey.size() > *opts.max_datacarrier_bytes) {
9192
return false;
9293
}
9394
}
@@ -110,7 +111,7 @@ static inline bool MaybeReject_(std::string& out_reason, const std::string& reas
110111
} \
111112
} while(0)
112113

113-
bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
114+
bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
114115
{
115116
const std::string reason_prefix;
116117

@@ -148,7 +149,7 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
148149
unsigned int nDataOut = 0;
149150
TxoutType whichType;
150151
for (const CTxOut& txout : tx.vout) {
151-
if (!::IsStandard(txout.scriptPubKey, max_datacarrier_bytes, whichType)) {
152+
if (!::IsStandard(txout.scriptPubKey, opts, whichType)) {
152153
if (whichType == TxoutType::WITNESS_UNKNOWN) {
153154
MaybeReject("scriptpubkey-unknown-witnessversion");
154155
} else {
@@ -160,10 +161,10 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
160161
nDataOut++;
161162
continue;
162163
}
163-
else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
164+
else if ((whichType == TxoutType::MULTISIG) && (!opts.permit_bare_multisig)) {
164165
MaybeReject("bare-multisig");
165166
}
166-
if (IsDust(txout, dust_relay_fee)) {
167+
if (IsDust(txout, opts.dust_relay_feerate)) {
167168
MaybeReject("dust");
168169
}
169170
}

src/policy/policy.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
class CCoinsViewCache;
2020
class CFeeRate;
2121
class CScript;
22+
namespace kernel {
23+
struct MemPoolOptions;
24+
};
2225

2326
/** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/
2427
static constexpr unsigned int DEFAULT_BLOCK_MAX_WEIGHT{MAX_BLOCK_WEIGHT - 4000};
@@ -129,7 +132,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
129132

130133
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
131134

132-
bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType);
135+
bool IsStandard(const CScript& scriptPubKey, const kernel::MemPoolOptions& opts, TxoutType& whichType);
133136

134137

135138
// Changing the default transaction version requires a two step process: first
@@ -141,7 +144,7 @@ static constexpr decltype(CTransaction::version) TX_MAX_STANDARD_VERSION{3};
141144
* Check for standard transaction types
142145
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
143146
*/
144-
bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& out_reason, const ignore_rejects_type& ignore_rejects=empty_ignore_rejects);
147+
bool IsStandardTx(const CTransaction& tx, const kernel::MemPoolOptions& opts, std::string& out_reason, const ignore_rejects_type& ignore_rejects=empty_ignore_rejects);
145148
/**
146149
* Check for standard transaction types
147150
* @param[in] mapInputs Map of previous transactions that have outputs we're spending

src/test/fuzz/key.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <chainparams.h>
6+
#include <kernel/mempool_options.h>
67
#include <key.h>
78
#include <key_io.h>
89
#include <outputtype.h>
@@ -149,12 +150,12 @@ FUZZ_TARGET(key, .init = initialize_key)
149150
assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
150151

151152
TxoutType which_type_tx_pubkey;
152-
const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, std::nullopt, which_type_tx_pubkey);
153+
const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, kernel::MemPoolOptions{}, which_type_tx_pubkey);
153154
assert(is_standard_tx_pubkey);
154155
assert(which_type_tx_pubkey == TxoutType::PUBKEY);
155156

156157
TxoutType which_type_tx_multisig;
157-
const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, std::nullopt, which_type_tx_multisig);
158+
const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, kernel::MemPoolOptions{.permit_bare_multisig = true}, which_type_tx_multisig);
158159
assert(is_standard_tx_multisig);
159160
assert(which_type_tx_multisig == TxoutType::MULTISIG);
160161

src/test/fuzz/script.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <compressor.h>
77
#include <core_io.h>
88
#include <core_memusage.h>
9+
#include <kernel/mempool_options.h>
910
#include <key_io.h>
1011
#include <policy/policy.h>
1112
#include <pubkey.h>
@@ -53,7 +54,7 @@ FUZZ_TARGET(script, .init = initialize_script)
5354
}
5455

5556
TxoutType which_type;
56-
bool is_standard_ret = IsStandard(script, std::nullopt, which_type);
57+
bool is_standard_ret = IsStandard(script, kernel::MemPoolOptions{}, which_type);
5758
if (!is_standard_ret) {
5859
assert(which_type == TxoutType::NONSTANDARD ||
5960
which_type == TxoutType::NULL_DATA ||

src/test/fuzz/transaction.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <consensus/validation.h>
1010
#include <core_io.h>
1111
#include <core_memusage.h>
12+
#include <kernel/mempool_options.h>
1213
#include <policy/policy.h>
1314
#include <policy/settings.h>
1415
#include <primitives/transaction.h>
@@ -57,10 +58,9 @@ FUZZ_TARGET(transaction, .init = initialize_transaction)
5758
Assert(res == state_with_dupe_check.IsValid());
5859
}
5960

60-
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
6161
std::string reason;
62-
const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
63-
const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
62+
const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, kernel::MemPoolOptions{.permit_bare_multisig = true}, reason);
63+
const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, kernel::MemPoolOptions{.permit_bare_multisig = false}, reason);
6464
if (is_standard_without_permit_bare_multisig) {
6565
assert(is_standard_with_permit_bare_multisig);
6666
}

src/test/multisig_tests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include <kernel/mempool_options.h>
56
#include <key.h>
67
#include <policy/policy.h>
78
#include <script/interpreter.h>
@@ -143,7 +144,7 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
143144

144145
const auto is_standard{[](const CScript& spk) {
145146
TxoutType type;
146-
bool res{::IsStandard(spk, std::nullopt, type)};
147+
bool res{::IsStandard(spk, kernel::MemPoolOptions{.max_datacarrier_bytes = std::nullopt}, type)};
147148
if (res) {
148149
BOOST_CHECK_EQUAL(type, TxoutType::MULTISIG);
149150
}

src/test/script_p2sh_tests.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <consensus/tx_verify.h>
6+
#include <kernel/mempool_options.h>
67
#include <key.h>
78
#include <policy/policy.h>
89
#include <policy/settings.h>
@@ -20,13 +21,20 @@
2021
// Helpers:
2122
static bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, std::string& reason)
2223
{
23-
return IsStandardTx(tx, std::nullopt, permit_bare_multisig, CFeeRate{DUST_RELAY_TX_FEE}, reason);
24+
const kernel::MemPoolOptions opts{
25+
.permit_bare_multisig = permit_bare_multisig,
26+
};
27+
return IsStandardTx(tx, opts, reason);
2428
}
2529

2630
static bool IsStandardTx(const CTransaction& tx, std::string& reason)
2731
{
28-
return IsStandardTx(tx, std::nullopt, /*permit_bare_multisig=*/true, CFeeRate{DUST_RELAY_TX_FEE}, reason) &&
29-
IsStandardTx(tx, std::nullopt, /*permit_bare_multisig=*/false, CFeeRate{DUST_RELAY_TX_FEE}, reason);
32+
kernel::MemPoolOptions opts{
33+
.permit_bare_multisig = true,
34+
};
35+
if (!IsStandardTx(tx, opts, reason)) return false;
36+
opts.permit_bare_multisig = false;
37+
return IsStandardTx(tx, opts, reason);
3038
}
3139

3240
static std::vector<unsigned char> Serialize(const CScript& s)

src/test/transaction_tests.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <consensus/tx_check.h>
1313
#include <consensus/validation.h>
1414
#include <core_io.h>
15+
#include <kernel/mempool_options.h>
1516
#include <key.h>
1617
#include <policy/policy.h>
1718
#include <policy/settings.h>
@@ -44,8 +45,7 @@ using util::ToString;
4445

4546
typedef std::vector<unsigned char> valtype;
4647

47-
static CFeeRate g_dust{DUST_RELAY_TX_FEE};
48-
static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
48+
static kernel::MemPoolOptions g_mempool_opts;
4949

5050
static std::map<std::string, unsigned int> mapFlagNames = {
5151
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
@@ -798,19 +798,19 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
798798

799799
constexpr auto CheckIsStandard = [](const auto& t) {
800800
std::string reason;
801-
BOOST_CHECK(IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_multi, g_dust, reason));
801+
BOOST_CHECK(IsStandardTx(CTransaction{t}, g_mempool_opts, reason));
802802
BOOST_CHECK(reason.empty());
803803
};
804804
constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in) {
805805
std::string reason;
806-
BOOST_CHECK(!IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_multi, g_dust, reason));
806+
BOOST_CHECK(!IsStandardTx(CTransaction{t}, g_mempool_opts, reason));
807807
BOOST_CHECK_EQUAL(reason_in, reason);
808808
};
809809

810810
CheckIsStandard(t);
811811

812812
// Check dust with default relay fee:
813-
CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;
813+
CAmount nDustThreshold = 182 * g_mempool_opts.dust_relay_feerate.GetFeePerK() / 1000;
814814
BOOST_CHECK_EQUAL(nDustThreshold, 546);
815815
// dust:
816816
t.vout[0].nValue = nDustThreshold - 1;
@@ -838,14 +838,14 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
838838

839839
// Check dust with odd relay fee to verify rounding:
840840
// nDustThreshold = 182 * 3702 / 1000
841-
g_dust = CFeeRate(3702);
841+
g_mempool_opts.dust_relay_feerate = CFeeRate(3702);
842842
// dust:
843843
t.vout[0].nValue = 674 - 1;
844844
CheckIsNotStandard(t, "dust");
845845
// not dust:
846846
t.vout[0].nValue = 674;
847847
CheckIsStandard(t);
848-
g_dust = CFeeRate{DUST_RELAY_TX_FEE};
848+
g_mempool_opts.dust_relay_feerate = CFeeRate{DUST_RELAY_TX_FEE};
849849

850850
t.vout[0].scriptPubKey = CScript() << OP_1;
851851
CheckIsNotStandard(t, "scriptpubkey");
@@ -958,15 +958,15 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
958958
CheckIsNotStandard(t, "tx-size");
959959

960960
// Check bare multisig (standard if policy flag g_bare_multi is set)
961-
g_bare_multi = true;
961+
g_mempool_opts.permit_bare_multisig = true;
962962
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
963963
t.vin.resize(1);
964964
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
965965
CheckIsStandard(t);
966966

967-
g_bare_multi = false;
967+
g_mempool_opts.permit_bare_multisig = false;
968968
CheckIsNotStandard(t, "bare-multisig");
969-
g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;
969+
g_mempool_opts.permit_bare_multisig = DEFAULT_PERMIT_BAREMULTISIG;
970970

971971
// Check compressed P2PK outputs dust threshold (must have leading 02 or 03)
972972
t.vout[0].scriptPubKey = CScript() << std::vector<unsigned char>(33, 0x02) << OP_CHECKSIG;

src/validation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
810810

811811
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
812812
std::string reason;
813-
if (m_pool.m_opts.require_standard && !IsStandardTx(tx, m_pool.m_opts.max_datacarrier_bytes, m_pool.m_opts.permit_bare_multisig, m_pool.m_opts.dust_relay_feerate, reason, ignore_rejects)) {
813+
if (m_pool.m_opts.require_standard && !IsStandardTx(tx, m_pool.m_opts, reason, ignore_rejects)) {
814814
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
815815
}
816816

0 commit comments

Comments
 (0)