Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 1,434 Lines • ▼ Show 20 Lines | DisconnectResult ApplyBlockUndo(const CBlockUndo &blockUndo, | ||||
} | } | ||||
// Move best block pointer to previous block. | // Move best block pointer to previous block. | ||||
view.SetBestBlock(block.hashPrevBlock); | view.SetBestBlock(block.hashPrevBlock); | ||||
return fClean ? DisconnectResult::OK : DisconnectResult::UNCLEAN; | return fClean ? DisconnectResult::OK : DisconnectResult::UNCLEAN; | ||||
} | } | ||||
static void FlushBlockFile(bool fFinalize = false) { | static void FlushUndoFile(int block_file, bool finalize = false) { | ||||
LOCK(cs_LastBlockFile); | FlatFilePos undo_pos_old(block_file, vinfoBlockFile[block_file].nUndoSize); | ||||
if (!UndoFileSeq().Flush(undo_pos_old, finalize)) { | |||||
AbortNode("Flushing undo file to disk failed. This is likely the " | |||||
"result of an I/O error."); | |||||
} | |||||
} | |||||
static void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false) { | |||||
LOCK(cs_LastBlockFile); | |||||
FlatFilePos block_pos_old(nLastBlockFile, | FlatFilePos block_pos_old(nLastBlockFile, | ||||
vinfoBlockFile[nLastBlockFile].nSize); | vinfoBlockFile[nLastBlockFile].nSize); | ||||
FlatFilePos undo_pos_old(nLastBlockFile, | if (!BlockFileSeq().Flush(block_pos_old, fFinalize)) { | ||||
vinfoBlockFile[nLastBlockFile].nUndoSize); | |||||
bool status = true; | |||||
status &= BlockFileSeq().Flush(block_pos_old, fFinalize); | |||||
status &= UndoFileSeq().Flush(undo_pos_old, fFinalize); | |||||
if (!status) { | |||||
AbortNode("Flushing block file to disk failed. This is likely the " | AbortNode("Flushing block file to disk failed. This is likely the " | ||||
"result of an I/O error."); | "result of an I/O error."); | ||||
} | } | ||||
// we do not always flush the undo file, as the chain tip may be lagging | |||||
// behind the incoming blocks, | |||||
// e.g. during IBD or a sync after a node going offline | |||||
if (!fFinalize || finalize_undo) { | |||||
FlushUndoFile(nLastBlockFile, finalize_undo); | |||||
} | |||||
} | } | ||||
static bool FindUndoPos(BlockValidationState &state, int nFile, | static bool FindUndoPos(BlockValidationState &state, int nFile, | ||||
FlatFilePos &pos, unsigned int nAddSize); | FlatFilePos &pos, unsigned int nAddSize); | ||||
static bool WriteUndoDataForBlock(const CBlockUndo &blockundo, | static bool WriteUndoDataForBlock(const CBlockUndo &blockundo, | ||||
BlockValidationState &state, | BlockValidationState &state, | ||||
CBlockIndex *pindex, | CBlockIndex *pindex, | ||||
const CChainParams &chainparams) { | const CChainParams &chainparams) { | ||||
// Write undo information to disk | // Write undo information to disk | ||||
if (pindex->GetUndoPos().IsNull()) { | if (pindex->GetUndoPos().IsNull()) { | ||||
FlatFilePos _pos; | FlatFilePos _pos; | ||||
if (!FindUndoPos(state, pindex->nFile, _pos, | if (!FindUndoPos(state, pindex->nFile, _pos, | ||||
::GetSerializeSize(blockundo, CLIENT_VERSION) + 40)) { | ::GetSerializeSize(blockundo, 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(), | ||||
chainparams.DiskMagic())) { | chainparams.DiskMagic())) { | ||||
return AbortNode(state, "Failed to write undo data"); | return AbortNode(state, "Failed to write undo data"); | ||||
} | } | ||||
// rev files are written in block height order, whereas blk files are | |||||
// written as blocks come in (often out of order) we want to flush the | |||||
// rev (undo) file once we've written the last block, which is indicated | |||||
// by the last height in the block file info as below; note that this | |||||
// does not catch the case where the undo writes are keeping up with the | |||||
// block writes (usually when a synced up node is getting newly mined | |||||
// blocks) -- this case is caught in the FindBlockPos function | |||||
if (_pos.nFile < nLastBlockFile && | |||||
static_cast<uint32_t>(pindex->nHeight) == | |||||
vinfoBlockFile[_pos.nFile].nHeightLast) { | |||||
FlushUndoFile(_pos.nFile, true); | |||||
} | |||||
// update nUndoPos in block index | // update nUndoPos in block index | ||||
pindex->nUndoPos = _pos.nPos; | pindex->nUndoPos = _pos.nPos; | ||||
pindex->nStatus = pindex->nStatus.withUndo(); | pindex->nStatus = pindex->nStatus.withUndo(); | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
} | } | ||||
return true; | return true; | ||||
▲ Show 20 Lines • Show All 2,146 Lines • ▼ Show 20 Lines | static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, | ||||
bool fKnown = false) { | bool fKnown = false) { | ||||
LOCK(cs_LastBlockFile); | LOCK(cs_LastBlockFile); | ||||
unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile; | unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile; | ||||
if (vinfoBlockFile.size() <= nFile) { | if (vinfoBlockFile.size() <= nFile) { | ||||
vinfoBlockFile.resize(nFile + 1); | vinfoBlockFile.resize(nFile + 1); | ||||
} | } | ||||
bool finalize_undo = false; | |||||
if (!fKnown) { | if (!fKnown) { | ||||
while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) { | while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) { | ||||
// when the undo file is keeping up with the block file, we want to | |||||
// flush it explicitly when it is lagging behind (more blocks arrive | |||||
// than are being connected), we let the undo block write case | |||||
// handle it | |||||
finalize_undo = (vinfoBlockFile[nFile].nHeightLast == | |||||
(unsigned int)ChainActive().Tip()->nHeight); | |||||
nFile++; | nFile++; | ||||
if (vinfoBlockFile.size() <= nFile) { | if (vinfoBlockFile.size() <= nFile) { | ||||
vinfoBlockFile.resize(nFile + 1); | vinfoBlockFile.resize(nFile + 1); | ||||
} | } | ||||
} | } | ||||
pos.nFile = nFile; | pos.nFile = nFile; | ||||
pos.nPos = vinfoBlockFile[nFile].nSize; | pos.nPos = vinfoBlockFile[nFile].nSize; | ||||
} | } | ||||
if ((int)nFile != nLastBlockFile) { | if ((int)nFile != nLastBlockFile) { | ||||
if (!fKnown) { | if (!fKnown) { | ||||
LogPrintf("Leaving block file %i: %s\n", nLastBlockFile, | LogPrintf("Leaving block file %i: %s\n", nLastBlockFile, | ||||
vinfoBlockFile[nLastBlockFile].ToString()); | vinfoBlockFile[nLastBlockFile].ToString()); | ||||
} | } | ||||
FlushBlockFile(!fKnown); | FlushBlockFile(!fKnown, finalize_undo); | ||||
nLastBlockFile = nFile; | nLastBlockFile = nFile; | ||||
} | } | ||||
vinfoBlockFile[nFile].AddBlock(nHeight, nTime); | vinfoBlockFile[nFile].AddBlock(nHeight, nTime); | ||||
if (fKnown) { | if (fKnown) { | ||||
vinfoBlockFile[nFile].nSize = | vinfoBlockFile[nFile].nSize = | ||||
std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize); | std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize); | ||||
} else { | } else { | ||||
▲ Show 20 Lines • Show All 2,465 Lines • Show Last 20 Lines |