Skip to content

Commit 582d2cd

Browse files
jamesobryanofsky
andcommitted
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 <[email protected]>
1 parent 5693530 commit 582d2cd

File tree

4 files changed

+22
-14
lines changed

4 files changed

+22
-14
lines changed

src/init.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,11 @@ void Shutdown(InitInterfaces& interfaces)
235235
//
236236
// g_chainstate is referenced here directly (instead of ::ChainstateActive()) because it
237237
// may not have been initialized yet.
238-
if (g_chainstate && g_chainstate->CanFlushToDisk()) {
239-
g_chainstate->ForceFlushStateToDisk();
238+
{
239+
LOCK(cs_main);
240+
if (g_chainstate && g_chainstate->CanFlushToDisk()) {
241+
g_chainstate->ForceFlushStateToDisk();
242+
}
240243
}
241244

242245
// After there are no more peers/RPC left to give us new data which may generate

src/rpc/blockchain.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1062,7 +1062,9 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
10621062

10631063
CCoinsStats stats;
10641064
::ChainstateActive().ForceFlushStateToDisk();
1065-
if (GetUTXOStats(&::ChainstateActive().CoinsDB(), stats)) {
1065+
1066+
CCoinsView* coins_view = WITH_LOCK(cs_main, return &ChainstateActive().CoinsDB());
1067+
if (GetUTXOStats(coins_view, stats)) {
10661068
ret.pushKV("height", (int64_t)stats.nHeight);
10671069
ret.pushKV("bestblock", stats.hashBlock.GetHex());
10681070
ret.pushKV("transactions", (int64_t)stats.nTransactions);

src/validation.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flag
314314
// Returns the script flags which should be checked for a given block
315315
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams);
316316

317-
static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
317+
static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age)
318+
EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main)
318319
{
319320
int expired = pool.Expire(GetTime() - age);
320321
if (expired != 0) {
@@ -2160,7 +2161,9 @@ static void AppendWarning(std::string& res, const std::string& warn)
21602161
}
21612162

21622163
/** Check warning conditions and do some notifications on new chain tip set. */
2163-
void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainParams) {
2164+
void static UpdateTip(const CBlockIndex* pindexNew, const CChainParams& chainParams)
2165+
EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
2166+
{
21642167
// New best block
21652168
mempool.AddTransactionsUpdated(1);
21662169

src/validation.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -519,14 +519,14 @@ class CoinsViews {
519519
public:
520520
//! The lowest level of the CoinsViews cache hierarchy sits in a leveldb database on disk.
521521
//! All unspent coins reside in this store.
522-
CCoinsViewDB m_dbview;
522+
CCoinsViewDB m_dbview GUARDED_BY(cs_main);
523523

524524
//! This view wraps access to the leveldb instance and handles read errors gracefully.
525-
CCoinsViewErrorCatcher m_catcherview;
525+
CCoinsViewErrorCatcher m_catcherview GUARDED_BY(cs_main);
526526

527527
//! This is the top layer of the cache hierarchy - it keeps as many coins in memory as
528528
//! can fit per the dbcache setting.
529-
std::unique_ptr<CCoinsViewCache> m_cacheview;
529+
std::unique_ptr<CCoinsViewCache> m_cacheview GUARDED_BY(cs_main);
530530

531531
//! This constructor initializes CCoinsViewDB and CCoinsViewErrorCatcher instances, but it
532532
//! *does not* create a CCoinsViewCache instance by default. This is done separately because the
@@ -537,7 +537,7 @@ class CoinsViews {
537537
CoinsViews(std::string ldb_name, size_t cache_size_bytes, bool in_memory, bool should_wipe);
538538

539539
//! Initialize the CCoinsViewCache member.
540-
void InitCache();
540+
void InitCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
541541
};
542542

543543
/**
@@ -609,11 +609,11 @@ class CChainState {
609609

610610
//! Initialize the in-memory coins cache (to be done after the health of the on-disk database
611611
//! is verified).
612-
void InitCoinsCache();
612+
void InitCoinsCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
613613

614614
//! @returns whether or not the CoinsViews object has been fully initialized and we can
615615
//! safely flush this object to disk.
616-
bool CanFlushToDisk() {
616+
bool CanFlushToDisk() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
617617
return m_coins_views && m_coins_views->m_cacheview;
618618
}
619619

@@ -629,21 +629,21 @@ class CChainState {
629629
std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
630630

631631
//! @returns A reference to the in-memory cache of the UTXO set.
632-
CCoinsViewCache& CoinsTip()
632+
CCoinsViewCache& CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
633633
{
634634
assert(m_coins_views->m_cacheview);
635635
return *m_coins_views->m_cacheview.get();
636636
}
637637

638638
//! @returns A reference to the on-disk UTXO set database.
639-
CCoinsViewDB& CoinsDB()
639+
CCoinsViewDB& CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
640640
{
641641
return m_coins_views->m_dbview;
642642
}
643643

644644
//! @returns A reference to a wrapped view of the in-memory UTXO set that
645645
//! handles disk read errors gracefully.
646-
CCoinsViewErrorCatcher& CoinsErrorCatcher()
646+
CCoinsViewErrorCatcher& CoinsErrorCatcher() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
647647
{
648648
return m_coins_views->m_catcherview;
649649
}

0 commit comments

Comments
 (0)