25 #include <unordered_map> 45 if (pa < pb)
return false;
46 if (pa > pb)
return true;
61 std::vector<CBlockIndex*> BlockManager::GetAllBlockIndices()
64 std::vector<CBlockIndex*> rv;
65 rv.reserve(m_block_index.size());
66 for (
auto& [
_, block_index] : m_block_index) {
67 rv.push_back(&block_index);
75 BlockMap::iterator it = m_block_index.find(hash);
76 return it == m_block_index.end() ? nullptr : &it->second;
82 BlockMap::const_iterator it = m_block_index.find(hash);
83 return it == m_block_index.end() ? nullptr : &it->second;
90 auto [mi, inserted] = m_block_index.try_emplace(block.
GetHash(), block);
102 BlockMap::iterator miPrev = m_block_index.find(block.
hashPrevBlock);
103 if (miPrev != m_block_index.end()) {
104 pindexNew->
pprev = &(*miPrev).second;
112 best_header = pindexNew;
125 for (
auto& entry : m_block_index) {
127 if (pindex->nFile == fileNumber) {
131 pindex->nDataPos = 0;
132 pindex->nUndoPos = 0;
140 while (range.first != range.second) {
141 std::multimap<CBlockIndex*, CBlockIndex*>::iterator _it = range.first;
143 if (_it->second == pindex) {
159 if (chain_tip_height < 0) {
164 unsigned int nLastBlockWeCanPrune = std::min((
unsigned)nManualPruneHeight, chain_tip_height -
MIN_BLOCKS_TO_KEEP);
171 setFilesToPrune.insert(fileNumber);
174 LogPrintf(
"Prune (Manual): prune_height=%d removed %d blk/rev pairs\n", nLastBlockWeCanPrune,
count);
183 if ((uint64_t)chain_tip_height <= nPruneAfterHeight) {
187 unsigned int nLastBlockWeCanPrune{(unsigned)std::min(prune_height, chain_tip_height - static_cast<int>(
MIN_BLOCKS_TO_KEEP))};
193 uint64_t nBytesToPrune;
224 setFilesToPrune.insert(fileNumber);
225 nCurrentUsage -= nBytesToPrune;
230 LogPrint(
BCLog::PRUNE,
"target=%dMiB actual=%dMiB diff=%dMiB max_prune_height=%d removed %d blk/rev pairs\n",
232 ((int64_t)
nPruneTarget - (int64_t)nCurrentUsage)/1024/1024,
233 nLastBlockWeCanPrune,
count);
236 void BlockManager::UpdatePruneLock(
const std::string&
name,
const PruneLockInfo& lock_info) {
238 m_prune_locks[
name] = lock_info;
249 const auto [mi, inserted]{m_block_index.try_emplace(hash)};
264 std::vector<CBlockIndex*> vSortedByHeight{GetAllBlockIndices()};
265 std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),
270 pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) +
GetBlockProof(*pindex);
271 pindex->nTimeMax = (pindex->pprev ? std::max(pindex->pprev->nTimeMax, pindex->nTime) : pindex->nTime);
277 if (pindex->nTx > 0) {
279 if (pindex->pprev->nChainTx > 0) {
280 pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
282 pindex->nChainTx = 0;
286 pindex->nChainTx = pindex->nTx;
301 bool BlockManager::WriteBlockIndexDB()
304 std::vector<std::pair<int, const CBlockFileInfo*>> vFiles;
310 std::vector<const CBlockIndex*> vBlocks;
313 vBlocks.push_back(*it);
338 if (m_block_tree_db->ReadBlockFileInfo(nFile, info)) {
346 LogPrintf(
"Checking all blk files are present...\n");
347 std::set<int> setBlkDataFiles;
348 for (
const auto& [
_, block_index] : m_block_index) {
350 setBlkDataFiles.insert(block_index.nFile);
353 for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) {
361 m_block_tree_db->ReadFlag(
"prunedblockfiles",
m_have_pruned);
363 LogPrintf(
"LoadBlockIndexDB(): Block files have previously been pruned\n");
367 bool fReindexing =
false;
368 m_block_tree_db->ReadReindexing(fReindexing);
378 for (
const MapCheckpoints::value_type& i :
reverse_iterate(checkpoints)) {
379 const uint256& hash = i.second;
388 bool BlockManager::IsBlockPruned(
const CBlockIndex* pblockindex)
399 last_block = last_block->
pprev;
412 std::map<std::string, fs::path> mapBlockFiles;
417 LogPrintf(
"Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
419 for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
421 if (fs::is_regular_file(*it) &&
422 path.length() == 12 &&
423 path.substr(8,4) ==
".dat")
425 if (path.substr(0, 3) ==
"blk") {
426 mapBlockFiles[path.substr(3, 5)] = it->path();
427 }
else if (path.substr(0, 3) ==
"rev") {
437 int nContigCounter = 0;
438 for (
const std::pair<const std::string, fs::path>& item : mapBlockFiles) {
439 if (LocaleIndependentAtoi<int>(item.first) == nContigCounter) {
459 return error(
"%s: OpenUndoFile failed", __func__);
464 fileout << messageStart << nSize;
467 long fileOutPos = ftell(fileout.
Get());
468 if (fileOutPos < 0) {
469 return error(
"%s: ftell failed", __func__);
471 pos.
nPos = (
unsigned int)fileOutPos;
472 fileout << blockundo;
478 fileout << hasher.GetHash();
488 return error(
"%s: no undo data available", __func__);
494 return error(
"%s: OpenUndoFile failed", __func__);
502 verifier >> blockundo;
503 filein >> hashChecksum;
504 }
catch (
const std::exception& e) {
505 return error(
"%s: Deserialize or I/O error - %s", __func__, e.what());
509 if (hashChecksum != verifier.
GetHash()) {
510 return error(
"%s: Checksum mismatch", __func__);
519 if (!
UndoFileSeq().Flush(undo_pos_old, finalize)) {
520 AbortNode(
"Flushing undo file to disk failed. This is likely the result of an I/O error.");
529 AbortNode(
"Flushing block file to disk failed. This is likely the result of an I/O error.");
542 retval += file.nSize + file.nUndoSize;
549 for (std::set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) {
592 bool finalize_undo =
false;
627 return AbortNode(
"Disk space is too low!",
_(
"Disk space is too low!"));
651 return AbortNode(state,
"Disk space is too low!",
_(
"Disk space is too low!"));
665 return error(
"WriteBlockToDisk: OpenBlockFile failed");
670 fileout << messageStart << nSize;
673 long fileOutPos = ftell(fileout.
Get());
674 if (fileOutPos < 0) {
675 return error(
"WriteBlockToDisk: ftell failed");
677 pos.
nPos = (
unsigned int)fileOutPos;
690 return error(
"ConnectBlock(): FindUndoPos failed");
693 return AbortNode(state,
"Failed to write undo data");
705 pindex->nUndoPos = _pos.
nPos;
720 return error(
"ReadBlockFromDisk: OpenBlockFile failed for %s", pos.
ToString());
726 }
catch (
const std::exception& e) {
727 return error(
"%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.
ToString());
732 return error(
"ReadBlockFromDisk: Errors in block header at %s", pos.
ToString());
737 return error(
"ReadBlockFromDisk: Errors in block solution at %s", pos.
ToString());
751 return error(
"ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
752 pindex->
ToString(), block_pos.ToString());
763 return error(
"%s: OpenBlockFile failed for %s", __func__, pos.
ToString());
768 unsigned int blk_size;
770 filein >> blk_start >> blk_size;
773 return error(
"%s: Block magic mismatch for %s: %s versus expected %s", __func__, pos.
ToString(),
779 return error(
"%s: Block data is larger than maximum deserialization size for %s: %s versus %s", __func__, pos.
ToString(),
783 block.resize(blk_size);
785 }
catch (
const std::exception& e) {
786 return error(
"%s: Read from block file failed: %s for %s", __func__, e.what(), pos.
ToString());
797 if (dbp !=
nullptr) {
801 error(
"%s: FindBlockPos failed", __func__);
804 if (dbp ==
nullptr) {
840 std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
850 LogPrintf(
"Reindexing block file blk%05u.dat...\n", (
unsigned int)nFile);
851 chainman.
ActiveChainstate().LoadExternalBlockFile(file, &pos, &blocks_with_unknown_parent);
853 LogPrintf(
"Shutdown requested. Exit %s\n", __func__);
866 for (
const fs::path& path : vImportFiles) {
872 LogPrintf(
"Shutdown requested. Exit %s\n", __func__);
887 if (!chainstate->ActivateBestChain(state,
nullptr)) {
895 LogPrintf(
"Stopping after block import\n");
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
uint256 GetHash()
Compute the double-SHA256 hash of all data written to this object.
void CleanupBlockRevFiles()
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
std::string ToString() const
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
int32_t nSequenceId
(memory only) Sequential id assigned to distinguish order in which blocks are received.
static FILE * OpenUndoFile(const FlatFilePos &pos, bool fReadOnly=false)
Open an undo file (rev?????.dat)
std::set< int > m_dirty_fileinfo
Dirty block file entries.
bool m_check_for_pruning
Global flag to indicate we should check to see if there are block/undo files that should be deleted...
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
#define LogPrint(category,...)
static FlatFileSeq BlockFileSeq()
FILE * fopen(const fs::path &p, const char *mode)
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
descends from failed block
void ScheduleBatchPriority()
On platforms that support it, tell the kernel the calling thread is CPU-intensive and non-interactive...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
uint64_t CalculateCurrentUsage()
Calculate the amount of disk space the block & undo files currently use.
std::map< int, uint256 > MapCheckpoints
std::atomic_bool fReindex
FILE * OpenBlockFile(const FlatFilePos &pos, bool fReadOnly)
Open a block file (blk?????.dat)
RecursiveMutex cs_LastBlockFile
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT
void FindFilesToPrune(std::set< int > &setFilesToPrune, uint64_t nPruneAfterHeight, int chain_tip_height, int prune_height, bool is_ibd)
Prune block and undo files (blk???.dat and rev???.dat) so that the disk space used is less than a use...
An in-memory indexed chain of blocks.
reverse_range< T > reverse_iterate(T &x)
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
static FlatFileSeq UndoFileSeq()
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
undo data available in rev*.dat
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Reads data from an underlying stream, while hashing the read data.
FILE * Open(const FlatFilePos &pos, bool read_only=false)
Open a handle to the file at the given position.
void FlushUndoFile(int block_file, bool finalize=false)
size_t GetSerializeSize(const T &t, int nVersion=0)
std::vector< CBlockIndex * > GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(std::multimap< CBlockIndex *, CBlockIndex * > m_blocks_unlinked
All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
uint256 GetBlockHash() const
std::string ToString(const T &t)
Locale-independent version of std::to_string.
bool WriteUndoDataForBlock(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex *pindex, const CChainParams &chainparams) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePo SaveBlockToDisk)(const CBlock &block, int nHeight, CChain &active_chain, const CChainParams &chainparams, const FlatFilePos *dbp)
Store block on disk.
static const unsigned int BLOCKFILE_CHUNK_SIZE
The pre-allocation chunk size for blk?????.dat files (since 0.8)
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(bool LoadBlockIndexDB(const Consensus::Params &consensus_params) EXCLUSIVE_LOCKS_REQUIRED(CBlockIndex * AddToBlockIndex(const CBlockHeader &block, CBlockIndex *&best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
unsigned int nTimeMax
(memory only) Maximum nTime in the chain up to and including this block.
static std::string PathToString(const path &path)
Convert path object to a byte string.
uint64_t nPruneTarget
Number of bytes of block files that we're trying to stay below.
Chainstate stores and provides an API to update our local knowledge of the current best chain...
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
bool FindUndoPos(BlockValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize)
static bool UndoWriteToDisk(const CBlockUndo &blockundo, FlatFilePos &pos, const uint256 &hashBlock, const CMessageHeader::MessageStartChars &messageStart)
std::string ToString() const
bilingual_str _(const char *psz)
Translation function.
A writer stream (for serialization) that computes a 256-bit hash.
void FindFilesToPruneManual(std::set< int > &setFilesToPrune, int nManualPruneHeight, int chain_tip_height)
bool signet_blocks
If true, witness commitments contain a payload equal to a Bitcoin Script solution to the signet chall...
void LoadMempool(const fs::path &load_path, fsbridge::FopenFn mockable_fopen_function=fsbridge::fopen)
Load the persisted mempool from disk.
void BuildSkip()
Build the skiplist pointer for this entry.
const CMessageHeader::MessageStartChars & MessageStart() const
void read(Span< std::byte > dst)
void SetSyscallSandboxPolicy(SyscallSandboxPolicy syscall_policy)
Force the current thread (and threads created from the current thread) into a restricted-service oper...
Parameters that influence chain consensus.
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params ¶ms)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const
Chainstate &InitializeChainstate(CTxMemPool *mempool, const std::optional< uint256 > &snapshot_blockhash=std::nullopt) LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(std::vector< Chainstate * GetAll)()
Instantiate a new chainstate and assign it based upon whether it is from a snapshot.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
size_t Allocate(const FlatFilePos &pos, size_t add_size, bool &out_of_space)
Allocate additional space in a file after the given starting position.
FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(
const CBlockIndex * GetLastCheckpoint(const CCheckpointData &data) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Returns last CBlockIndex* that is a checkpoint.
bool fPruneMode
Pruning-related variables and constants.
std::string ToString() const
static bool WriteBlockToDisk(const CBlock &block, FlatFilePos &pos, const CMessageHeader::MessageStartChars &messageStart)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
fs::path FileName(const FlatFilePos &pos) const
Get the name of the file at the given position.
MapCheckpoints mapCheckpoints
std::set< CBlockIndex * > m_dirty_blockindex
Dirty block index entries.
bool LoadBlockIndex(const Consensus::Params &consensus_params) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the blocktree off disk and into memory.
const CBlockIndex *GetFirstStoredBlock(const CBlockIndex &start_block LIFETIMEBOUND) EXCLUSIVE_LOCKS_REQUIRED(bool m_have_pruned
Find the first block that is not pruned.
The block chain is a tree shaped structure starting with the genesis block at the root...
Undo information for a CBlock.
static const unsigned int MAX_BLOCKFILE_SIZE
The maximum size of a blk?????.dat file (since 0.8)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(
Raise the validity level of this block index entry.
bool UndoReadFromDisk(CBlockUndo &blockundo, const CBlockIndex *pindex)
void ThreadImport(ChainstateManager &chainman, std::vector< fs::path > vImportFiles, const ArgsManager &args, const fs::path &mempool_path)
static constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
void FlushBlockFile(bool fFinalize=false, bool finalize_undo=false)
void StartShutdown()
Request shutdown of the application.
CBlockIndex * InsertBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Create a new block index entry for a given block hash.
fs::path GetBlockPosFilename(const FlatFilePos &pos)
Translation to a filesystem path.
static const unsigned int UNDOFILE_CHUNK_SIZE
The pre-allocation chunk size for rev?????.dat files (since 0.8)
const fs::path & GetBlocksDirPath() const
Get blocks directory path.
bool ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos, const CMessageHeader::MessageStartChars &message_start)
arith_uint256 GetBlockProof(const CBlockIndex &block)
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
Chainstate & ActiveChainstate() const
The most-work chain.
full block available in blk*.dat
std::atomic_bool fImporting
static bool exists(const path &p)
CBlockFileInfo * GetBlockFileInfo(size_t n)
Get block file info entry for one block file.
void UnlinkPrunedFiles(const std::set< int > &setFilesToPrune)
Actually unlink the specified files.
void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mark one block file as pruned (modify associated database entries)
FlatFileSeq represents a sequence of numbered files storing raw data.
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
FILE * Get() const
Get wrapped FILE* without transfer of ownership.
bool error(const char *fmt, const Args &... args)
unsigned int nTx
Number of transactions in this block.
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const
bool AbortNode(const std::string &strMessage, bilingual_str user_message)
Abort with a message.
bool CheckSignetBlockSolution(const CBlock &block, const Consensus::Params &consensusParams)
Extract signature and check whether a block has a valid solution.
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int nHeight, CChain &active_chain, uint64_t nTime, bool fKnown)
const uint256 * phashBlock
pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
std::vector< CBlockFileInfo > m_blockfile_info