validation: Guard all chainstates with cs_main

Since these chainstates are:

1. Also vulnerable to the race condition described in the previous
   commit
2. Documented as having similar semantics as m_active_chainstate

we should also protect them with ::cs_main.
This commit is contained in:
Carl Dong 2021-01-27 16:20:59 -05:00
parent f72d80b07a
commit 20677ffa22
2 changed files with 10 additions and 8 deletions

View file

@ -5159,7 +5159,7 @@ double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pin
} }
Optional<uint256> ChainstateManager::SnapshotBlockhash() const { Optional<uint256> ChainstateManager::SnapshotBlockhash() const {
LOCK(::cs_main); // for m_active_chainstate access LOCK(::cs_main);
if (m_active_chainstate != nullptr) { if (m_active_chainstate != nullptr) {
// If a snapshot chainstate exists, it will always be our active. // If a snapshot chainstate exists, it will always be our active.
return m_active_chainstate->m_from_snapshot_blockhash; return m_active_chainstate->m_from_snapshot_blockhash;
@ -5169,6 +5169,7 @@ Optional<uint256> ChainstateManager::SnapshotBlockhash() const {
std::vector<CChainState*> ChainstateManager::GetAll() std::vector<CChainState*> ChainstateManager::GetAll()
{ {
LOCK(::cs_main);
std::vector<CChainState*> out; std::vector<CChainState*> out;
if (!IsSnapshotValidated() && m_ibd_chainstate) { if (!IsSnapshotValidated() && m_ibd_chainstate) {
@ -5213,11 +5214,13 @@ CChainState& ChainstateManager::ActiveChainstate() const
bool ChainstateManager::IsSnapshotActive() const bool ChainstateManager::IsSnapshotActive() const
{ {
return m_snapshot_chainstate && WITH_LOCK(::cs_main, return m_active_chainstate) == m_snapshot_chainstate.get(); LOCK(::cs_main);
return m_snapshot_chainstate && m_active_chainstate == m_snapshot_chainstate.get();
} }
CChainState& ChainstateManager::ValidatedChainstate() const CChainState& ChainstateManager::ValidatedChainstate() const
{ {
LOCK(::cs_main);
if (m_snapshot_chainstate && IsSnapshotValidated()) { if (m_snapshot_chainstate && IsSnapshotValidated()) {
return *m_snapshot_chainstate.get(); return *m_snapshot_chainstate.get();
} }
@ -5227,6 +5230,7 @@ CChainState& ChainstateManager::ValidatedChainstate() const
bool ChainstateManager::IsBackgroundIBD(CChainState* chainstate) const bool ChainstateManager::IsBackgroundIBD(CChainState* chainstate) const
{ {
LOCK(::cs_main);
return (m_snapshot_chainstate && chainstate == m_ibd_chainstate.get()); return (m_snapshot_chainstate && chainstate == m_ibd_chainstate.get());
} }
@ -5242,12 +5246,10 @@ void ChainstateManager::Unload()
void ChainstateManager::Reset() void ChainstateManager::Reset()
{ {
LOCK(::cs_main);
m_ibd_chainstate.reset(); m_ibd_chainstate.reset();
m_snapshot_chainstate.reset(); m_snapshot_chainstate.reset();
{ m_active_chainstate = nullptr;
LOCK(::cs_main);
m_active_chainstate = nullptr;
}
m_snapshot_validated = false; m_snapshot_validated = false;
} }

View file

@ -802,7 +802,7 @@ private:
//! This is especially important when, e.g., calling ActivateBestChain() //! This is especially important when, e.g., calling ActivateBestChain()
//! on all chainstates because we are not able to hold ::cs_main going into //! on all chainstates because we are not able to hold ::cs_main going into
//! that call. //! that call.
std::unique_ptr<CChainState> m_ibd_chainstate; std::unique_ptr<CChainState> m_ibd_chainstate GUARDED_BY(::cs_main);
//! A chainstate initialized on the basis of a UTXO snapshot. If this is //! A chainstate initialized on the basis of a UTXO snapshot. If this is
//! non-null, it is always our active chainstate. //! non-null, it is always our active chainstate.
@ -815,7 +815,7 @@ private:
//! This is especially important when, e.g., calling ActivateBestChain() //! This is especially important when, e.g., calling ActivateBestChain()
//! on all chainstates because we are not able to hold ::cs_main going into //! on all chainstates because we are not able to hold ::cs_main going into
//! that call. //! that call.
std::unique_ptr<CChainState> m_snapshot_chainstate; std::unique_ptr<CChainState> m_snapshot_chainstate GUARDED_BY(::cs_main);
//! Points to either the ibd or snapshot chainstate; indicates our //! Points to either the ibd or snapshot chainstate; indicates our
//! most-work chain. //! most-work chain.