v30.3-roots.1 · Commit 3: [PATCH 03/68] feat(policy): preserve Roots relay and network controls on Core 30.3
src/node/mempool_args.cpp
Before: src/node/mempool_args.cpp · After: src/node/mempool_args.cpp
File metadata
index abbe97d9221c6731c314992c4e4469ff049f4794..570bc9769ecfbe5a087843b0763bb4d4ed764e17 100644
Download original patch · Release notes
Diff rows 1–254 of 254. 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/node/mempool_args.cpp
CHANGED
|
@@ -9,17 +9,27 @@
|
|
|
9
9
|
|
|
10
10
|
#include <common/args.h>
|
|
11
11
|
#include <common/messages.h>
|
|
12
|
+
#include <common/settings.h>
|
|
12
13
|
#include <consensus/amount.h>
|
|
13
14
|
#include <kernel/chainparams.h>
|
|
14
15
|
#include <logging.h>
|
|
16
|
+
#include <node/interface_ui.h>
|
|
15
17
|
#include <policy/feerate.h>
|
|
18
|
+
#include <policy/fees.h>
|
|
16
19
|
#include <policy/policy.h>
|
|
17
20
|
#include <tinyformat.h>
|
|
21
|
+
#include <univalue.h>
|
|
18
22
|
#include <util/moneystr.h>
|
|
23
|
+
#include <util/result.h>
|
|
24
|
+
#include <util/strencodings.h>
|
|
25
|
+
#include <util/string.h>
|
|
19
26
|
#include <util/translation.h>
|
|
20
27
|
|
|
21
28
|
#include <chrono>
|
|
29
|
+
#include <cstdint>
|
|
22
30
|
#include <memory>
|
|
31
|
+
#include <string_view>
|
|
32
|
+
#include <utility>
|
|
23
33
|
|
|
24
34
|
using common::AmountErrMsg;
|
|
25
35
|
using kernel::MemPoolLimits;
|
|
@@ -41,6 +51,86 @@ void ApplyArgsManOptions(const ArgsManager& argsman, MemPoolLimits& mempool_limi
|
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
53
|
|
|
54
|
+
util::Result<std::pair<int32_t, int>> ParseDustDynamicOpt(std::string_view optstr, const unsigned int max_fee_estimate_blocks)
|
|
55
|
+
{
|
|
56
|
+
if (optstr == "0" || optstr == "off") {
|
|
57
|
+
return std::pair<int32_t, int>(0, DEFAULT_DUST_RELAY_MULTIPLIER);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
int multiplier{DEFAULT_DUST_RELAY_MULTIPLIER};
|
|
61
|
+
if (auto pos = optstr.find('*'); pos != optstr.npos) {
|
|
62
|
+
int64_t parsed;
|
|
63
|
+
if ((!ParseFixedPoint(optstr.substr(0, pos), 3, &parsed)) || parsed > std::numeric_limits<int>::max() || parsed < 1) {
|
|
64
|
+
return util::Error{_("failed to parse multiplier")};
|
|
65
|
+
}
|
|
66
|
+
multiplier = parsed;
|
|
67
|
+
optstr.remove_prefix(pos + 1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (optstr.rfind("target:", 0) == 0) {
|
|
71
|
+
const auto val = ToIntegral<uint16_t>(optstr.substr(7));
|
|
72
|
+
if (!val) {
|
|
73
|
+
return util::Error{_("failed to parse target block count")};
|
|
74
|
+
}
|
|
75
|
+
if (*val < 2) {
|
|
76
|
+
return util::Error{_("target must be at least 2 blocks")};
|
|
77
|
+
}
|
|
78
|
+
if (Assume(max_fee_estimate_blocks) && *val > max_fee_estimate_blocks) {
|
|
79
|
+
return util::Error{strprintf(_("target can only be at most %s blocks"), max_fee_estimate_blocks)};
|
|
80
|
+
}
|
|
81
|
+
return std::pair<int32_t, int>(-*val, multiplier);
|
|
82
|
+
} else if (optstr.rfind("mempool:", 0) == 0) {
|
|
83
|
+
const auto val = ToIntegral<int32_t>(optstr.substr(8));
|
|
84
|
+
if (!val) {
|
|
85
|
+
return util::Error{_("failed to parse mempool position")};
|
|
86
|
+
}
|
|
87
|
+
if (*val < 1) {
|
|
88
|
+
return util::Error{_("mempool position must be at least 1 kB")};
|
|
89
|
+
}
|
|
90
|
+
return std::pair<int32_t, int>(*val, multiplier);
|
|
91
|
+
} else {
|
|
92
|
+
return util::Error{strprintf(_("\"%s\""), optstr)};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
void ApplyPermitEphemeralOption(const common::SettingsValue& value, MemPoolOptions& mempool_opts)
|
|
97
|
+
{
|
|
98
|
+
std::optional<bool> flag_anchor, flag_send, flag_dust;
|
|
99
|
+
if (SettingToBool(value, false)) {
|
|
100
|
+
flag_anchor = flag_send = flag_dust = true;
|
|
101
|
+
}
|
|
102
|
+
for (auto& opt : util::SplitString(SettingToString(value).value_or(""), ",+")) {
|
|
103
|
+
bool v{true};
|
|
104
|
+
if (opt.size() && opt[0] == '-') {
|
|
105
|
+
opt.erase(opt.begin());
|
|
106
|
+
v = false;
|
|
107
|
+
}
|
|
108
|
+
if (opt == "anchor") {
|
|
109
|
+
flag_anchor = v;
|
|
110
|
+
} else if (opt == "dust") {
|
|
111
|
+
flag_dust = v;
|
|
112
|
+
} else if (opt == "send") {
|
|
113
|
+
flag_send = v;
|
|
114
|
+
} else if (opt == "reject" || opt == "0") {
|
|
115
|
+
flag_anchor = flag_send = flag_dust = !v;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!flag_send) {
|
|
120
|
+
flag_send = flag_dust.value_or(false) && !flag_anchor.value_or(false);
|
|
121
|
+
}
|
|
122
|
+
if (!flag_dust) {
|
|
123
|
+
flag_dust = flag_send;
|
|
124
|
+
}
|
|
125
|
+
if (!flag_anchor) {
|
|
126
|
+
flag_anchor = true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
mempool_opts.permitephemeral_dust = *flag_dust;
|
|
130
|
+
mempool_opts.permitephemeral_anchor = *flag_anchor;
|
|
131
|
+
mempool_opts.permitephemeral_send = *flag_send;
|
|
132
|
+
}
|
|
133
|
+
|
|
44
134
|
util::Result<void> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, MemPoolOptions& mempool_opts)
|
|
45
135
|
{
|
|
46
136
|
mempool_opts.check_ratio = argsman.GetIntArg("-checkmempool", mempool_opts.check_ratio);
|
|
@@ -55,6 +145,9 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& argsman, const CChainP
|
|
|
55
145
|
|
|
56
146
|
if (auto hours = argsman.GetIntArg("-mempoolexpiry")) mempool_opts.expiry = std::chrono::hours{*hours};
|
|
57
147
|
|
|
148
|
+
mempool_opts.minrelaycoinblocks = argsman.GetIntArg("-minrelaycoinblocks", mempool_opts.minrelaycoinblocks);
|
|
149
|
+
mempool_opts.minrelaymaturity = argsman.GetIntArg("-minrelaymaturity", mempool_opts.minrelaymaturity);
|
|
150
|
+
|
|
58
151
|
// incremental relay fee sets the minimum feerate increase necessary for replacement in the mempool
|
|
59
152
|
// and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
|
|
60
153
|
if (const auto arg{argsman.GetArg("-incrementalrelayfee")}) {
|
|
@@ -88,18 +181,130 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& argsman, const CChainP
|
|
|
88
181
|
return util::Error{AmountErrMsg("dustrelayfee", *arg)};
|
|
89
182
|
}
|
|
90
183
|
}
|
|
184
|
+
if (argsman.IsArgSet("-dustdynamic")) {
|
|
185
|
+
const auto optstr = argsman.GetArg("-dustdynamic", DEFAULT_DUST_DYNAMIC);
|
|
186
|
+
// TODO: Should probably reject target-based dustdynamic if there's no estimator, but currently we're checking parameters long before we have the fee estimator initialised
|
|
187
|
+
const auto max_fee_estimate_blocks = mempool_opts.estimator ? mempool_opts.estimator->HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE) : (CBlockPolicyEstimator::LONG_BLOCK_PERIODS * CBlockPolicyEstimator::LONG_SCALE);
|
|
188
|
+
const auto parsed = ParseDustDynamicOpt(optstr, max_fee_estimate_blocks);
|
|
189
|
+
if (!parsed) {
|
|
190
|
+
return util::Error{strprintf(_("Invalid mode for dustdynamic: %s"), util::ErrorString(parsed))};
|
|
191
|
+
}
|
|
192
|
+
mempool_opts.dust_relay_target = parsed->first;
|
|
193
|
+
mempool_opts.dust_relay_multiplier = parsed->second;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
mempool_opts.maxtxlegacysigops = argsman.GetIntArg("-maxtxlegacysigops", mempool_opts.maxtxlegacysigops);
|
|
197
|
+
|
|
198
|
+
mempool_opts.permitbareanchor = argsman.GetBoolArg("-permitbareanchor", mempool_opts.permitbareanchor);
|
|
199
|
+
|
|
200
|
+
mempool_opts.permit_bare_pubkey = argsman.GetBoolArg("-permitbarepubkey", DEFAULT_PERMIT_BAREPUBKEY);
|
|
91
201
|
|
|
92
202
|
mempool_opts.permit_bare_multisig = argsman.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
|
|
93
203
|
|
|
204
|
+
mempool_opts.reject_parasites = argsman.GetBoolArg("-rejectparasites", DEFAULT_REJECT_PARASITES);
|
|
205
|
+
|
|
206
|
+
mempool_opts.reject_tokens = argsman.GetBoolArg("-rejecttokens", DEFAULT_REJECT_TOKENS);
|
|
207
|
+
|
|
208
|
+
mempool_opts.subdustfeepenalty = argsman.GetBoolArg("-subdustfeepenalty", DEFAULT_SUBDUSTFEEPENALTY);
|
|
209
|
+
|
|
94
210
|
if (argsman.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER)) {
|
|
95
211
|
mempool_opts.max_datacarrier_bytes = argsman.GetIntArg("-datacarriersize", MAX_OP_RETURN_RELAY);
|
|
96
212
|
} else {
|
|
97
213
|
mempool_opts.max_datacarrier_bytes = std::nullopt;
|
|
98
214
|
}
|
|
215
|
+
mempool_opts.datacarrier_fullcount = argsman.GetBoolArg("-datacarrierfullcount", DEFAULT_DATACARRIER_FULLCOUNT);
|
|
216
|
+
mempool_opts.accept_non_std_datacarrier = argsman.GetBoolArg("-acceptnonstddatacarrier", DEFAULT_ACCEPT_NON_STD_DATACARRIER);
|
|
217
|
+
|
|
218
|
+
mempool_opts.permitbaredatacarrier = argsman.GetBoolArg("-permitbaredatacarrier", mempool_opts.permitbaredatacarrier);
|
|
99
219
|
|
|
100
220
|
mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", DEFAULT_ACCEPT_NON_STD_TXN);
|
|
101
|
-
if (!chainparams.IsTestChain() && !mempool_opts.require_standard) {
|
|
102
|
-
return util::Error{Untranslated(strprintf("acceptnonstdtxn is not currently supported for %s chain", chainparams.GetChainTypeString()))};
|
|
221
|
+
|
|
222
|
+
mempool_opts.acceptunknownwitness = argsman.GetBoolArg("-acceptunknownwitness", mempool_opts.acceptunknownwitness);
|
|
223
|
+
|
|
224
|
+
if (argsman.IsArgSet("-mempoolreplacement") || argsman.IsArgSet("-mempoolfullrbf")) {
|
|
225
|
+
// Generally, mempoolreplacement overrides mempoolfullrbf, but the latter is used to infer intent in some cases
|
|
226
|
+
std::optional<bool> optin_flag;
|
|
227
|
+
bool fee_flag{false};
|
|
228
|
+
if (argsman.GetBoolArg("-mempoolreplacement", false)) {
|
|
229
|
+
fee_flag = true;
|
|
230
|
+
} else {
|
|
231
|
+
for (auto& opt : util::SplitString(argsman.GetArg("-mempoolreplacement", ""), ",+")) {
|
|
232
|
+
if (opt == "optin") {
|
|
233
|
+
optin_flag = true;
|
|
234
|
+
} else if (opt == "-optin") {
|
|
235
|
+
optin_flag = false;
|
|
236
|
+
} else if (opt == "fee") {
|
|
237
|
+
fee_flag = true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (optin_flag.value_or(false)) {
|
|
242
|
+
// "optin" is explicitly specified
|
|
243
|
+
mempool_opts.rbf_policy = RBFPolicy::OptIn;
|
|
244
|
+
} else if (argsman.GetBoolArg("-mempoolfullrbf", false)) {
|
|
245
|
+
const bool mempoolreplacement_false{argsman.IsArgSet("-mempoolreplacement") && !(fee_flag || optin_flag.has_value())};
|
|
246
|
+
if (mempoolreplacement_false) {
|
|
247
|
+
// This is a contradiction, but override rather than error
|
|
248
|
+
InitWarning(_("False mempoolreplacement option contradicts true mempoolfullrbf; disallowing all RBF"));
|
|
249
|
+
mempool_opts.rbf_policy = RBFPolicy::Never;
|
|
250
|
+
} else {
|
|
251
|
+
mempool_opts.rbf_policy = RBFPolicy::Always;
|
|
252
|
+
}
|
|
253
|
+
} else if (!optin_flag.value_or(true)) {
|
|
254
|
+
// "-optin" is explicitly specified
|
|
255
|
+
mempool_opts.rbf_policy = fee_flag ? RBFPolicy::Always : RBFPolicy::Never;
|
|
256
|
+
} else if (fee_flag) {
|
|
257
|
+
// Just "fee" by itself
|
|
258
|
+
if (!argsman.GetBoolArg("-mempoolfullrbf", true)) {
|
|
259
|
+
mempool_opts.rbf_policy = RBFPolicy::OptIn;
|
|
260
|
+
} else {
|
|
261
|
+
// Fallback to default, unless it's been changed to Never
|
|
262
|
+
if (mempool_opts.rbf_policy == RBFPolicy::Never) {
|
|
263
|
+
mempool_opts.rbf_policy = RBFPolicy::Always;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
} else if (!argsman.IsArgSet("-mempoolreplacement")) {
|
|
267
|
+
// mempoolfullrbf is always explicitly false here
|
|
268
|
+
// Fallback to default, as long as it isn't Always
|
|
269
|
+
if (mempool_opts.rbf_policy == RBFPolicy::Always) {
|
|
270
|
+
mempool_opts.rbf_policy = RBFPolicy::OptIn;
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
// mempoolreplacement is explicitly false here
|
|
274
|
+
mempool_opts.rbf_policy = RBFPolicy::Never;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (argsman.IsArgSet("-mempooltruc")) {
|
|
279
|
+
std::optional<bool> accept_flag, enforce_flag;
|
|
280
|
+
if (argsman.GetBoolArg("-mempooltruc", false)) {
|
|
281
|
+
enforce_flag = true;
|
|
282
|
+
}
|
|
283
|
+
for (auto& opt : util::SplitString(argsman.GetArg("-mempooltruc", ""), ",+")) {
|
|
284
|
+
if (opt == "optin" || opt == "enforce") {
|
|
285
|
+
enforce_flag = true;
|
|
286
|
+
} else if (opt == "-optin" || opt == "-enforce") {
|
|
287
|
+
enforce_flag = false;
|
|
288
|
+
} else if (opt == "accept") {
|
|
289
|
+
accept_flag = true;
|
|
290
|
+
} else if (opt == "reject" || opt == "0") {
|
|
291
|
+
accept_flag = false;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (accept_flag && !*accept_flag) { // reject
|
|
296
|
+
mempool_opts.truc_policy = TRUCPolicy::Reject;
|
|
297
|
+
} else if (enforce_flag && *enforce_flag) { // enforce
|
|
298
|
+
mempool_opts.truc_policy = TRUCPolicy::Enforce;
|
|
299
|
+
} else if ((!accept_flag) && !enforce_flag) {
|
|
300
|
+
// nothing specified, leave at default
|
|
301
|
+
} else { // accept or -enforce
|
|
302
|
+
mempool_opts.truc_policy = TRUCPolicy::Accept;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (argsman.IsArgSet("-permitephemeral")) {
|
|
307
|
+
ApplyPermitEphemeralOption(argsman.GetSetting("-permitephemeral"), mempool_opts);
|
|
103
308
|
}
|
|
104
309
|
|
|
105
310
|
mempool_opts.persist_v1_dat = argsman.GetBoolArg("-persistmempoolv1", mempool_opts.persist_v1_dat);
|