v31.1-roots.1 · Commit 1: [PATCH 01/17] build(roots): establish v31 portability foundation
doc/feature-contracts/policy-parsing.md
Before: /dev/null · After: doc/feature-contracts/policy-parsing.md
File metadata
new file mode 100644 index 0000000000000000000000000000000000000000..c646bfdb4e044ea02e58efdfbcd61a9eae1795dd
Download original patch · Release notes
Diff rows 1–249 of 249. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
doc/feature-contracts/policy-parsing.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Roots policy input compatibility
|
| 2 |
+
|
| 3 |
+
**v31 candidate status: deferred.** This preserved contract describes the
|
| 4 |
+
accepted 30.3 source, including its documented gaps; the foundation does not
|
| 5 |
+
implement its Roots controls or RPC fields. Source code/test paths below refer
|
| 6 |
+
to `10d772eb7f4b00b5193428a0dde4c06558d6c297`, not current candidate behavior.
|
| 7 |
+
[The port review](../roots-v31-port-review.md) records ownership and current gates.
|
| 8 |
+
|
| 9 |
+
**Contract ID: policy-parsing.** Scope: startup input for the Roots-added local
|
| 10 |
+
policy controls listed below. This contract supplements `runtime-config` and the
|
| 11 |
+
policy contracts in [the catalog](../roots-features.md). It does not change
|
| 12 |
+
admission rules, block validity, or defaults. Scoped startup validation enforces
|
| 13 |
+
the decided grammar; the baseline column records the former permissive behavior
|
| 14 |
+
and explains migration.
|
| 15 |
+
|
| 16 |
+
## Scope, defaults and ranges
|
| 17 |
+
|
| 18 |
+
| Options (without leading `-`) | Default | Accepted effective value |
|
| 19 |
+
| --- | --- | --- |
|
| 20 |
+
| `subdustfeepenalty`, `rejectparasites`, `acceptunknownwitness`, `datacarrierfullcount`, `permitbareanchor` | `1` | Boolean below |
|
| 21 |
+
| `rejecttokens`, `permitbarepubkey`, `permitbaredatacarrier`, `acceptnonstddatacarrier` | `0` | Boolean below |
|
| 22 |
+
| `maxscriptsize` | `1650` bytes | Integer, 0 through 4,294,967,295 |
|
| 23 |
+
| `bytespersigopstrict` | `20` bytes | Integer, 0 through 4,294,967,295 |
|
| 24 |
+
| `maxtxlegacysigops` | `2500` sigops | Integer, 0 through 4,294,967,295 |
|
| 25 |
+
| `minrelaycoinblocks` | `0` coin blocks | Integer, 0 through 9,223,372,036,854,775,807 |
|
| 26 |
+
| `minrelaymaturity` | `0` blocks | Integer, 0 through 2,147,483,647 |
|
| 27 |
+
| `blockmaxsize` | Unset: 4,000,000 serialized-byte cap, with 1,200,000 default weight cap | Integer, 0 through 4,000,000; retain existing template clamping |
|
| 28 |
+
| `blockprioritysize` | `100000` bytes | Integer, 0 through 9,223,372,036,854,775,807 |
|
| 29 |
+
| `datacarriercost` | `1` vbyte/data byte | Fixed point, 0 through 1,073,741,823.75; round up to quarters of a vbyte |
|
| 30 |
+
| `dustdynamic` | `off` | Existing structured grammar below |
|
| 31 |
+
| `mempoolreplacement` | `fee,-optin` (full RBF) | Mode/list below |
|
| 32 |
+
| `mempooltruc` | `enforce` | Mode/list below |
|
| 33 |
+
| `permitephemeral` | anchor allowed, dust/send disallowed | Mode/list below |
|
| 34 |
+
| `spkreuse` | `allow` | `allow`, `conflict`, or Boolean alias |
|
| 35 |
+
|
| 36 |
+
Inherited Core options, including `bytespersigop`, `datacarrier`,
|
| 37 |
+
`datacarriersize`, `permitbaremultisig`, `mempoolfullrbf`, `blockmaxweight`,
|
| 38 |
+
`blockreservedweight`, and fee amounts, keep their existing parsers. Changing
|
| 39 |
+
Roots defaults for an inherited option does not bring its parser into this scope.
|
| 40 |
+
Peer, wallet, RPC and runtime options are outside this contract.
|
| 41 |
+
|
| 42 |
+
**Baseline help conflict:** `blockmaxsize` help advertised `300000` as its
|
| 43 |
+
default, but initialized template options leave the serialized cap at 4,000,000
|
| 44 |
+
when it is unset. Omitting both size and weight options retains the conservative
|
| 45 |
+
1,200,000 weight cap. Explicitly setting only `blockmaxsize` makes weight
|
| 46 |
+
unrestricted up to the consensus maximum; setting only `blockmaxweight` leaves
|
| 47 |
+
the serialized cap at 4,000,000. Preserve these effective defaults and option
|
| 48 |
+
interactions. Updated help reports the actual unset serialized cap.
|
| 49 |
+
|
| 50 |
+
## Grammar and migration decisions
|
| 51 |
+
|
| 52 |
+
A Boolean accepts exactly `0`, `1`, or the empty string. The empty string,
|
| 53 |
+
including an elided CLI flag, means true. Keep `-noOPTION`, `-noOPTION=1`, and
|
| 54 |
+
`-noOPTION=0` (the last means true); explicit empty negation means false. A
|
| 55 |
+
negated value must itself be empty, `0`, or `1` before conversion, so malformed
|
| 56 |
+
negations cannot hide behind the inherited coercion. Other numbers, signs,
|
| 57 |
+
leading zeros, whitespace, textual `true`/`false`, fractions, and suffixes are
|
| 58 |
+
errors. JSON Boolean settings retain their corresponding Boolean meaning.
|
| 59 |
+
|
| 60 |
+
Integers consume the complete ASCII decimal string, with an optional `+` or `-`
|
| 61 |
+
sign and one or more digits. Leading zeros are allowed. The parsed value must
|
| 62 |
+
be nonnegative and fit the range above; `-0` remains zero. Empty/elided values,
|
| 63 |
+
whitespace, fractions, suffixes, and overflow are errors. The upper bounds
|
| 64 |
+
prevent narrowing/wrapping or saturating an out-of-range value; coin-block and
|
| 65 |
+
priority-size controls retain the nonnegative range of the former signed
|
| 66 |
+
64-bit getter rather than silently expanding it. Existing `-noOPTION` and
|
| 67 |
+
`-noOPTION=1` retain zero; `-noOPTION=0` retains one, except fixed-point cost,
|
| 68 |
+
where its existing string conversion also means a cost of one vbyte. Negated
|
| 69 |
+
values are checked as Booleans before conversion.
|
| 70 |
+
|
| 71 |
+
Carrier cost retains the existing whole-value `ParseFixedPoint` grammar:
|
| 72 |
+
optional minus sign, integer part `0` or a nonzero digit followed by digits,
|
| 73 |
+
optional decimal point followed by at least one digit, and optional `e`/`E`
|
| 74 |
+
exponent with optional sign and at least one digit. The result must be exactly
|
| 75 |
+
representable in hundredths and within the range above. Thus `1.2300`, `1e0`,
|
| 76 |
+
`1e-2` and `-0` remain valid; `+1`, `01`, `.5`, `1.`, `0.001`, whitespace,
|
| 77 |
+
trailing junk and arithmetic overflow remain invalid. There is no new ban on
|
| 78 |
+
exponents or redundant fractional zeros. The existing fixed-point parser's
|
| 79 |
+
bounded mantissa/exponent rules remain authoritative, including for zero.
|
| 80 |
+
|
| 81 |
+
`dustdynamic` retains `off`/`0` or
|
| 82 |
+
`[<multiplier>*]target:<blocks>` / `[<multiplier>*]mempool:<kvB>`.
|
| 83 |
+
The multiplier uses the same fixed-point grammar with thousandth precision,
|
| 84 |
+
scaled range 1 through 2,147,483,647; default multiplier is 3. Target is an
|
| 85 |
+
unsigned decimal integer from 2 through the existing estimator horizon.
|
| 86 |
+
Mempool position is a signed decimal integer from 1 through 2,147,483,647.
|
| 87 |
+
Their existing `ToIntegral` grammar rejects a leading `+` and accepts leading
|
| 88 |
+
zeros. Empty values, extra separators, suffixes and unknown modes are errors.
|
| 89 |
+
`-nodustdynamic` and `-nodustdynamic=1` retain `off`/`0`; the inherited
|
| 90 |
+
double-negative `-nodustdynamic=0` yields `1` and remains an invalid mode.
|
| 91 |
+
Validate the raw negated Boolean value before conversion.
|
| 92 |
+
|
| 93 |
+
Keep these mode/list forms and their existing precedence semantics:
|
| 94 |
+
|
| 95 |
+
- `mempoolreplacement`: Boolean alias, or `fee`, `optin`, `-optin` tokens
|
| 96 |
+
separated by `,` or `+`. `0` disables replacement; empty/`1` enables fee-based
|
| 97 |
+
replacement. Repeated recognized tokens retain their current meaning;
|
| 98 |
+
the last `optin`/`-optin` token wins. Preserve the existing interaction with
|
| 99 |
+
inherited `mempoolfullrbf`, including its contradiction warning.
|
| 100 |
+
- `mempooltruc`: Boolean alias, or `reject`, `accept`, `enforce`, `optin`,
|
| 101 |
+
`-enforce`, `-optin`, `0` tokens separated by `,` or `+`. Empty/`1` means
|
| 102 |
+
enforce. `0`/`reject` means reject; enforce takes priority over accept;
|
| 103 |
+
later assignments to the same flag win. Preserve all recognized aliases.
|
| 104 |
+
- `permitephemeral`: Boolean alias, or `anchor`, `dust`, `send`, `reject`, `0`
|
| 105 |
+
tokens with an optional `-` prefix, separated by `,` or `+`. Empty/`1` enables
|
| 106 |
+
all three exceptions, `0`/`reject` disables them. Preserve existing implied
|
| 107 |
+
flags and last assignment to each flag, including signed recognized tokens.
|
| 108 |
+
- `spkreuse`: `allow`/`1`/empty allows reuse, `conflict`/`0` rejects conflicts.
|
| 109 |
+
|
| 110 |
+
Lists must contain recognized nonempty tokens only; unknown tokens and leading,
|
| 111 |
+
trailing, or doubled separators are errors. Whitespace is not token syntax.
|
| 112 |
+
Booleans used as aliases must consume the entire string; `2` and `1junk` are
|
| 113 |
+
errors. Negation retains each mode's existing Boolean alias behavior.
|
| 114 |
+
|
| 115 |
+
| Input class | Baseline behavior | Decided behavior / migration |
|
| 116 |
+
| --- | --- | --- |
|
| 117 |
+
| Omitted option | Built-in default | Unchanged |
|
| 118 |
+
| Empty/elided Boolean or list | Enables Boolean behavior | Unchanged; use `=0` to disable explicitly |
|
| 119 |
+
| Empty/elided integer | Converts to zero | Error; write `=0` |
|
| 120 |
+
| `+1`, `01`, `-0` integer | Numeric conversion | Retain within range |
|
| 121 |
+
| `+1`, `01`, `-1`, `2` Boolean | Nonzero becomes true | Error; write `=1` or `=0` |
|
| 122 |
+
| CLI value containing outer whitespace | Numeric getters trim; carrier cost rejects | Error for scoped values; remove whitespace |
|
| 123 |
+
| Config whitespace around `=`/value | Config reader trims before parsing | Retain config formatting; parser sees trimmed value |
|
| 124 |
+
| `12junk`, `1.5` integer | Prefix becomes 12 or 1 | Error; write the intended whole integer |
|
| 125 |
+
| `junk`, `false`, `0.5` Boolean | Converts to false | Error; write `=0` |
|
| 126 |
+
| Signed overflow | Getter saturates, then may narrow/wrap | Error; choose an in-range value |
|
| 127 |
+
| Negative nonzero integer | May wrap in unsigned destinations | Error; use zero or a supported positive value |
|
| 128 |
+
| Unknown list token / empty token | Ignored, possibly changing the selected mode | Error; remove or correct token |
|
| 129 |
+
| Unknown `spkreuse` string | Selects conflict rejection | Error; write `conflict` |
|
| 130 |
+
| Exact fractional/exponent carrier cost | Whole-value parse | Unchanged; not a partial parse |
|
| 131 |
+
| Malformed negated value | Converts permissively before policy sees it | Error; use an explicit `0` or `1` |
|
| 132 |
+
|
| 133 |
+
These incompatibilities replace silent guesses with actionable startup errors.
|
| 134 |
+
They do not authorize narrowing valid documented policy semantics or changing
|
| 135 |
+
how accepted values influence transactions or templates.
|
| 136 |
+
|
| 137 |
+
## Sources, precedence and diagnostics
|
| 138 |
+
|
| 139 |
+
Preserve `runtime-config` precedence: forced settings, CLI, read/write config,
|
| 140 |
+
JSON settings, network config section, default config section, built-in default.
|
| 141 |
+
For scalar options the last CLI occurrence and first config occurrence win after
|
| 142 |
+
inherited negation processing. Validate the selected effective value; shadowed
|
| 143 |
+
ordinary values need not cause errors. Raw negations must be checked before the
|
| 144 |
+
argument manager converts them, even when subsequently shadowed. No change to
|
| 145 |
+
how config comments or outer whitespace are removed is intended. Config lines
|
| 146 |
+
without `=` remain syntax errors; CLI elision follows the option grammar above.
|
| 147 |
+
|
| 148 |
+
Invalid scoped effective values must produce a startup error naming the option,
|
| 149 |
+
the offending value, and its accepted grammar/range. Preserve the existing
|
| 150 |
+
`Invalid -datacarriercost value: '…'` diagnostic prefix and the specific
|
| 151 |
+
`dustdynamic` failure context, adding useful bounds without disguising the
|
| 152 |
+
reason. Errors must not report unrelated configuration values or secrets.
|
| 153 |
+
|
| 154 |
+
## Baseline evidence and remaining acceptance gates
|
| 155 |
+
|
| 156 |
+
Characterized at `f66eca4ae466e198fecd66cac22a0033918b12ec` (same production
|
| 157 |
+
parser as source `17e1d484aba2a881be03b8928fba3c0125e027a2`). Paths:
|
| 158 |
+
argument conversion (`src/common/args.cpp`, source reference),
|
| 159 |
+
config reading (`src/common/config.cpp`, source reference),
|
| 160 |
+
merging (`src/common/settings.cpp`, source reference),
|
| 161 |
+
mempool options (`src/node/mempool_args.cpp`, source reference),
|
| 162 |
+
startup options (`src/init.cpp`, source reference),
|
| 163 |
+
template options (`src/node/miner.cpp`, source reference), and
|
| 164 |
+
fixed-point conversion (`src/util/strencodings.cpp`, source reference).
|
| 165 |
+
|
| 166 |
+
Focused baseline evidence: `getarg_tests` (10 cases),
|
| 167 |
+
`feature_config_args.py`, and a 160-case isolated regtest startup matrix exercising
|
| 168 |
+
Boolean/integer/cost classes, list aliases/junk, CLI/config pairs, repeated
|
| 169 |
+
options, section precedence, negation and bounds. Configuration trims outer
|
| 170 |
+
whitespace; CLI does not. The cost cases verify last CLI / first config /
|
| 171 |
+
CLI-over-config / network-over-default selection with invalid shadowed values.
|
| 172 |
+
The matrix produced 127 clean startups/shutdowns, 30 expected startup diagnostics,
|
| 173 |
+
and the three existing runtime aborts described below. All 160 outcomes matched
|
| 174 |
+
the source-derived characterization; an expected rejection is not a test failure.
|
| 175 |
+
|
| 176 |
+
**Existing runtime gap:** non-off `dustdynamic` modes can parse successfully but
|
| 177 |
+
abort startup because the mempool is constructed without its required scheduler.
|
| 178 |
+
Parser acceptance does not prove these modes operate. This contract records that
|
| 179 |
+
baseline failure; repairing scheduler wiring is a separate runtime change.
|
| 180 |
+
|
| 181 |
+
Acceptance: policy_args_tests.cpp (`src/test/policy_args_tests.cpp`, source reference)
|
| 182 |
+
`boolean_values`, `integer_boundaries`, `carrier_cost_compatibility`, `mode_tokens`,
|
| 183 |
+
`raw_negation_is_scoped`, `defaults_and_mode_semantics`,
|
| 184 |
+
`settings_types_and_precedence`, and `dynamic_dust_grammar_without_runtime_claim`
|
| 185 |
+
cover parser boundaries, exact weight rounding, defaults, types and aliases.
|
| 186 |
+
feature_policy_args.py (`test/functional/feature_policy_args.py`, source reference) `run_test`
|
| 187 |
+
covers isolated CLI/config startup parity, shadowing, negation and unchanged
|
| 188 |
+
inherited Core parsing. Dynamic-dust non-off grammar is unit-tested without
|
| 189 |
+
claiming a working startup. Configuration and affected
|
| 190 |
+
carrier/sub-dust/dust/replacement/TRUC/template policy suites remain regression
|
| 191 |
+
gates.
|
| 192 |
+
Retirement requires an upstream parser with the same grammar, default values,
|
| 193 |
+
precedence, diagnostics and covered policy behavior. No PR number is known;
|
| 194 |
+
a release note must be added when one is assigned.
|
| 195 |
+
|
| 196 |
+
## Scoped fuzz evidence
|
| 197 |
+
|
| 198 |
+
`policy_args` in policy_args.cpp (`src/test/fuzz/policy_args.cpp`, source reference) exercises
|
| 199 |
+
the production option validator, carrier-cost and dynamic-dust parsers, and raw
|
| 200 |
+
Boolean negation. Its independent bounded decimal oracle checks complete integer
|
| 201 |
+
consumption and range limits; Boolean grammar, rejection of appended junk,
|
| 202 |
+
canonical cost/dynamic round trips and JSON setting types have explicit
|
| 203 |
+
invariants. The entire input is a value, retaining embedded NULs; only the argv
|
| 204 |
+
negation check skips NUL-containing values because argv strings cannot carry them.
|
| 205 |
+
Dynamic parsing does not construct a dynamic mempool or establish runtime support.
|
| 206 |
+
|
| 207 |
+
`subdust_fee_penalty` exercises actual admission and entry fee accounting against
|
| 208 |
+
a wide-integer oracle; its supported arithmetic domain and remaining gates are
|
| 209 |
+
in [the sub-dust contract](subdust.md). Both targets use the existing fuzz registry.
|
| 210 |
+
|
| 211 |
+
Use the existing `libfuzzer` preset when its compiler runtime is installed. A
|
| 212 |
+
sanitizer corpus replay can also use the supported standalone fuzz runner:
|
| 213 |
+
|
| 214 |
+
```sh
|
| 215 |
+
cmake -B build_fuzz_policy -G Ninja -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ \
|
| 216 |
+
-DCMAKE_BUILD_TYPE=Debug -DBUILD_FOR_FUZZING=ON -DSANITIZERS=address,undefined \
|
| 217 |
+
-DENABLE_WALLET=OFF -DBUILD_GUI=OFF -DENABLE_IPC=OFF
|
| 218 |
+
cmake --build build_fuzz_policy -j4
|
| 219 |
+
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 FUZZ=policy_args \
|
| 220 |
+
timeout 120 build_fuzz_policy/bin/fuzz /path/to/local/policy_args
|
| 221 |
+
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 FUZZ=subdust_fee_penalty \
|
| 222 |
+
timeout 120 build_fuzz_policy/bin/fuzz /path/to/local/subdust_fee_penalty
|
| 223 |
+
```
|
| 224 |
+
|
| 225 |
+
Keep inputs and artifacts outside Git. Capture the exact source revision and dirty
|
| 226 |
+
diff, binary/configuration, generator, PRNG seed, input counts, wall time and exits
|
| 227 |
+
for every campaign. The preservation run at base `b60a6e04` plus the L5 test diff
|
| 228 |
+
used GCC 14 ASan/UBSan, Python PRNG seed `310503`, 52 parser boundary spellings
|
| 229 |
+
plus 5,000 mutations, and 225 arithmetic boundaries plus 1,000 generated cases.
|
| 230 |
+
Both 120-second replay budgets completed: 5,052 parser inputs in 34 seconds and
|
| 231 |
+
1,225 arithmetic inputs in 4 seconds, without sanitizer reports. These are bounded
|
| 232 |
+
smoke results, not proof of exhaustive coverage.
|
| 233 |
+
|
| 234 |
+
Parser seeds include empty/Boolean/signed/overflow integers, exact and rounded
|
| 235 |
+
carrier costs, exponents, embedded NUL and trailing junk, malformed lists, JSON
|
| 236 |
+
types, dynamic multiplier/target bounds and a 4,096-digit value. Arithmetic seeds
|
| 237 |
+
combine rates `0`, `1`, `3000`, `INT64_MAX/2` and `INT64_MAX`; actual fees `0`,
|
| 238 |
+
`1000`, `1000000`; deltas `-MAX_MONEY`, `0`, `MAX_MONEY`; zero-valued P2TR/P2A/
|
| 239 |
+
OP_RETURN, mixed sixteen-output fixtures and sixteen above-default-dust outputs.
|
| 240 |
+
Arithmetic inputs consume integers from the end using `FuzzedDataProvider`:
|
| 241 |
+
rate (8 bytes), fee (3), delta plus `MAX_MONEY` (7), output count minus one (1),
|
| 242 |
+
then each output value (2) and script index (1); integers are little endian and
|
| 243 |
+
the chunks are concatenated in reverse consumption order.
|
| 244 |
+
|
| 245 |
+
The installed Clang 19 lacked compiler-rt/libFuzzer/ASan archives; the compile
|
| 246 |
+
probe failed before testing. GCC sanitizer compilation and execution succeeded.
|
| 247 |
+
The executed campaigns therefore used corpus replay, including generated
|
| 248 |
+
mutations, with no coverage-guided engine. A coverage-guided libFuzzer campaign
|
| 249 |
+
remains an explicit evidence gap, and cannot be claimed from these replay counts.
|