LCOV - code coverage report
Current view: top level - src/node - blockstorage.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 295 369 79.9 %
Date: 2021-06-29 14:35:33 Functions: 27 27 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 100 142 70.4 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2011-2021 The Bitcoin Core developers
#       2                 :            : // Distributed under the MIT software license, see the accompanying
#       3                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       4                 :            : 
#       5                 :            : #include <node/blockstorage.h>
#       6                 :            : 
#       7                 :            : #include <chain.h>
#       8                 :            : #include <chainparams.h>
#       9                 :            : #include <clientversion.h>
#      10                 :            : #include <consensus/validation.h>
#      11                 :            : #include <flatfile.h>
#      12                 :            : #include <fs.h>
#      13                 :            : #include <hash.h>
#      14                 :            : #include <pow.h>
#      15                 :            : #include <shutdown.h>
#      16                 :            : #include <signet.h>
#      17                 :            : #include <streams.h>
#      18                 :            : #include <undo.h>
#      19                 :            : #include <util/system.h>
#      20                 :            : #include <validation.h>
#      21                 :            : 
#      22                 :            : std::atomic_bool fImporting(false);
#      23                 :            : std::atomic_bool fReindex(false);
#      24                 :            : bool fHavePruned = false;
#      25                 :            : bool fPruneMode = false;
#      26                 :            : uint64_t nPruneTarget = 0;
#      27                 :            : 
#      28                 :            : // TODO make namespace {
#      29                 :            : RecursiveMutex cs_LastBlockFile;
#      30                 :            : std::vector<CBlockFileInfo> vinfoBlockFile;
#      31                 :            : int nLastBlockFile = 0;
#      32                 :            : /** Global flag to indicate we should check to see if there are
#      33                 :            : *  block/undo files that should be deleted.  Set on startup
#      34                 :            : *  or if we allocate more file space when we're in prune mode
#      35                 :            : */
#      36                 :            : bool fCheckForPruning = false;
#      37                 :            : 
#      38                 :            : /** Dirty block index entries. */
#      39                 :            : std::set<CBlockIndex*> setDirtyBlockIndex;
#      40                 :            : 
#      41                 :            : /** Dirty block file entries. */
#      42                 :            : std::set<int> setDirtyFileInfo;
#      43                 :            : // } // namespace
#      44                 :            : 
#      45                 :            : static FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false);
#      46                 :            : static FlatFileSeq BlockFileSeq();
#      47                 :            : static FlatFileSeq UndoFileSeq();
#      48                 :            : 
#      49                 :            : bool IsBlockPruned(const CBlockIndex* pblockindex)
#      50                 :       5283 : {
#      51 [ -  + ][ #  # ]:       5283 :     return (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0);
#                 [ #  # ]
#      52                 :       5283 : }
#      53                 :            : 
#      54                 :            : // If we're using -prune with -reindex, then delete block files that will be ignored by the
#      55                 :            : // reindex.  Since reindexing works by starting at block file 0 and looping until a blockfile
#      56                 :            : // is missing, do the same here to delete any later block files after a gap.  Also delete all
#      57                 :            : // rev files since they'll be rewritten by the reindex anyway.  This ensures that vinfoBlockFile
#      58                 :            : // is in sync with what's actually on disk by the time we start downloading, so that pruning
#      59                 :            : // works correctly.
#      60                 :            : void CleanupBlockRevFiles()
#      61                 :          1 : {
#      62                 :          1 :     std::map<std::string, fs::path> mapBlockFiles;
#      63                 :            : 
#      64                 :            :     // Glob all blk?????.dat and rev?????.dat files from the blocks directory.
#      65                 :            :     // Remove the rev files immediately and insert the blk file paths into an
#      66                 :            :     // ordered map keyed by block file index.
#      67                 :          1 :     LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
#      68                 :          1 :     fs::path blocksdir = gArgs.GetBlocksDirPath();
#      69         [ +  + ]:          8 :     for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
#      70 [ +  + ][ +  + ]:          7 :         if (fs::is_regular_file(*it) &&
#      71         [ +  - ]:          7 :             it->path().filename().string().length() == 12 &&
#      72         [ +  - ]:          7 :             it->path().filename().string().substr(8,4) == ".dat")
#      73                 :          6 :         {
#      74         [ +  + ]:          6 :             if (it->path().filename().string().substr(0, 3) == "blk") {
#      75                 :          3 :                 mapBlockFiles[it->path().filename().string().substr(3, 5)] = it->path();
#      76         [ +  - ]:          3 :             } else if (it->path().filename().string().substr(0, 3) == "rev") {
#      77                 :          3 :                 remove(it->path());
#      78                 :          3 :             }
#      79                 :          6 :         }
#      80                 :          7 :     }
#      81                 :            : 
#      82                 :            :     // Remove all block files that aren't part of a contiguous set starting at
#      83                 :            :     // zero by walking the ordered map (keys are block file indices) by
#      84                 :            :     // keeping a separate counter.  Once we hit a gap (or if 0 doesn't exist)
#      85                 :            :     // start removing block files.
#      86                 :          1 :     int nContigCounter = 0;
#      87         [ +  + ]:          3 :     for (const std::pair<const std::string, fs::path>& item : mapBlockFiles) {
#      88         [ -  + ]:          3 :         if (atoi(item.first) == nContigCounter) {
#      89                 :          0 :             nContigCounter++;
#      90                 :          0 :             continue;
#      91                 :          0 :         }
#      92                 :          3 :         remove(item.second);
#      93                 :          3 :     }
#      94                 :          1 : }
#      95                 :            : 
#      96                 :            : std::string CBlockFileInfo::ToString() const
#      97                 :        632 : {
#      98                 :        632 :     return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast));
#      99                 :        632 : }
#     100                 :            : 
#     101                 :            : CBlockFileInfo* GetBlockFileInfo(size_t n)
#     102                 :          2 : {
#     103                 :          2 :     LOCK(cs_LastBlockFile);
#     104                 :            : 
#     105                 :          2 :     return &vinfoBlockFile.at(n);
#     106                 :          2 : }
#     107                 :            : 
#     108                 :            : static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
#     109                 :      66218 : {
#     110                 :            :     // Open history file to append
#     111                 :      66218 :     CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
#     112         [ -  + ]:      66218 :     if (fileout.IsNull()) {
#     113                 :          0 :         return error("%s: OpenUndoFile failed", __func__);
#     114                 :          0 :     }
#     115                 :            : 
#     116                 :            :     // Write index header
#     117                 :      66218 :     unsigned int nSize = GetSerializeSize(blockundo, fileout.GetVersion());
#     118                 :      66218 :     fileout << messageStart << nSize;
#     119                 :            : 
#     120                 :            :     // Write undo data
#     121                 :      66218 :     long fileOutPos = ftell(fileout.Get());
#     122         [ -  + ]:      66218 :     if (fileOutPos < 0) {
#     123                 :          0 :         return error("%s: ftell failed", __func__);
#     124                 :          0 :     }
#     125                 :      66218 :     pos.nPos = (unsigned int)fileOutPos;
#     126                 :      66218 :     fileout << blockundo;
#     127                 :            : 
#     128                 :            :     // calculate & write checksum
#     129                 :      66218 :     CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
#     130                 :      66218 :     hasher << hashBlock;
#     131                 :      66218 :     hasher << blockundo;
#     132                 :      66218 :     fileout << hasher.GetHash();
#     133                 :            : 
#     134                 :      66218 :     return true;
#     135                 :      66218 : }
#     136                 :            : 
#     137                 :            : bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex)
#     138                 :      16502 : {
#     139                 :      16502 :     FlatFilePos pos = pindex->GetUndoPos();
#     140         [ -  + ]:      16502 :     if (pos.IsNull()) {
#     141                 :          0 :         return error("%s: no undo data available", __func__);
#     142                 :          0 :     }
#     143                 :            : 
#     144                 :            :     // Open history file to read
#     145                 :      16502 :     CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
#     146         [ +  + ]:      16502 :     if (filein.IsNull()) {
#     147                 :          2 :         return error("%s: OpenUndoFile failed", __func__);
#     148                 :          2 :     }
#     149                 :            : 
#     150                 :            :     // Read block
#     151                 :      16500 :     uint256 hashChecksum;
#     152                 :      16500 :     CHashVerifier<CAutoFile> verifier(&filein); // We need a CHashVerifier as reserializing may lose data
#     153                 :      16500 :     try {
#     154                 :      16500 :         verifier << pindex->pprev->GetBlockHash();
#     155                 :      16500 :         verifier >> blockundo;
#     156                 :      16500 :         filein >> hashChecksum;
#     157                 :      16500 :     } catch (const std::exception& e) {
#     158                 :          1 :         return error("%s: Deserialize or I/O error - %s", __func__, e.what());
#     159                 :          1 :     }
#     160                 :            : 
#     161                 :            :     // Verify checksum
#     162         [ -  + ]:      16499 :     if (hashChecksum != verifier.GetHash()) {
#     163                 :          0 :         return error("%s: Checksum mismatch", __func__);
#     164                 :          0 :     }
#     165                 :            : 
#     166                 :      16499 :     return true;
#     167                 :      16499 : }
#     168                 :            : 
#     169                 :            : static void FlushUndoFile(int block_file, bool finalize = false)
#     170                 :       1604 : {
#     171                 :       1604 :     FlatFilePos undo_pos_old(block_file, vinfoBlockFile[block_file].nUndoSize);
#     172         [ -  + ]:       1604 :     if (!UndoFileSeq().Flush(undo_pos_old, finalize)) {
#     173                 :          0 :         AbortNode("Flushing undo file to disk failed. This is likely the result of an I/O error.");
#     174                 :          0 :     }
#     175                 :       1604 : }
#     176                 :            : 
#     177                 :            : void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false)
#     178                 :       1604 : {
#     179                 :       1604 :     LOCK(cs_LastBlockFile);
#     180                 :       1604 :     FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize);
#     181         [ -  + ]:       1604 :     if (!BlockFileSeq().Flush(block_pos_old, fFinalize)) {
#     182                 :          0 :         AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error.");
#     183                 :          0 :     }
#     184                 :            :     // we do not always flush the undo file, as the chain tip may be lagging behind the incoming blocks,
#     185                 :            :     // e.g. during IBD or a sync after a node going offline
#     186 [ +  + ][ +  - ]:       1604 :     if (!fFinalize || finalize_undo) FlushUndoFile(nLastBlockFile, finalize_undo);
#     187                 :       1604 : }
#     188                 :            : 
#     189                 :            : uint64_t CalculateCurrentUsage()
#     190                 :        425 : {
#     191                 :        425 :     LOCK(cs_LastBlockFile);
#     192                 :            : 
#     193                 :        425 :     uint64_t retval = 0;
#     194         [ +  + ]:        532 :     for (const CBlockFileInfo& file : vinfoBlockFile) {
#     195                 :        532 :         retval += file.nSize + file.nUndoSize;
#     196                 :        532 :     }
#     197                 :        425 :     return retval;
#     198                 :        425 : }
#     199                 :            : 
#     200                 :            : void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
#     201                 :          5 : {
#     202         [ +  + ]:         12 :     for (std::set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) {
#     203                 :          7 :         FlatFilePos pos(*it, 0);
#     204                 :          7 :         fs::remove(BlockFileSeq().FileName(pos));
#     205                 :          7 :         fs::remove(UndoFileSeq().FileName(pos));
#     206                 :          7 :         LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, *it);
#     207                 :          7 :     }
#     208                 :          5 : }
#     209                 :            : 
#     210                 :            : static FlatFileSeq BlockFileSeq()
#     211                 :     256139 : {
#     212         [ +  + ]:     256139 :     return FlatFileSeq(gArgs.GetBlocksDirPath(), "blk", gArgs.GetBoolArg("-fastprune", false) ? 0x4000 /* 16kb */ : BLOCKFILE_CHUNK_SIZE);
#     213                 :     256139 : }
#     214                 :            : 
#     215                 :            : static FlatFileSeq UndoFileSeq()
#     216                 :     150549 : {
#     217                 :     150549 :     return FlatFileSeq(gArgs.GetBlocksDirPath(), "rev", UNDOFILE_CHUNK_SIZE);
#     218                 :     150549 : }
#     219                 :            : 
#     220                 :            : FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly)
#     221                 :     186516 : {
#     222                 :     186516 :     return BlockFileSeq().Open(pos, fReadOnly);
#     223                 :     186516 : }
#     224                 :            : 
#     225                 :            : /** Open an undo file (rev?????.dat) */
#     226                 :            : static FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly)
#     227                 :      82720 : {
#     228                 :      82720 :     return UndoFileSeq().Open(pos, fReadOnly);
#     229                 :      82720 : }
#     230                 :            : 
#     231                 :            : fs::path GetBlockPosFilename(const FlatFilePos& pos)
#     232                 :         19 : {
#     233                 :         19 :     return BlockFileSeq().FileName(pos);
#     234                 :         19 : }
#     235                 :            : 
#     236                 :            : bool FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight, CChain& active_chain, uint64_t nTime, bool fKnown = false)
#     237                 :      69448 : {
#     238                 :      69448 :     LOCK(cs_LastBlockFile);
#     239                 :            : 
#     240         [ +  + ]:      69448 :     unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile;
#     241         [ +  + ]:      69448 :     if (vinfoBlockFile.size() <= nFile) {
#     242                 :        167 :         vinfoBlockFile.resize(nFile + 1);
#     243                 :        167 :     }
#     244                 :            : 
#     245                 :      69448 :     bool finalize_undo = false;
#     246         [ +  + ]:      69448 :     if (!fKnown) {
#     247 [ +  + ][ +  + ]:      68009 :         while (vinfoBlockFile[nFile].nSize + nAddSize >= (gArgs.GetBoolArg("-fastprune", false) ? 0x10000 /* 64kb */ : MAX_BLOCKFILE_SIZE)) {
#     248                 :            :             // when the undo file is keeping up with the block file, we want to flush it explicitly
#     249                 :            :             // when it is lagging behind (more blocks arrive than are being connected), we let the
#     250                 :            :             // undo block write case handle it
#     251                 :         16 :             assert(std::addressof(::ChainActive()) == std::addressof(active_chain));
#     252                 :         16 :             finalize_undo = (vinfoBlockFile[nFile].nHeightLast == (unsigned int)active_chain.Tip()->nHeight);
#     253                 :         16 :             nFile++;
#     254         [ +  - ]:         16 :             if (vinfoBlockFile.size() <= nFile) {
#     255                 :         16 :                 vinfoBlockFile.resize(nFile + 1);
#     256                 :         16 :             }
#     257                 :         16 :         }
#     258                 :      67993 :         pos.nFile = nFile;
#     259                 :      67993 :         pos.nPos = vinfoBlockFile[nFile].nSize;
#     260                 :      67993 :     }
#     261                 :            : 
#     262         [ +  + ]:      69448 :     if ((int)nFile != nLastBlockFile) {
#     263         [ +  - ]:         16 :         if (!fKnown) {
#     264         [ +  - ]:         16 :             LogPrint(BCLog::VALIDATION, "Leaving block file %i: %s\n", nLastBlockFile, vinfoBlockFile[nLastBlockFile].ToString());
#     265                 :         16 :         }
#     266                 :         16 :         FlushBlockFile(!fKnown, finalize_undo);
#     267                 :         16 :         nLastBlockFile = nFile;
#     268                 :         16 :     }
#     269                 :            : 
#     270                 :      69448 :     vinfoBlockFile[nFile].AddBlock(nHeight, nTime);
#     271         [ +  + ]:      69448 :     if (fKnown) {
#     272                 :       1455 :         vinfoBlockFile[nFile].nSize = std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize);
#     273                 :      67993 :     } else {
#     274                 :      67993 :         vinfoBlockFile[nFile].nSize += nAddSize;
#     275                 :      67993 :     }
#     276                 :            : 
#     277         [ +  + ]:      69448 :     if (!fKnown) {
#     278                 :      67993 :         bool out_of_space;
#     279                 :      67993 :         size_t bytes_allocated = BlockFileSeq().Allocate(pos, nAddSize, out_of_space);
#     280         [ -  + ]:      67993 :         if (out_of_space) {
#     281                 :          0 :             return AbortNode("Disk space is too low!", _("Disk space is too low!"));
#     282                 :          0 :         }
#     283 [ +  + ][ +  + ]:      67993 :         if (bytes_allocated != 0 && fPruneMode) {
#     284                 :         26 :             fCheckForPruning = true;
#     285                 :         26 :         }
#     286                 :      67993 :     }
#     287                 :            : 
#     288                 :      69448 :     setDirtyFileInfo.insert(nFile);
#     289                 :      69448 :     return true;
#     290                 :      69448 : }
#     291                 :            : 
#     292                 :            : static bool FindUndoPos(BlockValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize)
#     293                 :      66218 : {
#     294                 :      66218 :     pos.nFile = nFile;
#     295                 :            : 
#     296                 :      66218 :     LOCK(cs_LastBlockFile);
#     297                 :            : 
#     298                 :      66218 :     pos.nPos = vinfoBlockFile[nFile].nUndoSize;
#     299                 :      66218 :     vinfoBlockFile[nFile].nUndoSize += nAddSize;
#     300                 :      66218 :     setDirtyFileInfo.insert(nFile);
#     301                 :            : 
#     302                 :      66218 :     bool out_of_space;
#     303                 :      66218 :     size_t bytes_allocated = UndoFileSeq().Allocate(pos, nAddSize, out_of_space);
#     304         [ -  + ]:      66218 :     if (out_of_space) {
#     305                 :          0 :         return AbortNode(state, "Disk space is too low!", _("Disk space is too low!"));
#     306                 :          0 :     }
#     307 [ +  + ][ +  + ]:      66218 :     if (bytes_allocated != 0 && fPruneMode) {
#     308                 :          7 :         fCheckForPruning = true;
#     309                 :          7 :     }
#     310                 :            : 
#     311                 :      66218 :     return true;
#     312                 :      66218 : }
#     313                 :            : 
#     314                 :            : static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart)
#     315                 :      67993 : {
#     316                 :            :     // Open history file to append
#     317                 :      67993 :     CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
#     318         [ -  + ]:      67993 :     if (fileout.IsNull()) {
#     319                 :          0 :         return error("WriteBlockToDisk: OpenBlockFile failed");
#     320                 :          0 :     }
#     321                 :            : 
#     322                 :            :     // Write index header
#     323                 :      67993 :     unsigned int nSize = GetSerializeSize(block, fileout.GetVersion());
#     324                 :      67993 :     fileout << messageStart << nSize;
#     325                 :            : 
#     326                 :            :     // Write block
#     327                 :      67993 :     long fileOutPos = ftell(fileout.Get());
#     328         [ -  + ]:      67993 :     if (fileOutPos < 0) {
#     329                 :          0 :         return error("WriteBlockToDisk: ftell failed");
#     330                 :          0 :     }
#     331                 :      67993 :     pos.nPos = (unsigned int)fileOutPos;
#     332                 :      67993 :     fileout << block;
#     333                 :            : 
#     334                 :      67993 :     return true;
#     335                 :      67993 : }
#     336                 :            : 
#     337                 :            : bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams)
#     338                 :      67966 : {
#     339                 :            :     // Write undo information to disk
#     340         [ +  + ]:      67966 :     if (pindex->GetUndoPos().IsNull()) {
#     341                 :      66218 :         FlatFilePos _pos;
#     342         [ -  + ]:      66218 :         if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40)) {
#     343                 :          0 :             return error("ConnectBlock(): FindUndoPos failed");
#     344                 :          0 :         }
#     345         [ -  + ]:      66218 :         if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) {
#     346                 :          0 :             return AbortNode(state, "Failed to write undo data");
#     347                 :          0 :         }
#     348                 :            :         // rev files are written in block height order, whereas blk files are written as blocks come in (often out of order)
#     349                 :            :         // we want to flush the rev (undo) file once we've written the last block, which is indicated by the last height
#     350                 :            :         // in the block file info as below; note that this does not catch the case where the undo writes are keeping up
#     351                 :            :         // with the block writes (usually when a synced up node is getting newly mined blocks) -- this case is caught in
#     352                 :            :         // the FindBlockPos function
#     353 [ -  + ][ #  # ]:      66218 :         if (_pos.nFile < nLastBlockFile && static_cast<uint32_t>(pindex->nHeight) == vinfoBlockFile[_pos.nFile].nHeightLast) {
#     354                 :          0 :             FlushUndoFile(_pos.nFile, true);
#     355                 :          0 :         }
#     356                 :            : 
#     357                 :            :         // update nUndoPos in block index
#     358                 :      66218 :         pindex->nUndoPos = _pos.nPos;
#     359                 :      66218 :         pindex->nStatus |= BLOCK_HAVE_UNDO;
#     360                 :      66218 :         setDirtyBlockIndex.insert(pindex);
#     361                 :      66218 :     }
#     362                 :            : 
#     363                 :      67966 :     return true;
#     364                 :      67966 : }
#     365                 :            : 
#     366                 :            : bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams)
#     367                 :     107561 : {
#     368                 :     107561 :     block.SetNull();
#     369                 :            : 
#     370                 :            :     // Open history file to read
#     371                 :     107561 :     CAutoFile filein(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
#     372         [ +  + ]:     107561 :     if (filein.IsNull()) {
#     373                 :        108 :         return error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString());
#     374                 :        108 :     }
#     375                 :            : 
#     376                 :            :     // Read block
#     377                 :     107453 :     try {
#     378                 :     107453 :         filein >> block;
#     379                 :     107453 :     } catch (const std::exception& e) {
#     380                 :          0 :         return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString());
#     381                 :          0 :     }
#     382                 :            : 
#     383                 :            :     // Check the header
#     384         [ -  + ]:     107453 :     if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) {
#     385                 :          0 :         return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
#     386                 :          0 :     }
#     387                 :            : 
#     388                 :            :     // Signet only: check block solution
#     389 [ +  + ][ -  + ]:     107453 :     if (consensusParams.signet_blocks && !CheckSignetBlockSolution(block, consensusParams)) {
#     390                 :          0 :         return error("ReadBlockFromDisk: Errors in block solution at %s", pos.ToString());
#     391                 :          0 :     }
#     392                 :            : 
#     393                 :     107453 :     return true;
#     394                 :     107453 : }
#     395                 :            : 
#     396                 :            : bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
#     397                 :     107324 : {
#     398                 :     107324 :     FlatFilePos blockPos;
#     399                 :     107324 :     {
#     400                 :     107324 :         LOCK(cs_main);
#     401                 :     107324 :         blockPos = pindex->GetBlockPos();
#     402                 :     107324 :     }
#     403                 :            : 
#     404         [ +  + ]:     107324 :     if (!ReadBlockFromDisk(block, blockPos, consensusParams)) {
#     405                 :        108 :         return false;
#     406                 :        108 :     }
#     407         [ -  + ]:     107216 :     if (block.GetHash() != pindex->GetBlockHash()) {
#     408                 :          0 :         return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
#     409                 :          0 :                      pindex->ToString(), pindex->GetBlockPos().ToString());
#     410                 :          0 :     }
#     411                 :     107216 :     return true;
#     412                 :     107216 : }
#     413                 :            : 
#     414                 :            : bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start)
#     415                 :      10344 : {
#     416                 :      10344 :     FlatFilePos hpos = pos;
#     417                 :      10344 :     hpos.nPos -= 8; // Seek back 8 bytes for meta header
#     418                 :      10344 :     CAutoFile filein(OpenBlockFile(hpos, true), SER_DISK, CLIENT_VERSION);
#     419         [ -  + ]:      10344 :     if (filein.IsNull()) {
#     420                 :          0 :         return error("%s: OpenBlockFile failed for %s", __func__, pos.ToString());
#     421                 :          0 :     }
#     422                 :            : 
#     423                 :      10344 :     try {
#     424                 :      10344 :         CMessageHeader::MessageStartChars blk_start;
#     425                 :      10344 :         unsigned int blk_size;
#     426                 :            : 
#     427                 :      10344 :         filein >> blk_start >> blk_size;
#     428                 :            : 
#     429         [ -  + ]:      10344 :         if (memcmp(blk_start, message_start, CMessageHeader::MESSAGE_START_SIZE)) {
#     430                 :          0 :             return error("%s: Block magic mismatch for %s: %s versus expected %s", __func__, pos.ToString(),
#     431                 :          0 :                          HexStr(blk_start),
#     432                 :          0 :                          HexStr(message_start));
#     433                 :          0 :         }
#     434                 :            : 
#     435         [ -  + ]:      10344 :         if (blk_size > MAX_SIZE) {
#     436                 :          0 :             return error("%s: Block data is larger than maximum deserialization size for %s: %s versus %s", __func__, pos.ToString(),
#     437                 :          0 :                          blk_size, MAX_SIZE);
#     438                 :          0 :         }
#     439                 :            : 
#     440                 :      10344 :         block.resize(blk_size); // Zeroing of memory is intentional here
#     441                 :      10344 :         filein.read((char*)block.data(), blk_size);
#     442                 :      10344 :     } catch (const std::exception& e) {
#     443                 :          0 :         return error("%s: Read from block file failed: %s for %s", __func__, e.what(), pos.ToString());
#     444                 :          0 :     }
#     445                 :            : 
#     446                 :      10344 :     return true;
#     447                 :      10344 : }
#     448                 :            : 
#     449                 :            : bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start)
#     450                 :      10344 : {
#     451                 :      10344 :     FlatFilePos block_pos;
#     452                 :      10344 :     {
#     453                 :      10344 :         LOCK(cs_main);
#     454                 :      10344 :         block_pos = pindex->GetBlockPos();
#     455                 :      10344 :     }
#     456                 :            : 
#     457                 :      10344 :     return ReadRawBlockFromDisk(block, block_pos, message_start);
#     458                 :      10344 : }
#     459                 :            : 
#     460                 :            : /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
#     461                 :            : FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp)
#     462                 :      69448 : {
#     463                 :      69448 :     unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION);
#     464                 :      69448 :     FlatFilePos blockPos;
#     465         [ +  + ]:      69448 :     if (dbp != nullptr) {
#     466                 :       1455 :         blockPos = *dbp;
#     467                 :       1455 :     }
#     468         [ -  + ]:      69448 :     if (!FindBlockPos(blockPos, nBlockSize + 8, nHeight, active_chain, block.GetBlockTime(), dbp != nullptr)) {
#     469                 :          0 :         error("%s: FindBlockPos failed", __func__);
#     470                 :          0 :         return FlatFilePos();
#     471                 :          0 :     }
#     472         [ +  + ]:      69448 :     if (dbp == nullptr) {
#     473         [ -  + ]:      67993 :         if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) {
#     474                 :          0 :             AbortNode("Failed to write block");
#     475                 :          0 :             return FlatFilePos();
#     476                 :          0 :         }
#     477                 :      69448 :     }
#     478                 :      69448 :     return blockPos;
#     479                 :      69448 : }
#     480                 :            : 
#     481                 :            : struct CImportingNow {
#     482                 :            :     CImportingNow()
#     483                 :        621 :     {
#     484                 :        621 :         assert(fImporting == false);
#     485                 :        621 :         fImporting = true;
#     486                 :        621 :     }
#     487                 :            : 
#     488                 :            :     ~CImportingNow()
#     489                 :        621 :     {
#     490                 :        621 :         assert(fImporting == true);
#     491                 :        621 :         fImporting = false;
#     492                 :        621 :     }
#     493                 :            : };
#     494                 :            : 
#     495                 :            : void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args)
#     496                 :        621 : {
#     497                 :        621 :     const CChainParams& chainparams = Params();
#     498                 :        621 :     ScheduleBatchPriority();
#     499                 :            : 
#     500                 :        621 :     {
#     501                 :        621 :         CImportingNow imp;
#     502                 :            : 
#     503                 :            :         // -reindex
#     504         [ +  + ]:        621 :         if (fReindex) {
#     505                 :         10 :             int nFile = 0;
#     506                 :         19 :             while (true) {
#     507                 :         19 :                 FlatFilePos pos(nFile, 0);
#     508         [ +  + ]:         19 :                 if (!fs::exists(GetBlockPosFilename(pos))) {
#     509                 :         10 :                     break; // No block files left to reindex
#     510                 :         10 :                 }
#     511                 :          9 :                 FILE* file = OpenBlockFile(pos, true);
#     512         [ -  + ]:          9 :                 if (!file) {
#     513                 :          0 :                     break; // This error is logged in OpenBlockFile
#     514                 :          0 :                 }
#     515                 :          9 :                 LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
#     516                 :          9 :                 chainman.ActiveChainstate().LoadExternalBlockFile(chainparams, file, &pos);
#     517         [ -  + ]:          9 :                 if (ShutdownRequested()) {
#     518                 :          0 :                     LogPrintf("Shutdown requested. Exit %s\n", __func__);
#     519                 :          0 :                     return;
#     520                 :          0 :                 }
#     521                 :          9 :                 nFile++;
#     522                 :          9 :             }
#     523                 :         10 :             pblocktree->WriteReindexing(false);
#     524                 :         10 :             fReindex = false;
#     525                 :         10 :             LogPrintf("Reindexing finished\n");
#     526                 :            :             // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
#     527                 :         10 :             chainman.ActiveChainstate().LoadGenesisBlock(chainparams);
#     528                 :         10 :         }
#     529                 :            : 
#     530                 :            :         // -loadblock=
#     531         [ +  + ]:        621 :         for (const fs::path& path : vImportFiles) {
#     532                 :          1 :             FILE* file = fsbridge::fopen(path, "rb");
#     533         [ +  - ]:          1 :             if (file) {
#     534                 :          1 :                 LogPrintf("Importing blocks file %s...\n", path.string());
#     535                 :          1 :                 chainman.ActiveChainstate().LoadExternalBlockFile(chainparams, file);
#     536         [ -  + ]:          1 :                 if (ShutdownRequested()) {
#     537                 :          0 :                     LogPrintf("Shutdown requested. Exit %s\n", __func__);
#     538                 :          0 :                     return;
#     539                 :          0 :                 }
#     540                 :          0 :             } else {
#     541                 :          0 :                 LogPrintf("Warning: Could not open blocks file %s\n", path.string());
#     542                 :          0 :             }
#     543                 :          1 :         }
#     544                 :            : 
#     545                 :            :         // scan for better chains in the block chain database, that are not yet connected in the active best chain
#     546                 :            : 
#     547                 :            :         // We can't hold cs_main during ActivateBestChain even though we're accessing
#     548                 :            :         // the chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve
#     549                 :            :         // the relevant pointers before the ABC call.
#     550         [ +  + ]:        621 :         for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
#     551                 :        621 :             BlockValidationState state;
#     552         [ -  + ]:        621 :             if (!chainstate->ActivateBestChain(state, chainparams, nullptr)) {
#     553                 :          0 :                 LogPrintf("Failed to connect best block (%s)\n", state.ToString());
#     554                 :          0 :                 StartShutdown();
#     555                 :          0 :                 return;
#     556                 :          0 :             }
#     557                 :        621 :         }
#     558                 :            : 
#     559         [ -  + ]:        621 :         if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
#     560                 :          0 :             LogPrintf("Stopping after block import\n");
#     561                 :          0 :             StartShutdown();
#     562                 :          0 :             return;
#     563                 :          0 :         }
#     564                 :        621 :     } // End scope of CImportingNow
#     565                 :        621 :     chainman.ActiveChainstate().LoadMempool(args);
#     566                 :        621 : }

Generated by: LCOV version 1.14