-
Notifications
You must be signed in to change notification settings - Fork 1.2k
backport: assumeutxo M4 — evo snapshot format v3 and LLMQ reconstruction #7579
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
1d3b001
8c3485a
52d6a92
e396b35
8baac21
d3880a5
3cfd05d
34fc56a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,6 +42,12 @@ CEvoDB::CEvoDB(const util::DbWrapperParams& db_params) : | |
|
|
||
| CEvoDB::~CEvoDB() = default; | ||
|
|
||
| bool CEvoDB::HasActiveTransaction() | ||
| { | ||
| LOCK(cs); | ||
| return active_transaction.has_value(); | ||
| } | ||
|
|
||
| CEvoDB::TransactionContext& CEvoDB::GetContext(EvoDbIdentity identity) | ||
| { | ||
| auto it = transaction_contexts.find(identity); | ||
|
|
@@ -182,6 +188,37 @@ bool CEvoDB::ReadBackgroundMNListHash(uint256& block_hash, uint256& mn_list_hash | |
| return true; | ||
| } | ||
|
|
||
| void CEvoDB::WriteRequiredWorkMNListHashes(const std::vector<uint256>& block_hashes) | ||
| { | ||
| Write(EVODB_REQUIRED_WORK_MNLISTS, block_hashes); | ||
| } | ||
|
|
||
| bool CEvoDB::ReadRequiredWorkMNListHashes(std::vector<uint256>& block_hashes) | ||
| { | ||
| return Read(EVODB_REQUIRED_WORK_MNLISTS, block_hashes); | ||
| } | ||
|
|
||
| void CEvoDB::WriteBackgroundWorkMNListHash(const uint256& block_hash, const uint256& mn_list_hash) | ||
| { | ||
| Write(std::make_pair(EVODB_BACKGROUND_WORK_MNLIST_HASH, block_hash), mn_list_hash); | ||
| } | ||
|
|
||
| bool CEvoDB::ReadBackgroundWorkMNListHash(const uint256& block_hash, uint256& mn_list_hash) | ||
| { | ||
| return Read(std::make_pair(EVODB_BACKGROUND_WORK_MNLIST_HASH, block_hash), mn_list_hash); | ||
| } | ||
|
|
||
| static void EraseHistoricalMNListMarkers(CDBWrapper& db, CDBBatch& batch) | ||
| { | ||
| std::vector<uint256> required; | ||
| if (db.Read(EVODB_REQUIRED_WORK_MNLISTS, required)) { | ||
| for (const auto& block_hash : required) { | ||
| batch.Erase(std::make_pair(EVODB_BACKGROUND_WORK_MNLIST_HASH, block_hash)); | ||
| } | ||
| } | ||
| batch.Erase(EVODB_REQUIRED_WORK_MNLISTS); | ||
| } | ||
|
|
||
| bool CEvoDB::PromoteSnapshotMarkers(const uint256& expected_snapshot_tip) | ||
| { | ||
| LOCK(cs); | ||
|
|
@@ -198,7 +235,9 @@ bool CEvoDB::PromoteSnapshotMarkers(const uint256& expected_snapshot_tip) | |
| uint256 normal_tip; | ||
| const bool already_promoted = db->Read(EVODB_BEST_BLOCK, normal_tip) && normal_tip == expected_snapshot_tip && | ||
| !db->Exists(EVODB_DUAL_CHAINSTATE) && !db->Exists(EVODB_SNAPSHOT_MNLIST_HASH) && | ||
| !db->Exists(EVODB_BACKGROUND_MNLIST_HASH); | ||
| !db->Exists(EVODB_BACKGROUND_MNLIST_HASH) && | ||
| !db->Exists(EVODB_REQUIRED_WORK_MNLISTS) && | ||
| !db->Exists(EVODB_SNAPSHOT_EVO_SECTION); | ||
| if (already_promoted) m_default_identity = EvoDbIdentity::NORMAL; | ||
| return already_promoted; | ||
| } | ||
|
|
@@ -209,6 +248,8 @@ bool CEvoDB::PromoteSnapshotMarkers(const uint256& expected_snapshot_tip) | |
| batch.Erase(snapshot_key); | ||
| batch.Erase(EVODB_SNAPSHOT_MNLIST_HASH); | ||
| batch.Erase(EVODB_BACKGROUND_MNLIST_HASH); | ||
| EraseHistoricalMNListMarkers(*db, batch); | ||
| batch.Erase(EVODB_SNAPSHOT_EVO_SECTION); | ||
| batch.Erase(EVODB_DUAL_CHAINSTATE); | ||
| if (!db->WriteBatch(batch, /*fSync=*/true)) return false; | ||
| // The dual-chainstate run is over: the promoted state is the NORMAL | ||
|
|
@@ -231,6 +272,8 @@ bool CEvoDB::DiscardSnapshotMarkers() | |
| batch.Erase(std::make_pair(EVODB_BEST_BLOCK, uint8_t{1})); | ||
| batch.Erase(EVODB_SNAPSHOT_MNLIST_HASH); | ||
| batch.Erase(EVODB_BACKGROUND_MNLIST_HASH); | ||
| EraseHistoricalMNListMarkers(*db, batch); | ||
| batch.Erase(EVODB_SNAPSHOT_EVO_SECTION); | ||
| batch.Erase(EVODB_DUAL_CHAINSTATE); | ||
|
Comment on lines
+261
to
+277
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Remove or isolate seeded evo state when discarding a snapshot DiscardSnapshotMarkers() removes lifecycle metadata but not the snapshot-provided deterministic-MN snapshots, mined commitments and inverse-height indexes, rotation snapshots, quorum modifiers, credit-pool snapshot, or MNHF state committed under ordinary unprefixed EvoDB keys. EraseSnapshotMarkers() has the same problem if activation fails after seeding, such as when writing base_blockhash fails. After the invalid snapshot is quarantined and the process restarts, NORMAL reads can consume these records; CDeterministicMNManager::GetListForBlockInternal(), for example, checks DB_LIST_SNAPSHOT before reconstructing from NORMAL diffs. This defeats the promised fallback to independently validated state and can also make subsequent valid background derivations collide with rejected data. Snapshot-derived records need identity-isolated keys or a cleanup/promotion design that can atomically remove or replace every seeded record without deleting independently generated NORMAL state. source: ['codex'] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolved in this update — Remove or isolate seeded evo state when discarding a snapshot no longer present. Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread. |
||
| if (!db->WriteBatch(batch, /*fSync=*/true)) return false; | ||
| // The snapshot chainstate is gone; transaction-less access must resolve | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When background validation rejects a loaded snapshot, this batch removes only lifecycle metadata, while
PopulateAndValidateSnapshot()has already committed snapshot-providedDB_LIST_SNAPSHOT, quorum commitments/snapshots/modifiers, credit-pool, and MNHF records into the shared, unprefixed EvoDB namespace. After shutdown and restart, the restored NORMAL chainstate can consume those invalid records—for example,GetListForBlockInternal()checksDB_LIST_SNAPSHOTbefore reconstructing from NORMAL diffs—so the advertised fallback to independently validated state remains contaminated and can reproduce the mismatch or use rejected masternode/quorum state. The discard path must remove or replace every seeded record using the independently validated background state, or snapshot-derived records must be identity-isolated.AGENTS.md reference: AGENTS.md:L162-L180
Useful? React with 👍 / 👎.