aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2019-05-14 08:22:08 -0400
committerMarcoFalke <falke.marco@gmail.com>2019-05-14 08:23:24 -0400
commit40c66bb3d15b0342e89b2a0334137b56663e5522 (patch)
tree8da0cca9c22518d087552784ed9c1b131386b956
parent667a8617418d837092de5b37568d60b372519462 (diff)
parentfa3c6511435149782545ac0d09d4722dc115d709 (diff)
Merge #15855: [refactor] interfaces: Add missing LockAnnotation for cs_main
fa3c651143 [refactor] interfaces: Add missing LockAnnotation for cs_main (MarcoFalke) Pull request description: This adds missing `LockAnnotation lock(::cs_main);` to `src/interfaces/chain.cpp` (as well as tests and benchmarks) ACKs for commit fa3c65: practicalswift: utACK fa3c6511435149782545ac0d09d4722dc115d709 ryanofsky: utACK fa3c6511435149782545ac0d09d4722dc115d709 Tree-SHA512: b67082fe3718c94b4addf7f2530593915225c25080f20c3ffa4ff7e08f1f49548f255fb285f89a8feff84be3f6c91e1792495ced9f6bf396732396d1356d597a
-rw-r--r--src/bench/bench.cpp1
-rw-r--r--src/bench/duplicate_inputs.cpp1
-rw-r--r--src/interfaces/chain.cpp15
-rw-r--r--src/qt/test/wallettests.cpp2
-rw-r--r--src/test/miner_tests.cpp6
-rw-r--r--src/test/txvalidationcache_tests.cpp20
-rw-r--r--src/test/util.cpp1
-rw-r--r--src/test/validation_block_tests.cpp1
-rw-r--r--src/validation.cpp4
-rw-r--r--src/validation.h2
-rw-r--r--src/wallet/test/wallet_tests.cpp22
11 files changed, 55 insertions, 20 deletions
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index d0e0109546..f2b520e893 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -114,6 +114,7 @@ void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double
for (const auto& p : benchmarks()) {
TestingSetup test{CBaseChainParams::REGTEST};
{
+ LOCK(cs_main);
assert(::ChainActive().Height() == 0);
const bool witness_enabled{IsWitnessEnabled(::ChainActive().Tip(), Params().GetConsensus())};
assert(witness_enabled);
diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp
index aa3f219b18..80ff13612c 100644
--- a/src/bench/duplicate_inputs.cpp
+++ b/src/bench/duplicate_inputs.cpp
@@ -29,6 +29,7 @@ static void DuplicateInputs(benchmark::State& state)
CMutableTransaction coinbaseTx{};
CMutableTransaction naughtyTx{};
+ LOCK(cs_main);
CBlockIndex* pindexPrev = ::ChainActive().Tip();
assert(pindexPrev != nullptr);
block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus());
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index fcbc442d12..59623284d2 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -41,6 +41,7 @@ class LockImpl : public Chain::Lock
{
Optional<int> getHeight() override
{
+ LockAnnotation lock(::cs_main);
int height = ::ChainActive().Height();
if (height >= 0) {
return height;
@@ -49,6 +50,7 @@ class LockImpl : public Chain::Lock
}
Optional<int> getBlockHeight(const uint256& hash) override
{
+ LockAnnotation lock(::cs_main);
CBlockIndex* block = LookupBlockIndex(hash);
if (block && ::ChainActive().Contains(block)) {
return block->nHeight;
@@ -63,29 +65,34 @@ class LockImpl : public Chain::Lock
}
uint256 getBlockHash(int height) override
{
+ LockAnnotation lock(::cs_main);
CBlockIndex* block = ::ChainActive()[height];
assert(block != nullptr);
return block->GetBlockHash();
}
int64_t getBlockTime(int height) override
{
+ LockAnnotation lock(::cs_main);
CBlockIndex* block = ::ChainActive()[height];
assert(block != nullptr);
return block->GetBlockTime();
}
int64_t getBlockMedianTimePast(int height) override
{
+ LockAnnotation lock(::cs_main);
CBlockIndex* block = ::ChainActive()[height];
assert(block != nullptr);
return block->GetMedianTimePast();
}
bool haveBlockOnDisk(int height) override
{
+ LockAnnotation lock(::cs_main);
CBlockIndex* block = ::ChainActive()[height];
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
}
Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
{
+ LockAnnotation lock(::cs_main);
CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
if (block) {
if (hash) *hash = block->GetBlockHash();
@@ -95,6 +102,7 @@ class LockImpl : public Chain::Lock
}
Optional<int> findPruned(int start_height, Optional<int> stop_height) override
{
+ LockAnnotation lock(::cs_main);
if (::fPruneMode) {
CBlockIndex* block = stop_height ? ::ChainActive()[*stop_height] : ::ChainActive().Tip();
while (block && block->nHeight >= start_height) {
@@ -108,6 +116,7 @@ class LockImpl : public Chain::Lock
}
Optional<int> findFork(const uint256& hash, Optional<int>* height) override
{
+ LockAnnotation lock(::cs_main);
const CBlockIndex* block = LookupBlockIndex(hash);
const CBlockIndex* fork = block ? ::ChainActive().FindFork(block) : nullptr;
if (height) {
@@ -122,7 +131,11 @@ class LockImpl : public Chain::Lock
}
return nullopt;
}
- CBlockLocator getTipLocator() override { return ::ChainActive().GetLocator(); }
+ CBlockLocator getTipLocator() override
+ {
+ LockAnnotation lock(::cs_main);
+ return ::ChainActive().GetLocator();
+ }
Optional<int> findLocatorFork(const CBlockLocator& locator) override
{
LockAnnotation lock(::cs_main);
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 71867a59d8..21209d4994 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -145,6 +145,8 @@ void TestGUI()
}
{
auto locked_chain = wallet->chain().lock();
+ LockAnnotation lock(::cs_main);
+
WalletRescanReserver reserver(wallet.get());
reserver.reserve();
CWallet::ScanResult result = wallet->ScanForWalletTransactions(locked_chain->getBlockHash(0), {} /* stop_block */, reserver, true /* fUpdate */);
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 73deab2805..4321d7d16e 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -8,15 +8,15 @@
#include <consensus/merkle.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
-#include <validation.h>
#include <miner.h>
#include <policy/policy.h>
#include <pubkey.h>
#include <script/standard.h>
#include <txmempool.h>
#include <uint256.h>
-#include <util/system.h>
#include <util/strencodings.h>
+#include <util/system.h>
+#include <validation.h>
#include <test/setup_common.h>
@@ -82,7 +82,7 @@ struct {
{2, 0xbbbeb305}, {2, 0xfe1c810a},
};
-static CBlockIndex CreateBlockIndex(int nHeight)
+static CBlockIndex CreateBlockIndex(int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
CBlockIndex index;
index.nHeight = nHeight;
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 6b0775a73a..fe30d5f3a7 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -66,18 +66,27 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
// Test 1: block with both of those transactions should be rejected.
block = CreateAndProcessBlock(spends, scriptPubKey);
- BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ }
// Test 2: ... and should be rejected if spend1 is in the memory pool
BOOST_CHECK(ToMemPool(spends[0]));
block = CreateAndProcessBlock(spends, scriptPubKey);
- BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ }
mempool.clear();
// Test 3: ... and should be rejected if spend2 is in the memory pool
BOOST_CHECK(ToMemPool(spends[1]));
block = CreateAndProcessBlock(spends, scriptPubKey);
- BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ }
mempool.clear();
// Final sanity test: first spend in mempool, second in block, that's OK:
@@ -85,7 +94,10 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
oneSpend.push_back(spends[0]);
BOOST_CHECK(ToMemPool(spends[1]));
block = CreateAndProcessBlock(oneSpend, scriptPubKey);
- BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() == block.GetHash());
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() == block.GetHash());
+ }
// spends[1] should have been removed from the mempool when the
// block with spends[0] is accepted:
BOOST_CHECK_EQUAL(mempool.size(), 0U);
diff --git a/src/test/util.cpp b/src/test/util.cpp
index 2afa88bd2c..64ecc6623a 100644
--- a/src/test/util.cpp
+++ b/src/test/util.cpp
@@ -84,6 +84,7 @@ std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
.CreateNewBlock(coinbase_scriptPubKey)
->block);
+ LOCK(cs_main);
block->nTime = ::ChainActive().Tip()->GetMedianTimePast() + 1;
block->hashMerkleRoot = BlockMerkleRoot(*block);
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index 7c8d4ea49d..5dee034b20 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -181,6 +181,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
UnregisterValidationInterface(&sub);
+ LOCK(cs_main);
BOOST_CHECK_EQUAL(sub.m_expected_tip, ::ChainActive().Tip()->GetBlockHash());
}
diff --git a/src/validation.cpp b/src/validation.cpp
index b71e8daf97..dcd2350fd8 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3224,7 +3224,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
}
//! Returns last CBlockIndex* that is a checkpoint
-static CBlockIndex* GetLastCheckpoint(const CCheckpointData& data)
+static CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
const MapCheckpoints& checkpoints = data.mapCheckpoints;
@@ -3248,7 +3248,7 @@ static CBlockIndex* GetLastCheckpoint(const CCheckpointData& data)
* in ConnectBlock().
* Note that -reindex-chainstate skips the validation that happens here!
*/
-static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
+static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
assert(pindexPrev != nullptr);
const int nHeight = pindexPrev->nHeight + 1;
diff --git a/src/validation.h b/src/validation.h
index 3cd64bc391..ad978f0e05 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -412,7 +412,7 @@ public:
/** Replay blocks that aren't fully applied to the database. */
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
-inline CBlockIndex* LookupBlockIndex(const uint256& hash)
+inline CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
BlockMap::const_iterator it = mapBlockIndex.find(hash);
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 0922a5d147..69a78f1fc0 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -12,12 +12,12 @@
#include <consensus/validation.h>
#include <interfaces/chain.h>
+#include <policy/policy.h>
#include <rpc/server.h>
#include <test/setup_common.h>
#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/test/wallet_test_fixture.h>
-#include <policy/policy.h>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
@@ -36,16 +36,15 @@ static void AddKey(CWallet& wallet, const CKey& key)
BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
{
- auto chain = interfaces::MakeChain();
-
// Cap last block file size, and mine new block in a new block file.
CBlockIndex* oldTip = ::ChainActive().Tip();
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- LockAnnotation lock(::cs_main);
+ auto chain = interfaces::MakeChain();
auto locked_chain = chain->lock();
+ LockAnnotation lock(::cs_main);
// Verify ScanForWalletTransactions accommodates a null start block.
{
@@ -116,16 +115,15 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
{
- auto chain = interfaces::MakeChain();
-
// Cap last block file size, and mine new block in a new block file.
CBlockIndex* oldTip = ::ChainActive().Tip();
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- LockAnnotation lock(::cs_main);
+ auto chain = interfaces::MakeChain();
auto locked_chain = chain->lock();
+ LockAnnotation lock(::cs_main);
// Prune the older block file.
PruneOneBlockFile(oldTip->GetBlockPos().nFile);
@@ -177,8 +175,6 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
// than or equal to key birthday.
BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
{
- auto chain = interfaces::MakeChain();
-
// Create two blocks with same timestamp to verify that importwallet rescan
// will pick up both blocks, not just the first.
const int64_t BLOCK_TIME = ::ChainActive().Tip()->GetBlockTimeMax() + 5;
@@ -192,7 +188,9 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(KEY_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
+ auto chain = interfaces::MakeChain();
auto locked_chain = chain->lock();
+ LockAnnotation lock(::cs_main);
std::string backup_file = (SetDataDir("importwallet_rescan") / "wallet.backup").string();
@@ -245,10 +243,14 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
auto chain = interfaces::MakeChain();
+
CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
CWalletTx wtx(&wallet, m_coinbase_txns.back());
+
auto locked_chain = chain->lock();
+ LockAnnotation lock(::cs_main);
LOCK(wallet.cs_wallet);
+
wtx.hashBlock = ::ChainActive().Tip()->GetBlockHash();
wtx.nIndex = 0;
@@ -375,6 +377,8 @@ public:
blocktx = CMutableTransaction(*wallet->mapWallet.at(tx->GetHash()).tx);
}
CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+
+ LOCK(cs_main);
LOCK(wallet->cs_wallet);
auto it = wallet->mapWallet.find(tx->GetHash());
BOOST_CHECK(it != wallet->mapWallet.end());