1 Commits

Author SHA1 Message Date
2f3f320d28 Handle ReadBlockFromDisk failure during IBD gracefully
During Initial Block Download, block data may not be flushed to disk
when the wallet notification thread tries to read it. Instead of
crashing with a fatal error, log a message and retry on the next cycle.
2026-03-27 14:01:50 -05:00
3 changed files with 17 additions and 15 deletions

View File

@@ -32,12 +32,8 @@ class CChainPower;
#include <boost/foreach.hpp>
extern bool fZindex;
// These version thresholds control whether nSproutValue/nSaplingValue are
// serialized in the block index. They must be <= CLIENT_VERSION or the
// values will never be persisted, causing nChainSaplingValue to reset
// to 0 after node restart. DragonX CLIENT_VERSION is 1000150 (v1.0.1.50).
static const int SPROUT_VALUE_VERSION = 1000000;
static const int SAPLING_VALUE_VERSION = 1000000;
static const int SPROUT_VALUE_VERSION = 1001400;
static const int SAPLING_VALUE_VERSION = 1010100;
extern int32_t ASSETCHAINS_LWMAPOS;
extern char SMART_CHAIN_SYMBOL[65];
extern uint64_t ASSETCHAINS_NOTARY_PAY[];

View File

@@ -322,15 +322,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("anchor", blockindex->hashFinalSproutRoot.GetHex()));
result.push_back(Pair("blocktype", "mined"));
// Report block subsidy and fees separately so explorers don't have to
// reimplement the reward schedule to display them.
CAmount nSubsidy = GetBlockSubsidy(blockindex->GetHeight(), Params().GetConsensus());
CAmount nCoinbase = block.vtx[0].GetValueOut();
CAmount nFees = nCoinbase - nSubsidy;
if (nFees < 0) nFees = 0; // block 1 has premine, avoid negative
result.push_back(Pair("subsidy", ValueFromAmount(nSubsidy)));
result.push_back(Pair("fees", ValueFromAmount(nFees)));
UniValue valuePools(UniValue::VARR);
valuePools.push_back(ValuePoolDesc("sapling", blockindex->nChainSaplingValue, blockindex->nSaplingValue));
result.push_back(Pair("valuePools", valuePools));

View File

@@ -179,6 +179,13 @@ void ThreadNotifyWallets(CBlockIndex *pindexLastTip)
// Read block from disk.
CBlock block;
if (!ReadBlockFromDisk(block, pindexLastTip,1)) {
if (IsInitialBlockDownload()) {
// During IBD, block data may not be flushed to disk yet.
// Sleep briefly and retry on the next cycle instead of crashing.
LogPrintf("%s: block at height %d not yet readable, will retry\n",
__func__, pindexLastTip->GetHeight());
break;
}
LogPrintf("*** %s\n", "Failed to read block while notifying wallets of block disconnects");
uiInterface.ThreadSafeMessageBox(
_("Error: A fatal internal error occurred, see debug.log for details"),
@@ -206,6 +213,14 @@ void ThreadNotifyWallets(CBlockIndex *pindexLastTip)
// Read block from disk.
CBlock block;
if (!ReadBlockFromDisk(block, blockData.pindex, 1)) {
if (IsInitialBlockDownload()) {
// During IBD, block data may not be flushed to disk yet.
// Push unprocessed blocks back and retry on the next cycle.
LogPrintf("%s: block at height %d not yet readable, will retry\n",
__func__, blockData.pindex->GetHeight());
blockStack.push_back(blockData);
break;
}
LogPrintf("*** %s\n", "Failed to read block while notifying wallets of block connects");
uiInterface.ThreadSafeMessageBox(
_("Error: A fatal internal error occurred, see debug.log for details"),