Skip to content

backport: assumeutxo M2 — EvoDB multi-chainstate isolation and subsystem gating#7456

Draft
PastaPastaPasta wants to merge 9 commits into
dashpay:developfrom
PastaPastaPasta:assumeutxo/m2-evodb-roles
Draft

backport: assumeutxo M2 — EvoDB multi-chainstate isolation and subsystem gating#7456
PastaPastaPasta wants to merge 9 commits into
dashpay:developfrom
PastaPastaPasta:assumeutxo/m2-evodb-roles

Conversation

@PastaPastaPasta

Copy link
Copy Markdown
Member

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 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.

The batch contains eight focused 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.
  • 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.
  • Every rewritten commit passes git diff-tree --check. GitHub lint and build jobs are running against the current eight-commit head.

Breaking Changes

No external or released-interface changes. Internally, ActivateExistingSnapshot becomes fallible so startup can reject a snapshot chainstate whose EvoDB marker is missing.

Checklist:

  • 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 (the AssumeUTXO documentation update is part of a later milestone)
  • I have assigned this pull request to a milestone

@PastaPastaPasta

Copy link
Copy Markdown
Member Author

See https://gist.github.com/PastaPastaPasta/c5108775f7b126f88856cde20d7a8556 for ai generated commit by commit explanation.

@PastaPastaPasta
PastaPastaPasta force-pushed the assumeutxo/m2-evodb-roles branch from 014afb4 to 06b5c6f Compare July 14, 2026 05:10
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.
@github-actions

Copy link
Copy Markdown

This pull request has conflicts, please rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant