diff options
Diffstat (limited to 'src/node')
-rw-r--r-- | src/node/blockstorage.cpp | 37 | ||||
-rw-r--r-- | src/node/blockstorage.h | 30 | ||||
-rw-r--r-- | src/node/chainstate.cpp | 4 | ||||
-rw-r--r-- | src/node/context.cpp | 1 | ||||
-rw-r--r-- | src/node/context.h | 2 | ||||
-rw-r--r-- | src/node/interfaces.cpp | 9 |
6 files changed, 62 insertions, 21 deletions
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 763fd29744..8ed22bbbce 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -21,10 +21,11 @@ #include <util/system.h> #include <validation.h> +#include <unordered_map> + namespace node { std::atomic_bool fImporting(false); std::atomic_bool fReindex(false); -bool fHavePruned = false; bool fPruneMode = false; uint64_t nPruneTarget = 0; @@ -81,7 +82,7 @@ const CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) const return it == m_block_index.end() ? nullptr : &it->second; } -CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block) +CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block, CBlockIndex*& best_header) { AssertLockHeld(cs_main); @@ -106,8 +107,9 @@ CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block) pindexNew->nTimeMax = (pindexNew->pprev ? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) : pindexNew->nTime); pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew); pindexNew->RaiseValidity(BLOCK_VALID_TREE); - if (pindexBestHeader == nullptr || pindexBestHeader->nChainWork < pindexNew->nChainWork) - pindexBestHeader = pindexNew; + if (best_header == nullptr || best_header->nChainWork < pindexNew->nChainWork) { + best_header = pindexNew; + } m_dirty_blockindex.insert(pindexNew); @@ -230,6 +232,11 @@ void BlockManager::FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPr nLastBlockWeCanPrune, count); } +void BlockManager::UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) { + AssertLockHeld(::cs_main); + m_prune_locks[name] = lock_info; +} + CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash) { AssertLockHeld(cs_main); @@ -285,8 +292,6 @@ bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params) if (pindex->pprev) { pindex->BuildSkip(); } - if (pindex->IsValid(BLOCK_VALID_TREE) && (pindexBestHeader == nullptr || CBlockIndexWorkComparator()(pindexBestHeader, pindex))) - pindexBestHeader = pindex; } return true; @@ -302,6 +307,8 @@ void BlockManager::Unload() m_last_blockfile = 0; m_dirty_blockindex.clear(); m_dirty_fileinfo.clear(); + + m_have_pruned = false; } bool BlockManager::WriteBlockIndexDB() @@ -364,8 +371,8 @@ bool BlockManager::LoadBlockIndexDB() } // Check whether we have ever pruned block & undo files - m_block_tree_db->ReadFlag("prunedblockfiles", fHavePruned); - if (fHavePruned) { + m_block_tree_db->ReadFlag("prunedblockfiles", m_have_pruned); + if (m_have_pruned) { LogPrintf("LoadBlockIndexDB(): Block files have previously been pruned\n"); } @@ -391,10 +398,20 @@ const CBlockIndex* BlockManager::GetLastCheckpoint(const CCheckpointData& data) return nullptr; } -bool IsBlockPruned(const CBlockIndex* pblockindex) +bool BlockManager::IsBlockPruned(const CBlockIndex* pblockindex) { AssertLockHeld(::cs_main); - return (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0); + return (m_have_pruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0); +} + +const CBlockIndex* GetFirstStoredBlock(const CBlockIndex* start_block) { + AssertLockHeld(::cs_main); + assert(start_block); + const CBlockIndex* last_block = start_block; + while (last_block->pprev && (last_block->pprev->nStatus & BLOCK_HAVE_DATA)) { + last_block = last_block->pprev; + } + return last_block; } // If we're using -prune with -reindex, then delete block files that will be ignored by the diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 7c6c379a47..e4b9657372 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -13,6 +13,7 @@ #include <atomic> #include <cstdint> +#include <unordered_map> #include <vector> extern RecursiveMutex cs_main; @@ -45,8 +46,6 @@ static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB extern std::atomic_bool fImporting; extern std::atomic_bool fReindex; /** Pruning-related variables and constants */ -/** True if any block files have ever been pruned. */ -extern bool fHavePruned; /** True if we're running in -prune mode. */ extern bool fPruneMode; /** Number of MiB of block files that we're trying to stay below. */ @@ -67,6 +66,10 @@ struct CBlockIndexHeightOnlyComparator { bool operator()(const CBlockIndex* pa, const CBlockIndex* pb) const; }; +struct PruneLockInfo { + int height_first{std::numeric_limits<int>::max()}; //! Height of earliest block that should be kept and not pruned +}; + /** * Maintains a tree of blocks (stored in `m_block_index`) which is consulted * to determine where the most-work tip is. @@ -127,6 +130,14 @@ private: /** Dirty block file entries. */ std::set<int> m_dirty_fileinfo; + /** + * Map from external index name to oldest block that must not be pruned. + * + * @note Internally, only blocks at height (height_first - PRUNE_LOCK_BUFFER - 1) and + * below will be pruned, but callers should avoid assuming any particular buffer size. + */ + std::unordered_map<std::string, PruneLockInfo> m_prune_locks GUARDED_BY(::cs_main); + public: BlockMap m_block_index GUARDED_BY(cs_main); @@ -146,7 +157,7 @@ public: /** Clear all data members. */ void Unload() EXCLUSIVE_LOCKS_REQUIRED(cs_main); - CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + CBlockIndex* AddToBlockIndex(const CBlockHeader& block, CBlockIndex*& best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** Create a new block index entry for a given block hash */ CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); @@ -170,14 +181,23 @@ public: //! Returns last CBlockIndex* that is a checkpoint const CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + /** True if any block files have ever been pruned. */ + bool m_have_pruned = false; + + //! Check whether the block associated with this index entry is pruned or not. + bool IsBlockPruned(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); + + //! Create or update a prune lock identified by its name + void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); + ~BlockManager() { Unload(); } }; -//! Check whether the block associated with this index entry is pruned or not. -bool IsBlockPruned(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); +//! Find the first block that is not pruned +const CBlockIndex* GetFirstStoredBlock(const CBlockIndex* start_block) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); void CleanupBlockRevFiles(); diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index 9fdeb036fd..e43211402c 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -49,7 +49,7 @@ std::optional<ChainstateLoadingError> LoadChainstate(bool fReset, if (shutdown_requested && shutdown_requested()) return ChainstateLoadingError::SHUTDOWN_PROBED; - // LoadBlockIndex will load fHavePruned if we've ever removed a + // LoadBlockIndex will load m_have_pruned if we've ever removed a // block file from disk. // Note that it also sets fReindex based on the disk flag! // From here on out fReindex and fReset mean something different! @@ -65,7 +65,7 @@ std::optional<ChainstateLoadingError> LoadChainstate(bool fReset, // Check for changed -prune state. What we are concerned about is a user who has pruned blocks // in the past, but is now trying to run unpruned. - if (fHavePruned && !fPruneMode) { + if (chainman.m_blockman.m_have_pruned && !fPruneMode) { return ChainstateLoadingError::ERROR_PRUNED_NEEDS_REINDEX; } diff --git a/src/node/context.cpp b/src/node/context.cpp index 893c32f1bc..0b31c10f44 100644 --- a/src/node/context.cpp +++ b/src/node/context.cpp @@ -9,6 +9,7 @@ #include <interfaces/chain.h> #include <net.h> #include <net_processing.h> +#include <netgroup.h> #include <policy/fees.h> #include <scheduler.h> #include <txmempool.h> diff --git a/src/node/context.h b/src/node/context.h index 644c997531..91ba456219 100644 --- a/src/node/context.h +++ b/src/node/context.h @@ -18,6 +18,7 @@ class CConnman; class CScheduler; class CTxMemPool; class ChainstateManager; +class NetGroupManager; class PeerManager; namespace interfaces { class Chain; @@ -43,6 +44,7 @@ struct NodeContext { std::unique_ptr<AddrMan> addrman; std::unique_ptr<CConnman> connman; std::unique_ptr<CTxMemPool> mempool; + std::unique_ptr<const NetGroupManager> netgroupman; std::unique_ptr<CBlockPolicyEstimator> fee_estimator; std::unique_ptr<PeerManager> peerman; std::unique_ptr<ChainstateManager> chainman; diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 73d15652b1..954bd1c31d 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -212,9 +212,10 @@ public: bool getHeaderTip(int& height, int64_t& block_time) override { LOCK(::cs_main); - if (::pindexBestHeader) { - height = ::pindexBestHeader->nHeight; - block_time = ::pindexBestHeader->GetBlockTime(); + auto best_header = chainman().m_best_header; + if (best_header) { + height = best_header->nHeight; + block_time = best_header->GetBlockTime(); return true; } return false; @@ -644,7 +645,7 @@ public: bool havePruned() override { LOCK(cs_main); - return node::fHavePruned; + return m_node.chainman->m_blockman.m_have_pruned; } bool isReadyToBroadcast() override { return !node::fImporting && !node::fReindex && !isInitialBlockDownload(); } bool isInitialBlockDownload() override { |