v31.1-roots.1 · Commit 2: [PATCH 02/17] feat(policy): preserve Roots parsing and local transaction checks
src/test/policy_args_tests.cpp
Before: /dev/null · After: src/test/policy_args_tests.cpp
File metadata
new file mode 100644 index 0000000000000000000000000000000000000000..ee01e859e56684e025eafb8e4ddc2fa2e8f272f6
Download original patch · Release notes
Diff rows 1–219 of 219. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
src/test/policy_args_tests.cpp
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// Copyright (c) 2026 The Bitcoin Roots developers
|
|
2
|
+
// Distributed under the MIT software license, see the accompanying
|
|
3
|
+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
4
|
+
|
|
5
|
+
#include <chainparams.h>
|
|
6
|
+
#include <common/args.h>
|
|
7
|
+
#include <common/settings.h>
|
|
8
|
+
#include <consensus/consensus.h>
|
|
9
|
+
#include <init.h>
|
|
10
|
+
#include <kernel/mempool_options.h>
|
|
11
|
+
#include <node/mempool_args.h>
|
|
12
|
+
#include <policy/settings.h>
|
|
13
|
+
#include <test/util/setup_common.h>
|
|
14
|
+
#include <univalue.h>
|
|
15
|
+
#include <util/result.h>
|
|
16
|
+
#include <util/translation.h>
|
|
17
|
+
|
|
18
|
+
#include <cstdint>
|
|
19
|
+
#include <string>
|
|
20
|
+
#include <utility>
|
|
21
|
+
#include <vector>
|
|
22
|
+
|
|
23
|
+
#include <boost/test/unit_test.hpp>
|
|
24
|
+
|
|
25
|
+
namespace {
|
|
26
|
+
const std::vector<std::string> BOOL_OPTIONS{
|
|
27
|
+
"subdustfeepenalty", "rejectparasites", "acceptunknownwitness", "datacarrierfullcount",
|
|
28
|
+
"permitbareanchor", "rejecttokens", "permitbarepubkey", "permitbaredatacarrier", "acceptnonstddatacarrier"};
|
|
29
|
+
|
|
30
|
+
bool ParseOptions(ArgsManager& args, const std::vector<std::string>& options, std::string& error)
|
|
31
|
+
{
|
|
32
|
+
std::vector<const char*> argv{"test_bitcoin"};
|
|
33
|
+
for (const auto& option : options) argv.push_back(option.c_str());
|
|
34
|
+
return args.ParseParameters(argv.size(), argv.data(), error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
BOOST_FIXTURE_TEST_SUITE(policy_args_tests, BasicTestingSetup)
|
|
39
|
+
|
|
40
|
+
BOOST_AUTO_TEST_CASE(boolean_values)
|
|
41
|
+
{
|
|
42
|
+
for (const auto& option : BOOL_OPTIONS) {
|
|
43
|
+
for (const std::string value : {"", "0", "1", "2", "-1", "+1", "01", " 1", "1 ", "1junk", "junk", "false", "0.5", "1.0", "2147483648"}) {
|
|
44
|
+
BOOST_TEST_CONTEXT(option << "=" << value) {
|
|
45
|
+
ArgsManager args;
|
|
46
|
+
args.ForceSetArg("-" + option, value);
|
|
47
|
+
const auto result = ValidateRootsPolicyOptions(args);
|
|
48
|
+
BOOST_CHECK_EQUAL(bool(result), value.empty() || value == "0" || value == "1");
|
|
49
|
+
if (!result) BOOST_CHECK(util::ErrorString(result).original.find("-" + option) != std::string::npos);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
BOOST_AUTO_TEST_CASE(integer_boundaries)
|
|
56
|
+
{
|
|
57
|
+
for (const auto& [option, maximum] : std::vector<std::pair<std::string, std::string>>{
|
|
58
|
+
{"maxscriptsize", "4294967295"}, {"bytespersigopstrict", "4294967295"},
|
|
59
|
+
{"maxtxlegacysigops", "4294967295"}, {"minrelaycoinblocks", "9223372036854775807"},
|
|
60
|
+
{"minrelaymaturity", "2147483647"}, {"blockmaxsize", "4000000"},
|
|
61
|
+
{"blockprioritysize", "9223372036854775807"}}) {
|
|
62
|
+
for (const auto& value : std::vector<std::string>{"0", "1", "+1", "01", "-0", maximum}) {
|
|
63
|
+
BOOST_TEST_CONTEXT(option << "=" << value) {
|
|
64
|
+
ArgsManager args;
|
|
65
|
+
args.ForceSetArg("-" + option, value);
|
|
66
|
+
BOOST_CHECK(ValidateRootsPolicyOptions(args));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (const auto& value : std::vector<std::string>{"", "-1", "+-0", "++1", " 1", "1 ", "1junk", "1.5", "1e0", "junk", "9223372036854775808", std::to_string(std::stoull(maximum) + 1)}) {
|
|
70
|
+
BOOST_TEST_CONTEXT(option << "=" << value) {
|
|
71
|
+
ArgsManager args;
|
|
72
|
+
args.ForceSetArg("-" + option, value);
|
|
73
|
+
BOOST_CHECK(!ValidateRootsPolicyOptions(args));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
BOOST_AUTO_TEST_CASE(carrier_cost_compatibility)
|
|
80
|
+
{
|
|
81
|
+
for (const auto& [value, weight] : std::vector<std::pair<std::string, uint32_t>>{
|
|
82
|
+
{"0", 0}, {"-0", 0}, {"-0.00", 0}, {"0.01", 1}, {"0.25", 1}, {"0.26", 2},
|
|
83
|
+
{"1", 4}, {"1.2300", 5}, {"1e0", 4}, {"1e-2", 1}, {"1073741823.75", 4294967295U}}) {
|
|
84
|
+
ArgsManager args;
|
|
85
|
+
args.ForceSetArg("-datacarriercost", value);
|
|
86
|
+
BOOST_TEST_CONTEXT(value) {
|
|
87
|
+
BOOST_CHECK(ValidateRootsPolicyOptions(args));
|
|
88
|
+
const auto parsed = ParseDataCarrierCost(value);
|
|
89
|
+
BOOST_REQUIRE(parsed);
|
|
90
|
+
BOOST_CHECK_EQUAL(*parsed, weight);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
for (const std::string value : {"", "-1", "+1", "01", ".5", "1.", "0.001", " 1", "1 ", "1junk", "1073741823.76", "1e100", "9223372036854775808"}) {
|
|
94
|
+
ArgsManager args;
|
|
95
|
+
args.ForceSetArg("-datacarriercost", value);
|
|
96
|
+
BOOST_TEST_CONTEXT(value) { BOOST_CHECK(!ValidateRootsPolicyOptions(args)); }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
BOOST_AUTO_TEST_CASE(mode_tokens)
|
|
101
|
+
{
|
|
102
|
+
const std::vector<std::pair<std::string, std::vector<std::string>>> modes{
|
|
103
|
+
{"mempoolreplacement", {"fee", "optin", "-optin", "fee,optin", "fee+-optin", "optin,-optin,fee"}},
|
|
104
|
+
{"mempooltruc", {"reject", "accept", "enforce", "optin", "-enforce", "-optin", "accept+enforce", "reject,accept", "0,enforce"}},
|
|
105
|
+
{"permitephemeral", {"anchor", "dust", "send", "reject", "-anchor", "-dust", "-send", "-reject", "-0", "anchor+dust,-send", "0,anchor"}},
|
|
106
|
+
{"spkreuse", {"allow", "conflict"}}};
|
|
107
|
+
for (const auto& [option, tokens] : modes) {
|
|
108
|
+
auto accepted{tokens};
|
|
109
|
+
accepted.insert(accepted.end(), {"", "0", "1"});
|
|
110
|
+
for (const auto& value : accepted) {
|
|
111
|
+
ArgsManager args;
|
|
112
|
+
args.ForceSetArg("-" + option, value);
|
|
113
|
+
BOOST_TEST_CONTEXT(option << "=" << value) { BOOST_CHECK(ValidateRootsPolicyOptions(args)); }
|
|
114
|
+
}
|
|
115
|
+
for (const auto& value : std::vector<std::string>{"junk", "2", "01", "1junk", " 1", "1 ", tokens[0] + ",junk", "," + tokens[0], tokens[0] + ",", tokens[0] + ",," + tokens[0]}) {
|
|
116
|
+
ArgsManager args;
|
|
117
|
+
args.ForceSetArg("-" + option, value);
|
|
118
|
+
BOOST_TEST_CONTEXT(option << "=" << value) { BOOST_CHECK(!ValidateRootsPolicyOptions(args)); }
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
BOOST_AUTO_TEST_CASE(raw_negation_is_scoped)
|
|
124
|
+
{
|
|
125
|
+
auto options{BOOL_OPTIONS};
|
|
126
|
+
options.insert(options.end(), {"maxscriptsize", "bytespersigopstrict", "maxtxlegacysigops", "minrelaycoinblocks", "minrelaymaturity", "blockmaxsize", "blockprioritysize", "datacarriercost", "dustdynamic", "mempoolreplacement", "mempooltruc", "permitephemeral", "spkreuse"});
|
|
127
|
+
for (const auto& option : options) {
|
|
128
|
+
ArgsManager args;
|
|
129
|
+
SetupServerArgs(args);
|
|
130
|
+
std::string error;
|
|
131
|
+
for (const std::string value : {"junk", "2", "01", "+1", "1junk", "1.0", " 1"}) {
|
|
132
|
+
BOOST_TEST_CONTEXT(option << " negated=" << value) {
|
|
133
|
+
BOOST_CHECK(!ParseOptions(args, {"-no" + option + "=" + value, "-" + option + "=1"}, error));
|
|
134
|
+
BOOST_CHECK(error.find("-no" + option) != std::string::npos);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
for (const std::string value : {"", "0", "1"}) {
|
|
138
|
+
BOOST_REQUIRE(ParseOptions(args, {"-no" + option + "=" + value}, error));
|
|
139
|
+
BOOST_CHECK_EQUAL(args.GetArg("-" + option, "missing"), value == "0" ? "1" : "0");
|
|
140
|
+
}
|
|
141
|
+
BOOST_REQUIRE(ParseOptions(args, {"-no" + option}, error));
|
|
142
|
+
BOOST_CHECK_EQUAL(args.GetArg("-" + option, "missing"), "0");
|
|
143
|
+
}
|
|
144
|
+
ArgsManager args;
|
|
145
|
+
SetupServerArgs(args);
|
|
146
|
+
std::string error;
|
|
147
|
+
BOOST_REQUIRE(ParseOptions(args, {"-nodatacarrier=junk", "-bytespersigop=12junk", "-datacarriersize=83junk"}, error));
|
|
148
|
+
BOOST_CHECK(args.GetBoolArg("-datacarrier", false));
|
|
149
|
+
BOOST_CHECK_EQUAL(args.GetIntArg("-bytespersigop", 0), 12);
|
|
150
|
+
BOOST_CHECK_EQUAL(args.GetIntArg("-datacarriersize", 0), 83);
|
|
151
|
+
BOOST_CHECK(ValidateRootsPolicyOptions(args));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
BOOST_AUTO_TEST_CASE(local_defaults_and_ephemeral_semantics)
|
|
155
|
+
{
|
|
156
|
+
ArgsManager args;
|
|
157
|
+
kernel::MemPoolOptions options;
|
|
158
|
+
BOOST_REQUIRE(ApplyArgsManOptions(args, Params(), options));
|
|
159
|
+
BOOST_CHECK_EQUAL(g_script_size_policy_limit, 1650);
|
|
160
|
+
BOOST_CHECK_EQUAL(nBytesPerSigOpStrict, 20);
|
|
161
|
+
BOOST_CHECK(options.reject_parasites && options.acceptunknownwitness);
|
|
162
|
+
BOOST_CHECK(options.datacarrier_fullcount && options.permitbareanchor);
|
|
163
|
+
BOOST_CHECK(!options.reject_tokens && !options.permit_bare_pubkey && !options.permit_bare_multisig);
|
|
164
|
+
BOOST_CHECK(!options.permitbaredatacarrier && !options.accept_non_std_datacarrier);
|
|
165
|
+
BOOST_CHECK_EQUAL(options.maxtxlegacysigops, 2500);
|
|
166
|
+
BOOST_CHECK_EQUAL(options.minrelaycoinblocks, 0);
|
|
167
|
+
BOOST_CHECK_EQUAL(options.minrelaymaturity, 0);
|
|
168
|
+
BOOST_CHECK_EQUAL(options.max_datacarrier_bytes.value(), 83);
|
|
169
|
+
BOOST_CHECK_EQUAL(options.min_relay_feerate.GetFeePerK(), 1000);
|
|
170
|
+
BOOST_CHECK_EQUAL(options.incremental_relay_feerate.GetFeePerK(), 100);
|
|
171
|
+
BOOST_CHECK(options.permitephemeral_anchor && !options.permitephemeral_dust && !options.permitephemeral_send);
|
|
172
|
+
args.ForceSetArg("-permitephemeral", "0,anchor,dust,-send");
|
|
173
|
+
BOOST_REQUIRE(ApplyArgsManOptions(args, Params(), options));
|
|
174
|
+
BOOST_CHECK(options.permitephemeral_anchor && options.permitephemeral_dust && !options.permitephemeral_send);
|
|
175
|
+
args.ForceSetArg("-permitephemeral", "1");
|
|
176
|
+
BOOST_REQUIRE(ApplyArgsManOptions(args, Params(), options));
|
|
177
|
+
BOOST_CHECK(options.permitephemeral_anchor && options.permitephemeral_dust && options.permitephemeral_send);
|
|
178
|
+
args.ForceSetArg("-permitephemeral", "reject");
|
|
179
|
+
BOOST_REQUIRE(ApplyArgsManOptions(args, Params(), options));
|
|
180
|
+
BOOST_CHECK(!options.permitephemeral_anchor && !options.permitephemeral_dust && !options.permitephemeral_send);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
BOOST_AUTO_TEST_CASE(settings_types_and_precedence)
|
|
184
|
+
{
|
|
185
|
+
ArgsManager args;
|
|
186
|
+
SetupServerArgs(args);
|
|
187
|
+
for (const auto& value : std::vector<UniValue>{UniValue{true}, UniValue{false}, UniValue{1}, UniValue{"0"}}) {
|
|
188
|
+
args.LockSettings([&](common::Settings& settings) { settings.rw_settings["subdustfeepenalty"] = value; });
|
|
189
|
+
BOOST_CHECK(ValidateRootsPolicyOptions(args));
|
|
190
|
+
}
|
|
191
|
+
for (const auto& value : std::vector<UniValue>{UniValue{2}, UniValue{UniValue::VARR}, UniValue{UniValue::VOBJ}}) {
|
|
192
|
+
args.LockSettings([&](common::Settings& settings) { settings.rw_settings["subdustfeepenalty"] = value; });
|
|
193
|
+
BOOST_CHECK(!ValidateRootsPolicyOptions(args));
|
|
194
|
+
}
|
|
195
|
+
std::string error;
|
|
196
|
+
BOOST_REQUIRE(ParseOptions(args, {"-subdustfeepenalty=junk", "-subdustfeepenalty=1"}, error));
|
|
197
|
+
BOOST_CHECK(ValidateRootsPolicyOptions(args));
|
|
198
|
+
BOOST_REQUIRE(ParseOptions(args, {"-subdustfeepenalty=1", "-subdustfeepenalty=junk"}, error));
|
|
199
|
+
BOOST_CHECK(!ValidateRootsPolicyOptions(args));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
BOOST_AUTO_TEST_CASE(dynamic_dust_grammar_without_runtime_claim)
|
|
203
|
+
{
|
|
204
|
+
const auto target = ParseDustDynamicOpt("1e0*target:2", 1008);
|
|
205
|
+
BOOST_REQUIRE(target);
|
|
206
|
+
BOOST_CHECK_EQUAL(target->first, -2);
|
|
207
|
+
BOOST_CHECK_EQUAL(target->second, 1000);
|
|
208
|
+
const auto position = ParseDustDynamicOpt("1.0000*mempool:01", 1008);
|
|
209
|
+
BOOST_REQUIRE(position);
|
|
210
|
+
BOOST_CHECK_EQUAL(position->first, 1);
|
|
211
|
+
for (const std::string value : {"", "target:1", "target:2junk", "mempool:+1", "mempool:0", "mempool:2147483648", "0*mempool:1", "1.0001*mempool:1", "junk"}) {
|
|
212
|
+
ArgsManager args;
|
|
213
|
+
args.ForceSetArg("-dustdynamic", value);
|
|
214
|
+
kernel::MemPoolOptions options;
|
|
215
|
+
BOOST_TEST_CONTEXT(value) { BOOST_CHECK(!ApplyArgsManOptions(args, Params(), options)); }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
BOOST_AUTO_TEST_SUITE_END()
|