backport: assumeutxo M1 — snapshot persistence (bitcoin#25308, #24513, #25667, #26828) - #7451
Conversation
|
⛔ Blockers found — Sonnet deferred (commit 912c108) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 183f168ef9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
Caution Review failedThe pull request is closed. Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📥 CommitsReviewing files that changed from the base of the PR and between fe6da7c9b7a2a9085518afc3856b4f8f2f219452 and 912c108. 📒 Files selected for processing (66)
WalkthroughThis change renames the chainstate implementation to Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/dbwrapper.h (1)
338-345: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMake
StoragePath()const.This read-only accessor should be callable through
const CDBWrapper&; otherwise const database/view wrappers cannot expose the storage path without changing their own constness.Proposed fix
- std::optional<fs::path> StoragePath() { + std::optional<fs::path> StoragePath() const {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/dbwrapper.h` around lines 338 - 345, Update the StoragePath() accessor in CDBWrapper to be const-qualified, preserving its existing read-only behavior and return values so it can be called through a const CDBWrapper reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/init.cpp`:
- Around line 2031-2037: Update the -parbls calculation in the bls_threads
initializer to use int for the threads intermediate, including the core-count
adjustment and clamp input. Clamp the value in int, then cast the final clamped
result to int8_t when returning, preserving the existing bounds and behavior.
---
Nitpick comments:
In `@src/dbwrapper.h`:
- Around line 338-345: Update the StoragePath() accessor in CDBWrapper to be
const-qualified, preserving its existing read-only behavior and return values so
it can be called through a const CDBWrapper reference.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: bbd6e530-cc5f-4077-98be-a3ee5b67e71f
📒 Files selected for processing (66)
ci/dash/lint-tidy.shdoc/design/assumeutxo.mddoc/developer-notes.mdsrc/Makefile.amsrc/bench/load_external.cppsrc/bitcoin-chainstate.cppsrc/chainlock/signing.cppsrc/chainlock/signing.hsrc/coinjoin/client.cppsrc/coinjoin/client.hsrc/coinjoin/coinjoin.cppsrc/coinjoin/coinjoin.hsrc/coinjoin/walletman.cppsrc/coinjoin/walletman.hsrc/dbwrapper.cppsrc/dbwrapper.hsrc/index/base.cppsrc/index/base.hsrc/init.cppsrc/instantsend/net_instantsend.cppsrc/instantsend/net_instantsend.hsrc/instantsend/signing.cppsrc/instantsend/signing.hsrc/kernel/checks.cppsrc/kernel/checks.hsrc/kernel/coinstats.cppsrc/kernel/coinstats.hsrc/kernel/mempool_persist.cppsrc/kernel/mempool_persist.hsrc/llmq/blockprocessor.cppsrc/llmq/blockprocessor.hsrc/llmq/signing.hsrc/node/blockstorage.cppsrc/node/blockstorage.hsrc/node/chainstate.cppsrc/node/chainstate.hsrc/node/interfaces.cppsrc/node/miner.cppsrc/node/miner.hsrc/node/utxo_snapshot.cppsrc/node/utxo_snapshot.hsrc/rpc/blockchain.cppsrc/rpc/blockchain.hsrc/rpc/mempool.cppsrc/rpc/mining.cppsrc/rpc/rawtransaction.cppsrc/rpc/txoutproof.cppsrc/streams.hsrc/test/coinstatsindex_tests.cppsrc/test/fuzz/mempool_utils.hsrc/test/fuzz/tx_pool.cppsrc/test/net_tests.cppsrc/test/util/chainstate.hsrc/test/util/setup_common.cppsrc/test/util/setup_common.hsrc/test/util/validation.hsrc/test/validation_chainstate_tests.cppsrc/test/validation_chainstatemanager_tests.cppsrc/test/validation_flush_tests.cppsrc/txdb.hsrc/txmempool.hsrc/validation.cppsrc/validation.htest/functional/feature_init.pytest/lint/lint-circular-dependencies.pytest/sanitizer_suppressions/tsan
💤 Files with no reviewable changes (1)
- test/functional/feature_init.py
ff6b46b to
bb0378e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bb0378e607
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
bb0378e to
52ef36c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 52ef36c57a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@coderabbitai review |
✅ Action performedReview finished.
|
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Policy gate: an agent-reported missing upstream prerequisite was restored as a blocking finding. This PR is a full Bitcoin backport, and omitted upstream hunks require their prerequisite PRs unless the finding is explicitly allowlisted (intentional_exclusion / policy_override). The agent's original evidence is preserved in the finding(s) below.
Prior verifier summary (overridden by policy gate): PR #7451 (assumeutxo M1/7 backport: bitcoin#25308, bitcoin#24513, bitcoin#25667, bitcoin#26828) is functionally sound at head 52ef36c57ab — no consensus-affecting defect was found. Six non-blocking issues survive independent verification against the live source and PR body: a standalone-build hazard in the squashed bitcoin#25667 commit, a latent dangling-reference bug in a test helper, two PR-body inaccuracies, an unrelated scope-creep commit, and a narrow soft-prerequisite gap around reindex-chainstate error handling. The prior bitcoin#21009/NeedsRedownload claim was refuted from first principles as SegWit-specific and architecturally inapplicable to Dash.
Source: reviewers gpt-5.6-sol and claude-sonnet-5 (general, dash-core-commit-history, backport-reviewer); verifier claude-sonnet-5.
Note: GitHub does not allow PastaClaw to submit REQUEST_CHANGES on its own PR, so the canonical blocking verdict is posted as a COMMENT.
🔴 9 blocking | 🟡 3 suggestion(s) | 💬 3 nitpick(s)
5 additional finding(s) omitted (not in diff).
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/test/util/setup_common.h`:
- [SUGGESTION] src/test/util/setup_common.h:221-224: Squashed bitcoin#25667 merge commit (3ed61a861ad) does not build standalone
Verified directly: at commit 3ed61a861ad, src/test/validation_chainstatemanager_tests.cpp's SnapshotTestSetup constructor calls `TestChain100Setup{{}, {}, /*coins_db_in_memory=*/false, /*block_tree_db_in_memory=*/false}` (4 arguments), but that exact commit's setup_common.h:222 declares only the 2-argument `TestChain100Setup(chain_name, extra_args)`. Checking out 3ed61a861ad alone is a compile error — the following commit, cc49052fb15, is required to widen the constructor. This breaks `git bisect` across that boundary and violates the project's own commit-atomicity convention (CLAUDE.md: 'Each commit should build and make sense on its own').
- [BLOCKING] src/test/util/setup_common.h:221-224: [Carried forward from p2, STILL VALID under new SHA] 3ed61a861ad (bitcoin#25667 merge) still does not build standalone; cc49052fb15 still exists only to repair it
The branch was rebased since the last review — the prior-reported commit 19c3ee07885 no longer exists in this branch's ancestry, replaced by 3ed61a861ad (content-diffed and confirmed near-identical plus the new review-follow-up hunks described in the finding above). The underlying defect is unchanged: at 3ed61a861ad, src/test/validation_chainstatemanager_tests.cpp's `SnapshotTestSetup() : TestChain100Setup{{}, {}, /*coins_db_in_memory=*/false, /*block_tree_db_in_memory=*/false}` calls a 4-argument constructor, but that same commit's src/test/util/setup_common.h:222 still declares only `TestChain100Setup(const std::string& chain_name = ..., const std::vector<const char*>& extra_args = {})` (2 parameters) — a compile error if checked out alone. The next commit, cc49052fb15 ('backport: adapt Dash chainstate init and tests for bitcoin#25667', the rebased successor of ea68d3b2ed0), widens the constructor to 4 parameters. Squash the constructor-signature widening into 3ed61a861ad so every commit in the stack builds independently and git bisect remains usable.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
In `src/test/validation_chainstatemanager_tests.cpp`:
- [SUGGESTION] src/test/validation_chainstatemanager_tests.cpp:387-421: SimulateNodeRestart() leaves clhandler and peerman holding dangling ChainstateManager references
Verified directly: SimulateNodeRestart() calls DashChainstateSetupClose(m_node) (src/node/chainstate.cpp:233-245), which only resets chain_helper, llmq_ctx, and dmnman, then replaces m_node.chainman with a new ChainstateManager (line 419). It never touches m_node.clhandler or m_node.peerman. Both chainlock::ChainlockHandler::m_chainman (src/chainlock/handler.h:47) and PeerManagerImpl::m_chainman (src/net_processing.cpp:821) are ChainstateManager& reference members bound once at fixture construction — after restart, both still reference the destroyed manager. Currently latent (neither component is exercised through this path in the test), but a future test invoking clhandler/peerman after SimulateNodeRestart() would use freed memory. Recreate or reset both alongside the chainman replacement.
- [BLOCKING] src/test/validation_chainstatemanager_tests.cpp:387-421: Restart adaptation retains references to the destroyed ChainstateManager
STILL VALID; carried forward from p2. SimulateNodeRestart() stops the txindex, resets governance and the Dash chainstate helper hierarchy, then destroys and replaces m_node.chainman. DashChainstateSetupClose() resets chain_helper, llmq_ctx, and dmnman, but does not reset m_node.clhandler or m_node.peerman. Those objects retain ChainstateManager references established against the destroyed instance. The latest delta expands restart coverage but does not repair these references. Recreate or clear both manager-dependent objects around the replacement.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
In `src/node/chainstate.cpp`:
- [SUGGESTION] src/node/chainstate.cpp:64-69: Reindex-time snapshot-deletion failure returns generic FAILURE instead of upstream's FAILURE_FATAL, with a narrow user-facing quirk for -reindex-chainstate-only runs
Dash's ChainstateLoadStatus enum (src/node/chainstate.h:56) has no FAILURE_FATAL value — that's added upstream by bitcoin#27862, which this PR correctly defers to M3 (it depends on bitcoin#25740's SnapshotCompletionResult). The adapted code at chainstate.cpp:69 returns plain FAILURE when snapshot deletion fails during a reindex. I verified the actual behavioral impact in src/init.cpp:2076-2112: when `-reindex` is set, FAILURE and FAILURE_INCOMPATIBLE_DB both short-circuit to InitError() with no difference in practice, so the originally-claimed 'prompts to rebuild while already reindexing' UX bug does NOT occur for plain -reindex. It does occur, narrowly, when only `-reindex-chainstate` (not `-reindex`) is passed and snapshot deletion fails: `!options.reindex` is then true, so the code prompts 'restart with -reindex or -reindex-chainstate to recover' even though -reindex-chainstate was already what triggered the failure. This is a real but narrow, non-crashing edge case tied to the already-acknowledged M3 deferral, not a new defect introduced by this PR's own code.
- [BLOCKING] src/node/chainstate.cpp:173-180: Missing prerequisite: bitcoin#21009
STILL VALID; consolidates p5 and p7. Upstream bitcoin#25308 starts from a LoadChainstate path containing Chainstate::NeedsRedownload() and the witness-insufficiently-validated result introduced by bitcoin#21009 (merge 19a56d1519f, implementation commit d831e711cab). bitcoin#25308 transforms that check into the new ChainstateLoadResult form. Dash's pre-PR and current paths instead leave the chainstate-loading loop at lines 173-180 and proceed directly to Dash database migrations, with no NeedsRedownload check or explicit PR-description exclusion for bitcoin#21009. Dash lacks SegWit machinery, but the authoritative classification rule says an absent subsystem is not by itself evidence of intentional divergence when a PR claims the complete upstream PR. Backport bitcoin#21009 or explicitly document this permanent Dash-specific exclusion.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
- [BLOCKING] src/node/chainstate.cpp:64-69: New in this delta: reindex-time snapshot deletion (adapted from bitcoin#27596/c711ca186f8) silently downgrades FAILURE_FATAL to FAILURE, a soft prerequisite gap from bitcoin#27862
This code block is new since the last review (it does not exist in the prior-reviewed commit; independently confirmed via `diff <(git show 3ed61a861ad) <(git show 19c3ee07885)`, which shows it introduced under a 'Review follow-ups' note in the #25667 merge commit message: 'Adapt c711ca186f8 from bitcoin#27596 so reindex modes delete a persisted snapshot before database initialization'). Upstream's actual c711ca186f8 (bitcoin#27596, 'assumeutxo: remove snapshot during -reindex{-chainstate}') returns `ChainstateLoadStatus::FAILURE_FATAL` on deletion failure: `return {ChainstateLoadStatus::FAILURE_FATAL, Untranslated("Couldn't remove snapshot chainstate.")};`. Dash's adaptation at line 69 instead returns `ChainstateLoadStatus::FAILURE` because Dash's `enum class ChainstateLoadStatus` (src/node/chainstate.h) only has `{SUCCESS, FAILURE, FAILURE_INCOMPATIBLE_DB, INTERRUPTED}` — no `FAILURE_FATAL`. Traced the origin: `FAILURE_FATAL` is added to the enum by bitcoin#27862 commit 9047337d369d800e6eca4d3b686139073a8e8905 ('validation: Stricter assumeutxo error handling in LoadChainstate'), confirmed via `--follow` history pickaxe on src/node/chainstate.h. That same commit references `SnapshotCompletionResult::SUCCESS` (from bitcoin#25740), so bitcoin#27862 genuinely cannot be cleanly backported without #25740 — consistent with, and validating, this PR's own stated reason for deferring #27862 to M3. The practical effect on Dash's current code: in src/init.cpp:2089-2097, `FAILURE_INCOMPATIBLE_DB` is special-cased to abort immediately, but plain `FAILURE` (which this new reindex-deletion failure now returns) falls through to the generic path that prompts the user 'Do you want to rebuild the block database now? ... restart with -reindex or -reindex-chainstate to recover' — even though the failure occurred while a `-reindex`/`-reindex-chainstate` request was already being processed (retrying the same flag cannot fix a stuck/locked snapshot-directory deletion). This is a real, if narrow and non-crashing, UX/behavior degradation traceable to a missing prerequisite (bitcoin#27862), not a Dash-specific design choice. Given #25740/#27862 are correctly out of M1 scope, the pragmatic fix is not to backport them here, but to document this specific known limitation (either in the PR body's existing #27862 exclusion note, or as a code comment at line 69) so it isn't mistaken for an oversight in a later milestone.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
In `(PR description)`:
- [BLOCKING] (PR description): Backport-prerequisite items (bitcoin#21009/NeedsRedownload, bitcoin#21110 chrono check) — out of this role's scope entirely
Per review.md, prerequisite analysis is owned exclusively by the backport-reviewer specialist. Noting only that the PR body now contains new audit text ('bitcoin#21585 was audited and found already present...', 'bitcoin#27862 ... moved to M3', and the existing '### Intentional exclusion: bitcoin#21110' section) that appears responsive to some of the prior policy-restored prerequisite findings; the backport-reviewer lane should make the actual determination at this exact head.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
- [BLOCKING] (PR description): Snapshot persistence remains attributed to the wrong upstream PR
STILL VALID; consolidates p3, p6, and p9. The supplied PR context continues to attribute the chainstate_snapshot directory and persistence to bitcoin#25308. Upstream bitcoin#25308 only introduces the LoadChainstate options, status, and result refactor. The directory rename and persisted base_blockhash come from bitcoin#25667, including f9f1735f139. The implementation is present, so this is a metadata issue rather than a missing code prerequisite; move the persistence wording to the bitcoin#25667 entry.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
In `src/validation.cpp`:
- [BLOCKING] src/validation.cpp:5822-5829: Missing prerequisite: bitcoin#25740 before the bitcoin#27596 follow-up
NEW IN THE LATEST DELTA. Commit 3ed61a861ad explicitly imports c711ca186f8 from bitcoin#27596. That upstream commit starts after bitcoin#25740 (merge d5e4f9a4395), which factors chainstate initialization and adds background-validation completion state. Dash has not backported that starting state, so DeleteSnapshotChainstate is rewritten to discover the directory directly because the snapshot has no initialized CoinsViews. The current comment states this difference explicitly, making it a workaround for not-yet-backported upstream content rather than a Dash architectural divergence. The adaptation is coherent and tested, so this is a soft, non-blocking per the agent (restored to blocking by policy) prerequisite gap; document the partial bitcoin#27596 backport and its bitcoin#25740 dependency, or stage it after bitcoin#25740.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
In `<commit:3ed61a861ad>`:
- [BLOCKING] <commit:3ed61a861ad>:1: The bitcoin#25667 commit is not independently buildable
STILL VALID; carried forward from p1 with rewritten commit hashes. At 3ed61a861ad, SnapshotTestSetup calls TestChain100Setup with four arguments, while that exact commit's src/test/util/setup_common.h still declares only the two-argument constructor. The following Dash adaptation commit cc49052fb15 adds the database-option parameters. The final head contains the repair, but the upstream backport commit itself cannot compile. Move the required constructor adaptation into 3ed61a861ad or otherwise restructure the pair so every permanent commit builds independently.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
In `src/init.cpp`:
- [BLOCKING] src/init.cpp:2031-2037: The unrelated parbls fix remains outside the advertised backport scope
STILL VALID; carried forward from p4. The tail commit 52ef36c57ab fixes pre-existing -parbls truncation but is not part of bitcoin#25308, #24513, #25667, or #26828. The fix itself introduces no prerequisite gap. Mention it in the PR description or move it to a separate change so the advertised backport ledger matches the reachable commit stack.
---
**Policy gate (backport-prereq-restore):** For full upstream backport PRs, a missing prerequisite is blocking unless the finding is explicitly allowlisted (e.g. `intentional_exclusion: true` or a matching entry in `policy_overrides`). The agent's original evidence above is the basis for this block; either backport the prerequisite or annotate the intentional exclusion in the PR description.
52ef36c to
ef11d90
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef11d9069a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/dbwrapper.h (1)
338-344: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider marking
StoragePath()const.It's a pure accessor with no mutation, consistent with
Read/Exists/etc. which are alreadyconst.♻️ Proposed fix
- std::optional<fs::path> StoragePath() { + std::optional<fs::path> StoragePath() const {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/dbwrapper.h` around lines 338 - 344, Mark the StoragePath() accessor as const, matching the existing const-qualified read-only methods such as Read and Exists, without changing its return behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/dbwrapper.h`:
- Around line 338-344: Mark the StoragePath() accessor as const, matching the
existing const-qualified read-only methods such as Read and Exists, without
changing its return behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: fdfa8010-0fea-412f-b735-5423f14bf082
📥 Commits
Reviewing files that changed from the base of the PR and between 52ef36c57ab4ad043ed055a9fd450a7729296145 and ef11d9069a14115ec39a9814d5ef792c60a8cbe8.
📒 Files selected for processing (20)
doc/design/assumeutxo.mdsrc/Makefile.amsrc/dbwrapper.cppsrc/dbwrapper.hsrc/init.cppsrc/node/blockstorage.cppsrc/node/chainstate.cppsrc/node/utxo_snapshot.cppsrc/node/utxo_snapshot.hsrc/streams.hsrc/test/util/chainstate.hsrc/test/util/setup_common.cppsrc/test/util/setup_common.hsrc/test/validation_chainstate_tests.cppsrc/test/validation_chainstatemanager_tests.cppsrc/txdb.hsrc/validation.cppsrc/validation.htest/functional/feature_init.pytest/lint/lint-circular-dependencies.py
💤 Files with no reviewable changes (1)
- test/functional/feature_init.py
🚧 Files skipped from review as they are similar to previous changes (11)
- src/dbwrapper.cpp
- test/lint/lint-circular-dependencies.py
- src/txdb.h
- doc/design/assumeutxo.md
- src/node/blockstorage.cpp
- src/streams.h
- src/node/utxo_snapshot.h
- src/node/chainstate.cpp
- src/test/util/chainstate.h
- src/validation.h
- src/validation.cpp
ef11d90 to
7d207dc
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7d207dc5f4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/test/validation_chainstatemanager_tests.cpp`:
- Around line 400-435: Update SimulateNodeRestart to reset m_node.peerman before
destroying and recreating m_node.chainman. Ensure the peer manager is torn down
while the existing ChainstateManager is still valid, before
m_node.chainman.reset(new ChainstateManager(...)), so no validation-interface
callbacks can use a dangling ChainstateManager reference.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 0ecc9e85-2c30-4cb8-b41b-e71425f1b06f
📥 Commits
Reviewing files that changed from the base of the PR and between ef11d9069a14115ec39a9814d5ef792c60a8cbe8 and 7d207dc5f42a23abd76d26cadee58d375efb8f60.
📒 Files selected for processing (20)
doc/design/assumeutxo.mdsrc/Makefile.amsrc/dbwrapper.cppsrc/dbwrapper.hsrc/init.cppsrc/node/blockstorage.cppsrc/node/chainstate.cppsrc/node/utxo_snapshot.cppsrc/node/utxo_snapshot.hsrc/streams.hsrc/test/util/chainstate.hsrc/test/util/setup_common.cppsrc/test/util/setup_common.hsrc/test/validation_chainstate_tests.cppsrc/test/validation_chainstatemanager_tests.cppsrc/txdb.hsrc/validation.cppsrc/validation.htest/functional/feature_init.pytest/lint/lint-circular-dependencies.py
💤 Files with no reviewable changes (1)
- test/functional/feature_init.py
🚧 Files skipped from review as they are similar to previous changes (11)
- src/Makefile.am
- src/streams.h
- src/txdb.h
- doc/design/assumeutxo.md
- src/dbwrapper.cpp
- src/node/blockstorage.cpp
- src/node/utxo_snapshot.h
- src/test/validation_chainstate_tests.cpp
- src/node/chainstate.cpp
- src/init.cpp
- src/validation.cpp
|
@coderabbitai review |
✅ Action performedReview finished.
|
7d207dc to
4a319cd
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
✅ Action performedReview finished.
|
|
This pull request has conflicts, please rebase. |
✅ Action performedReview finished.
|
Upstream verification script: sed -i 's/CChainState/Chainstate/g' $(git grep -l CChainState ':(exclude)doc/release-notes*') Verification: PASS. Applying the replacement to the parent tree reproduces this commit exactly across all 51 affected files, with no missing, unexpected, or non-mechanical changes.
Upstream commits: d14bebf db: add StoragePath to CDBWrapper/CCoinsViewDB f9f1735 validation: rename snapshot chainstate dir 252abd1 init: add utxo snapshot detection 34d1590 add utilities for deleting on-disk leveldb data ad67ff3 validation: remove snapshot datadirs upon validation failure 8153bd9 blockmanager: avoid undefined behavior during FlushBlockFile 3a29dfb move-only: test: make snapshot chainstate setup reusable 00b357c validation: add ResetChainstates() 3c36139 test: add reset_chainstate parameter for snapshot unittests 51fc924 test: allow on-disk coins and block tree dbs in tests cced4e7 test: move-only-ish: factor out LoadVerifyActivateChainstate() e4d7995 test: add testcases for snapshot initialization bf95976 doc: add note about snapshot chainstate init
Thread on-disk database options through Dash's generalized TestChainSetup hierarchy, and make snapshot restart tests tear down and recreate Dash managers and txindex around ChainstateManager replacement.
…ad of two exist checks
fe6da7c to
912c108
Compare
|
I believe some of the automated code review from rabbit / openai are flagging issues bitcoin fixes later; and we fix in later prs in the stacked series. |
✅ Action performedReview finished.
|
thepastaclaw
left a comment
There was a problem hiding this comment.
Preliminary review — Codex only
At exact HEAD 912c108, one blocking commit-history defect remains: cc4903f uses constructor parameters added only by a1a2448. SimulateNodeRestart() also leaves ChainlockHandler and PeerManager bound to the destroyed ChainstateManager; the PeerManager regression was introduced by the latest rebase. The historical review artifact was read, the checkout and commit boundaries were verified, and git diff --check passed. No local test binary was available.
Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (failed),gpt-5.6-sol— dash-core-commit-history (failed),gpt-5.6-sol— backport-reviewer (failed),gpt-5.6-sol— general (completed),gpt-5.6-sol— dash-core-commit-history (completed),gpt-5.6-sol— backport-reviewer (completed) - Verifier:
gpt-5.6-sol— verifier - Sonnet: not run (deferred by blocker gate)
🔴 1 blocking | 🟡 2 suggestion(s)
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/test/validation_chainstatemanager_tests.cpp`:
- [BLOCKING] src/test/validation_chainstatemanager_tests.cpp:189-194: bitcoin#25667 cherry-pick is not independently buildable
Commit cc4903f2b85 constructs SnapshotTestSetup with four TestChain100Setup arguments, but that commit's setup_common.h declares only the two-argument constructor. The required coins_db_in_memory and block_tree_db_in_memory plumbing first appears in a1a24480661. Upstream merge 6912a28f08c included the fixture call and constructor widening in one transformation, so checking out or bisecting to the permanent bitcoin#25667 import produces a compile error. Move the constructor-plumbing hunks into cc4903f2b85 or place them in a coherent preparatory commit before it.
- [SUGGESTION] src/test/validation_chainstatemanager_tests.cpp:387-419: Dash restart adaptation leaves ChainlockHandler bound to the destroyed manager
SimulateNodeRestart() destroys m_node.chainman without destroying or recreating m_node.clhandler. ChainTestingSetup constructs that handler with the original ChainstateManager&, ChainlockHandler stores it as the direct reference m_chainman, and DashChainstateSetupClose() does not own the handler. The current test does not exercise a chainstate-dependent ChainLocks operation after restart, but the fixture retains a dangling reference. Stop and reset the handler before replacing the manager, then recreate it against the replacement if the restarted fixture needs ChainLocks.
- [SUGGESTION] src/test/validation_chainstatemanager_tests.cpp:387-419: Latest rebase restores a dangling PeerManager reference
The 5686926e92e..912c10871b1 delta removes m_node.peerman.reset() before m_node.chainman is destroyed and replaced. PeerManagerImpl stores the original manager as the direct reference m_chainman, and LoadVerifyActivateChainstate() does not recreate PeerManager. The current test does not invoke peer processing after restart, but the fixture leaves PeerManager attached to freed state. Reset PeerManager while the old manager is alive and recreate it, including the connection-manager message-processor binding, if later fixture operations require peer processing.
GitHub does not permit an author to request changes on its own PR. This review is posted as a comment; the preliminary gate remains blocked by the validated blocker above.
| SnapshotTestSetup() : TestChain100Setup{ | ||
| CBaseChainParams::REGTEST, | ||
| {}, | ||
| /*coins_db_in_memory=*/false, | ||
| /*block_tree_db_in_memory=*/false, | ||
| } |
There was a problem hiding this comment.
🔴 Blocking: bitcoin#25667 cherry-pick is not independently buildable
Commit cc4903f constructs SnapshotTestSetup with four TestChain100Setup arguments, but that commit's setup_common.h declares only the two-argument constructor. The required coins_db_in_memory and block_tree_db_in_memory plumbing first appears in a1a2448. Upstream merge 6912a28 included the fixture call and constructor widening in one transformation, so checking out or bisecting to the permanent bitcoin#25667 import produces a compile error. Move the constructor-plumbing hunks into cc4903f or place them in a coherent preparatory commit before it.
source: ['codex']
| ChainstateManager& SimulateNodeRestart() | ||
| { | ||
| ChainstateManager& chainman = *Assert(m_node.chainman); | ||
|
|
||
| BOOST_TEST_MESSAGE("Simulating node restart"); | ||
| // TestChainSetup owns a txindex connected to the old chainstate. Stop it | ||
| // before destroying that chainstate, just as TestChainSetup's destructor does. | ||
| IndexWaitSynced(*g_txindex); | ||
| g_txindex->Interrupt(); | ||
| g_txindex->Stop(); | ||
| SyncWithValidationInterfaceQueue(); | ||
| g_txindex.reset(); | ||
| { | ||
| LOCK(::cs_main); | ||
| for (Chainstate* cs : chainman.GetAll()) { | ||
| cs->ForceFlushStateToDisk(); | ||
| } | ||
| // Tear down Dash managers connected to the mempool and old chainstate | ||
| // before LoadVerifyActivateChainstate() recreates them below. | ||
| m_node.govman.reset(); | ||
| DashChainstateSetupClose(m_node); | ||
| chainman.ResetChainstates(); | ||
| BOOST_CHECK_EQUAL(chainman.GetAll().size(), 0); | ||
| const ChainstateManager::Options chainman_opts{ | ||
| .chainparams = ::Params(), | ||
| .adjusted_time_callback = GetAdjustedTime, | ||
| }; | ||
| // For robustness, ensure the old manager is destroyed before creating a | ||
| // new one. | ||
| m_node.chainman.reset(); | ||
| m_node.chainman.reset(new ChainstateManager(chainman_opts)); | ||
| } | ||
| return *Assert(m_node.chainman); |
There was a problem hiding this comment.
🟡 Suggestion: Dash restart adaptation leaves ChainlockHandler bound to the destroyed manager
SimulateNodeRestart() destroys m_node.chainman without destroying or recreating m_node.clhandler. ChainTestingSetup constructs that handler with the original ChainstateManager&, ChainlockHandler stores it as the direct reference m_chainman, and DashChainstateSetupClose() does not own the handler. The current test does not exercise a chainstate-dependent ChainLocks operation after restart, but the fixture retains a dangling reference. Stop and reset the handler before replacing the manager, then recreate it against the replacement if the restarted fixture needs ChainLocks.
source: ['codex']
| ChainstateManager& SimulateNodeRestart() | ||
| { | ||
| ChainstateManager& chainman = *Assert(m_node.chainman); | ||
|
|
||
| BOOST_TEST_MESSAGE("Simulating node restart"); | ||
| // TestChainSetup owns a txindex connected to the old chainstate. Stop it | ||
| // before destroying that chainstate, just as TestChainSetup's destructor does. | ||
| IndexWaitSynced(*g_txindex); | ||
| g_txindex->Interrupt(); | ||
| g_txindex->Stop(); | ||
| SyncWithValidationInterfaceQueue(); | ||
| g_txindex.reset(); | ||
| { | ||
| LOCK(::cs_main); | ||
| for (Chainstate* cs : chainman.GetAll()) { | ||
| cs->ForceFlushStateToDisk(); | ||
| } | ||
| // Tear down Dash managers connected to the mempool and old chainstate | ||
| // before LoadVerifyActivateChainstate() recreates them below. | ||
| m_node.govman.reset(); | ||
| DashChainstateSetupClose(m_node); | ||
| chainman.ResetChainstates(); | ||
| BOOST_CHECK_EQUAL(chainman.GetAll().size(), 0); | ||
| const ChainstateManager::Options chainman_opts{ | ||
| .chainparams = ::Params(), | ||
| .adjusted_time_callback = GetAdjustedTime, | ||
| }; | ||
| // For robustness, ensure the old manager is destroyed before creating a | ||
| // new one. | ||
| m_node.chainman.reset(); | ||
| m_node.chainman.reset(new ChainstateManager(chainman_opts)); | ||
| } | ||
| return *Assert(m_node.chainman); |
There was a problem hiding this comment.
🟡 Suggestion: Latest rebase restores a dangling PeerManager reference
The 5686926e92e..912c108 delta removes m_node.peerman.reset() before m_node.chainman is destroyed and replaced. PeerManagerImpl stores the original manager as the direct reference m_chainman, and LoadVerifyActivateChainstate() does not recreate PeerManager. The current test does not invoke peer processing after restart, but the fixture leaves PeerManager attached to freed state. Reset PeerManager while the old manager is alive and recreate it, including the connection-manager message-processor binding, if later fixture operations require peer processing.
source: ['codex']
…tence (bitcoin#25308, bitcoin#24513, bitcoin#25667, bitcoin#26828)" This reverts commit f153015, reversing changes made to f435ae5.
Revert changes that introduced by non-backported yet bitcoin#31061 Set default value for worker_count Move data_dir, mn_metaman, sporkman, chainlocks, mn_sync to node::ChainstateLoadOptions same as mempool is done Pass notify_bls_state to VerifyLoadedChainstate only Added missing changes for strLoadError from bitcoin#25308 Added missing changes for node::fPruneMode node::fReindex from bitcoin#25308 Fixed duplicated entities in src/test/util/setup_common.cpp as follow-up for bitcoin#25290
…ted changes] a3fdcd6 refactor: address review feedback for #7471 (UdjinM6) 570a202 fix: disconnect mempool from managers before dmnman and isman dtor (Konstantin Akimov) bf1608e fix: follow-up changes for #7451 [bitcoin#25308 and related] (Konstantin Akimov) 0774f56 refactor: inline methods DashChainstateSetupClose and DashChainstateSetup (Konstantin Akimov) 513261c refactor: move const DEFAULT_MAX_RECOVERED_SIGS_AGE to llmq/options (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented Follow-up changes for #7451 ## What was done? - fixed issue with calling dtor of isman after DisconnectManager from mempool - inline methods DashChainstateSetupClose and DashChainstateSetup They are pretty trivial and simple but they are obstacle to backport bitcoin#25308 as close as possible due to un-needed complexity - Revert changes that introduced by non-backported yet bitcoin#31061 - Set default value for bls_threads, worker_count, max_recsigs_age - Move chainhelper, evodb, dmnman, llmq_ctx, data_dir, mn_metaman, sporkman, chainlocks, mn_sync to node::ChainstateLoadOptions the same as mempool exists here by 25308 - Pass notify_bls_state to VerifyLoadedChainstate only and add TODO to remove it completely - Added missing changes for strLoadError from bitcoin#25308 - Added missing changes for node::fPruneMode node::fReindex from bitcoin#25308 - Fixed duplicated entities in src/test/util/setup_common.cpp as follow-up for bitcoin#25290 ## How Has This Been Tested? Run unit & functional tests ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK a3fdcd6 Tree-SHA512: a87774e0006923e5f56ad05549443c900d488199d66ac4c9a8601b0df4486e3b81a8621fedde54b1c2d1e49d7045ca9b1d2dfc54ab039a903a0eac3cc090aa87
…on and subsystem gating 066fca8 validation: discard snapshot state when the snapshot chainstate goes away (pasta) 6f2aabc evo: scope an open EvoDB transaction to the thread that began it (pasta) 311efbc validation: establish the connecting chainstate's BLS scheme (pasta) 5639e45 dash: only swallow unavailable-history errors from GetListForBlock (pasta) a1fbefc dash: tolerate unavailable masternode list in scheduler-thread callbacks (pasta) 0e6172d evo: resolve transaction-less EvoDB access against the active chainstate (pasta) 7ff8231 evo: preserve EvoDB inconsistency classification across GetForBlock rethrow (pasta) ec7ec1a evo: abort node on WriteDerived mismatch instead of consensus rejection (pasta) 2cb2a02 test: adapt AssumeUTXO fixtures after txindex removal (Pasta) 341972d fix: canonicalize serialization of block-derived EvoDB payloads (Pasta) 8010353 dash: refuse masternode duty on unvalidated snapshots (Pasta) d3aea54 dash: guard serving unavailable snapshot history (Pasta) f5c93ce validation: suppress background chainstate notifications (Pasta) 2fc3c51 dash: bind block validation to the calling chainstate (Pasta) 8cd55e6 test: add dual-chainstate EvoDB consistency coverage (Pasta) 3775ae4 evo: wire per-chainstate transactions into validation (Pasta) 990d950 evo: make CEvoDB consistency state per-chainstate (Pasta) Pull request description: ## Issue being fixed or feature implemented [M1 (#7451)](#7451) added AssumeUTXO snapshot persistence, but Dash stores deterministic masternode, quorum, MNHF, and credit-pool state in a shared EvoDB. Running the snapshot and background chainstates concurrently therefore requires independent EvoDB transaction state and markers, chain-aware Dash validation, and protection against emitting or signing from the wrong chainstate. This is milestone 2 of the AssumeUTXO series. It supplies the Dash-specific multi-chainstate foundation required by the later background-completion and `loadtxoutset` milestones. ## What was done? - Added stable NORMAL and SNAPSHOT EvoDB identities, each with an independent transaction overlay, root batch, and best-block marker while retaining one physical EvoDB. - Added `WriteDerived` for immutable block-derived records. Independently derived values must serialize identically, including values pending in the other chainstate's overlay. - Wired block connect, disconnect, replay, verification, flushing, and snapshot activation to the calling chainstate's EvoDB identity. Snapshot activation now refuses a missing EvoDB marker instead of attaching snapshot coins to inconsistent Dash state. - Protected shared mined-quorum commitments from cross-chainstate erasure. - Passed the validating chainstate through Dash special-transaction and quorum processing. MNHF, asset-unlock, and quorum lookups now evaluate membership relative to the caller's chain instead of implicitly borrowing the active chain. - Suppressed active-tip, wallet, UI, and deterministic-masternode notifications from background validation. `BlockChecked` remains ungated because it reports validation results rather than active-tip changes. - Avoided penalizing peers when this snapshot-backed or pruned node cannot serve otherwise plausible masternode-list or quorum-rotation history. - Disabled DKG participation and quorum signing while an active snapshot remains unvalidated, including a final guard at the signature-share production boundary and clear RPC/status reporting. - Canonicalized serialization of block-derived masternode-list diffs and MNHF signals so logically identical values cannot produce false EvoDB mismatches. Review follow-ups (appended commits): - A `WriteDerived` mismatch is local EvoDB corruption, never evidence about the block. It now aborts the node with `M_ERROR` (matching the existing `EvoDbInconsistencyMessage` convention) instead of marking the block `BLOCK_CONSENSUS`-invalid and penalizing the relaying peer. A typed `EvoDbInconsistencyError` preserves that classification through the catch blocks on the miner, RPC, and MNHF-recomputation paths. - EvoDB access outside a `BeginTransaction` scope previously always bound to the NORMAL identity, so transaction-less consumers (RPC, mempool, miner, P2P serving) could not see snapshot-chain records pending in the SNAPSHOT overlay. `CEvoDB` now tracks a default identity that snapshot activation sets to SNAPSHOT and `ResetChainstates` resets; the background-completion milestone must reset it to NORMAL at marker promotion (TODO noted in code). - `GetListForBlockInternal` no longer fabricates an empty "initial snapshot" masternode list when a diff for a DIP3-active block is missing; it throws instead. The message deliberately carries the `IsBlockDataUnavailableError` sentinel and is deliberately a plain `runtime_error` rather than `EvoDbInconsistencyError`: at that layer a missing diff can be benign (pending in the other chainstate's unflushed overlay, e.g. while serving historical `mnlistdiff`), so it is reported as unavailable history without penalizing the requesting peer, and only definite mismatches abort the node. Scheduler-thread consumers (`CActiveMasternodeManager::UpdatedBlockTip`, governance trigger creation) catch it and skip the update, since an uncaught exception there would terminate the node. Second review round (appended commits): - `bls::bls_legacy_scheme` is process-wide, but the correct value belongs to the block being validated. `ConnectBlock` only saved and committed the flag; it never established it, and `ProcessSpecialTxsInBlock` switches legacy to basic only when crossing V19 forward. With an active post-V19 snapshot, the background chainstate therefore validated pre-V19 blocks under the basic scheme, and a background disconnect across V19 could commit legacy onto the active chain's consumers. `ConnectBlock` now enters under the scheme the block's parent left behind, and `ConnectTip`/`DisconnectTip` commit it only from the active chainstate. - The scheduler-thread guards caught every `std::exception`, so the plain `runtime_error`s that `CDeterministicMNList::ApplyDiff` raises for missing removals or updates, duplicate masternodes, and duplicate unique properties were logged as benign unavailable history while the active masternode stayed READY. The unavailable-history condition now has its own `BlockDataUnavailableError` type and is the only thing those guards (and `BuildSimplifiedMNListDiff`) catch; everything else propagates exactly as before the guards existed. - `CEvoDB::GetCurrentIdentity()` resolved to a process-wide `active_transaction`, so an open background NORMAL transaction redirected every concurrent transaction-less read away from the active snapshot's overlay. An open transaction is one validation execution context, not a process mode, so it now resolves only for the thread that began it. - Snapshot state could outlive the chainstate it describes in two ways, both fixed: `PopulateAndValidateSnapshot` commits the SNAPSHOT best-block and dual-chainstate markers as its last step, so abandoning activation afterwards (e.g. `WriteSnapshotBaseBlockhash` on an unwritable datadir) left a single-chainstate node carrying both; and `-reindex`/`-reindex-chainstate` wiped the shared EvoDB, erasing the SNAPSHOT marker while `chainstate_snapshot` stayed on disk, so startup failed on the erased marker with advice the user had already followed. Markers are now rolled back on abandoned activation, and the persisted snapshot chainstate's on-disk artifacts are discarded alongside the EvoDB wipe -- the Dash-shaped equivalent of the reindex-time cleanup in bitcoin#27596/bitcoin#29726, which runs before any chainstate has coins views and so needs no mempool transfer or leveldb-lock dance. The batch contains the original eight focused commits, a rebase fixture adaptation after the txindex removal, and eight review follow-up commits. The partial Bitcoin Core `BlockInfo` and `ChainstateRole` prerequisites were intentionally moved to the later `loadtxoutset` milestone where their APIs are first consumed. ## How Has This Been Tested? - Added focused EvoDB unit coverage for overlay isolation, tombstones, cross-overlay derived-value checks, independent marker flushing, disk mismatch rejection, and preservation of the legacy NORMAL marker key. - Added dual-chainstate integration coverage for restart consistency, snapshot-only flushing, shared quorum erasure, chain-aware commitment/quorum lookup, cache-order isolation, and suppression of background notifications. - Added canonical serialization coverage for deterministic masternode-list diffs. - Added `transaction_less_access_uses_default_identity` covering default-identity resolution of transaction-less reads and writes. Known gap: the DIP3-active missing-diff throw has no end-to-end unit test because regtest activates DIP3 at height 432, above the unit-test chain heights; it is covered by the serving-path catch and review. - Before the stack-only relocation of the two unused Bitcoin prerequisite commits, `make check` passed and the following functional subset passed: `feature_mnehf.py`, `feature_asset_locks.py`, `feature_dip3_deterministicmns.py` (both modes), `feature_llmq_signing.py` (both modes), `feature_llmq_rotation.py`, and `rpc_quorum.py`. - After the review follow-up commits: full rebuild plus `evo_db_tests`, `evo_deterministicmns_tests`, `evo_mnhf_tests`, `evo_assetlocks_tests`, and `validation_chainstatemanager_tests` pass (20 cases), and `lint-circular-dependencies` is clean. - After the second review round (rebased onto develop at e829261): full rebuild clean and the complete `test_dash` suite passes (815 cases). Each new regression test was negative-controlled -- `chainstate_connectblock_bls_scheme` fails on both halves of the BLS fix independently, `open_transaction_does_not_capture_other_threads` fails without the thread scoping, and `chainstatemanager_snapshot_discarded_on_reindex` reproduces the unrecoverable reindex before the fix. - Every rewritten commit passes `git diff-tree --check`. ## Breaking Changes No released-interface changes. Internally, `ActivateExistingSnapshot` becomes fallible so startup can reject a snapshot chainstate whose EvoDB marker is missing. Two RPC-visible additions while a snapshot is active and unvalidated: `masternode status` gains a `quorumParticipation` field and appends a "DKG participation and quorum signing disabled" clause to `status`, and `quorum sign` fails with an explanatory error. `AbstractEHFManager::Signals` changed from `std::unordered_map` to `std::map` (canonical serialization); the on-disk encoding is unchanged, but iteration order of EHF signals in `getblockchaininfo` output is now sorted. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation (the AssumeUTXO documentation update is part of a later milestone) - [ ] I have assigned this pull request to a milestone Top commit has no ACKs. Tree-SHA512: 9acaf1a789ba06aa30b3ac2a0d8e5b8380f8e03ac1aecda14115b2c7c75af1838ba355eda91a5b8ccc91a5f9054dfb0dbfec45054ae6a9375afa88ddc7aa7f38
Issue being fixed or feature implemented
This is milestone 1 of 7 in the stacked assumeutxo backport series. It restores the previously approved minimal snapshot-initialization groundwork needed by later milestones while preserving Dash-specific chainstate manager behavior.
bitcoin#27596is intentionally deferred to M5, when snapshots become user-loadable through the completed assumeutxo flow. M1 does not exposeloadtxoutsetand does not include any partial snapshot-deletion/reindex lifecycle from that later upstream change.What was done?
bitcoin#25308, reducingLoadChainstateparameters and return values through the upstream options/status plumbing while retaining Dash-specific options and the merged-parblsclamp.bitcoin#24513, the mechanicalCChainStatetoChainstaterename across 51 files (204 additions and 204 deletions).bitcoin#25667snapshot-initialization implementation.bitcoin#25667: test-fixture/database-option plumbing, teardown/recreation of Dash managers and txindex aroundChainstateManagerreplacement, and removal of a redundantcs_maindeclaration already supplied byvalidation.h.bitcoin#26828, catching and logging snapshot-pathfs::removeerrors.This branch contains no partial
bitcoin#27596behavior, crash-recovery hardening, reindex cleanup, manager-rebinding workaround, or unrelated-parblsfix. M2-M7 were not restacked by this update.How Has This Been Tested?
make -C src -j"$(sysctl -n hw.ncpu)" test/test_dash../src/test/test_dash --run_test=validation_chainstatemanager_tests(5 cases)../src/test/test_dash --run_test=validation_flush_tests(1 case)../src/test/test_dash --run_test=coinstatsindex_tests(2 cases)../src/test/test_dash --run_test=dbwrapper_tests(9 cases)../src/test/test_dash --run_test=blockmanager_tests(2 cases)../src/test/test_dash --run_test=validation_chainstate_testsreproduces the samechainstate_update_tipabort on the exact previously approved head183f168ef9d32a809fed0f8b51002f01bfb2bb77; this reconstruction intentionally does not change inherited approved-baseline behavior.=patch identity; commit 1 differs only by preserving the merged-parblsclamp through theLoadChainstaterefactor, and commit 4 differs only by removing the redundant declaration. The sole rebase conflict was resolved transformation-faithfully insrc/init.cpp.Breaking Changes
None. This is unreleased assumeutxo groundwork;
loadtxoutsetremains unavailable in M1.Checklist: