v31.1-roots.1 · Commit 1: [PATCH 01/17] build(roots): establish v31 portability foundation
doc/roots-features.md
Before: /dev/null · After: doc/roots-features.md
File metadata
new file mode 100644 index 0000000000000000000000000000000000000000..48a828421d2248b4362e480e8c5f0088978a010d
Download original patch · Release notes
Diff rows 1–400 of 442. 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/roots-features.md
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Bitcoin Roots v31 preservation contracts
|
| 2 |
+
|
| 3 |
+
This unpublished candidate starts directly from authenticated Core v31.1.
|
| 4 |
+
[The port review](roots-v31-port-review.md) pins the exact source and new base,
|
| 5 |
+
accounts for every source commit, and records thematic ownership and gaps.
|
| 6 |
+
|
| 7 |
+
## Availability in this candidate
|
| 8 |
+
|
| 9 |
+
The foundation carries the contract documents and CMake support for selecting
|
| 10 |
+
Qt 5/6 and optional system LevelDB/libsecp256k1. Embedded libraries remain the
|
| 11 |
+
default. Native crypto probes, descriptor-wallet/SQLite boundaries, external
|
| 12 |
+
signer support and QR/DBus/IPC build conditions use the v31 implementations.
|
| 13 |
+
These upstream build conditions are not evidence that a missing optional
|
| 14 |
+
library or platform was tested. See [portability profiles](roots-build-portability.md).
|
| 15 |
+
|
| 16 |
+
The source contracts below are preservation requirements, **not a claim that
|
| 17 |
+
Roots behavior has been ported**. Local policy/mining and strict Roots parsing
|
| 18 |
+
are deferred to L7; peer controls/health to L8; sweep, coin-control and per-send
|
| 19 |
+
RBF extensions to L9; read/write config, effective-policy RPC, resource support
|
| 20 |
+
and dormant statistics to L10; identity/desktop and maintenance integration to
|
| 21 |
+
L11. The narrow monotonic `uptime` RPC sub-aspect has reviewed upstream
|
| 22 |
+
equivalence; this does not retire the remaining operator-stats contract.
|
| 23 |
+
|
| 24 |
+
MiniUPnPc dependency discovery is retained, but its UPnP runtime and depends
|
| 25 |
+
recipe integration belong to the peer theme. The legacy `ENABLE_TOR_SUBPROCESS` declaration has no dedicated
|
| 26 |
+
launcher consumer; it is not an available feature. Roots Windows taskbar
|
| 27 |
+
progress remains deferred to desktop integration. Passing either undeclared
|
| 28 |
+
option to CMake does not implement it. No intended behavior is retired by a
|
| 29 |
+
missing dependency.
|
| 30 |
+
|
| 31 |
+
Code and test references in the contract body identify paths at pinned source
|
| 32 |
+
`10d772eb7f4b00b5193428a0dde4c06558d6c297`; they are rendered as source
|
| 33 |
+
references rather than links into this candidate when their implementation
|
| 34 |
+
has not been carried. Historical test results are not current candidate passes.
|
| 35 |
+
|
| 36 |
+
## Preservation contracts
|
| 37 |
+
|
| 38 |
+
These stable IDs describe behavior to retain when moving between Core versions.
|
| 39 |
+
The source checked for this collection is Roots
|
| 40 |
+
`17e1d484aba2a881be03b8928fba3c0125e027a2`, based on authenticated Core v30.3
|
| 41 |
+
commit `49faec4f87f5cd19c88db01a82e5c68b087c8227`. Source and test links are
|
| 42 |
+
version-specific aids; neither a function name nor the location of an admission
|
| 43 |
+
check is a preservation requirement. The contracts do not authorize a change in
|
| 44 |
+
consensus, a new feature, or repair of a documented gap.
|
| 45 |
+
|
| 46 |
+
**Acceptance rule for every ID:** preserve its observable results, defaults,
|
| 47 |
+
supported configuration, units, errors and boundaries. Tests named below are
|
| 48 |
+
acceptance evidence for the cases they actually exercise, not proof of all
|
| 49 |
+
configurations. A **gap** names an unproved case or an implementation/documentation
|
| 50 |
+
conflict. Existing non-features and the wallet authorization boundary still apply.
|
| 51 |
+
|
| 52 |
+
**Retirement rule for every ID:** remove a Roots implementation only after a
|
| 53 |
+
reviewed upstream-equivalence comparison demonstrates the same behavior and
|
| 54 |
+
defaults for the listed acceptance cases and dependencies. Re-run the tests on
|
| 55 |
+
the new base and account for remaining gaps. A similar upstream option name,
|
| 56 |
+
RPC or feature is insufficient. Maintenance may retire when the new base makes
|
| 57 |
+
it unnecessary and its relevant validation still passes. Dormant support cannot
|
| 58 |
+
be represented as an adopted working feature; enabling it requires a separate
|
| 59 |
+
compatibility decision.
|
| 60 |
+
|
| 61 |
+
### Local policy and mining
|
| 62 |
+
|
| 63 |
+
- **policy-parsing:** the [policy input compatibility contract](feature-contracts/policy-parsing.md)
|
| 64 |
+
specifies scoped grammar, effective defaults, diagnostics, migration decisions
|
| 65 |
+
and baseline characterization for Roots-added policy controls. Parser and
|
| 66 |
+
isolated startup regressions enforce the scoped strict behavior; inherited
|
| 67 |
+
Core option parsing remains outside that scope.
|
| 68 |
+
- **effective-policy:** the [effective mempool policy contract](feature-contracts/effective-policy.md)
|
| 69 |
+
defines an additive `getmempoolinfo.policy` object, initialized-state provenance,
|
| 70 |
+
units, enforcement gates and compatibility. RPC functional assertions cover
|
| 71 |
+
defaults, overrides, disabled settings, precedence and carrier/sub-dust
|
| 72 |
+
reporting/admission parity without changing local policy or consensus rules.
|
| 73 |
+
- **policy-standardness:** configurable local transaction, input and witness
|
| 74 |
+
bounds preserve rejection reasons without changing script consensus. Defaults
|
| 75 |
+
include 1,650-byte script policy, 20 equivalent bytes per sigop and 20 strict
|
| 76 |
+
bytes per sigop, 2,500 legacy sigops, bare pubkey/multisig disabled, unknown
|
| 77 |
+
witness outputs allowed, CAT21 locktime-marker rejection enabled and token
|
| 78 |
+
filters disabled. Ephemeral defaults permit anchors, but not arbitrary dust
|
| 79 |
+
or sends; bare anchors are allowed. See policy settings (`src/policy/settings.h`, source reference),
|
| 80 |
+
standardness options and constants (`src/policy/policy.h`, source reference),
|
| 81 |
+
checks (`src/policy/policy.cpp`, source reference) and admission (`src/validation.cpp`, source reference).
|
| 82 |
+
Acceptance: mempool_sigoplimit.py (`test/functional/mempool_sigoplimit.py`, source reference)
|
| 83 |
+
`test_sigops_limit`, `test_sigops_package`, `test_legacy_sigops_stdness` and
|
| 84 |
+
transaction_tests.cpp (`src/test/transaction_tests.cpp`, source reference). Gap: a complete
|
| 85 |
+
option/ephemeral/filter interaction matrix and explicit valid-block cases for
|
| 86 |
+
each local rejection are not supplied by these tests.
|
| 87 |
+
- **policy-carrier:** default `datacarrier=1`, aggregate carrier budget 83 bytes,
|
| 88 |
+
full counting enabled, nonstandard carriers and bare-carrier transactions
|
| 89 |
+
disabled. Recognized input/witness carriers also count with full counting;
|
| 90 |
+
permitting nonstandard transactions alone does not disable these checks.
|
| 91 |
+
`datacarriercost` defaults to 1 virtual byte per detected data byte, accepts
|
| 92 |
+
fixed-point values with two decimal places from 0 through 1,073,741,823.75,
|
| 93 |
+
and rounds the requested cost upward to integral weight units (quarters of a
|
| 94 |
+
vbyte). Extra weight only raises policy size. See
|
| 95 |
+
startup parsing (`src/init.cpp`, source reference), carrier detection (`src/policy/policy.cpp`, source reference)
|
| 96 |
+
and admission (`src/validation.cpp`, source reference). Acceptance:
|
| 97 |
+
mempool_datacarrier.py (`test/functional/mempool_datacarrier.py`, source reference) `run_test`
|
| 98 |
+
covers budget boundaries, disabling, extreme cost/invalid inputs and valid
|
| 99 |
+
blocks containing locally rejected transactions;
|
| 100 |
+
mempool_tests.cpp (`src/test/mempool_tests.cpp`, source reference) `MempoolExtraWeightBoundary`
|
| 101 |
+
covers size arithmetic. Conflict: current help says multiple outputs are
|
| 102 |
+
allowed, but standardness rejects more than one OP_RETURN output as
|
| 103 |
+
`multi-op-return`. Preserve the actual rejection until explicitly decided;
|
| 104 |
+
help wording is not authority to widen admission. `test_taproot_carrier` in
|
| 105 |
+
`mempool_datacarrier.py` independently checks a maximum-size push/OP_DROP
|
| 106 |
+
tapscript: default nonstandard-carrier rejection, aggregate budget rejection,
|
| 107 |
+
admission at the exact carrier budget when permitted, and valid-block acceptance.
|
| 108 |
+
mempool_subdust_fee_penalty.py (`test/functional/mempool_subdust_fee_penalty.py`, source reference)
|
| 109 |
+
`test_carrier_cost_interaction` covers output-carrier fractional cost rounding,
|
| 110 |
+
zero cost, full-count disabling and composition with the dust deficit.
|
| 111 |
+
Gap: other recognized input/witness carrier patterns and their fractional
|
| 112 |
+
cost/full-count interactions.
|
| 113 |
+
The inherited feature_taproot.py (`test/functional/feature_taproot.py`, source reference)
|
| 114 |
+
fixture `tapscript/pushmaxlimit` expects admission under that test's explicit
|
| 115 |
+
nonstandard-carrier allowance and enlarged budget, subject to its existing
|
| 116 |
+
witness-size checks. The incorrect unconditional nonstandard marker was
|
| 117 |
+
removed to match this configuration; the oversized push still fails consensus.
|
| 118 |
+
- **policy-dust:** thresholds use the effective dust relay rate; the floor is
|
| 119 |
+
3,000 sat/kvB (`dustrelayfee=0.00003000` BTC/kvB). `dustdynamic=off` is the
|
| 120 |
+
default. Dynamic mode is `[multiplier*]target:blocks` or
|
| 121 |
+
`[multiplier*]mempool:kvB`; multiplier defaults to 3, is stored in thousandths
|
| 122 |
+
and must be positive. Target is at least two blocks and no more than the
|
| 123 |
+
estimator's longest tracked target; mempool position is at least 1 kvB.
|
| 124 |
+
Dynamic estimates are multiplied, converted to integral sat/kvB and clamped
|
| 125 |
+
to the configured floor. The scheduler updates the rate every 15 minutes;
|
| 126 |
+
missing estimates fall back to the floor. The published rate
|
| 127 |
+
and standardness snapshot must agree under concurrent access. See
|
| 128 |
+
parser (`src/node/mempool_args.cpp`, source reference), publication (`src/txmempool.cpp`, source reference) and
|
| 129 |
+
threshold calculation (`src/policy/policy.cpp`, source reference). Acceptance:
|
| 130 |
+
mempool_dust.py (`test/functional/mempool_dust.py`, source reference) `test_dust_output` and
|
| 131 |
+
`test_dustrelay` cover script-dependent thresholds, exact threshold/one below,
|
| 132 |
+
and zero-rate behavior; mempool_tests.cpp (`src/test/mempool_tests.cpp`, source reference)
|
| 133 |
+
`DynamicDustFeePublication` covers changing snapshots. Gap: estimator-target
|
| 134 |
+
mode without an estimator is accepted by the parser; it is not evidence of a
|
| 135 |
+
working estimate. Extreme dynamic multiplier arithmetic needs separate coverage.
|
| 136 |
+
- **policy-subdust:** apply a configurable deficit penalty to modified fees,
|
| 137 |
+
using script-specific dust thresholds, without changing the actual fee or
|
| 138 |
+
consensus validity. Enabled by default. The
|
| 139 |
+
[worked contract](/doc/feature-contracts/subdust.md) defines units, rounding,
|
| 140 |
+
saturation, exemptions, precedence, interactions, acceptance cases and gaps.
|
| 141 |
+
- **policy-replacement:** default full RBF (`mempoolreplacement=fee,-optin`)
|
| 142 |
+
and enforced TRUC (`mempooltruc=enforce`). `Never` disables all replacement;
|
| 143 |
+
`OptIn` replaces directly signaling originals or v3 originals, including
|
| 144 |
+
non-signaling v3; full RBF still requires fee/resource replacement checks.
|
| 145 |
+
TRUC can instead be rejected or accepted without enforcing TRUC-specific
|
| 146 |
+
limits. `getmempoolinfo.fullrbf` means configured full RBF, so false does not
|
| 147 |
+
mean v3 replacements are disabled. Explicit `optin` wins over
|
| 148 |
+
`mempoolfullrbf=1`; explicit replacement disabling also wins and warns on
|
| 149 |
+
that contradiction. See selection (`src/node/mempool_args.cpp`, source reference),
|
| 150 |
+
admission/replacement (`src/validation.cpp`, source reference) and RPC (`src/rpc/mempool.cpp`, source reference).
|
| 151 |
+
Acceptance: mempool_rbf_policy.py (`test/functional/mempool_rbf_policy.py`, source reference)
|
| 152 |
+
`POLICIES`/`check_replacement` and
|
| 153 |
+
mempool_truc.py (`test/functional/mempool_truc.py`, source reference) `test_truc_replacement`,
|
| 154 |
+
`test_truc_reorg`, `test_minrelay_in_package_combos`, plus package/sibling
|
| 155 |
+
cases. Gap: all TRUC-mode/replacement-mode combinations and conflicting option
|
| 156 |
+
inputs. Current initialized incremental relay fee is 100 sat/kvB, while
|
| 157 |
+
startup help advertises 1,000; this is a recorded conflict, not a promised
|
| 158 |
+
change to the effective default.
|
| 159 |
+
- **policy-coinage:** minimum relay maturity and coin-block age both default to
|
| 160 |
+
zero (disabled). Maturity counts depth at the next block height; coin-block
|
| 161 |
+
age sums input satoshis times blocks since each coin's height. Unconfirmed
|
| 162 |
+
inputs add no confirmed age. These are additional local gates, never changes
|
| 163 |
+
to coinbase consensus maturity. See coin age (`src/policy/coin_age_priority.cpp`, source reference)
|
| 164 |
+
and admission (`src/validation.cpp`, source reference). Acceptance: priority accounting cases in
|
| 165 |
+
miner_tests.cpp (`src/test/miner_tests.cpp`, source reference) `CreateNewBlock_validity` cover the
|
| 166 |
+
shared age cache. Gap: dedicated enabled/disabled relay maturity/coin-block
|
| 167 |
+
boundaries and their valid-block fixtures.
|
| 168 |
+
- **policy-reuse:** `spkreuse=allow` defaults to no extra restriction. The
|
| 169 |
+
documented alternative `conflict` uses mempool scriptPubKey creation/spend
|
| 170 |
+
tracking to reject reuse or consider policy conflicts for replacement. This is a local
|
| 171 |
+
script rule, not a privacy score, address-ownership inference or consensus
|
| 172 |
+
prohibition. See mode selection (`src/init.cpp`, source reference), admission (`src/validation.cpp`, source reference)
|
| 173 |
+
and tracking (`src/txmempool.cpp`, source reference). Gap: no dedicated functional acceptance
|
| 174 |
+
test for these modes, reorg tracking and replacement interactions is identified;
|
| 175 |
+
generic mempool tests are not a substitute.
|
| 176 |
+
- **mining-template:** with neither size nor weight option specified, the
|
| 177 |
+
effective local limit is 1,200,000 weight units with no additional size cap
|
| 178 |
+
below the 4,000,000-byte protocol bound; minimum fee is 1,000 sat/kvB and
|
| 179 |
+
priority area is 100,000 serialized bytes. An explicit size-only option leaves
|
| 180 |
+
weight unrestricted up to consensus maximum, and a weight-only option leaves
|
| 181 |
+
size unrestricted; setting both enforces both. Priority area can be zero. Transactions
|
| 182 |
+
selected by priority and their fee-selected descendants must have accurate
|
| 183 |
+
ancestor weight/sigop accounting and appear at most once in dependency order.
|
| 184 |
+
See option normalization/assembly (`src/node/miner.cpp`, source reference) and
|
| 185 |
+
defaults (`src/policy/policy.h`, source reference). Acceptance:
|
| 186 |
+
miner_tests.cpp (`src/test/miner_tests.cpp`, source reference) `CreateNewBlock_validity` priority
|
| 187 |
+
ancestor boundary cases and
|
| 188 |
+
mining_prioritisetransaction.py (`test/functional/mining_prioritisetransaction.py`, source reference)
|
| 189 |
+
`run_test`. `test_mining_and_block_acceptance` in
|
| 190 |
+
mempool_subdust_fee_penalty.py (`test/functional/mempool_subdust_fee_penalty.py`, source reference)
|
| 191 |
+
covers modified-fee selection with priority enabled/disabled, penalty
|
| 192 |
+
disabling, unchanged actual fee rewards and a locally rejected valid-block
|
| 193 |
+
fixture. Conflict: inherited help advertised a 300,000-byte size default, while
|
| 194 |
+
assembler options (`src/node/miner.h`, source reference) leave size at the protocol maximum when
|
| 195 |
+
unset; `policy-parsing` corrected that help while preserving the interaction.
|
| 196 |
+
Gap: every size/weight/reserve/priority combination; mining a small
|
| 197 |
+
local template must never limit acceptance of a larger consensus-valid block.
|
| 198 |
+
|
| 199 |
+
### Peer controls and current-connection health
|
| 200 |
+
|
| 201 |
+
- **peer-controls:** retain Core's P2P protocol and inherited orphan/upload/
|
| 202 |
+
whitelist controls. Roots additionally bounds compact reconstruction extras
|
| 203 |
+
by count (default 32,768) and memory (10 decimal MB), excluding oversized
|
| 204 |
+
individual extras; provides `forceinbound` (implies `noban`) and explicit
|
| 205 |
+
compact-filter permissions; permits subnet disconnect; and can disable
|
| 206 |
+
outbound v1 on clearnet (`v2onlyclearnet`, default false). Default fee filters
|
| 207 |
+
are enabled. Bloom service is not globally advertised by default, with
|
| 208 |
+
implicit loopback permission when not explicitly disabled. Retain inactivity
|
| 209 |
+
limits, protected outbound/manual peers, bounded address scoring/cache behavior,
|
| 210 |
+
duplicate manual-connection checks and block-fetch safeguards. Tor binds must
|
| 211 |
+
not accidentally grant clearnet whitelist permission; SOCKS credentials must
|
| 212 |
+
not be logged. See networking (`src/net.cpp`, source reference),
|
| 213 |
+
processing (`src/net_processing.cpp`, source reference), permissions (`src/net_permissions.cpp`, source reference)
|
| 214 |
+
and proxy (`src/netbase.cpp`, source reference). Acceptance:
|
| 215 |
+
p2p_compactblocks_extratxs.py (`test/functional/p2p_compactblocks_extratxs.py`, source reference),
|
| 216 |
+
p2p_permissions.py (`test/functional/p2p_permissions.py`, source reference),
|
| 217 |
+
p2p_disconnect_ban.py (`test/functional/p2p_disconnect_ban.py`, source reference),
|
| 218 |
+
p2p_eviction.py (`test/functional/p2p_eviction.py`, source reference),
|
| 219 |
+
p2p_filter.py (`test/functional/p2p_filter.py`, source reference) and
|
| 220 |
+
p2p_invalid_messages.py (`test/functional/p2p_invalid_messages.py`, source reference), each
|
| 221 |
+
`run_test`. Gap: the full new permission/memory/transport/Tor-bind combination
|
| 222 |
+
matrix and platform-specific CPU measurement.
|
| 223 |
+
- **peer-health:** keep sorting/selection and current connection facts in the
|
| 224 |
+
existing peer table/detail pane. Missing state must reset to unavailable,
|
| 225 |
+
never another peer's stale values. Node RPC adds last block announcement,
|
| 226 |
+
forced-inbound state, deprecated misbehavior score and optional CPU load in
|
| 227 |
+
per mille of connection duration; omit CPU load when not measured or duration
|
| 228 |
+
is unsuitable. No history retention or content/activity feed. See
|
| 229 |
+
peer RPC (`src/rpc/net.cpp`, source reference), peer table (`src/qt/peertablemodel.cpp`, source reference) and
|
| 230 |
+
details (`src/qt/rpcconsole.cpp`, source reference). Acceptance:
|
| 231 |
+
apptests.cpp (`src/qt/test/apptests.cpp`, source reference) `consoleTests` resets unavailable
|
| 232 |
+
details; rpc_net.py (`test/functional/rpc_net.py`, source reference) `run_test` covers RPC.
|
| 233 |
+
Gap: visual checks at 1280×800 and 1920×1080, 100%/150% font scale, populated
|
| 234 |
+
sorting/selection and refresh; these were not executed by the headless baseline.
|
| 235 |
+
|
| 236 |
+
### Wallet authorization, signing and spend controls
|
| 237 |
+
|
| 238 |
+
- **wallet-foundation:** descriptor/SQLite wallets and optional external signing
|
| 239 |
+
are inherited Core foundations. Roots rejects unwritable database directories,
|
| 240 |
+
avoids recursively scanning node database directories and symlink/reparse
|
| 241 |
+
points, and closes unrelated child descriptors for signer commands. Preserve
|
| 242 |
+
normal wallet locking and error reporting; do not introduce another database,
|
| 243 |
+
backup/flush promise or Berkeley DB build option. See database (`src/wallet/db.cpp`, source reference),
|
| 244 |
+
SQLite (`src/wallet/sqlite.cpp`, source reference), filesystem helpers (`src/util/fs_helpers.cpp`, source reference)
|
| 245 |
+
and signer child invocation (`src/common/run_command.cpp`, source reference). Acceptance:
|
| 246 |
+
wallet_multiwallet.py (`test/functional/wallet_multiwallet.py`, source reference),
|
| 247 |
+
wallet_signer.py (`test/functional/wallet_signer.py`, source reference) and
|
| 248 |
+
wallet_tests.cpp (`src/wallet/test/wallet_tests.cpp`, source reference). Gap: platform-specific
|
| 249 |
+
reparse-point/permission cases and external signer availability in each build.
|
| 250 |
+
- **wallet-rbf:** the per-send GUI choice starts from the wallet's `walletrbf`
|
| 251 |
+
preference (Core default true), explicitly overrides it for the prepared
|
| 252 |
+
transaction, and shows its resulting signaling in confirmation and saved
|
| 253 |
+
PSBT. It is a signaling choice, not a guarantee of network replacement. See
|
| 254 |
+
Send dialog (`src/qt/sendcoinsdialog.cpp`, source reference) and
|
| 255 |
+
wallet model (`src/qt/walletmodel.cpp`, source reference). Acceptance:
|
| 256 |
+
wallettests.cpp (`src/qt/test/wallettests.cpp`, source reference) `walletTests` explicit on/off
|
| 257 |
+
override and decoded PSBT sequence assertions. Gap: visual confirmation/font
|
| 258 |
+
scale matrix, not established by a headless build.
|
| 259 |
+
- **wallet-sweep:** only documented WIF/script forms, local-key descriptor
|
| 260 |
+
destination in the selected wallet, no key import, preview by default and
|
| 261 |
+
final authorization before broadcast. Fee state is snapshotted under wallet
|
| 262 |
+
locking; cancellation/invalidation can stop scanning or preview, while accepted
|
| 263 |
+
broadcast submission completes. Reduce secret lifetime using secure storage,
|
| 264 |
+
cleansing and console redaction without claiming complete host/toolkit erasure.
|
| 265 |
+
The full operational contract is [wallet-privacy.md](/doc/wallet-privacy.md).
|
| 266 |
+
See RPC (`src/wallet/rpc/spend.cpp`, source reference), construction (`src/wallet/spend.cpp`, source reference)
|
| 267 |
+
and dialog (`src/qt/sweepdialog.cpp`, source reference). Acceptance:
|
| 268 |
+
wallet_sweepprivkeys.py (`test/functional/wallet_sweepprivkeys.py`, source reference) `run_test`
|
| 269 |
+
covers supported script forms, destination rejection, no import, stale/conflicting
|
| 270 |
+
previews and broadcast; wallettests.cpp (`src/qt/test/wallettests.cpp`, source reference)
|
| 271 |
+
`walletTests` covers secure cache and preview invalidation;
|
| 272 |
+
test_wallet_privacy_contract.py (`ci/test/test_wallet_privacy_contract.py`, source reference)
|
| 273 |
+
checks source structure of authorization/redaction boundaries. Gap: that static
|
| 274 |
+
check is not a race proof; cancellation/authorization concurrency and GUI
|
| 275 |
+
confirmation need runtime and visual evidence.
|
| 276 |
+
- **wallet-coin-control:** expose wallet facts, effective value, locked/reused/
|
| 277 |
+
grouped outputs and send fee/change/RBF consequences. Locked outputs remain
|
| 278 |
+
visible but unselectable; ordinary availability filters still exclude unsafe
|
| 279 |
+
and immature outputs. Material wallet changes clear explicit selection.
|
| 280 |
+
Conspicuously validate custom change; do not add automatic consolidation or
|
| 281 |
+
anonymity claims. See [wallet-privacy.md](/doc/wallet-privacy.md),
|
| 282 |
+
coin control (`src/qt/coincontroldialog.cpp`, source reference) and
|
| 283 |
+
wallet facts (`src/wallet/rpc/wallet.cpp`, source reference). Acceptance:
|
| 284 |
+
wallettests.cpp (`src/qt/test/wallettests.cpp`, source reference) `walletTests` selected/locked
|
| 285 |
+
and invalidation cases, wallet_send.py (`test/functional/wallet_send.py`, source reference) and
|
| 286 |
+
test_wallet_privacy_contract.py (`ci/test/test_wallet_privacy_contract.py`, source reference)
|
| 287 |
+
row-filter assertions. Gap: populated GUI and custom-change visual matrix.
|
| 288 |
+
|
| 289 |
+
### Runtime, configuration, portability and identity
|
| 290 |
+
|
| 291 |
+
- **runtime-config:** `confrw` defaults to network-datadir `bitcoin_rw.conf`.
|
| 292 |
+
Preserve recognized settings and precedence: internal forced settings, CLI,
|
| 293 |
+
read/write config, JSON settings, network config section, default config
|
| 294 |
+
section, then built-in default. For ordinary scalar values, CLI uses its last
|
| 295 |
+
value and config uses its first after negation processing; list/chain/network
|
| 296 |
+
options have separate inherited rules. Typed getters and diagnostics must not
|
| 297 |
+
leak secrets. See merging (`src/common/settings.cpp`, source reference),
|
| 298 |
+
configuration (`src/common/config.cpp`, source reference) and access/writes (`src/common/args.cpp`, source reference).
|
| 299 |
+
Acceptance: getarg_tests.cpp (`src/test/getarg_tests.cpp`, source reference) and
|
| 300 |
+
feature_config_args.py (`test/functional/feature_config_args.py`, source reference) `run_test`.
|
| 301 |
+
Scoped Roots policy grammar and its acceptance gates are specified by
|
| 302 |
+
`policy-parsing`.
|
| 303 |
+
- **operator-stats:** `uptime` returns elapsed seconds from a monotonic clock,
|
| 304 |
+
independent of adjusted wall-clock time; acceptance:
|
| 305 |
+
rpc_uptime.py (`test/functional/rpc_uptime.py`, source reference) `run_test`.
|
| 306 |
+
Retained statistics source defines `time_from`, `time_to`, and arrays of
|
| 307 |
+
`[relative_seconds, tx_count, mempool_bytes, minimum_fee_sat_per_kB]`, without
|
| 308 |
+
interpolation. The in-memory target is 10 MiB, cleanup is periodic rather
|
| 309 |
+
than a hard allocation ceiling, and enabled collection would be controlled
|
| 310 |
+
by a positive target. See stats model (`src/stats/stats.cpp`, source reference),
|
| 311 |
+
schema (`src/stats/rpc_stats.cpp`, source reference), startup declarations (`src/stats/init.cpp`, source reference)
|
| 312 |
+
and monotonic source (`src/common/system.cpp`, source reference). Gap/conflict: production does
|
| 313 |
+
not call registration, option initialization or sample collection at the
|
| 314 |
+
pinned source. `stats_tests/stats` in
|
| 315 |
+
stats_tests.cpp (`src/stats/test/stats_tests.cpp`, source reference) exercises the model directly,
|
| 316 |
+
not an available RPC. GUI-on/headless-off help wording also conflicts with
|
| 317 |
+
the model's default-disabled constant. Wiring and schema/default decisions
|
| 318 |
+
must be reviewed before claiming preservation of a working statistics service.
|
| 319 |
+
- **runtime-resources:** RAM detection influences inherited node cache sizing;
|
| 320 |
+
advisory file allocation must preserve existing bytes, FD limits and GiB
|
| 321 |
+
conversion must avoid overflow. Memory-pressure and I/O-priority helpers are
|
| 322 |
+
platform-scoped support, not proof of active consumers on each platform.
|
| 323 |
+
See cache sizing (`src/node/caches.cpp`, source reference), FS helpers (`src/util/fs_helpers.cpp`, source reference),
|
| 324 |
+
memory pressure (`src/util/mempressure.cpp`, source reference) and I/O priority (`src/util/ioprio.cpp`, source reference).
|
| 325 |
+
Acceptance: system_ram_tests.cpp (`src/test/system_ram_tests.cpp`, source reference),
|
| 326 |
+
fs_tests.cpp (`src/test/fs_tests.cpp`, source reference) and util_tests.cpp (`src/test/util_tests.cpp`, source reference).
|
| 327 |
+
Gap: platform/failure/concurrency evidence for unused helpers; no dedicated
|
| 328 |
+
Tor-launch behavior is established by a build flag.
|
| 329 |
+
- **build-portability:** retain supported CMake switches and actual dependency
|
| 330 |
+
probes, Qt 5/6 branches, QR/signer/taskbar conditions, native crypto flags,
|
| 331 |
+
and usable system LevelDB memory environment. Defaults include wallet/tests
|
| 332 |
+
enabled, GUI disabled, embedded LevelDB/secp256k1. IPC can be deliberately
|
| 333 |
+
disabled, with no IPC coverage claim. See CMakeLists.txt (`CMakeLists.txt`, source reference),
|
| 334 |
+
build guides (`doc/build-unix.md`, source reference), dependencies (`doc/dependencies.md`, source reference) and
|
| 335 |
+
LevelDB probe (`cmake/module/FindLevelDB.cmake`, source reference). Acceptance: configure/build
|
| 336 |
+
each supported profile and its registered `ctest` targets; build-contract
|
| 337 |
+
checks in ci/test (`ci/test`, source reference). Gap: the baseline covers one Linux headless
|
| 338 |
+
wallet profile, not all optional/platform configurations. `ENABLE_TOR_SUBPROCESS`
|
| 339 |
+
has no production consumer and cannot promise an automatic Tor instance.
|
| 340 |
+
- **identity-desktop:** built tools identify Roots and the selected version;
|
| 341 |
+
retain Roots icons and upstream/protocol attribution, QR-to-PNG export and
|
| 342 |
+
supported Windows taskbar progress without mass-rebranding history. See
|
| 343 |
+
version (`src/clientversion.cpp`, source reference), QR export (`src/qt/qrimagewidget.cpp`, source reference) and
|
| 344 |
+
taskbar (`src/qt/wintaskbarprogress.cpp`, source reference). Acceptance:
|
| 345 |
+
apptests.cpp (`src/qt/test/apptests.cpp`, source reference) `consoleTests` QR/icon assertions,
|
| 346 |
+
binary `-version`, and supported Qt/platform builds. Gap: QR/receive UI at both
|
| 347 |
+
resolutions/font scales and Windows taskbar runtime evidence.
|
| 348 |
+
|
| 349 |
+
### Maintenance dispositions
|
| 350 |
+
|
| 351 |
+
These IDs account for source work without treating it as operator behavior.
|
| 352 |
+
|
| 353 |
+
- **maintenance-ci:** classifiers, test fixtures, sanitizer/corpus scheduling,
|
| 354 |
+
platform checks and reuse of proven promotion CI. Acceptance:
|
| 355 |
+
`python3 -m unittest discover -s ci/test`, relevant lint and actual required
|
| 356 |
+
candidate CI profiles. Equivalent infrastructure must test the exact candidate;
|
| 357 |
+
a successful older workflow/build cannot retire the gate.
|
| 358 |
+
- **maintenance-release:** immutable source/tag/asset validation, portable
|
| 359 |
+
export/replay with `.github` exclusions and `git am -3 --keep-cr`, contributor
|
| 360 |
+
credit, five-platform archives, canonical COPYING, signature trust and
|
| 361 |
+
new-draft-only behavior. See maintainer workflow (`contrib/roots/README.md`, source reference)
|
| 362 |
+
and release tools (`ci/release/README.md`, source reference); acceptance: their tests under
|
| 363 |
+
ci/test (`ci/test`, source reference) and temporary export/replay. Optional notice tools do not
|
| 364 |
+
prove complete dependency copyright coverage. Publishing, tagging and remote
|
| 365 |
+
canonical updates are outside these contracts' implementation work.
|
| 366 |
+
- **maintenance-docs:** catalog/provenance/privacy/guidance, release notes and
|
| 367 |
+
generated manuals/example config follow the actual source/help. Acceptance:
|
| 368 |
+
check-doc.py (`test/lint/check-doc.py`, source reference), local links, `git diff --check` and
|
| 369 |
+
regenerated-output comparison when interfaces change. Preserve upstream names
|
| 370 |
+
where they identify lineage rather than Roots UI.
|
| 371 |
+
- **maintenance-native:** behavior-preserving C++ modernization and test/fuzz
|
| 372 |
+
fixture adaptation, safe empty file writes and test-only assertion hooks.
|
| 373 |
+
Acceptance: affected unit/functional/fuzz suites and diff inspection. Reverted
|
| 374 |
+
transient script changes do not create a consensus contract or require a port.
|
| 375 |
+
|
| 376 |
+
### Dependencies by stable ID
|
| 377 |
+
|
| 378 |
+
The shared consensus-neutral and configuration rules apply to every contract.
|
| 379 |
+
This table records additional feature dependencies; identifiers remain separate
|
| 380 |
+
even when implementations share a commit or file.
|
| 381 |
+
|
| 382 |
+
| Contract | Depends on |
|
| 383 |
+
| --- | --- |
|
| 384 |
+
| policy-standardness | None |
|
| 385 |
+
| policy-carrier | policy-standardness |
|
| 386 |
+
| policy-dust | policy-standardness |
|
| 387 |
+
| policy-subdust | policy-dust |
|
| 388 |
+
| policy-replacement | policy-standardness |
|
| 389 |
+
| policy-coinage | None |
|
| 390 |
+
| policy-reuse | policy-standardness |
|
| 391 |
+
| mining-template | policy-coinage, policy-carrier, policy-replacement |
|
| 392 |
+
| policy-parsing | runtime-config, policy-standardness, policy-carrier, policy-dust, policy-subdust, policy-replacement, policy-coinage, policy-reuse, mining-template |
|
| 393 |
+
| effective-policy | policy-parsing, runtime-config, policy-standardness, policy-carrier, policy-dust, policy-subdust, policy-replacement, policy-coinage, policy-reuse |
|
| 394 |
+
| peer-controls | policy-replacement |
|
| 395 |
+
| peer-health | peer-controls |
|
| 396 |
+
| wallet-foundation | build-portability |
|
| 397 |
+
| wallet-rbf | wallet-foundation, policy-replacement |
|
| 398 |
+
| wallet-sweep | wallet-foundation, wallet-rbf, runtime-config |
|
| 399 |
+
| wallet-coin-control | wallet-foundation, wallet-rbf |
|
| 400 |
+
| operator-stats | runtime-config |
|