From 8e2ecfe2496d8a015f3ee8723025a438feffbd28 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Wed, 11 Dec 2019 16:41:40 -0500 Subject: validation: add CChainState.m_from_snapshot_blockhash This parameter is unused, but in future commits will allow ChainstateManager to differentiate between chainstates created from a UTXO snapshot from those that weren't. --- src/validation.cpp | 8 +++++++- src/validation.h | 11 +++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/validation.cpp b/src/validation.cpp index a5b68e4ebd..31b78380af 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1244,7 +1244,9 @@ void CoinsViews::InitCache() // NOTE: for now m_blockman is set to a global, but this will be changed // in a future commit. -CChainState::CChainState() : m_blockman(g_blockman) {} +CChainState::CChainState(uint256 from_snapshot_blockhash) + : m_blockman(g_blockman), + m_from_snapshot_blockhash(from_snapshot_blockhash) {} void CChainState::InitCoinsDB( @@ -1253,6 +1255,10 @@ void CChainState::InitCoinsDB( bool should_wipe, std::string leveldb_name) { + if (!m_from_snapshot_blockhash.IsNull()) { + leveldb_name += "_" + m_from_snapshot_blockhash.ToString(); + } + m_coins_views = MakeUnique( leveldb_name, cache_size_bytes, in_memory, should_wipe); } diff --git a/src/validation.h b/src/validation.h index a5335edc43..07d90ab110 100644 --- a/src/validation.h +++ b/src/validation.h @@ -591,8 +591,8 @@ private: std::unique_ptr m_coins_views; public: - CChainState(BlockManager& blockman) : m_blockman(blockman) {} - CChainState(); + explicit CChainState(BlockManager& blockman) : m_blockman(blockman) {} + explicit CChainState(uint256 from_snapshot_blockhash = uint256()); /** * Initialize the CoinsViews UTXO set database management data structures. The in-memory @@ -620,6 +620,13 @@ public: //! @see CChain, CBlockIndex. CChain m_chain; + /** + * The blockhash which is the base of the snapshot this chainstate was created from. + * + * IsNull() if this chainstate was not created from a snapshot. + */ + const uint256 m_from_snapshot_blockhash{}; + /** * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be -- cgit v1.2.3 From 89cdf4d5692d396b8c7177b3918aa9dab07f9624 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Thu, 12 Dec 2019 10:20:44 -0500 Subject: validation: introduce unused ChainstateManager ChainstateManager is responsible for creating and managing multiple chainstates, and will provide a high-level interface for accessing the appropriate chainstate based upon a certain use. Incorporates feedback from Marco Falke. Additional documentation written by Russ Yanofsky. Co-authored-by: Russell Yanofsky --- src/validation.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++ src/validation.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+) (limited to 'src') diff --git a/src/validation.cpp b/src/validation.cpp index 31b78380af..a6b1344792 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -4950,6 +4951,14 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams) assert(nNodes == forward.size()); } +std::string CChainState::ToString() +{ + CBlockIndex* tip = m_chain.Tip(); + return strprintf("Chainstate [%s] @ height %d (%s)", + m_from_snapshot_blockhash.IsNull() ? "ibd" : "snapshot", + tip ? tip->nHeight : -1, tip ? tip->GetBlockHash().ToString() : "null"); +} + std::string CBlockFileInfo::ToString() const { return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast)); @@ -5144,3 +5153,90 @@ public: } }; static CMainCleanup instance_of_cmaincleanup; + +Optional ChainstateManager::SnapshotBlockhash() const { + if (m_active_chainstate != nullptr) { + // If a snapshot chainstate exists, it will always be our active. + return m_active_chainstate->m_from_snapshot_blockhash; + } + return {}; +} + +std::vector ChainstateManager::GetAll() +{ + std::vector out; + + if (!IsSnapshotValidated() && m_ibd_chainstate) { + out.push_back(m_ibd_chainstate.get()); + } + + if (m_snapshot_chainstate) { + out.push_back(m_snapshot_chainstate.get()); + } + + return out; +} + +CChainState& ChainstateManager::InitializeChainstate(const uint256& snapshot_blockhash) +{ + bool is_snapshot = !snapshot_blockhash.IsNull(); + std::unique_ptr& to_modify = + is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate; + + if (to_modify) { + throw std::logic_error("should not be overwriting a chainstate"); + } + + to_modify.reset(new CChainState(snapshot_blockhash)); + + // Snapshot chainstates and initial IBD chaintates always become active. + if (is_snapshot || (!is_snapshot && !m_active_chainstate)) { + LogPrintf("Switching active chainstate to %s\n", to_modify->ToString()); + m_active_chainstate = to_modify.get(); + } else { + throw std::logic_error("unexpected chainstate activation"); + } + + return *to_modify; +} + +CChain& ChainstateManager::ActiveChain() const +{ + assert(m_active_chainstate); + return m_active_chainstate->m_chain; +} + +bool ChainstateManager::IsSnapshotActive() const +{ + return m_snapshot_chainstate && m_active_chainstate == m_snapshot_chainstate.get(); +} + +CChainState& ChainstateManager::ValidatedChainstate() const +{ + if (m_snapshot_chainstate && IsSnapshotValidated()) { + return *m_snapshot_chainstate.get(); + } + assert(m_ibd_chainstate); + return *m_ibd_chainstate.get(); +} + +bool ChainstateManager::IsBackgroundIBD(CChainState* chainstate) const +{ + return (m_snapshot_chainstate && chainstate == m_ibd_chainstate.get()); +} + +void ChainstateManager::Unload() +{ + for (CChainState* chainstate : this->GetAll()) { + chainstate->m_chain.SetTip(nullptr); + chainstate->UnloadBlockIndex(); + } +} + +void ChainstateManager::Reset() +{ + m_ibd_chainstate.reset(); + m_snapshot_chainstate.reset(); + m_active_chainstate = nullptr; + m_snapshot_validated = false; +} diff --git a/src/validation.h b/src/validation.h index 07d90ab110..35e4380bc0 100644 --- a/src/validation.h +++ b/src/validation.h @@ -14,6 +14,7 @@ #include #include // for ReadLE64 #include +#include #include #include // For CMessageHeader::MessageStartChars #include