|
81 | 81 | #include <coinjoin/server.h> |
82 | 82 | #include <coinjoin/walletman.h> |
83 | 83 | #include <dsnotificationinterface.h> |
| 84 | +#include <evo/chainhelper.h> |
84 | 85 | #include <evo/deterministicmns.h> |
85 | 86 | #include <evo/evodb.h> |
86 | 87 | #include <evo/mnhftx.h> |
| 88 | +#include <evo/specialtxman.h> |
87 | 89 | #include <flat-database.h> |
88 | 90 | #include <governance/governance.h> |
89 | 91 | #include <instantsend/instantsend.h> |
@@ -751,6 +753,7 @@ void SetupServerArgs(ArgsManager& argsman) |
751 | 753 | argsman.AddArg("-checkmempool=<n>", strprintf("Run mempool consistency checks every <n> transactions. Use 0 to disable. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); |
752 | 754 | argsman.AddArg("-checkpoints", strprintf("Enable rejection of any forks from the known historical chain until block %s (default: %u)", defaultChainParams->Checkpoints().GetHeight(), DEFAULT_CHECKPOINTS_ENABLED), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); |
753 | 755 | argsman.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); |
| 756 | + argsman.AddArg("-forceevodbrepair", "Force evodb masternode list diff verification and repair on startup, even if already repaired (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); |
754 | 757 | argsman.AddArg("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); |
755 | 758 | argsman.AddArg("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); |
756 | 759 | argsman.AddArg("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); |
@@ -2408,6 +2411,53 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) |
2408 | 2411 | LogPrintf("Filling coin cache with masternode UTXOs: done in %dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start)); |
2409 | 2412 | } |
2410 | 2413 |
|
| 2414 | + if (fReindex || fReindexChainState) { |
| 2415 | + LogPrintf("Skipping evodb repair during reindex\n"); |
| 2416 | + node.dmnman->CompleteRepair(); // Mark as repaired since we're rebuilding fresh |
| 2417 | + } else if (node.dmnman->IsRepaired() && !args.GetBoolArg("-forceevodbrepair", false)) { |
| 2418 | + LogPrintf("Masternode list diffs are already repaired\n"); |
| 2419 | + } else { |
| 2420 | + const CBlockIndex* start_index; |
| 2421 | + const CBlockIndex* stop_index; |
| 2422 | + { |
| 2423 | + LOCK(cs_main); |
| 2424 | + const auto& consensus_params = Params().GetConsensus(); |
| 2425 | + start_index = chainman.ActiveChain()[consensus_params.DIP0003Height]; |
| 2426 | + stop_index = chainman.ActiveChain().Tip(); |
| 2427 | + } |
| 2428 | + |
| 2429 | + if (start_index && stop_index && start_index->nHeight < stop_index->nHeight) { |
| 2430 | + LogPrintf("Verifying and repairing masternode list diffs...\n"); |
| 2431 | + const auto start{SteadyClock::now()}; |
| 2432 | + // Create a callback that wraps CSpecialTxProcessor::BuildNewListFromBlock |
| 2433 | + auto build_list_func = [&node](const CBlock& block, gsl::not_null<const CBlockIndex*> pindexPrev, |
| 2434 | + const CDeterministicMNList& prevList, const CCoinsViewCache& view, |
| 2435 | + bool debugLogs, BlockValidationState& state, |
| 2436 | + CDeterministicMNList& mnListRet) -> bool { |
| 2437 | + return node.chain_helper->special_tx->RebuildListFromBlock(block, pindexPrev, prevList, view, debugLogs, state, mnListRet); |
| 2438 | + }; |
| 2439 | + auto result = node.dmnman->RecalculateAndRepairDiffs(start_index, stop_index, chainman, build_list_func, true); |
| 2440 | + |
| 2441 | + if (!result.verification_errors.empty()) { |
| 2442 | + LogPrintf("WARNING: Verification errors:\n%s\n", Join(result.verification_errors, "\n")); |
| 2443 | + } |
| 2444 | + |
| 2445 | + if (!result.repair_errors.empty()) { |
| 2446 | + // Critical errors occurred - reindex required |
| 2447 | + LogPrintf("Failed to repair masternode list diffs. Database corruption detected. " /* Continued */ |
| 2448 | + "Please restart with -reindex to rebuild the database.\n" |
| 2449 | + "Errors:\n%s\n", |
| 2450 | + Join(result.repair_errors, "\n")); |
| 2451 | + StartShutdown(); |
| 2452 | + return; |
| 2453 | + } |
| 2454 | + node.dmnman->CompleteRepair(); |
| 2455 | + LogPrintf("Successfully repaired %d masternode list diffs, verified %d snapshots in %ds\n", |
| 2456 | + result.diffs_recalculated, result.snapshots_verified, |
| 2457 | + Ticks<std::chrono::seconds>(SteadyClock::now() - start)); |
| 2458 | + } |
| 2459 | + } |
| 2460 | + |
2411 | 2461 | if (node.mn_activeman != nullptr) { |
2412 | 2462 | node.mn_activeman->Init(chainman.ActiveTip()); |
2413 | 2463 | } |
|
0 commit comments