From 582d2cd74754d6b9a2394616a9c82a89d2d71976 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Wed, 24 Jul 2019 13:39:42 -0400 Subject: Cover UTXO set access with lock annotations i.e. any CoinsViews members. Adds a lock acquisition to `gettxoutsetinfo` RPC to comply with added annotations. Co-authored-by: Russell Yanofsky --- src/init.cpp | 7 +++++-- src/rpc/blockchain.cpp | 4 +++- src/validation.cpp | 7 +++++-- src/validation.h | 18 +++++++++--------- 4 files changed, 22 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/init.cpp b/src/init.cpp index 50ae0c6252..97be4637a6 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -235,8 +235,11 @@ void Shutdown(InitInterfaces& interfaces) // // g_chainstate is referenced here directly (instead of ::ChainstateActive()) because it // may not have been initialized yet. - if (g_chainstate && g_chainstate->CanFlushToDisk()) { - g_chainstate->ForceFlushStateToDisk(); + { + LOCK(cs_main); + if (g_chainstate && g_chainstate->CanFlushToDisk()) { + g_chainstate->ForceFlushStateToDisk(); + } } // After there are no more peers/RPC left to give us new data which may generate diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 8061939a26..e3d5394a2c 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1062,7 +1062,9 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request) CCoinsStats stats; ::ChainstateActive().ForceFlushStateToDisk(); - if (GetUTXOStats(&::ChainstateActive().CoinsDB(), stats)) { + + CCoinsView* coins_view = WITH_LOCK(cs_main, return &ChainstateActive().CoinsDB()); + if (GetUTXOStats(coins_view, stats)) { ret.pushKV("height", (int64_t)stats.nHeight); ret.pushKV("bestblock", stats.hashBlock.GetHex()); ret.pushKV("transactions", (int64_t)stats.nTransactions); diff --git a/src/validation.cpp b/src/validation.cpp index 0f24321aaf..8f44e2565a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -314,7 +314,8 @@ bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flag // Returns the script flags which should be checked for a given block static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams); -static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) EXCLUSIVE_LOCKS_REQUIRED(pool.cs) +static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) + EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main) { int expired = pool.Expire(GetTime() - age); if (expired != 0) { @@ -2160,7 +2161,9 @@ static void AppendWarning(std::string& res, const std::string& warn) } /** Check warning conditions and do some notifications on new chain tip set. */ -void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainParams) { +void static UpdateTip(const CBlockIndex* pindexNew, const CChainParams& chainParams) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main) +{ // New best block mempool.AddTransactionsUpdated(1); diff --git a/src/validation.h b/src/validation.h index 2a268d8cab..65f86e3070 100644 --- a/src/validation.h +++ b/src/validation.h @@ -519,14 +519,14 @@ class CoinsViews { public: //! The lowest level of the CoinsViews cache hierarchy sits in a leveldb database on disk. //! All unspent coins reside in this store. - CCoinsViewDB m_dbview; + CCoinsViewDB m_dbview GUARDED_BY(cs_main); //! This view wraps access to the leveldb instance and handles read errors gracefully. - CCoinsViewErrorCatcher m_catcherview; + CCoinsViewErrorCatcher m_catcherview GUARDED_BY(cs_main); //! This is the top layer of the cache hierarchy - it keeps as many coins in memory as //! can fit per the dbcache setting. - std::unique_ptr m_cacheview; + std::unique_ptr m_cacheview GUARDED_BY(cs_main); //! This constructor initializes CCoinsViewDB and CCoinsViewErrorCatcher instances, but it //! *does not* create a CCoinsViewCache instance by default. This is done separately because the @@ -537,7 +537,7 @@ public: CoinsViews(std::string ldb_name, size_t cache_size_bytes, bool in_memory, bool should_wipe); //! Initialize the CCoinsViewCache member. - void InitCache(); + void InitCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); }; /** @@ -609,11 +609,11 @@ public: //! Initialize the in-memory coins cache (to be done after the health of the on-disk database //! is verified). - void InitCoinsCache(); + void InitCoinsCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); //! @returns whether or not the CoinsViews object has been fully initialized and we can //! safely flush this object to disk. - bool CanFlushToDisk() { + bool CanFlushToDisk() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return m_coins_views && m_coins_views->m_cacheview; } @@ -629,21 +629,21 @@ public: std::set setBlockIndexCandidates; //! @returns A reference to the in-memory cache of the UTXO set. - CCoinsViewCache& CoinsTip() + CCoinsViewCache& CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { assert(m_coins_views->m_cacheview); return *m_coins_views->m_cacheview.get(); } //! @returns A reference to the on-disk UTXO set database. - CCoinsViewDB& CoinsDB() + CCoinsViewDB& CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return m_coins_views->m_dbview; } //! @returns A reference to a wrapped view of the in-memory UTXO set that //! handles disk read errors gracefully. - CCoinsViewErrorCatcher& CoinsErrorCatcher() + CCoinsViewErrorCatcher& CoinsErrorCatcher() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return m_coins_views->m_catcherview; } -- cgit v1.2.3