|
|
@ -1552,6 +1552,24 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Abort with a message */ |
|
|
|
|
|
|
|
bool AbortNode(const std::string& strMessage, const std::string& userMessage="") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
strMiscWarning = strMessage; |
|
|
|
|
|
|
|
LogPrintf("*** %s\n", strMessage); |
|
|
|
|
|
|
|
uiInterface.ThreadSafeMessageBox( |
|
|
|
|
|
|
|
userMessage.empty() ? _("Error: A fatal internal error occured, see debug.log for details") : userMessage, |
|
|
|
|
|
|
|
"", CClientUIInterface::MSG_ERROR); |
|
|
|
|
|
|
|
StartShutdown(); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool AbortNode(CValidationState& state, const std::string& strMessage, const std::string& userMessage="") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
AbortNode(strMessage, userMessage); |
|
|
|
|
|
|
|
return state.Error(strMessage); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} // anon namespace
|
|
|
|
} // anon namespace
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -1831,7 +1849,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin |
|
|
|
if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) |
|
|
|
if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) |
|
|
|
return error("ConnectBlock(): FindUndoPos failed"); |
|
|
|
return error("ConnectBlock(): FindUndoPos failed"); |
|
|
|
if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash())) |
|
|
|
if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash())) |
|
|
|
return state.Abort("Failed to write undo data"); |
|
|
|
return AbortNode(state, "Failed to write undo data"); |
|
|
|
|
|
|
|
|
|
|
|
// update nUndoPos in block index
|
|
|
|
// update nUndoPos in block index
|
|
|
|
pindex->nUndoPos = pos.nPos; |
|
|
|
pindex->nUndoPos = pos.nPos; |
|
|
@ -1844,7 +1862,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin |
|
|
|
|
|
|
|
|
|
|
|
if (fTxIndex) |
|
|
|
if (fTxIndex) |
|
|
|
if (!pblocktree->WriteTxIndex(vPos)) |
|
|
|
if (!pblocktree->WriteTxIndex(vPos)) |
|
|
|
return state.Abort("Failed to write transaction index"); |
|
|
|
return AbortNode(state, "Failed to write transaction index"); |
|
|
|
|
|
|
|
|
|
|
|
// add this block to the view's block chain
|
|
|
|
// add this block to the view's block chain
|
|
|
|
view.SetBestBlock(pindex->GetBlockHash()); |
|
|
|
view.SetBestBlock(pindex->GetBlockHash()); |
|
|
@ -1938,7 +1956,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { |
|
|
|
setDirtyBlockIndex.erase(it++); |
|
|
|
setDirtyBlockIndex.erase(it++); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!pblocktree->WriteBatchSync(vFiles, nLastBlockFile, vBlocks)) { |
|
|
|
if (!pblocktree->WriteBatchSync(vFiles, nLastBlockFile, vBlocks)) { |
|
|
|
return state.Abort("Files to write to block index database"); |
|
|
|
return AbortNode(state, "Files to write to block index database"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// Finally remove any pruned files
|
|
|
|
// Finally remove any pruned files
|
|
|
@ -1959,7 +1977,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { |
|
|
|
return state.Error("out of disk space"); |
|
|
|
return state.Error("out of disk space"); |
|
|
|
// Flush the chainstate (which may refer to block index entries).
|
|
|
|
// Flush the chainstate (which may refer to block index entries).
|
|
|
|
if (!pcoinsTip->Flush()) |
|
|
|
if (!pcoinsTip->Flush()) |
|
|
|
return state.Abort("Failed to write to coin database"); |
|
|
|
return AbortNode(state, "Failed to write to coin database"); |
|
|
|
nLastFlush = nNow; |
|
|
|
nLastFlush = nNow; |
|
|
|
} |
|
|
|
} |
|
|
|
if ((mode == FLUSH_STATE_ALWAYS || mode == FLUSH_STATE_PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000) { |
|
|
|
if ((mode == FLUSH_STATE_ALWAYS || mode == FLUSH_STATE_PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000) { |
|
|
@ -1968,7 +1986,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { |
|
|
|
nLastSetChain = nNow; |
|
|
|
nLastSetChain = nNow; |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (const std::runtime_error& e) { |
|
|
|
} catch (const std::runtime_error& e) { |
|
|
|
return state.Abort(std::string("System error while flushing: ") + e.what()); |
|
|
|
return AbortNode(state, std::string("System error while flushing: ") + e.what()); |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
@ -2032,7 +2050,7 @@ bool static DisconnectTip(CValidationState &state) { |
|
|
|
// Read block from disk.
|
|
|
|
// Read block from disk.
|
|
|
|
CBlock block; |
|
|
|
CBlock block; |
|
|
|
if (!ReadBlockFromDisk(block, pindexDelete)) |
|
|
|
if (!ReadBlockFromDisk(block, pindexDelete)) |
|
|
|
return state.Abort("Failed to read block"); |
|
|
|
return AbortNode(state, "Failed to read block"); |
|
|
|
// Apply the block atomically to the chain state.
|
|
|
|
// Apply the block atomically to the chain state.
|
|
|
|
int64_t nStart = GetTimeMicros(); |
|
|
|
int64_t nStart = GetTimeMicros(); |
|
|
|
{ |
|
|
|
{ |
|
|
@ -2083,7 +2101,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * |
|
|
|
CBlock block; |
|
|
|
CBlock block; |
|
|
|
if (!pblock) { |
|
|
|
if (!pblock) { |
|
|
|
if (!ReadBlockFromDisk(block, pindexNew)) |
|
|
|
if (!ReadBlockFromDisk(block, pindexNew)) |
|
|
|
return state.Abort("Failed to read block"); |
|
|
|
return AbortNode(state, "Failed to read block"); |
|
|
|
pblock = █ |
|
|
|
pblock = █ |
|
|
|
} |
|
|
|
} |
|
|
|
// Apply the block atomically to the chain state.
|
|
|
|
// Apply the block atomically to the chain state.
|
|
|
@ -2790,11 +2808,11 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, |
|
|
|
return error("AcceptBlock(): FindBlockPos failed"); |
|
|
|
return error("AcceptBlock(): FindBlockPos failed"); |
|
|
|
if (dbp == NULL) |
|
|
|
if (dbp == NULL) |
|
|
|
if (!WriteBlockToDisk(block, blockPos)) |
|
|
|
if (!WriteBlockToDisk(block, blockPos)) |
|
|
|
return state.Abort("Failed to write block"); |
|
|
|
AbortNode(state, "Failed to write block"); |
|
|
|
if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) |
|
|
|
if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) |
|
|
|
return error("AcceptBlock(): ReceivedBlockTransactions failed"); |
|
|
|
return error("AcceptBlock(): ReceivedBlockTransactions failed"); |
|
|
|
} catch (const std::runtime_error& e) { |
|
|
|
} catch (const std::runtime_error& e) { |
|
|
|
return state.Abort(std::string("System error: ") + e.what()); |
|
|
|
return AbortNode(state, std::string("System error: ") + e.what()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fCheckForPruning) |
|
|
|
if (fCheckForPruning) |
|
|
@ -2869,24 +2887,6 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool AbortNode(const std::string &strMessage, const std::string &userMessage) { |
|
|
|
|
|
|
|
strMiscWarning = strMessage; |
|
|
|
|
|
|
|
LogPrintf("*** %s\n", strMessage); |
|
|
|
|
|
|
|
uiInterface.ThreadSafeMessageBox( |
|
|
|
|
|
|
|
userMessage.empty() ? _("Error: A fatal internal error occured, see debug.log for details") : userMessage, |
|
|
|
|
|
|
|
"", CClientUIInterface::MSG_ERROR); |
|
|
|
|
|
|
|
StartShutdown(); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* BLOCK PRUNING CODE |
|
|
|
* BLOCK PRUNING CODE |
|
|
|
*/ |
|
|
|
*/ |
|
|
|