aboutsummaryrefslogtreecommitdiff
path: root/src/node/blockstorage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/node/blockstorage.cpp')
-rw-r--r--src/node/blockstorage.cpp111
1 files changed, 69 insertions, 42 deletions
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index c499bbfa6a..576c07a833 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -131,12 +131,14 @@ bool BlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, s
pindexNew->nTx = diskindex.nTx;
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) {
- return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString());
+ LogError("%s: CheckProofOfWork failed: %s\n", __func__, pindexNew->ToString());
+ return false;
}
pcursor->Next();
} else {
- return error("%s: failed to read value", __func__);
+ LogError("%s: failed to read value\n", __func__);
+ return false;
}
} else {
break;
@@ -402,7 +404,7 @@ bool BlockManager::LoadBlockIndex(const std::optional<uint256>& snapshot_blockha
if (snapshot_blockhash) {
const std::optional<AssumeutxoData> maybe_au_data = GetParams().AssumeutxoForBlockhash(*snapshot_blockhash);
if (!maybe_au_data) {
- m_opts.notifications.fatalError(strprintf("Assumeutxo data not found for the given blockhash '%s'.", snapshot_blockhash->ToString()));
+ m_opts.notifications.fatalError(strprintf(_("Assumeutxo data not found for the given blockhash '%s'."), snapshot_blockhash->ToString()));
return false;
}
const AssumeutxoData& au_data = *Assert(maybe_au_data);
@@ -432,7 +434,8 @@ bool BlockManager::LoadBlockIndex(const std::optional<uint256>& snapshot_blockha
for (CBlockIndex* pindex : vSortedByHeight) {
if (m_interrupt) return false;
if (previous_index && pindex->nHeight > previous_index->nHeight + 1) {
- return error("%s: block index is non-contiguous, index of height %d missing", __func__, previous_index->nHeight + 1);
+ LogError("%s: block index is non-contiguous, index of height %d missing\n", __func__, previous_index->nHeight + 1);
+ return false;
}
previous_index = pindex;
pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex);
@@ -671,7 +674,8 @@ bool BlockManager::UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos
// Open history file to append
AutoFile fileout{OpenUndoFile(pos)};
if (fileout.IsNull()) {
- return error("%s: OpenUndoFile failed", __func__);
+ LogError("%s: OpenUndoFile failed\n", __func__);
+ return false;
}
// Write index header
@@ -681,7 +685,8 @@ bool BlockManager::UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos
// Write undo data
long fileOutPos = ftell(fileout.Get());
if (fileOutPos < 0) {
- return error("%s: ftell failed", __func__);
+ LogError("%s: ftell failed\n", __func__);
+ return false;
}
pos.nPos = (unsigned int)fileOutPos;
fileout << blockundo;
@@ -700,13 +705,15 @@ bool BlockManager::UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex& in
const FlatFilePos pos{WITH_LOCK(::cs_main, return index.GetUndoPos())};
if (pos.IsNull()) {
- return error("%s: no undo data available", __func__);
+ LogError("%s: no undo data available\n", __func__);
+ return false;
}
// Open history file to read
AutoFile filein{OpenUndoFile(pos, true)};
if (filein.IsNull()) {
- return error("%s: OpenUndoFile failed", __func__);
+ LogError("%s: OpenUndoFile failed\n", __func__);
+ return false;
}
// Read block
@@ -717,12 +724,14 @@ bool BlockManager::UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex& in
verifier >> blockundo;
filein >> hashChecksum;
} catch (const std::exception& e) {
- return error("%s: Deserialize or I/O error - %s", __func__, e.what());
+ LogError("%s: Deserialize or I/O error - %s\n", __func__, e.what());
+ return false;
}
// Verify checksum
if (hashChecksum != verifier.GetHash()) {
- return error("%s: Checksum mismatch", __func__);
+ LogError("%s: Checksum mismatch\n", __func__);
+ return false;
}
return true;
@@ -732,7 +741,7 @@ bool BlockManager::FlushUndoFile(int block_file, bool finalize)
{
FlatFilePos undo_pos_old(block_file, m_blockfile_info[block_file].nUndoSize);
if (!UndoFileSeq().Flush(undo_pos_old, finalize)) {
- m_opts.notifications.flushError("Flushing undo file to disk failed. This is likely the result of an I/O error.");
+ m_opts.notifications.flushError(_("Flushing undo file to disk failed. This is likely the result of an I/O error."));
return false;
}
return true;
@@ -754,7 +763,7 @@ bool BlockManager::FlushBlockFile(int blockfile_num, bool fFinalize, bool finali
FlatFilePos block_pos_old(blockfile_num, m_blockfile_info[blockfile_num].nSize);
if (!BlockFileSeq().Flush(block_pos_old, fFinalize)) {
- m_opts.notifications.flushError("Flushing block file to disk failed. This is likely the result of an I/O error.");
+ m_opts.notifications.flushError(_("Flushing block file to disk failed. This is likely the result of an I/O error."));
success = false;
}
// we do not always flush the undo file, as the chain tip may be lagging behind the incoming blocks,
@@ -897,19 +906,19 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
if (!fKnown) {
LogPrint(BCLog::BLOCKSTORAGE, "Leaving block file %i: %s (onto %i) (height %i)\n",
last_blockfile, m_blockfile_info[last_blockfile].ToString(), nFile, nHeight);
- }
- // Do not propagate the return code. The flush concerns a previous block
- // and undo file that has already been written to. If a flush fails
- // here, and we crash, there is no expected additional block data
- // inconsistency arising from the flush failure here. However, the undo
- // data may be inconsistent after a crash if the flush is called during
- // a reindex. A flush error might also leave some of the data files
- // untrimmed.
- if (!FlushBlockFile(last_blockfile, !fKnown, finalize_undo)) {
- LogPrintLevel(BCLog::BLOCKSTORAGE, BCLog::Level::Warning,
- "Failed to flush previous block file %05i (finalize=%i, finalize_undo=%i) before opening new block file %05i\n",
- last_blockfile, !fKnown, finalize_undo, nFile);
+ // Do not propagate the return code. The flush concerns a previous block
+ // and undo file that has already been written to. If a flush fails
+ // here, and we crash, there is no expected additional block data
+ // inconsistency arising from the flush failure here. However, the undo
+ // data may be inconsistent after a crash if the flush is called during
+ // a reindex. A flush error might also leave some of the data files
+ // untrimmed.
+ if (!FlushBlockFile(last_blockfile, !fKnown, finalize_undo)) {
+ LogPrintLevel(BCLog::BLOCKSTORAGE, BCLog::Level::Warning,
+ "Failed to flush previous block file %05i (finalize=%i, finalize_undo=%i) before opening new block file %05i\n",
+ last_blockfile, !fKnown, finalize_undo, nFile);
+ }
}
// No undo data yet in the new file, so reset our undo-height tracking.
m_blockfile_cursors[chain_type] = BlockfileCursor{nFile};
@@ -926,7 +935,7 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
bool out_of_space;
size_t bytes_allocated = BlockFileSeq().Allocate(pos, nAddSize, out_of_space);
if (out_of_space) {
- m_opts.notifications.fatalError("Disk space is too low!", _("Disk space is too low!"));
+ m_opts.notifications.fatalError(_("Disk space is too low!"));
return false;
}
if (bytes_allocated != 0 && IsPruneMode()) {
@@ -951,7 +960,7 @@ bool BlockManager::FindUndoPos(BlockValidationState& state, int nFile, FlatFileP
bool out_of_space;
size_t bytes_allocated = UndoFileSeq().Allocate(pos, nAddSize, out_of_space);
if (out_of_space) {
- return FatalError(m_opts.notifications, state, "Disk space is too low!", _("Disk space is too low!"));
+ return FatalError(m_opts.notifications, state, _("Disk space is too low!"));
}
if (bytes_allocated != 0 && IsPruneMode()) {
m_check_for_pruning = true;
@@ -965,7 +974,8 @@ bool BlockManager::WriteBlockToDisk(const CBlock& block, FlatFilePos& pos) const
// Open history file to append
AutoFile fileout{OpenBlockFile(pos)};
if (fileout.IsNull()) {
- return error("WriteBlockToDisk: OpenBlockFile failed");
+ LogError("WriteBlockToDisk: OpenBlockFile failed\n");
+ return false;
}
// Write index header
@@ -975,7 +985,8 @@ bool BlockManager::WriteBlockToDisk(const CBlock& block, FlatFilePos& pos) const
// Write block
long fileOutPos = ftell(fileout.Get());
if (fileOutPos < 0) {
- return error("WriteBlockToDisk: ftell failed");
+ LogError("WriteBlockToDisk: ftell failed\n");
+ return false;
}
pos.nPos = (unsigned int)fileOutPos;
fileout << TX_WITH_WITNESS(block);
@@ -993,10 +1004,11 @@ bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValid
if (block.GetUndoPos().IsNull()) {
FlatFilePos _pos;
if (!FindUndoPos(state, block.nFile, _pos, ::GetSerializeSize(blockundo) + 40)) {
- return error("ConnectBlock(): FindUndoPos failed");
+ LogError("ConnectBlock(): FindUndoPos failed\n");
+ return false;
}
if (!UndoWriteToDisk(blockundo, _pos, block.pprev->GetBlockHash())) {
- return FatalError(m_opts.notifications, state, "Failed to write undo data");
+ return FatalError(m_opts.notifications, 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
@@ -1031,24 +1043,28 @@ bool BlockManager::ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos) cons
// Open history file to read
AutoFile filein{OpenBlockFile(pos, true)};
if (filein.IsNull()) {
- return error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString());
+ LogError("ReadBlockFromDisk: OpenBlockFile failed for %s\n", pos.ToString());
+ return false;
}
// Read block
try {
filein >> TX_WITH_WITNESS(block);
} catch (const std::exception& e) {
- return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString());
+ LogError("%s: Deserialize or I/O error - %s at %s\n", __func__, e.what(), pos.ToString());
+ return false;
}
// Check the header
if (!CheckProofOfWork(block.GetHash(), block.nBits, GetConsensus())) {
- return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
+ LogError("ReadBlockFromDisk: Errors in block header at %s\n", pos.ToString());
+ return false;
}
// Signet only: check block solution
if (GetConsensus().signet_blocks && !CheckSignetBlockSolution(block, GetConsensus())) {
- return error("ReadBlockFromDisk: Errors in block solution at %s", pos.ToString());
+ LogError("ReadBlockFromDisk: Errors in block solution at %s\n", pos.ToString());
+ return false;
}
return true;
@@ -1062,8 +1078,9 @@ bool BlockManager::ReadBlockFromDisk(CBlock& block, const CBlockIndex& index) co
return false;
}
if (block.GetHash() != index.GetBlockHash()) {
- return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
+ LogError("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s\n",
index.ToString(), block_pos.ToString());
+ return false;
}
return true;
}
@@ -1071,10 +1088,17 @@ bool BlockManager::ReadBlockFromDisk(CBlock& block, const CBlockIndex& index) co
bool BlockManager::ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos) const
{
FlatFilePos hpos = pos;
+ // If nPos is less than 8 the pos is null and we don't have the block data
+ // Return early to prevent undefined behavior of unsigned int underflow
+ if (hpos.nPos < 8) {
+ LogError("%s: OpenBlockFile failed for %s\n", __func__, pos.ToString());
+ return false;
+ }
hpos.nPos -= 8; // Seek back 8 bytes for meta header
AutoFile filein{OpenBlockFile(hpos, true)};
if (filein.IsNull()) {
- return error("%s: OpenBlockFile failed for %s", __func__, pos.ToString());
+ LogError("%s: OpenBlockFile failed for %s\n", __func__, pos.ToString());
+ return false;
}
try {
@@ -1084,20 +1108,23 @@ bool BlockManager::ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatF
filein >> blk_start >> blk_size;
if (blk_start != GetParams().MessageStart()) {
- return error("%s: Block magic mismatch for %s: %s versus expected %s", __func__, pos.ToString(),
+ LogError("%s: Block magic mismatch for %s: %s versus expected %s\n", __func__, pos.ToString(),
HexStr(blk_start),
HexStr(GetParams().MessageStart()));
+ return false;
}
if (blk_size > MAX_SIZE) {
- return error("%s: Block data is larger than maximum deserialization size for %s: %s versus %s", __func__, pos.ToString(),
+ LogError("%s: Block data is larger than maximum deserialization size for %s: %s versus %s\n", __func__, pos.ToString(),
blk_size, MAX_SIZE);
+ return false;
}
block.resize(blk_size); // Zeroing of memory is intentional here
filein.read(MakeWritableByteSpan(block));
} catch (const std::exception& e) {
- return error("%s: Read from block file failed: %s for %s", __func__, e.what(), pos.ToString());
+ LogError("%s: Read from block file failed: %s for %s\n", __func__, e.what(), pos.ToString());
+ return false;
}
return true;
@@ -1117,12 +1144,12 @@ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, cons
nBlockSize += static_cast<unsigned int>(BLOCK_SERIALIZATION_HEADER_SIZE);
}
if (!FindBlockPos(blockPos, nBlockSize, nHeight, block.GetBlockTime(), position_known)) {
- error("%s: FindBlockPos failed", __func__);
+ LogError("%s: FindBlockPos failed\n", __func__);
return FlatFilePos();
}
if (!position_known) {
if (!WriteBlockToDisk(block, blockPos)) {
- m_opts.notifications.fatalError("Failed to write block");
+ m_opts.notifications.fatalError(_("Failed to write block."));
return FlatFilePos();
}
}
@@ -1206,7 +1233,7 @@ void ImportBlocks(ChainstateManager& chainman, std::vector<fs::path> vImportFile
for (Chainstate* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
BlockValidationState state;
if (!chainstate->ActivateBestChain(state, nullptr)) {
- chainman.GetNotifications().fatalError(strprintf("Failed to connect best block (%s)", state.ToString()));
+ chainman.GetNotifications().fatalError(strprintf(_("Failed to connect best block (%s)."), state.ToString()));
return;
}
}