backport: assumeutxo M2 — EvoDB multi-chainstate isolation and subsystem gating - #7456
Draft
PastaPastaPasta wants to merge 13 commits into
Draft
backport: assumeutxo M2 — EvoDB multi-chainstate isolation and subsystem gating#7456PastaPastaPasta wants to merge 13 commits into
PastaPastaPasta wants to merge 13 commits into
Conversation
Member
Author
|
See https://gist.github.com/PastaPastaPasta/c5108775f7b126f88856cde20d7a8556 for ai generated commit by commit explanation. |
PastaPastaPasta
force-pushed
the
assumeutxo/m2-evodb-roles
branch
2 times, most recently
from
July 14, 2026 17:01
06b5c6f to
1a95697
Compare
|
This pull request has conflicts, please rebase. |
PastaPastaPasta
force-pushed
the
assumeutxo/m2-evodb-roles
branch
from
July 20, 2026 16:59
1a95697 to
a3c4476
Compare
5 tasks
PastaPastaPasta
force-pushed
the
assumeutxo/m2-evodb-roles
branch
from
July 25, 2026 00:07
a3c4476 to
26c8718
Compare
|
This pull request has conflicts, please rebase. |
Pass the validating chainstate through special transaction and quorum commitment processing instead of borrowing the active chainstate. Interpret mined-commitment records and quorum resolution relative to the caller's chain. The cached values remain reusable, but chain membership is reevaluated across reorgs and chainstates while public non-validation callers retain active-chain semantics. This prevents snapshot-seeded records from suppressing commitments or satisfying MNHF and asset-unlock quorum lookups during background validation. Add dual-chainstate coverage for a commitment seeded at a block not yet contained by the background chain, including HasQuorum and GetQuorum cache-order checks.
Emit block, tip, deterministic masternode-list, UI, and flush notifications only for the active chainstate. In particular, suppressing background ChainStateFlushed prevents a background locator from regressing wallet best-block state. Keep BlockChecked ungated because its subscribers are mining/block-submit and peer validation/relay accounting; it does not reach CMNAuth. Document all 21 B3 call-site dispositions and extend the dual-chainstate test with validation-interface and UI counters.
Check local block-data availability before building masternode-list diffs and quorum rotation info. Treat failures caused by pruning or an unvalidated snapshot base like pruned getdata: log and silently drop the plausible request without increasing the peer's misbehavior score. Malformed and implausible requests retain the pre-existing penalties.
Disable DKG participation and quorum signing until snapshot background validation completes. Enforce the refusal at CreateSigShare, the actual share-production boundary, so direct RPC, async, and queued signing paths cannot bypass it. The quorum sign RPC now returns a clear JSON-RPC error for both submit modes, and masternode status exposes the disabled participation state. Add unit coverage for the shared production-gate predicate across snapshot activation.
PastaPastaPasta
force-pushed
the
assumeutxo/m2-evodb-roles
branch
from
August 1, 2026 18:17
26c8718 to
b6edcf8
Compare
A WriteDerived failure means independently derived block data disagrees with the copy already recorded in EvoDB. That is local state corruption (or a cross-chainstate divergence bug), never evidence about the block being processed. Previously the mismatch surfaced as BLOCK_CONSENSUS: the block was persistently marked BLOCK_FAILED_VALID (surviving restart and forking the node off the network) and the relaying peer was handed a 100-point misbehavior score via BlockChecked, which background validation also triggers. Instead, follow the existing EvoDbInconsistencyMessage convention: request node shutdown via AbortNode and fail validation with M_ERROR, which neither marks the block invalid nor punishes peers. The credit-pool and MNHF sites abort at the throw site because miner and RPC callers never pass through a validation-state catch; a typed EvoDbInconsistencyError lets the four block-path catch blocks that would otherwise swallow it into BLOCK_CONSENSUS reclassify it as M_ERROR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ethrow CMNHFManager::GetForBlock re-throws internal ProcessBlock failures as a plain runtime_error, which would let a downstream generic catch misreport an EvoDB mismatch (M_ERROR) as a consensus failure. Re-throw typed when the validation state carries M_ERROR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reads and writes outside a BeginTransaction scope previously always bound to the NORMAL identity. While a snapshot chainstate is active, transaction-less consumers (RPC, mempool, miner, P2P serving) could not see snapshot-chain records still pending in the SNAPSHOT root overlay, and transaction-less writes dirtied the wrong overlay. CEvoDB now tracks a default identity which snapshot activation (ActivateSnapshot, ActivateExistingSnapshot) sets to SNAPSHOT and ResetChainstates resets; snapshot completion must reset it to NORMAL when marker promotion lands. Also make the GetListForBlockInternal fallback loud: a missing list diff for a DIP3-active block is pending-elsewhere or corrupt data, never the pre-DIP3 genesis of the masternode list, so throw instead of silently caching an empty list and clobbering m_initial_snapshot_index. The thrown message carries the IsBlockDataUnavailableError sentinel and BuildSimplifiedMNListDiff converts it into a serve failure, so peers requesting such history are not penalized. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GetListForBlock can now throw when list data is unavailable (missing diff for a DIP3-active block). CActiveMasternodeManager::UpdatedBlockTip and GovernanceSigner's trigger creation run on the scheduler thread, where an uncaught exception terminates the node; catch it there and skip the update instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PastaPastaPasta
force-pushed
the
assumeutxo/m2-evodb-roles
branch
from
August 1, 2026 22:40
11a31da to
5f3a876
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue being fixed or feature implemented
M1 (#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
loadtxoutsetmilestones.What was done?
WriteDerivedfor immutable block-derived records. Independently derived values must serialize identically, including values pending in the other chainstate's overlay.BlockCheckedremains ungated because it reports validation results rather than active-tip changes.Review follow-ups (appended commits):
WriteDerivedmismatch is local EvoDB corruption, never evidence about the block. It now aborts the node withM_ERROR(matching the existingEvoDbInconsistencyMessageconvention) instead of marking the blockBLOCK_CONSENSUS-invalid and penalizing the relaying peer. A typedEvoDbInconsistencyErrorpreserves that classification through the catch blocks on the miner, RPC, and MNHF-recomputation paths.BeginTransactionscope 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.CEvoDBnow tracks a default identity that snapshot activation sets to SNAPSHOT andResetChainstatesresets; the background-completion milestone must reset it to NORMAL at marker promotion (TODO noted in code).GetListForBlockInternalno 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 theIsBlockDataUnavailableErrorsentinel and is deliberately a plainruntime_errorrather thanEvoDbInconsistencyError: at that layer a missing diff can be benign (pending in the other chainstate's unflushed overlay, e.g. while serving historicalmnlistdiff), 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.The batch contains the original eight focused commits, a rebase fixture adaptation after the txindex removal, and four review follow-up commits. The partial Bitcoin Core
BlockInfoandChainstateRoleprerequisites were intentionally moved to the laterloadtxoutsetmilestone where their APIs are first consumed.How Has This Been Tested?
transaction_less_access_uses_default_identitycovering 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.make checkpassed 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, andrpc_quorum.py.evo_db_tests,evo_deterministicmns_tests,evo_mnhf_tests,evo_assetlocks_tests, andvalidation_chainstatemanager_testspass (20 cases), andlint-circular-dependenciesis clean.git diff-tree --check.Breaking Changes
No released-interface changes. Internally,
ActivateExistingSnapshotbecomes 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 statusgains aquorumParticipationfield and appends a "DKG participation and quorum signing disabled" clause tostatus, andquorum signfails with an explanatory error.AbstractEHFManager::Signalschanged fromstd::unordered_maptostd::map(canonical serialization); the on-disk encoding is unchanged, but iteration order of EHF signals ingetblockchaininfooutput is now sorted.Checklist: