42#include <validation.h>
54#include <system_error>
55#include <unordered_map>
95 for (
const auto& [file, info] :
fileInfo) {
123 std::unique_ptr<CDBIterator> pcursor(
NewIterator());
127 while (pcursor->Valid()) {
128 if (interrupt)
return false;
129 std::pair<uint8_t, uint256> key;
177 if (
pa->nChainWork >
pb->nChainWork)
return false;
178 if (
pa->nChainWork <
pb->nChainWork)
return true;
181 if (
pa->nSequenceId <
pb->nSequenceId)
return false;
182 if (
pa->nSequenceId >
pb->nSequenceId)
return true;
187 if (
pa <
pb)
return false;
188 if (
pa >
pb)
return true;
196 return pa->nHeight <
pb->nHeight;
199std::vector<CBlockIndex*> BlockManager::GetAllBlockIndices()
202 std::vector<CBlockIndex*>
rv;
264 for (
auto it = range.first; it != range.second; ++it) {
265 if (it->second == block)
return;
280 pindex->nDataPos = 0;
281 pindex->nUndoPos = 0;
289 while (range.first != range.second) {
290 std::multimap<CBlockIndex*, CBlockIndex*>::iterator
_it = range.first;
292 if (
_it->second == pindex) {
328 LogInfo(
"[%s] Prune (Manual): prune_height=%d removed %d blk/rev pairs",
347 const auto target = std::max(
407 LogDebug(
BCLog::PRUNE,
"[%s] target=%dMiB actual=%dMiB diff=%dMiB min_height=%d max_prune_height=%d removed %d blk/rev pairs\n",
418bool BlockManager::DeletePruneLock(
const std::string&
name)
484 pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) +
GetBlockProof(*pindex);
485 pindex->nTimeMax = (pindex->pprev ? std::max(pindex->pprev->nTimeMax, pindex->nTime) : pindex->nTime);
491 if (pindex->nTx > 0) {
496 Assert(pindex->m_chain_tx_count > 0);
497 }
else if (pindex->pprev->m_chain_tx_count > 0) {
498 pindex->m_chain_tx_count = pindex->pprev->m_chain_tx_count + pindex->nTx;
500 pindex->m_chain_tx_count = 0;
506 pindex->m_chain_tx_count = pindex->nTx;
529void BlockManager::WriteBlockIndexDB()
532 std::vector<std::pair<int, const CBlockFileInfo*>>
vFiles;
538 std::vector<const CBlockIndex*>
vBlocks;
574 LogInfo(
"Checking all blk files are present...");
599 LogInfo(
"Loading block index db: Block files have previously been pruned");
610void BlockManager::ScanAndUnlinkAlreadyPrunedFiles()
619 for (
int file_number = 0; file_number <
max_blockfile; file_number++) {
628bool BlockManager::IsBlockPruned(
const CBlockIndex& block)
const
680 LogInfo(
"Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune");
681 for (fs::directory_iterator it(
m_opts.
blocks_dir); it != fs::directory_iterator(); it++) {
683 if (fs::is_regular_file(*it) &&
684 path.length() == 12 &&
685 path.ends_with(
".dat"))
687 if (path.starts_with(
"blk")) {
689 }
else if (path.starts_with(
"rev")) {
722 LogError(
"OpenUndoFile failed for %s while reading block undo", pos.ToString());
739 LogError(
"Checksum mismatch at %s while reading block undo", pos.ToString());
742 }
catch (
const std::exception&
e) {
743 LogError(
"Deserialize or I/O error - %s at %s while reading block undo",
e.what(), pos.ToString());
797bool BlockManager::FlushChainstateBlockFile(
int tip_height)
811uint64_t BlockManager::CalculateCurrentUsage()
816 retval += file.nSize + file.nUndoSize;
915 "Failed to flush previous block file %05i (finalize=1, finalize_undo=%i) before opening new block file %05i\n",
951 const int nFile = pos.
nFile;
992 LogError(
"FindUndoPos failed for %s while writing block undo", pos.
ToString());
999 LogError(
"OpenUndoFile failed for %s while writing block undo", pos.
ToString());
1019 if (file.fclose() != 0) {
1042 block.nUndoPos = pos.
nPos;
1063 }
catch (
const std::exception&
e) {
1064 LogError(
"Deserialize or I/O error - %s at %s while reading block",
e.what(), pos.
ToString());
1068 const auto block_hash{block.
GetHash()};
1072 LogError(
"Errors in block header at %s while reading block", pos.
ToString());
1078 LogError(
"Errors in block solution at %s while reading block", pos.
ToString());
1083 LogError(
"GetHash() doesn't match index at %s while reading block (%s != %s)",
1103 LogError(
"Failed for %s while reading raw block storage header", pos.
ToString());
1108 LogError(
"OpenBlockFile failed for %s while reading raw block", pos.
ToString());
1119 LogError(
"Block magic mismatch for %s: %s versus expected %s while reading raw block",
1125 LogError(
"Block data is larger than maximum deserialization size for %s: %s versus %s while reading raw block",
1142 }
catch (
const std::exception&
e) {
1143 LogError(
"Read from block file failed: %s for %s while reading raw block",
e.what(), pos.
ToString());
1154 LogError(
"FindNextBlockPos failed for %s while writing block", pos.
ToString());
1158 if (file.IsNull()) {
1159 LogError(
"OpenBlockFile failed for %s while writing block", pos.
ToString());
1173 if (file.fclose() != 0) {
1186 std::array<std::byte, Obfuscation::KEY_SIZE>
obfuscation{};
1192 for (
const auto& entry : fs::directory_iterator(opts.
blocks_dir)) {
1194 if (!entry.is_regular_file() || !path.starts_with(
'.')) {
1216 throw std::runtime_error{
strprintf(
"Error closing XOR key file %s: %s",
1223 throw std::runtime_error{
1224 strprintf(
"The blocksdir XOR-key can not be disabled when a random key was already stored! "
1225 "Stored key: '%s', stored path: '%s'.",
1234 : m_prune_mode{opts.prune_target > 0},
1236 m_opts{
std::move(opts)},
1239 m_interrupt{interrupt}
1285 for (
int nFile{0}; nFile <
total_files; ++nFile) {
1288 if (file.IsNull()) {
1291 LogInfo(
"Reindexing block file blk%05u.dat (%d%% complete)...", (
unsigned int)nFile, nFile * 100 /
total_files);
1294 LogInfo(
"Interrupt requested. Exit reindexing.");
1300 LogInfo(
"Reindexing finished");
1308 if (!file.IsNull()) {
1312 LogInfo(
"Interrupt requested. Exit block importing.");
1321 if (
auto result = chainman.ActivateBestChains(); !result) {
1331 default:
os.setstate(std::ios_base::failbit);
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ BLOCK_HAVE_UNDO
undo data available in rev*.dat
@ BLOCK_HAVE_DATA
full block available in blk*.dat
@ BLOCK_FAILED_CHILD
Unused flag that was previously set when descending from failed block.
@ BLOCK_FAILED_VALID
stage after last reached validness failed
arith_uint256 GetBlockProof(const CBlockIndex &block)
Compute how much work a block index entry corresponds to.
constexpr int32_t SEQ_ID_INIT_FROM_DISK
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Non-refcounted RAII wrapper for FILE*.
Wrapper that buffers reads from an underlying stream.
Wrapper that buffers writes to an underlying stream.
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
uint64_t m_chain_tx_count
(memory only) Number of transactions in the chain up to and including this block.
int32_t nSequenceId
(memory only) Sequential id assigned to distinguish order in which blocks are received.
uint256 GetBlockHash() const
FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(
unsigned int nTx
Number of transactions in this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
const uint256 * phashBlock
pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
Undo information for a CBlock.
int Height() const
Return the maximal height in the chain.
const MessageStartChars & MessageStart() const
std::optional< AssumeutxoData > AssumeutxoForBlockhash(const uint256 &blockhash) const
uint64_t PruneAfterHeight() const
Batch of changes queued to be written to a CDBWrapper.
void Write(const K &key, const V &value)
CDBIterator * NewIterator()
void Erase(const K &key, bool fSync=false)
void WriteBatch(CDBBatch &batch, bool fSync=false)
void Write(const K &key, const V &value, bool fSync=false)
Used to marshal pointers into hashes for db storage.
Chainstate stores and provides an API to update our local knowledge of the current best chain.
CChain m_chain
The current chain of blockheaders we consult and build on.
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
Chainstate * HistoricalChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Return historical chainstate targeting a specific block, if any.
bool IsInitialBlockDownload() const noexcept
Check whether we are doing an initial block download (synchronizing from disk or network)
kernel::Notifications & GetNotifications() const
const util::SignalInterrupt & m_interrupt
void LoadExternalBlockFile(AutoFile &file_in, FlatFilePos *dbp=nullptr, std::multimap< uint256, FlatFilePos > *blocks_with_unknown_parent=nullptr)
Import blocks from an external file.
const CChainParams & GetParams() const
bool LoadGenesisBlock()
Ensures a genesis block is in the block tree, possibly writing one to disk.
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
void fillrand(std::span< std::byte > output) noexcept
Fill a byte span with random bytes.
FlatFileSeq represents a sequence of numbered files storing raw data.
FILE * Open(const FlatFilePos &pos, bool read_only=false) const
Open a handle to the file at the given position.
fs::path FileName(const FlatFilePos &pos) const
Get the name of the file at the given position.
bool Flush(const FlatFilePos &pos, bool finalize=false) const
Commit a file to disk, and optionally truncate off extra pre-allocated bytes if final.
size_t Allocate(const FlatFilePos &pos, size_t add_size, bool &out_of_space) const
Allocate additional space in a file after the given starting position.
Reads data from an underlying stream, while hashing the read data.
A writer stream (for serialization) that computes a 256-bit hash.
Minimal stream for reading from an existing byte array by std::span.
constexpr bool IsNull() const
void WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo * > > &fileInfo, int nLastFile, const std::vector< const CBlockIndex * > &blockinfo)
bool ReadLastBlockFile(int &nFile)
void WriteReindexing(bool fReindexing)
bool ReadFlag(const std::string &name, bool &fValue)
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info)
void ReadReindexing(bool &fReindexing)
void WriteFlag(const std::string &name, bool fValue)
uint32_t nSize
number of used bytes of block file
std::string ToString() const
uint64_t nTimeFirst
earliest time of block in file
uint64_t nTimeLast
latest time of block in file
uint32_t nHeightFirst
lowest height of block in file
uint32_t nBlocks
number of blocks stored in file
uint32_t nHeightLast
highest height of block in file
virtual void fatalError(const bilingual_str &message)
The fatal error notification is sent to notify the user when an error occurs in kernel code that can'...
virtual void flushError(const bilingual_str &message)
The flush error notification is sent to notify the user that an error occurred while flushing block d...
const kernel::BlockManagerOpts m_opts
std::set< int > m_dirty_fileinfo
Dirty block file entries.
const FlatFileSeq m_undo_file_seq
const CChainParams & GetParams() const
void PruneOneBlockFile(int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mark one block file as pruned (modify associated database entries)
void FindFilesToPrune(std::set< int > &setFilesToPrune, int last_prune, const Chainstate &chain, ChainstateManager &chainman)
Prune block and undo files (blk???.dat and rev???.dat) so that the disk space used is less than a use...
const Obfuscation m_obfuscation
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool ReadBlockUndo(CBlockUndo &blockundo, const CBlockIndex &index) const
int MaxBlockfileNum() const EXCLUSIVE_LOCKS_REQUIRED(
CBlockFileInfo *GetBlockFileInfo(size_t n) EXCLUSIVE_LOCKS_REQUIRED(bool WriteBlockUndo(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex &block) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePos WriteBlock(const CBlock &block, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(void UpdateBlockInfo(const CBlock &block, unsigned int nHeight, const FlatFilePos &pos) EXCLUSIVE_LOCKS_REQUIRED(bool IsPruneMode() const
Get block file info entry for one block file.
BlockfileType BlockfileTypeForHeight(int height)
std::atomic_bool m_blockfiles_indexed
Whether all blockfiles have been added to the block tree database.
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.
const Consensus::Params & GetConsensus() const
BlockManager(const util::SignalInterrupt &interrupt, Options opts)
std::set< CBlockIndex * > m_dirty_blockindex
Dirty block index entries.
fs::path GetBlockPosFilename(const FlatFilePos &pos) const
Translation to a filesystem path.
uint64_t GetPruneTarget() const
Attempt to stay below this number of bytes of block files.
void UnlinkPrunedFiles(const std::set< int > &setFilesToPrune) const
Actually unlink the specified files.
void WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(bool LoadBlockIndexDB(const std::optional< uint256 > &snapshot_blockhash) EXCLUSIVE_LOCKS_REQUIRED(void ScanAndUnlinkAlreadyPrunedFiles() EXCLUSIVE_LOCKS_REQUIRED(CBlockIndex * AddToBlockIndex(const CBlockHeader &block, CBlockIndex *&best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Remove any pruned block & undo files that are still on disk.
void AddUnlinkedBlock(CBlockIndex *block) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool FlushBlockFile(int blockfile_num, bool fFinalize, bool finalize_undo) EXCLUSIVE_LOCKS_REQUIRED(bool FlushUndoFile(int block_file, bool finalize=false)
Return false if block file or undo file flushing fails.
const util::SignalInterrupt & m_interrupt
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t > > block_part=std::nullopt) const
const FlatFileSeq m_block_file_seq
CBlockIndex * InsertBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Create a new block index entry for a given block hash.
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
bool m_check_for_pruning
Global flag to indicate we should check to see if there are block/undo files that should be deleted.
void CleanupBlockRevFiles() const
std::atomic< bool > m_importing
bool IsBlockPruned(const CBlockIndex &block) const EXCLUSIVE_LOCKS_REQUIRED(void UpdatePruneLock(const std::string &name, const PruneLockInfo &lock_info) EXCLUSIVE_LOCKS_REQUIRED(bool DeletePruneLock(const std::string &name) EXCLUSIVE_LOCKS_REQUIRED(AutoFile OpenBlockFile(const FlatFilePos &pos, bool fReadOnly) const
Check whether the block associated with this index entry is pruned or not.
std::vector< CBlockFileInfo > m_blockfile_info
void FindFilesToPruneManual(std::set< int > &setFilesToPrune, int nManualPruneHeight, const Chainstate &chain)
bool LoadBlockIndex(const std::optional< uint256 > &snapshot_blockhash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the blocktree off disk and into memory.
FlatFilePos FindNextBlockPos(unsigned int nAddSize, unsigned int nHeight, uint64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(bool FlushChainstateBlockFile(int tip_height) EXCLUSIVE_LOCKS_REQUIRED(bool FindUndoPos(BlockValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize) EXCLUSIVE_LOCKS_REQUIRED(AutoFile OpenUndoFile(const FlatFilePos &pos, bool fReadOnly=false) const
Helper function performing various preparations before a block can be saved to disk: Returns the corr...
std::optional< int > m_snapshot_height
The height of the base block of an assumeutxo snapshot, if one is in use.
uint64_t CalculateCurrentUsage() EXCLUSIVE_LOCKS_REQUIRED(bool CheckBlockDataAvailability(const CBlockIndex &upper_block, const CBlockIndex &lower_block, BlockStatus block_status=BLOCK_HAVE_DATA) EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex &GetFirstBlock(const CBlockIndex &upper_block LIFETIMEBOUND, uint32_t status_mask, const CBlockIndex *lower_block LIFETIMEBOUND=nullptr) const EXCLUSIVE_LOCKS_REQUIRED(boo m_have_pruned)
Calculate the amount of disk space the block & undo files currently use.
ImportingNow(std::atomic< bool > &importing)
std::atomic< bool > & m_importing
The util::Expected class provides a standard way for low-level functions to return either error value...
Helper class that manages an interrupt flag, and allows a thread or signal to interrupt another threa...
The util::Unexpected class represents an unexpected value stored in util::Expected.
static const PrecomputedData data
Precomputed COutPoint and CCoins values.
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
static bool exists(const path &p)
static std::string PathToString(const path &path)
Convert path object to a byte string.
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
is a home for simple enum and struct type definitions that can be used internally by functions in the...
#define LogDebug(category,...)
std::array< uint8_t, 4 > MessageStartChars
FILE * fopen(const fs::path &p, const char *mode)
static constexpr uint8_t DB_REINDEX_FLAG
static constexpr uint8_t DB_FLAG
static constexpr uint8_t DB_BLOCK_INDEX
static constexpr uint8_t DB_LAST_BLOCK
static constexpr uint8_t DB_BLOCK_FILES
static auto InitBlocksdirXorKey(const BlockManager::Options &opts)
constexpr uint32_t STORAGE_HEADER_BYTES
Size of header written by WriteBlock before a serialized CBlock (8 bytes)
std::ostream & operator<<(std::ostream &os, const BlockfileType &type)
constexpr unsigned int MAX_BLOCKFILE_SIZE
The maximum size of a blk?????.dat file (since 0.8)
constexpr uint32_t UNDO_DATA_DISK_OVERHEAD
Total overhead when writing undo data: header (8 bytes) plus checksum (32 bytes)
constexpr unsigned int UNDOFILE_CHUNK_SIZE
The pre-allocation chunk size for rev?????.dat files (since 0.8)
constexpr unsigned int BLOCKFILE_CHUNK_SIZE
The pre-allocation chunk size for blk?????.dat files (since 0.8)
void ImportBlocks(ChainstateManager &chainman, std::span< const fs::path > import_paths)
bilingual_str ErrorString(const Result< T > &result)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
T SaturatingAdd(const T i, const T j) noexcept
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.
constexpr TransactionSerParams TX_WITH_WITNESS
constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
uint64_t GetSerializeSize(const T &t)
bool CheckSignetBlockSolution(const CBlock &block, const Consensus::Params &consensusParams)
Extract signature and check whether a block has a valid solution.
Holds configuration for use during UTXO snapshot load and validation.
Parameters that influence chain consensus.
bool wipe_data
If true, remove all existing data.
std::string ToString() const
An options struct for BlockManager, more ergonomically referred to as BlockManager::Options due to th...
Notifications & notifications
const fs::path blocks_dir
DBParams block_tree_db_params
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define AssertLockHeld(cs)
std::string SysErrorString(int err)
Return system error string from errno value.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
consteval auto _(util::TranslatedLiteral str)
std::string FormatISO8601Date(int64_t nTime)
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
bool FatalError(Notifications ¬ifications, BlockValidationState &state, const bilingual_str &message)
constexpr uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES