Repository navigation
fix: restore the txindex requirement when governance validation is enabled - #7785
Conversation
… is enabled Governance looks up proposal collateral transactions through the transaction index, so a node running governance validation with -txindex=0 rejects every proposal as "Invalid proposal collateral", and adds misbehavior score to every peer that relays one. Commit 91129d4 removed the LoadChainstate check that refused this combination outside regtest, on the assumption that governance is now force-disabled in this case. Nothing does that: only -prune soft-sets -disablegovernance, so an explicit -txindex=0 starts a node with governance enabled and no warning. Bring the check back in AppInitParameterInteraction with the original error message and the regtest exemption, and cover it with a devnet functional test. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 34 minutes. View limit detailsLimit details: You’ve used all 4 included reviews currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (3)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
✅ Final review complete — no blockers (commit d77f357) · triage: low · Phase 2 only (queue backlog) |
thepastaclaw
left a comment
There was a problem hiding this comment.
Final validation — Phase 2 only (queue backlog)
The restored startup check matches the original governance/txindex condition and regtest exemption, preserves existing masternode and pruning checks, and has a registered devnet test covering both rejection and the governance-disabled alternative. The reviewed range contains one coherent commit with no unrelated changes or confirmed in-scope defects. Verification was static only: the supplied CI snapshot shows successful formatting and container preparation checks, two queued manifest jobs, and a PR-title validation failure consistent with the workflow excluding the init scope; independent build and functional-test results are not available in that snapshot.
Review provenance
Source: reviewer 1: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: dash-core-commit-history); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
lowbygpt-6.1-sol(effort low) — The diff restores a small, well-contained startup parameter check in src/init.cpp and adds a focused functional regression test without changing governance validation or peer-handling logic. - Phase 1 reviewers: not run (skipped for throughput: 20 PRs queued, above the 10 limit)
- Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— dash-core-commit-history (completed, effort medium); agentphase2-reviewer
| from test_framework.test_framework import BitcoinTestFramework | ||
|
|
||
|
|
||
| class GovernanceTxindexDevnetTest(BitcoinTestFramework): |
There was a problem hiding this comment.
nit: I'd move this scenario to test/functional/p2p_connect_to_devnet.py or test/functional/feature_masternode_params_devnet.py but that's fine for now
…idation is enabled d77f357 fix(init): restore the txindex requirement when governance validation is enabled (pasta) Pull request description: ## Issue being fixed or feature implemented Governance validation looks up each proposal's collateral transaction through the transaction index. Without `-txindex`, every proposal fails validation with "Invalid proposal collateral". Until v23.1.0 `dashd` refused to start with governance enabled and `-txindex=0` outside regtest: > Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index. Commit 91129d4 ("refactor: drop dead code with ERROR_TXINDEX_DISABLED_WHEN_GOV_ENABLED", merged in #7008) removed this check from `LoadChainstate`. Its commit message says governance is now force-disabled in this case and the "governance validation disabled" warning is shown instead. That is not the case: only `-prune` soft-sets `-disablegovernance`. An explicit `-txindex=0` on a non-pruned mainnet, testnet or devnet node that is not a masternode now starts quietly with governance enabled and no transaction index. That node then rejects every proposal it is asked to submit or receives from peers, and adds misbehavior score to each peer that relays one. ### Why this is a real problem Code path at c14104b: - The only parameter interaction that turns governance off is the `-prune` one: [src/init.cpp#L1083-L1091](https://github.com/dashpay/dash/blob/c14104b172a2/src/init.cpp#L1083-L1091). The txindex requirement applies only to masternodes ([src/init.cpp#L1398-L1400](https://github.com/dashpay/dash/blob/c14104b172a2/src/init.cpp#L1398-L1400)), the warning fires only when `-disablegovernance` is set ([src/init.cpp#L1442-L1447](https://github.com/dashpay/dash/blob/c14104b172a2/src/init.cpp#L1442-L1447)), and governance is enabled based solely on `-disablegovernance` ([src/init.cpp#L1732](https://github.com/dashpay/dash/blob/c14104b172a2/src/init.cpp#L1732)). - `CGovernanceObject::IsCollateralValid` finds the collateral only through `g_txindex` and fails with "Can't find collateral tx" when it is null: [src/governance/object.cpp#L796-L806](https://github.com/dashpay/dash/blob/c14104b172a2/src/governance/object.cpp#L796-L806). Proposals then fail `IsValidLocally` ([src/governance/object.cpp#L738-L741](https://github.com/dashpay/dash/blob/c14104b172a2/src/governance/object.cpp#L738-L741)), and `ProcessObject` returns false ([src/governance/governance.cpp#L266-L269](https://github.com/dashpay/dash/blob/c14104b172a2/src/governance/governance.cpp#L266-L269)). - For a proposal received from a peer, a false return from `ProcessObject` adds 20 misbehavior points to that peer: [src/governance/net_governance.cpp#L193-L198](https://github.com/dashpay/dash/blob/c14104b172a2/src/governance/net_governance.cpp#L193-L198). After five proposals the peer reaches the discouragement threshold and, unless it is a manual or `noban` connection, is disconnected and its address discouraged: [src/net_processing.cpp#L5833-L5869](https://github.com/dashpay/dash/blob/c14104b172a2/src/net_processing.cpp#L5833-L5869). The reproductions below ran against an unfixed `dashd`: Parts A and B against c14104b, Part C against the branch rebased on 8819507 with the `src/init.cpp` hunk reversed (nothing between those two commits touches C++). They are small `BitcoinTestFramework` scripts. Part A uses devnet because regtest is exempt from the check. The framework cannot mine the devnet genesis block, so Parts B and C show the effects on regtest, where `-txindex=0` with governance is allowed on every revision. The collateral lookup and peer scoring are the same on every network. <details> <summary>Part A (devnet): a node with <code>-txindex=0</code> starts with governance enabled and no warning</summary> ``` $ DASH_WORKTREE=<worktree> python3 repro_a_devnet_startup.py --configfile=<worktree>/test/config.ini TestFramework (INFO): Start a devnet node with -txindex=0 (governance not disabled) TestFramework (INFO): RESULT: dashd started; stderr: '' TestFramework (INFO): getindexinfo: {} TestFramework (INFO): debug.log: ... Command-line arg: txindex="0" TestFramework (INFO): debug.log: ... [flat-database.h:194] [Store] Verifying governance.dat format... TestFramework (INFO): debug.log: ... [flat-database.h:200] [Store] Writing info to governance.dat... TestFramework (INFO): debug.log: ... [flat-database.h:71] [CoreWrite] Governance Objects: 0 (Proposals: 0, Triggers: 0, Other: 0; Erased: 0) TestFramework (INFO): debug.log: ... [governance/governance.cpp:1105] [UpdatedBlockTip] [gobject] CGovernanceManager::UpdatedBlockTip -- nCachedBlockHeight: 0 TestFramework (INFO): Start a devnet node with -txindex=0 -disablegovernance TestFramework (INFO): RESULT: dashd started TestFramework (INFO): RESULT: stderr was the governance-disabled warning TestFramework (INFO): Tests successful ``` </details> <details> <summary>Part B (regtest): with governance enabled and <code>-txindex=0</code>, a valid proposal is rejected; the same node accepts it with <code>-txindex=1</code></summary> ``` $ DASH_WORKTREE=<worktree> python3 repro_b_regtest_proposal.py --configfile=<worktree>/test/config.ini TestFramework (INFO): Node started with -txindex=0; getindexinfo: {} TestFramework (INFO): Collateral 246c979b734f002c8f7d1f472fe159f2a1541472e00fd44b6682134b36327da6 confirmations: 6 TestFramework (INFO): RESULT (-txindex=0): gobject submit rejected: Governance object is not valid - 6926f935aa79335ddac0cf52ca7665a15dc58cda80c89af9dcd22501a819fe63 - Invalid proposal collateral (-32603) TestFramework (INFO): debug.log: ... [governance/object.cpp:804] [IsCollateralValid] CGovernanceObject::IsCollateralValid -- Can't find collateral tx 246c979b734f002c8f7d1f472fe159f2a1541472e00fd44b6682134b36327da6 TestFramework (INFO): gobject count: {'objects_total': 0, 'proposals': 0, 'triggers': 0, 'other': 0, 'erased': 0, 'votes': 0} TestFramework (INFO): Restart the same node with -txindex=1 and submit the same proposal TestFramework (INFO): RESULT (-txindex=1): gobject submit accepted: 6926f935aa79335ddac0cf52ca7665a15dc58cda80c89af9dcd22501a819fe63 TestFramework (INFO): gobject count: {'objects_total': 1, 'proposals': 1, 'triggers': 0, 'other': 0, 'erased': 0, 'votes': 0} TestFramework (INFO): Tests successful ``` </details> <details> <summary>Part C (regtest): the <code>-txindex=0</code> node scores 20 misbehavior points per valid proposal relayed by a peer and disconnects it after five</summary> node0 (`-txindex=1`) connects to node1 (`-txindex=0`, governance enabled), so node1 sees node0 as an ordinary inbound peer. node0 then submits five valid proposals. Because node0 is on a local address, node1 disconnects it without adding the address to the discouragement list; a non-local peer is disconnected and discouraged. ``` $ DASH_WORKTREE=<worktree> python3 repro_c_peer_misbehaving.py --configfile=<worktree>/test/config.ini TestFramework (INFO): node0 getindexinfo: {'txindex': {'synced': True, 'best_block_height': 0}} TestFramework (INFO): node1 getindexinfo: {} TestFramework (INFO): node1 sees node0 as peer=0 inbound=True connection_type=inbound permissions=[] TestFramework (INFO): node0 accepted proposal b23bc414c1e0b465070af792c669ab4eabc529f2deee560ef4593458f01a499e TestFramework (INFO): node0 accepted proposal c81ae2dd9fe14ac2c13eea80ad52a87df586e7be6e317a6540b240a940678ab4 TestFramework (INFO): node0 accepted proposal e6a890d8da141a791fb5cb5b4dfbde92da3e423f7258b383cc3f8e9fa1620c7b TestFramework (INFO): node0 accepted proposal 9e7706395cfacfdbb9aad6e3762abece051a60e5db0ebbec219a9e1201284c54 TestFramework (INFO): node0 accepted proposal 499abad8125b978ba13ec4b6e19bb2bab9d9d63a5475f6e8c37bbc739e8780e3 TestFramework (INFO): node0 gobject count: {'objects_total': 5, 'proposals': 5, 'triggers': 0, 'other': 0, 'erased': 0, 'votes': 0} TestFramework (INFO): node1 gobject count: {'objects_total': 0, 'proposals': 0, 'triggers': 0, 'other': 0, 'erased': 0, 'votes': 0} TestFramework (INFO): node1 peers after relay: 0 TestFramework (INFO): node1 debug.log: ... [governance/governance.cpp:268] [ProcessObject] [gobject] MNGOVERNANCEOBJECT -- Governance object is invalid - Invalid proposal collateral TestFramework (INFO): node1 debug.log: ... [net_processing.cpp:1954] [Misbehaving] [net] Misbehaving: peer=0 (0 -> 20) TestFramework (INFO): node1 debug.log: ... [governance/governance.cpp:268] [ProcessObject] [gobject] MNGOVERNANCEOBJECT -- Governance object is invalid - Invalid proposal collateral TestFramework (INFO): node1 debug.log: ... [net_processing.cpp:1954] [Misbehaving] [net] Misbehaving: peer=0 (20 -> 40) TestFramework (INFO): node1 debug.log: ... [governance/governance.cpp:268] [ProcessObject] [gobject] MNGOVERNANCEOBJECT -- Governance object is invalid - Invalid proposal collateral TestFramework (INFO): node1 debug.log: ... [net_processing.cpp:1954] [Misbehaving] [net] Misbehaving: peer=0 (40 -> 60) TestFramework (INFO): node1 debug.log: ... [governance/governance.cpp:268] [ProcessObject] [gobject] MNGOVERNANCEOBJECT -- Governance object is invalid - Invalid proposal collateral TestFramework (INFO): node1 debug.log: ... [net_processing.cpp:1954] [Misbehaving] [net] Misbehaving: peer=0 (60 -> 80) TestFramework (INFO): node1 debug.log: ... [governance/governance.cpp:268] [ProcessObject] [gobject] MNGOVERNANCEOBJECT -- Governance object is invalid - Invalid proposal collateral TestFramework (INFO): node1 debug.log: ... [net_processing.cpp:1954] [Misbehaving] [net] Misbehaving: peer=0 (80 -> 100) DISCOURAGE THRESHOLD EXCEEDED TestFramework (INFO): node1 debug.log: ... [net_processing.cpp:5860] [MaybeDiscourageAndDisconnect] [net] Warning: disconnecting but not discouraging local peer 0! TestFramework (INFO): Tests successful ``` </details> ### Why it matters This only affects operators who explicitly set `-txindex=0` (the default is `1`) on a non-pruned node that is not a masternode. Nothing at startup tells them anything is wrong, and: - `gobject list`/`count`, the governance view in the GUI and proposal vote tracking stay empty or incomplete, and `gobject submit` fails with an unhelpful collateral error. - The node does not relay proposals. - Every honest peer that relays five or more proposals to it, which on mainnet includes any peer it syncs governance objects from, reaches the discouragement threshold and is disconnected; non-local peers are also discouraged. This applies to its outbound peers as well as inbound ones, so the misconfigured node keeps losing its own connections. Trigger and superblock validation do not use the transaction index, so block validation is not affected. The regression was introduced in v23.1.0. It is not a v24.0.0 release-candidate regression. ## What was done? Restored the check in `AppInitParameterInteraction`, next to the other governance and masternode parameter checks. Outside regtest, if governance validation is enabled and `-txindex` is disabled, `dashd` now fails to start with the original error message. Added `feature_governance_txindex_devnet.py`. It runs on devnet, because regtest is exempt, and checks two things: `-txindex=0` alone is refused with that error, and `-txindex=0 -disablegovernance` still starts with the governance-disabled warning. ### Why this is the correct minimal fix - It brings back the behavior from before 91129d4: the same condition, the same translatable message and the same regtest exemption. It is a parameter check, so it lives with the other parameter checks instead of going back into `LoadChainstate`. That needs no changes to the `LoadChainstate` signature or to `ChainstateLoadingError`, and it fails before the block index is loaded. - The regtest exemption is kept on purpose. Many regtest functional tests run with `-txindex=0` and governance enabled (`feature_reindex.py`, `rpc_blockchain.py`, `rpc_misc.py`, `feature_unsupported_utxo_db.py`), as they did before the check was removed. - The alternative is to do what the 91129d4 commit message describes: soft-set `-disablegovernance` when `-txindex=0`. That would change behavior instead of restoring it, and it would quietly turn governance off for an operator who may simply have forgotten the index. A clear startup error matches how the neighbouring incompatible combinations are handled, such as `-prune` with `-disablegovernance=false`. If reviewers prefer the soft-set, it is an equally small change. - Unchanged: `-prune` still soft-sets `-disablegovernance`/`-txindex=0` and keeps its own error for `-disablegovernance=false`. A masternode with `-txindex=0` still gets the existing "Masternode must have transaction index enabled" error first, because the masternode block runs before the new check. The peer scoring in `net_governance.cpp` is left as is; with the check restored, a node that would score honest peers for valid proposals can no longer start outside regtest. ## How Has This Been Tested? Built on macOS arm64 (`--enable-debug --without-gui --enable-werror`). - New regression test against the unfixed `dashd`: `test/functional/test_runner.py feature_governance_txindex_devnet.py` fails. The node does not exit and keeps running with `-txindex=0`: `dashd should have exited within 60s with expected error Error: Transaction index can't be disabled with governance validation enabled. ...`. - The same test with the fix: passes (2-3 s), before and after rebasing onto 8819507. - Reproduction Part A with the fix: `dashd refused to start (exit 1); stderr: Error: Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index.` `-txindex=0 -disablegovernance` still starts with the warning. Parts B and C are regtest-only and are unaffected by the fix, as intended. - Related existing functional tests with the fix, all passed: `feature_config_args.py`, `feature_governance_objects.py`, `feature_masternode_params_devnet.py`, `p2p_connect_to_devnet.py`, `feature_reindex.py`, `rpc_blockchain.py` (v1 and v2 transport), `rpc_misc.py`, `wallet_import_rescan.py --legacy-wallet`. `feature_unsupported_utxo_db.py` was skipped locally (it needs previous-release binaries and Linux). - Lint: `lint-whitespace.py`, `lint-python.py`, `lint-files.py`, `lint-tests.py`, `lint-format-strings.py`, `lint-python-dead-code.py`, `lint-qt-translation.py` are clean. The C++ hunk is formatted with `contrib/devtools/clang-format-diff.py`. ## Breaking Changes Outside regtest, a node started with `-txindex=0` and without `-disablegovernance` now refuses to start, as it did before v23.1.0. Such a node could not validate proposals anyway. To keep running without the index, operators add `-disablegovernance`. The same applies to `-reindex-chainstate` runs, which already require `-txindex=0`. ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have made corresponding changes to the documentation - [ ] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) ACKs for top commit: knst: utACK d77f357 Tree-SHA512: 55ca460164adbe6e77ec7ba926e9d07516c20ee0162a86c2d98551ca47712090e03b08948929f40c7221ab9741b4ce8a6369b80a6800e4526f0efeaad147443c (cherry picked from commit 248a9d9)
fbe6526 Merge #7807: feat(consensus): hold EvoNode shares and multiple payouts behind a new evo_shares deployment (pasta) 57fd2d9 Merge #7776: fix: keep a pending ProUpServTx across a registrar update that keeps the operator key (pasta) ca69801 Merge #7803: fix: return non-zero amount of accounts after sethdseed (pasta) 57a8f07 Merge #7796: backport: bitcoin#26720 (remaining), partial bitcoin#29523: weight-check the knapsack exact-match selection (pasta) 4eb82f6 Merge #7786: fix(net): keep a dedicated onion listener when -bind is given and correct the bind release note (pasta) 70626a0 Merge #7793: backport: partial bitcoin#28868 (wallet: reload wallet if migration exited early, keep mixed watchonly txs) (pasta) 250a3cd Merge #7790: fix: guard cached governance object flags with the object lock (pasta) 700c195 Merge #7787: fix: only sign EHF signals inside the deployment's start/timeout window (pasta) a3b0f3c Merge #7785: fix: restore the txindex requirement when governance validation is enabled (pasta) 2d1735d Merge #7794: fix(wallet): floor the denomination gap threshold so rebalancing cannot oscillate (pasta) d9f6592 Merge #7783: fix: stop fish completion from re-running the typed dash-cli command (pasta) 89d44c8 Merge #7795: backport: bitcoin#34272, partial bitcoin#31650 (pass PSBT by const reference in PSBTInputSignedAndVerified) (pasta) a1d7411 Merge #7779: fix!: report legacy evonode Platform addresses when listdiff changes its address (pasta) 73f6ea2 Merge #7789: fix(qt): report malformed lang/font settings instead of aborting at startup (pasta) 40de493 Merge #7781: fix(rpc): use a consistent tip height in quorum dkgstatus (pasta) 7d1a90d Merge #7791: fix(net): request object votes from nPeersPerHashMax peers (pasta) 51b145c Merge #7778: test: use single-member in functional tests: feature_mnehf, feature_notifications, p2p_instantsend (pasta) Pull request description: ## Issue being fixed or feature implemented Backports for v24.0.0-rc.3. `v24.0.x` was cut at the v24.0.0-rc.2 tag (1e239d4), and develop has since moved to 24.1.0 (#7775), so rc.3 is built from this branch instead of being tagged on develop like rc.1 and rc.2. ## What was done? Cherry-picked (`git cherry-pick -m1 -x`) every develop merge since rc.2 that carries `backport-candidate-24.0.x`, plus #7778, which #7807's test needs. They are in develop merge order: - #7778 test: use single-member in functional tests: feature_mnehf, feature_notifications, p2p_instantsend (test-only. Needed because #7807's `feature_evo_shares_activation.py` depends on its `mine_quorum_single_member()` fix and fails without it.) - #7791 fix(net): request object votes from nPeersPerHashMax peers - #7781 fix(rpc): use a consistent tip height in quorum dkgstatus - #7789 fix(qt): report malformed lang/font settings instead of aborting at startup - #7779 fix!: report legacy evonode Platform addresses when listdiff changes its address - #7795 backport: bitcoin#34272, partial bitcoin#31650 (pass PSBT by const reference in PSBTInputSignedAndVerified) - #7783 fix: stop fish completion from re-running the typed dash-cli command - #7794 fix(wallet): floor the denomination gap threshold so rebalancing cannot oscillate - #7785 fix: restore the txindex requirement when governance validation is enabled - #7787 fix: only sign EHF signals inside the deployment's start/timeout window - #7790 fix: guard cached governance object flags with the object lock - #7793 backport: partial bitcoin#28868 (wallet: reload wallet if migration exited early, keep mixed watchonly txs) - #7786 fix(net): keep a dedicated onion listener when -bind is given and correct the bind release note. Includes partial bitcoin#36170 (5f40d56). Upstream's dedicated-onion-bind changes to `feature_torcontrol.py` and `p2p_private_broadcast.py` are not included, because those tests depend on upstream commits (5693833, e74d54e) that Dash does not have. - #7796 backport: bitcoin#26720 (remaining), partial bitcoin#29523: weight-check the knapsack exact-match selection - #7803 fix: return non-zero amount of accounts after sethdseed - #7776 fix: keep a pending ProUpServTx across a registrar update that keeps the operator key - #7807 feat(consensus): hold EvoNode shares and multiple payouts behind a new evo_shares deployment One pick needed conflict resolution, in a test only, described in its commit message: #7793, `test/functional/wallet_migration.py`. `test_conflict_txs()` comes from bitcoin#28542 (#7762), which is not on this branch, so it is left out. The C++ part of #7793 is identical to develop. Merged since rc.2 but intentionally not included: #7775 (24.1 version bump), #7260 and #7804 (new Qt feature and its CI fix), #7584 (refactor), routine upstream backports #7257, #7759, #7762, #7768, #7788, #7801, and test/CI-only changes #7777 and #7797. No version change is needed. `configure.ac` is already 24.0.0 with `CLIENT_VERSION_IS_RELEASE` false, so the build takes its version string from the `v24.0.0-rc.3` tag, as it did for rc.2. ## How Has This Been Tested? Built on macOS arm64 against depends with `--enable-debug --enable-werror` (dashd, dash-qt, tests). - `make check`: all unit test suites pass, including `test_dash-qt`. - Functional tests, all passing: `feature_evo_shares_activation.py`, `feature_masternode_shares.py`, `feature_mnehf.py`, `feature_governance.py --descriptors`, `feature_governance_objects.py`, `feature_governance_txindex_devnet.py`, `feature_proxy.py`, `feature_notifications.py`, `feature_llmq_connections.py`, `feature_llmq_chainlocks_automatic.py`, `feature_llmq_singlenode.py`, `p2p_instantsend.py`, `rpc_blockchain.py` (v1 and v2 transport), `rpc_netinfo.py`, `rpc_quorum.py`, `rpc_verifychainlock.py`, `wallet_hd.py` (legacy and descriptors), `wallet_migration.py`. - `feature_bind_extra.py` (from #7786) only runs on Linux and was skipped locally, so CI covers it. Every touched file was diffed against develop. The remaining differences come only from develop PRs that are not part of this backport. ## Breaking Changes Carried over from the picked PRs: - #7807: consensus change behind the new `evo_shares` deployment (bit 14). Mainnet and testnet are unaffected until it activates. Devnets with `v24` already active and an EvoNode carrying several owner payouts need to check or reset. New RPC `protx shared_register_prepare_evo`. - #7785: outside regtest, a node with `-txindex=0` and without `-disablegovernance` refuses to start again, as before v23.1.0. - #7786: carries a partial bitcoin#36170. A node started with `-bind` but no specific `-bind=<addr:port>=onion` now refuses to start while `-listenonion` is enabled. That is the default when listening, even without Tor configured. A wildcard onion bind is also refused. Such nodes need `-bind=127.0.0.1:<port>=onion` or `-listenonion=0`. Nodes without `-bind`, including those using only `-whitebind`, keep the default `127.0.0.1:9996` (`19996` testnet) onion target. See `doc/release-notes-7300.md`. - #7779: `protx listdiff` now includes `platform_p2p` and `platform_https` for a legacy-address evonode whose core P2P address changes. ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have made corresponding changes to the documentation - [ ] I have assigned this pull request to a milestone 🤖 Generated with [Claude Code](https://claude.com/claude-code) Top commit has no ACKs. Tree-SHA512: 8cb01bdb0234f31b5dd2c105b69673de148922991a7523627395c0e0ccfa22b94be5ffbecc842398d443bc90fd9baf2eee6a9cf6fcdbbd1626eb00b93726a55a
Fold in doc/release-notes-7861.md (pruning keeps 2304 blocks), which landed on v24.0.x after these notes were drafted, and document changes from the v23.1.9..v24.0.x range that the notes missed: - breaking: -txindex=0 now requires -disablegovernance (dashpay#7785), -deprecatedrpc=exclude_coinbase removed (dashpay#7492), rescanblockchain needs an unlocked wallet (dashpay#7711), per-element -rpcwhitelist batch checks (dashpay#7722), ProTx version 3 wire format and EvoNode ExtAddr rules (dashpay#7302, dashpay#7741, dashpay#7748, dashpay#7751), multiplicity-correct coinbase payment matching (dashpay#7362, dashpay#7377), mandatory script flag reject reason (dashpay#7710), system time for block validation (dashpay#7430) - How to Upgrade: index-flag continuity (dashpay#7745), -txindex/governance, pruning depth - RPC/REST/wallet/GUI items: scanblocks, getrawtransaction verbosity, generateblock submit, masternode status quorumParticipation, quorum dkgstatus semantics, index-syncing errors, REST mempool parameters, dash-wallet -legacy, stale fee estimates, importwallet on pruned nodes, hybrid keys, mixing-only unlock no longer signs PSBTs, shared_combine registrar checks, P2P penalties and spork announcements, SHA-256 acceleration, Asset Lock history rows, Migrate Wallet menu, splash screen, coin control and options moves Fix inaccuracies: _legacy RPCs never accept a payouts array while register_prepare(_evo) do, descriptorprocesspsbt does not exist in Dash, dashpay#7858 already shipped in v23.1.9, the Bitcoin Core coverage claim, and the stale devnet-reset note. Credit only people who contributed to Dash Core directly, and fix the dead v0.15.0.0 and v0.12.1 archive links. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d6c066f chore: add v23.1.10 to the flatpak release history (pasta) 202632c chore: release v24.0.0 (pasta) 2bf133c docs: cite #8042 for the index fixes in the v24.0.0 release notes (pasta) 8aa11f6 docs: add the v24.0.0-rc.7 picks and index fixes to the v24.0.0 release notes (pasta) ad4e5d6 docs: drop the index caveat from the -reindex-chainstate man page entry (pasta) 19a90bb test: blocks orphaned while the address index is disabled are removed from it (pasta) d2f2a1f fix(index): don't adopt an empty or rebuilt async index as migrated legacy data (pasta) e3bafdb fix(index): reject an uncommitted tip the block index lost (pasta) 9198962 fix(index): check the blocks governance resumes from at startup (pasta) baff347 fix(index): resume from the tip a skipped commit leaves behind (pasta) 2dbf5ca fix(index): write a rewound block's erasures in one batch with its locator (pasta) 252acbe fix(index): move the committed locator below the entries a rewind erases (Konstantin Akimov) e9f9c8a Merge bitcoin#36150: indexes: set prune lock to genesis before first block (Konstantin Akimov) 2edeb98 partial Merge bitcoin#34897: indexes: Don't commit ahead of the flushed chainstate (Konstantin Akimov) 3eba84c Merge bitcoin#32875: index: handle case where pindex_prev equals chain tip in NextSyncBlock() (Konstantin Akimov) 399125c Merge bitcoin#32882: index: remove unnecessary locator cleaning in BaseIndex::Init() (Konstantin Akimov) bb724c6 Merge bitcoin#33212: index: Don't commit state in BaseIndex::Rewind (Konstantin Akimov) d5ff431 Merge bitcoin#32878: index: fix wrong assert of current_tip == m_best_block_index (Konstantin Akimov) 31c7d8f partial Merge bitcoin#32580: wallet, test: best block locator matches scan state follow-ups (Konstantin Akimov) 94f5c58 partial Merge bitcoin#30221: wallet: Ensure best block matches wallet scan state (Konstantin Akimov) 8e0b1e8 partial Merge bitcoin#32069: test: fix intermittent failure in wallet_reorgsrestore.py (Konstantin Akimov) 4d17947 Merge bitcoin#25193: indexes: Read the locator's top block during init, allow interaction with reindex-chainstate (Konstantin Akimov) 0127df8 Merge #8045: test: scale the mempool-loaded wait by timeout_factor so TSAN reindex restarts stop timing out (pasta) 62d0cef Merge #8036: fix(qt): let a shared masternode participant follow a revised invitation that keeps their share (merge-script) 775d31c Merge #8018: fix(consensus): require IPv4 masternode primaries until IPv4 is optional, pin mainnet ports (merge-script) e1b826e Merge #8026: fix(qt): keep shared masternode contribution fields locked while coins are reserved (merge-script) 9fa3df3 Merge #8020: fix(rpc): make protx shared_sign sign only dissolutions that return every principal (merge-script) 246a465 Merge #8024: fix(qt): keep the shared masternode dissolve dialog consistent with what it will send (merge-script) 590ad0a Merge #8021: fix(qt): don't load a newer shared masternode session copy that changes your own share (merge-script) 974aaa3 Merge #8034: fix(qt): check a shared masternode's service and refund addresses before coins are reserved (merge-script) 0026e3e Merge #8027: fix(qt): fund a shared masternode's service update from this wallet by default (merge-script) 6a5d2dc Merge #8035: fix(qt): don't strand coins reserved for a shared masternode session (merge-script) df6083a Merge #8032: fix(qt): don't offer a new operator key when reopening a shared masternode session (merge-script) 2b5bf30 Merge #8029: fix: let dashd -version, -help and first start work without an existing data directory (merge-script) e33d9b1 Merge #8037: docs: list the config file path each Linux init system uses (merge-script) 6030ea0 docs: add the #8014 migratewallet fixes to the v24.0.0 release notes (pasta) 1b1ea95 Merge #8014: backport: bitcoin#28609, bitcoin#34215, bitcoin#34226, bitcoin#34370, partials bitcoin#31423, bitcoin#34156 (migratewallet fixes from 28.x) (merge-script) 608ff63 Merge bitcoin#28542: wallet: Check for uninitialized last processed and conflicting heights in MarkConflicted (DCG-Claude) 3af6f63 Merge bitcoin#28038: wallet: address book migration bug fixes (DCG-Claude) 2fe41fb docs: add ecosystem notes on Asset Unlock txids, coinbase payees and RPC errors (pasta) 0e3f653 docs: correct operator guidance in the v24.0.0 release notes for rc.7 (pasta) 11c8140 Merge #8019: fix(qt): stop reporting refused shared masternode broadcasts as sent (merge-script) cdb250c doc: note operator-relevant v23.1.x patch-release changes for v24.0.0 (pasta) fcd332b doc: state the provider-transaction InstantSend change on its own (pasta) e6f3ad4 fix(bls): stop weighted contribution batch verification on an invalid partial aggregate (pasta) e04acba fix(llmq): weight batched DKG contribution verification (UdjinM6) ed96227 fix(bls): weight batch-verified signatures so complementary errors cannot cancel (UdjinM6) b5c7985 fix(governance): don't vote on triggers while not synced (pasta) a79f432 fix(governance): don't vote NO-FUNDING on triggers before their maturity window (pasta) 8615244 fix(llmq): accept equal DKG secret key shares when aggregating a member's share (pasta) 1c356f4 test: cover DKG members dealing identical contributions (UdjinM6) f23f748 fix(llmq): drop DKG members whose verification vectors share coefficients (UdjinM6) 914c052 docs: add #8003 to the v24.0.0 release notes and man pages (pasta) e81c511 Merge #8003: fix(net): don't refuse to start over the automatic onion service unless -listenonion=1 (merge-script) 41b4578 ci: run cppcheck as test/lint/cppcheck-dash.py, as develop does since #7966 (pasta) c97f3b3 docs: regenerate man pages for v24.0.0-rc.6 (pasta) 784312c docs: add the v24.0.0-rc.6 changes to the v24.0.0 release notes (pasta) f15a53a Merge #7991: fix(qt): shared masternode wizard fixes for taken shares, unconfirmed funding and reply handling (merge-script) 1c46224 Merge #7995: fix(wallet): don't let a waiting CoinJoin promotion/demotion queue block standard mixing (merge-script) 546db2f Merge #7996: fix(wallet): fill a CoinJoin promotion with sibling coins when needed (merge-script) 349859f Merge #7957: fix(qt): validate shared-masternode shares with the consensus rules (merge-script) 9091f0b Merge #8005: backport: bitcoin#27114, bitcoin#33395 (merge-script) e915ab5 Merge #7990: fix(wallet): pay for 3 byte input and output counts so 253+ input sends work (merge-script) 4f4d188 Merge #7984: chore: Translations 2026-10 (pasta) 129a1fc Merge #7980: chore: update seeds, checkpoints, minimum chain work, assumevalid and tx stats for v24 (pasta) 5800e5d docs: state that SPORK_3/SPORK_9 were already hardened on mainnet (pasta) ddc82a8 docs: separate extended addresses from shared masternodes in v24 notes (pasta) 8660e54 docs: complete the v24.0.0 release notes against the full v24 changeset (pasta) 11ea306 Merge #7947: fix: stop quorum key warming from stalling DKG on 2-core masternodes (pasta) 25d7c85 Merge #7826: fix: skip repeated authenticated Platform bans (pasta) 18073dd Merge #7850: perf: let CHECKDATASIG use the signature cache (pasta) 3759397 Merge #7833: fix: gate signing intake before quorum retrieval (pasta) db98ee2 fix: keep flat-file positions 64-bit clean at the remaining raw seek/tell sites (Konstantin Akimov) 54c9738 Merge bitcoin#36667: net: enforce timeout interval for paused send peers (Konstantin Akimov) f1adb2c Merge bitcoin#36665: sock: align exception monitoring between poll() and select() backends (Konstantin Akimov) 8becf6a Merge bitcoin#36669: refactor: store positions as a 64 bits integer in flatfiles (Konstantin Akimov) 4c0cbd6 fix(llmq): judge every sig-share sender by its own verified shares (pasta) 649259f fix(governance): cap the orphan parent objects re-requested per tick (pasta) 418f5ee fix(llmq): verify DKG contributions individually when a batch vvec check fails (pasta) abf2eb0 fix(llmq): reject invalid decrypted DKG shares before aggregation (pasta) 39bda8f fix(consensus): reject negative transaction nVersion after DIP3 (pasta) 1ba2609 Merge #7951: fix(net): stop peers lingering after disconnect under edge-triggered epoll (pasta) 696d45f Merge #7861: feat: keep at least 4-days worth blocks after pruning (merge-script) 9cd1c72 Merge #7869: fix: let startup block replay handle quorum commitments and asset unlocks (pasta) 73e7254 Merge #7682: build: finish relic_conf.h regeneration before compiling BLS consumers (pasta) 7312925 ci: bake the macOS SDK into the CI runner image (pasta) d885ecd Merge #7916: backport: bitcoin#27800, bitcoin#28125, bitcoin#28232, bitcoin#27695 (merge-script) f55ad1d Merge bitcoin#28139: test: create wallet specific for test_locked_wallet case (DCG-Claude) 80f6cbe chore: add the v23.1.9 release entry to flatpak metainfo (pasta) 5ba801f chore: use translation source strings generated from v24.0.x (pasta) a3b9e30 Merge #7974: chore: update man pages, translation strings, SECURITY.md and flatpak for v24.0.0 (pasta) b5d26bd feat(consensus): schedule V24 and evo_shares on mainnet for November 9, 2026 (pasta) fe78211 docs: state the earliest v24 activation height and the v23.1.9 fixes (pasta) 3bbe3e2 docs: address review of v24.0.0 release notes (pasta) 28c39fc docs: add v24.0.0 release notes and remove individual release notes files (pasta) e8cbfaf docs: archive v23.1.8 and v23.1.9 release notes (pasta) 6c02b2b ci: let DEPENDS_ARCH override the machine arch for multiprocess and tsan (pasta) ce5dbf3 Merge #7888: fix(consensus): canonical ExtNetInfo encoding and strict netInfo decoding (pasta) 54cba5c Merge #7537: fix: data races and check-then-act races in the CoinJoin server (pasta) 08d8bca Merge #7909: feat(mining): build the masternode list incrementally during block assembly (pasta) 5633761 Merge #7895: test: cover retroactive provider tx refusal, fix wording (pasta) cbb9500 Merge #7846: fix: treat pending owner keys and Platform node IDs as one conflict namespace (pasta) 8efdf5e Merge #7857: fix: mine a pending ProUpServTx before a key change of its masternode (pasta) e56e6ae Merge #7842: fix(wallet): reject mnemonic passphrases that seed derivation truncates (pasta) 79480ff test: follow-up for #7821: check if wallet is locked after failed upgrade instead creating brand-new scenario (Konstantin Akimov) a56ed47 fix(net): announce sporks to new peers instead of requesting them during mnsync (pasta) cdaea5f Merge #7894: fix: due to logical conflicts feature_pruning.py had been broken while (pasta) 98d92f6 Merge #7817: backport: partial bitcoin#34156 restore cleanup ownership (pasta) 35e6d18 Merge #7858: fix: do not InstantSend-lock provider transactions (pasta) 904d73d Merge #7881: fix: refuse to sign shared registrar updates that move the funder's coins (pasta) 95982f5 Merge #7782: fix(wallet): persist pending-observation coin locks once the record becomes readable (pasta) cdf65d0 Merge #7836: backport: partial bitcoin#25812, bitcoin#29855 (pasta) cc5716f Merge #7824: fix: retain initialized DKG sessions during inventory reads (pasta) 588e458 Merge #7827: backport: partial bitcoin#35984 (pasta) 795c6f1 Merge #7839: fix: release InstantSend tracking after mempool eviction (pasta) dc1a6b2 Merge #7875: docs(rpc): clarify getchainlockbyheight availability (pasta) e4798ff Merge #7876: fix(consensus): capture operator key scheme changes with unchanged bytes in state diffs (pasta) fe68ecb Merge #7871: backport!: Merge bitcoin#27217: wallet: Replace use of purpose strings with an enum (pasta) 8348d22 Merge #7867: fix: refuse masternode list RPCs for blocks outside the active chain (pasta) 861a579 Merge #7866: fix: stop `masternode payments` at the genesis block (pasta) efcef71 Merge #7521: fix: update masternode rate limit on failed governance trigger path (pasta) 0623182 Merge #7831: fix: bound governance object signatures and reset the governance cache (pasta) b230657 Merge #7841: fix: authenticate cached InstantSend proof bytes (pasta) a1f37ea Merge #7820: fix: hold chainstate lock during CoinJoin input validation (pasta) 50a5617 Merge #7829: fix: preserve wallet permissions when changing passphrases (pasta) 2ff0103 Merge #7818: fix: return REST errors for unavailable deployment data (pasta) cb39369 Merge #7834: fix: validate Electrum import input boundaries (pasta) e7e3daa Merge #7821: fix: relock encrypted wallets after HD upgrade failures (pasta) 2fea45f Merge #7792: fix: treat missing snapshots during evodb repair as repair errors (pasta) 3c5c039 Merge #7838: fix(wallet): authenticate unlock deadline extensions (pasta) 0bf80f8 Merge #7810: fix(rpc): handle unavailable masternode payment inputs (pasta) bcefee4 Merge #7822: fix: reject malformed detached quorum share batches (pasta) 86a7737 Merge #7828: fix: omit recovery words from invalid mnemonic errors (pasta) 886d5c4 Merge #7816: fix: check credit pool amount accumulation (pasta) 00fc3b9 Merge #7851: fix(rpc): correct masternode status help for top-level service field (pasta) 0e75c22 Merge #7814: fix(qt): restore HTML escaping of send confirmation recipients (pasta) fbe6526 Merge #7807: feat(consensus): hold EvoNode shares and multiple payouts behind a new evo_shares deployment (pasta) 57fd2d9 Merge #7776: fix: keep a pending ProUpServTx across a registrar update that keeps the operator key (pasta) ca69801 Merge #7803: fix: return non-zero amount of accounts after sethdseed (pasta) 57a8f07 Merge #7796: backport: bitcoin#26720 (remaining), partial bitcoin#29523: weight-check the knapsack exact-match selection (pasta) 4eb82f6 Merge #7786: fix(net): keep a dedicated onion listener when -bind is given and correct the bind release note (pasta) 70626a0 Merge #7793: backport: partial bitcoin#28868 (wallet: reload wallet if migration exited early, keep mixed watchonly txs) (pasta) 250a3cd Merge #7790: fix: guard cached governance object flags with the object lock (pasta) 700c195 Merge #7787: fix: only sign EHF signals inside the deployment's start/timeout window (pasta) a3b0f3c Merge #7785: fix: restore the txindex requirement when governance validation is enabled (pasta) 2d1735d Merge #7794: fix(wallet): floor the denomination gap threshold so rebalancing cannot oscillate (pasta) d9f6592 Merge #7783: fix: stop fish completion from re-running the typed dash-cli command (pasta) 89d44c8 Merge #7795: backport: bitcoin#34272, partial bitcoin#31650 (pass PSBT by const reference in PSBTInputSignedAndVerified) (pasta) a1d7411 Merge #7779: fix!: report legacy evonode Platform addresses when listdiff changes its address (pasta) 73f6ea2 Merge #7789: fix(qt): report malformed lang/font settings instead of aborting at startup (pasta) 40de493 Merge #7781: fix(rpc): use a consistent tip height in quorum dkgstatus (pasta) 7d1a90d Merge #7791: fix(net): request object votes from nPeersPerHashMax peers (pasta) 51b145c Merge #7778: test: use single-member in functional tests: feature_mnehf, feature_notifications, p2p_instantsend (pasta) Pull request description: ## Issue being fixed or feature implemented Merges the v24.0.0 release back into develop, as the release process asks once `master` is fast-forwarded. `master`, `v24.0.x` and the signed `v24.0.0` tag all point to the same commit (938fba5). ## What was done? One merge commit of `master` into develop. `v24.0.x` was cut from develop, so all of its code is already here. Every commit on it that develop lacks by patch is one of these: - a `cherry-pick -x` of a develop commit; - covered by a develop PR: the index fixes by #8042, the mainnet V24 schedule by #7973, the cppcheck CI move by #7966; - release bookkeeping. Git reports conflicts in many files, because `v24.0.x` carries adapted copies of develop's changes. All of them resolve to develop's side, which keeps develop's code, translations and version (`configure.ac` stays at 24.1.0, `CLIENT_VERSION_IS_RELEASE` false). Taken from v24.0.0: - `doc/release-notes.md`: the v24.0.0 release notes. The v23.1.10 notes move to `doc/release-notes/dash/`. - The man pages regenerated for v24.0.0, replacing develop's older v24.0.0 pages. A few entries (`-prune`, `-par`, `-parbls`, `-maxconnections`) still trail develop's help text, as they did before, until the next regeneration. - `feature_addressindex.py`: the v24.0.x test that blocks orphaned while the address index is disabled are removed from it once it is re-enabled. Release notes: - Individual `doc/release-notes-*.md` files whose content is in the v24.0.0 notes are removed. This includes `release-notes-8018.md`, `release-notes-8029.md` and `release-notes-27114.md`, whose changes shipped in v24.0.0 without the files. - `release-notes-28113.md` and `release-notes-28414.md` also covered `descriptorprocesspsbt`, which only develop has. They are trimmed to that RPC instead of removed. - Notes for changes v24.0.0 doesn't include stay: #7812, #7847, #7860, #7862, bitcoin#25943, bitcoin#26485 and bitcoin#27501. ## How Has This Been Tested? macOS arm64 against depends, `--enable-debug --enable-werror --disable-hardening --without-gui`. `dashd`, `dash-cli` and `test_dash` build cleanly. - `src/` is byte-identical to develop's. The only non-doc change is the new `feature_addressindex.py` case. - Functional tests, all passing: `feature_addressindex.py` (with the new case) and `feature_spentindex.py`. - Unit suites, all passing: `txindex_tests`, `blockfilter_index_tests`, `coinstatsindex_tests`, `index_migration_tests`, `baseindex_tests`. - `lint-python.py`, `lint-whitespace.py`, `lint-includes.py` and `lint-circular-dependencies.py` pass. - An independent review checked every non-merge commit in `develop..master` against develop (by patch, by cherry-pick source, and line by line for the rest), re-merged each `v24.0.x` merge commit to look for content added in a merge, and checked each release-note file decision. I did not run the full functional suite locally; CI covers it. ## Breaking Changes None. Develop's code is unchanged; the only non-doc change is the new functional test case. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(if you have permission to set one)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Top commit has no ACKs. Tree-SHA512: 3c2d1b7d2885f983f1457a18920f42907009c8ca77522a6116739d387b011d8d5583da6a4b6a1227bcaa21fa07a7ef635aae58fb8b19e4f31a95582ee1ce2318
Issue being fixed or feature implemented
Governance validation looks up each proposal's collateral transaction through the transaction index. Without
-txindex, every proposal fails validation with "Invalid proposal collateral". Until v23.1.0dashdrefused to start with governance enabled and-txindex=0outside regtest:Commit 91129d4 ("refactor: drop dead code with ERROR_TXINDEX_DISABLED_WHEN_GOV_ENABLED", merged in #7008) removed this check from
LoadChainstate. Its commit message says governance is now force-disabled in this case and the "governance validation disabled" warning is shown instead. That is not the case: only-prunesoft-sets-disablegovernance. An explicit-txindex=0on a non-pruned mainnet, testnet or devnet node that is not a masternode now starts quietly with governance enabled and no transaction index. That node then rejects every proposal it is asked to submit or receives from peers, and adds misbehavior score to each peer that relays one.Why this is a real problem
Code path at c14104b:
-pruneone: src/init.cpp#L1083-L1091. The txindex requirement applies only to masternodes (src/init.cpp#L1398-L1400), the warning fires only when-disablegovernanceis set (src/init.cpp#L1442-L1447), and governance is enabled based solely on-disablegovernance(src/init.cpp#L1732).CGovernanceObject::IsCollateralValidfinds the collateral only throughg_txindexand fails with "Can't find collateral tx" when it is null: src/governance/object.cpp#L796-L806. Proposals then failIsValidLocally(src/governance/object.cpp#L738-L741), andProcessObjectreturns false (src/governance/governance.cpp#L266-L269).ProcessObjectadds 20 misbehavior points to that peer: src/governance/net_governance.cpp#L193-L198. After five proposals the peer reaches the discouragement threshold and, unless it is a manual ornobanconnection, is disconnected and its address discouraged: src/net_processing.cpp#L5833-L5869.The reproductions below ran against an unfixed
dashd: Parts A and B against c14104b, Part C against the branch rebased on 8819507 with thesrc/init.cpphunk reversed (nothing between those two commits touches C++). They are smallBitcoinTestFrameworkscripts. Part A uses devnet because regtest is exempt from the check. The framework cannot mine the devnet genesis block, so Parts B and C show the effects on regtest, where-txindex=0with governance is allowed on every revision. The collateral lookup and peer scoring are the same on every network.Part A (devnet): a node with
-txindex=0starts with governance enabled and no warningPart B (regtest): with governance enabled and
-txindex=0, a valid proposal is rejected; the same node accepts it with-txindex=1Part C (regtest): the
-txindex=0node scores 20 misbehavior points per valid proposal relayed by a peer and disconnects it after fivenode0 (
-txindex=1) connects to node1 (-txindex=0, governance enabled), so node1 sees node0 as an ordinary inbound peer. node0 then submits five valid proposals. Because node0 is on a local address, node1 disconnects it without adding the address to the discouragement list; a non-local peer is disconnected and discouraged.Why it matters
This only affects operators who explicitly set
-txindex=0(the default is1) on a non-pruned node that is not a masternode. Nothing at startup tells them anything is wrong, and:gobject list/count, the governance view in the GUI and proposal vote tracking stay empty or incomplete, andgobject submitfails with an unhelpful collateral error.Trigger and superblock validation do not use the transaction index, so block validation is not affected.
The regression was introduced in v23.1.0. It is not a v24.0.0 release-candidate regression.
What was done?
Restored the check in
AppInitParameterInteraction, next to the other governance and masternode parameter checks. Outside regtest, if governance validation is enabled and-txindexis disabled,dashdnow fails to start with the original error message.Added
feature_governance_txindex_devnet.py. It runs on devnet, because regtest is exempt, and checks two things:-txindex=0alone is refused with that error, and-txindex=0 -disablegovernancestill starts with the governance-disabled warning.Why this is the correct minimal fix
LoadChainstate. That needs no changes to theLoadChainstatesignature or toChainstateLoadingError, and it fails before the block index is loaded.-txindex=0and governance enabled (feature_reindex.py,rpc_blockchain.py,rpc_misc.py,feature_unsupported_utxo_db.py), as they did before the check was removed.-disablegovernancewhen-txindex=0. That would change behavior instead of restoring it, and it would quietly turn governance off for an operator who may simply have forgotten the index. A clear startup error matches how the neighbouring incompatible combinations are handled, such as-prunewith-disablegovernance=false. If reviewers prefer the soft-set, it is an equally small change.-prunestill soft-sets-disablegovernance/-txindex=0and keeps its own error for-disablegovernance=false. A masternode with-txindex=0still gets the existing "Masternode must have transaction index enabled" error first, because the masternode block runs before the new check. The peer scoring innet_governance.cppis left as is; with the check restored, a node that would score honest peers for valid proposals can no longer start outside regtest.How Has This Been Tested?
Built on macOS arm64 (
--enable-debug --without-gui --enable-werror).dashd:test/functional/test_runner.py feature_governance_txindex_devnet.pyfails. The node does not exit and keeps running with-txindex=0:dashd should have exited within 60s with expected error Error: Transaction index can't be disabled with governance validation enabled. ....dashd refused to start (exit 1); stderr: Error: Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index.-txindex=0 -disablegovernancestill starts with the warning. Parts B and C are regtest-only and are unaffected by the fix, as intended.feature_config_args.py,feature_governance_objects.py,feature_masternode_params_devnet.py,p2p_connect_to_devnet.py,feature_reindex.py,rpc_blockchain.py(v1 and v2 transport),rpc_misc.py,wallet_import_rescan.py --legacy-wallet.feature_unsupported_utxo_db.pywas skipped locally (it needs previous-release binaries and Linux).lint-whitespace.py,lint-python.py,lint-files.py,lint-tests.py,lint-format-strings.py,lint-python-dead-code.py,lint-qt-translation.pyare clean. The C++ hunk is formatted withcontrib/devtools/clang-format-diff.py.Breaking Changes
Outside regtest, a node started with
-txindex=0and without-disablegovernancenow refuses to start, as it did before v23.1.0. Such a node could not validate proposals anyway. To keep running without the index, operators add-disablegovernance. The same applies to-reindex-chainstateruns, which already require-txindex=0.Checklist:
🤖 Generated with Claude Code