aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/crypto/sha256_arm_shani.cpp2
-rw-r--r--src/fs.h22
-rw-r--r--src/index/base.cpp5
-rw-r--r--src/index/coinstatsindex.cpp4
-rw-r--r--src/node/blockstorage.cpp2
-rw-r--r--src/test/dbwrapper_tests.cpp4
-rw-r--r--src/test/fs_tests.cpp60
-rw-r--r--src/test/fuzz/script.cpp8
-rw-r--r--src/test/fuzz/script_format.cpp30
-rw-r--r--src/util/system.cpp11
-rw-r--r--src/validation.cpp62
-rw-r--r--src/validation.h14
-rw-r--r--src/wallet/test/wallet_tests.cpp2
14 files changed, 196 insertions, 31 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 1763dcb562..e2e08468a7 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -294,6 +294,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/script_bitcoin_consensus.cpp \
test/fuzz/script_descriptor_cache.cpp \
test/fuzz/script_flags.cpp \
+ test/fuzz/script_format.cpp \
test/fuzz/script_interpreter.cpp \
test/fuzz/script_ops.cpp \
test/fuzz/script_sigcache.cpp \
diff --git a/src/crypto/sha256_arm_shani.cpp b/src/crypto/sha256_arm_shani.cpp
index 7ffa56be70..2ea1d9c2ac 100644
--- a/src/crypto/sha256_arm_shani.cpp
+++ b/src/crypto/sha256_arm_shani.cpp
@@ -62,7 +62,7 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 48)));
chunk += 64;
- // Original implemenation preloaded message and constant addition which was 1-3% slower.
+ // Original implementation preloaded message and constant addition which was 1-3% slower.
// Now included as first step in quad round code saving one Q Neon register
// "TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0]));"
diff --git a/src/fs.h b/src/fs.h
index d2299db168..00b786453c 100644
--- a/src/fs.h
+++ b/src/fs.h
@@ -140,6 +140,28 @@ static inline path PathFromString(const std::string& string)
return std::filesystem::path(string);
#endif
}
+
+/**
+ * Create directory (and if necessary its parents), unless the leaf directory
+ * already exists or is a symlink to an existing directory.
+ * This is a temporary workaround for an issue in libstdc++ that has been fixed
+ * upstream [PR101510].
+ */
+static inline bool create_directories(const std::filesystem::path& p)
+{
+ if (std::filesystem::is_symlink(p) && std::filesystem::is_directory(p)) {
+ return false;
+ }
+ return std::filesystem::create_directories(p);
+}
+
+/**
+ * This variant is not used. Delete it to prevent it from accidentally working
+ * around the workaround. If it is needed, add a workaround in the same pattern
+ * as above.
+ */
+bool create_directories(const std::filesystem::path& p, std::error_code& ec) = delete;
+
} // namespace fs
/** Bridge operations to C stdio */
diff --git a/src/index/base.cpp b/src/index/base.cpp
index 2e3d500cd1..8fe30f8960 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -211,6 +211,11 @@ bool BaseIndex::Commit()
bool BaseIndex::CommitInternal(CDBBatch& batch)
{
LOCK(cs_main);
+ // Don't commit anything if we haven't indexed any block yet
+ // (this could happen if init is interrupted).
+ if (m_best_block_index == nullptr) {
+ return false;
+ }
GetDB().WriteBestBlock(batch, m_chainstate->m_chain.GetLocator(m_best_block_index));
return true;
}
diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp
index ef247dc119..7d4860b20b 100644
--- a/src/index/coinstatsindex.cpp
+++ b/src/index/coinstatsindex.cpp
@@ -360,9 +360,9 @@ bool CoinStatsIndex::Init()
if (pindex) {
DBVal entry;
if (!LookUpOne(*m_db, pindex, entry)) {
- return false;
+ return error("%s: Cannot read current %s state; index may be corrupted",
+ __func__, GetName());
}
-
m_transaction_output_count = entry.transaction_output_count;
m_bogo_size = entry.bogo_size;
m_total_amount = entry.total_amount;
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index 7691c9a5ce..8a99130fd0 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -295,7 +295,7 @@ bool BlockManager::LoadBlockIndex(
// them from the background chainstate's setBlockIndexCandidates set. This
// does mean that some blocks which are not technically assumed-valid
// (later blocks on a fork beginning before the first assumed-valid block)
- // might not get added to the the background chainstate, but this is ok,
+ // might not get added to the background chainstate, but this is ok,
// because they will still be attached to the active chainstate if they
// actually contain more work.
//
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index 2f95cc27a3..fc89fe1450 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
{
// We're going to share this fs::path between two wrappers
fs::path ph = m_args.GetDataDirBase() / "existing_data_no_obfuscate";
- create_directories(ph);
+ fs::create_directories(ph);
// Set up a non-obfuscated wrapper to write some initial data.
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false);
@@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
{
// We're going to share this fs::path between two wrappers
fs::path ph = m_args.GetDataDirBase() / "existing_data_reindex";
- create_directories(ph);
+ fs::create_directories(ph);
// Set up a non-obfuscated wrapper to write some initial data.
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false);
diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp
index 1256395849..313064b294 100644
--- a/src/test/fs_tests.cpp
+++ b/src/test/fs_tests.cpp
@@ -118,4 +118,62 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream)
}
}
-BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file
+BOOST_AUTO_TEST_CASE(rename)
+{
+ const fs::path tmpfolder{m_args.GetDataDirBase()};
+
+ const fs::path path1{GetUniquePath(tmpfolder)};
+ const fs::path path2{GetUniquePath(tmpfolder)};
+
+ const std::string path1_contents{"1111"};
+ const std::string path2_contents{"2222"};
+
+ {
+ std::ofstream file{path1};
+ file << path1_contents;
+ }
+
+ {
+ std::ofstream file{path2};
+ file << path2_contents;
+ }
+
+ // Rename path1 -> path2.
+ BOOST_CHECK(RenameOver(path1, path2));
+
+ BOOST_CHECK(!fs::exists(path1));
+
+ {
+ std::ifstream file{path2};
+ std::string contents;
+ file >> contents;
+ BOOST_CHECK_EQUAL(contents, path1_contents);
+ }
+ fs::remove(path2);
+}
+
+#ifndef WIN32
+BOOST_AUTO_TEST_CASE(create_directories)
+{
+ // Test fs::create_directories workaround.
+ const fs::path tmpfolder{m_args.GetDataDirBase()};
+
+ const fs::path dir{GetUniquePath(tmpfolder)};
+ fs::create_directory(dir);
+ BOOST_CHECK(fs::exists(dir));
+ BOOST_CHECK(fs::is_directory(dir));
+ BOOST_CHECK(!fs::create_directories(dir));
+
+ const fs::path symlink{GetUniquePath(tmpfolder)};
+ fs::create_directory_symlink(dir, symlink);
+ BOOST_CHECK(fs::exists(symlink));
+ BOOST_CHECK(fs::is_symlink(symlink));
+ BOOST_CHECK(fs::is_directory(symlink));
+ BOOST_CHECK(!fs::create_directories(symlink));
+
+ fs::remove(symlink);
+ fs::remove(dir);
+}
+#endif // WIN32
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index 14a59912db..fdcd0da37d 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -167,12 +167,4 @@ FUZZ_TARGET_INIT(script, initialize_script)
Assert(dest == GetScriptForDestination(tx_destination_2));
}
}
-
- (void)FormatScript(script);
- (void)ScriptToAsmStr(script, /*fAttemptSighashDecode=*/fuzzed_data_provider.ConsumeBool());
-
- UniValue o1(UniValue::VOBJ);
- ScriptPubKeyToUniv(script, o1, /*include_hex=*/fuzzed_data_provider.ConsumeBool());
- UniValue o3(UniValue::VOBJ);
- ScriptToUniv(script, o3);
}
diff --git a/src/test/fuzz/script_format.cpp b/src/test/fuzz/script_format.cpp
new file mode 100644
index 0000000000..2fa893f812
--- /dev/null
+++ b/src/test/fuzz/script_format.cpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2019-2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <core_io.h>
+#include <script/script.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <univalue.h>
+
+void initialize_script_format()
+{
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+FUZZ_TARGET_INIT(script_format, initialize_script_format)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const CScript script{ConsumeScript(fuzzed_data_provider)};
+
+ (void)FormatScript(script);
+ (void)ScriptToAsmStr(script, /*fAttemptSighashDecode=*/fuzzed_data_provider.ConsumeBool());
+
+ UniValue o1(UniValue::VOBJ);
+ ScriptPubKeyToUniv(script, o1, /*include_hex=*/fuzzed_data_provider.ConsumeBool());
+ UniValue o3(UniValue::VOBJ);
+ ScriptToUniv(script, o3);
+}
diff --git a/src/util/system.cpp b/src/util/system.cpp
index 5cef2be07a..69811a751b 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -1062,9 +1062,20 @@ void ArgsManager::LogArgs() const
bool RenameOver(fs::path src, fs::path dest)
{
+#ifdef __MINGW64__
+ // This is a workaround for a bug in libstdc++ which
+ // implements std::filesystem::rename with _wrename function.
+ // This bug has been fixed in upstream:
+ // - GCC 10.3: 8dd1c1085587c9f8a21bb5e588dfe1e8cdbba79e
+ // - GCC 11.1: 1dfd95f0a0ca1d9e6cbc00e6cbfd1fa20a98f312
+ // For more details see the commits mentioned above.
+ return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
+ MOVEFILE_REPLACE_EXISTING) != 0;
+#else
std::error_code error;
fs::rename(src, dest, error);
return !error;
+#endif
}
/**
diff --git a/src/validation.cpp b/src/validation.cpp
index e20e2fe523..5b52638fc5 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -286,8 +286,10 @@ bool CheckSequenceLocks(CBlockIndex* tip,
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams);
static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age)
- EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main)
+ EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
{
+ AssertLockHeld(::cs_main);
+ AssertLockHeld(pool.cs);
int expired = pool.Expire(GetTime<std::chrono::seconds>() - age);
if (expired != 0) {
LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired);
@@ -628,8 +630,10 @@ private:
EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
// Compare a package's feerate against minimum allowed.
- bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)
+ bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_pool.cs)
{
+ AssertLockHeld(::cs_main);
+ AssertLockHeld(m_pool.cs);
CAmount mempoolRejectFee = m_pool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(package_size);
if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
@@ -663,6 +667,8 @@ private:
bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
{
+ AssertLockHeld(cs_main);
+ AssertLockHeld(m_pool.cs);
const CTransactionRef& ptx = ws.m_ptx;
const CTransaction& tx = *ws.m_ptx;
const uint256& hash = ws.m_hash;
@@ -963,6 +969,8 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
{
+ AssertLockHeld(cs_main);
+ AssertLockHeld(m_pool.cs);
const CTransaction& tx = *ws.m_ptx;
TxValidationState& state = ws.m_state;
@@ -989,6 +997,8 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
{
+ AssertLockHeld(cs_main);
+ AssertLockHeld(m_pool.cs);
const CTransaction& tx = *ws.m_ptx;
const uint256& hash = ws.m_hash;
TxValidationState& state = ws.m_state;
@@ -1021,6 +1031,8 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
{
+ AssertLockHeld(cs_main);
+ AssertLockHeld(m_pool.cs);
const CTransaction& tx = *ws.m_ptx;
const uint256& hash = ws.m_hash;
TxValidationState& state = ws.m_state;
@@ -1342,8 +1354,9 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, const CTransactionRef& tx,
int64_t accept_time, bool bypass_limits, bool test_accept)
- EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+ EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
+ AssertLockHeld(::cs_main);
const CChainParams& chainparams{active_chainstate.m_params};
assert(active_chainstate.GetMempool() != nullptr);
CTxMemPool& pool{*active_chainstate.GetMempool()};
@@ -1421,6 +1434,7 @@ CoinsViews::CoinsViews(
void CoinsViews::InitCache()
{
+ AssertLockHeld(::cs_main);
m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
}
@@ -1451,6 +1465,7 @@ void CChainState::InitCoinsDB(
void CChainState::InitCoinsCache(size_t cache_size_bytes)
{
+ AssertLockHeld(::cs_main);
assert(m_coins_views != nullptr);
m_coinstip_cache_size_bytes = cache_size_bytes;
m_coins_views->InitCache();
@@ -1524,6 +1539,7 @@ void CChainState::CheckForkWarningConditions()
// Called both upon regular invalid block discovery *and* InvalidateBlock
void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
{
+ AssertLockHeld(cs_main);
if (!m_chainman.m_best_invalid || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork) {
m_chainman.m_best_invalid = pindexNew;
}
@@ -1546,6 +1562,7 @@ void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
// which does its own setBlockIndexCandidates management.
void CChainState::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state)
{
+ AssertLockHeld(cs_main);
if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {
pindex->nStatus |= BLOCK_FAILED_VALID;
m_chainman.m_failed_blocks.insert(pindex);
@@ -1906,7 +1923,10 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
{
AssertLockHeld(cs_main);
assert(pindex);
- assert(*pindex->phashBlock == block.GetHash());
+
+ uint256 block_hash{block.GetHash()};
+ assert(*pindex->phashBlock == block_hash);
+
int64_t nTimeStart = GetTimeMicros();
// Check it again in case a previous version let a bad block in
@@ -1940,7 +1960,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
- if (block.GetHash() == m_params.GetConsensus().hashGenesisBlock) {
+ if (block_hash == m_params.GetConsensus().hashGenesisBlock) {
if (!fJustCheck)
view.SetBestBlock(pindex->GetBlockHash());
return true;
@@ -2197,12 +2217,12 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
LogPrint(BCLog::BENCH, " - Index writing: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime5 - nTime4), nTimeIndex * MICRO, nTimeIndex * MILLI / nBlocksTotal);
TRACE6(validation, block_connected,
- block.GetHash().data(),
+ block_hash.data(),
pindex->nHeight,
block.vtx.size(),
nInputs,
nSigOpsCost,
- GetTimeMicros() - nTimeStart // in microseconds (µs)
+ nTime5 - nTimeStart // in microseconds (µs)
);
return true;
@@ -2210,6 +2230,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
CoinsCacheSizeState CChainState::GetCoinsCacheSizeState()
{
+ AssertLockHeld(::cs_main);
return this->GetCoinsCacheSizeState(
m_coinstip_cache_size_bytes,
gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
@@ -2219,6 +2240,7 @@ CoinsCacheSizeState CChainState::GetCoinsCacheSizeState(
size_t max_coins_cache_size_bytes,
size_t max_mempool_size_bytes)
{
+ AssertLockHeld(::cs_main);
const int64_t nMempoolUsage = m_mempool ? m_mempool->DynamicMemoryUsage() : 0;
int64_t cacheSize = CoinsTip().DynamicMemoryUsage();
int64_t nTotalSpace =
@@ -2427,6 +2449,7 @@ static void UpdateTipLog(
void CChainState::UpdateTip(const CBlockIndex* pindexNew)
{
+ AssertLockHeld(::cs_main);
const auto& coins_tip = this->CoinsTip();
// The remainder of the function isn't relevant if we are not acting on
@@ -2650,7 +2673,9 @@ bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew
* Return the tip of the chain with the most work in it, that isn't
* known to be invalid (it's however far from certain to be valid).
*/
-CBlockIndex* CChainState::FindMostWorkChain() {
+CBlockIndex* CChainState::FindMostWorkChain()
+{
+ AssertLockHeld(::cs_main);
do {
CBlockIndex *pindexNew = nullptr;
@@ -2854,7 +2879,7 @@ bool CChainState::ActivateBestChain(BlockValidationState& state, std::shared_ptr
// far from a guarantee. Things in the P2P/RPC will often end up calling
// us in the middle of ProcessNewBlock - do not assume pblock is set
// sanely for performance or correctness!
- AssertLockNotHeld(cs_main);
+ AssertLockNotHeld(::cs_main);
// ABC maintains a fair degree of expensive-to-calculate internal state
// because this function periodically releases cs_main so that it does not lock up other threads for too long
@@ -2950,6 +2975,8 @@ bool CChainState::ActivateBestChain(BlockValidationState& state, std::shared_ptr
bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
{
+ AssertLockNotHeld(m_chainstate_mutex);
+ AssertLockNotHeld(::cs_main);
{
LOCK(cs_main);
if (pindex->nChainWork < m_chain.Tip()->nChainWork) {
@@ -2980,6 +3007,7 @@ bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex
bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex)
{
AssertLockNotHeld(m_chainstate_mutex);
+ AssertLockNotHeld(::cs_main);
// Genesis block can't be invalidated
assert(pindex);
@@ -3158,6 +3186,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos)
{
+ AssertLockHeld(cs_main);
pindexNew->nTx = block.vtx.size();
pindexNew->nChainTx = 0;
pindexNew->nFile = pos.nFile;
@@ -3330,8 +3359,9 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
* in ConnectBlock().
* Note that -reindex-chainstate skips the validation that happens here!
*/
-static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
+ AssertLockHeld(::cs_main);
assert(pindexPrev != nullptr);
const int nHeight = pindexPrev->nHeight + 1;
@@ -3702,6 +3732,7 @@ bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const s
MempoolAcceptResult ChainstateManager::ProcessTransaction(const CTransactionRef& tx, bool test_accept)
{
+ AssertLockHeld(cs_main);
CChainState& active_chainstate = ActiveChainstate();
if (!active_chainstate.GetMempool()) {
TxValidationState state;
@@ -3915,6 +3946,7 @@ bool CVerifyDB::VerifyDB(
/** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */
bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs)
{
+ AssertLockHeld(cs_main);
// TODO: merge with ConnectBlock
CBlock block;
if (!ReadBlockFromDisk(block, pindex, m_params.GetConsensus())) {
@@ -4018,7 +4050,9 @@ bool CChainState::NeedsRedownload() const
return false;
}
-void CChainState::UnloadBlockIndex() {
+void CChainState::UnloadBlockIndex()
+{
+ AssertLockHeld(::cs_main);
nBlockSequenceId = 1;
setBlockIndexCandidates.clear();
}
@@ -4090,6 +4124,7 @@ bool CChainState::LoadGenesisBlock()
void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
{
+ AssertLockNotHeld(m_chainstate_mutex);
// Map of disk positions for blocks with unknown parent (only used for reindex)
static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
int64_t nStart = GetTimeMillis();
@@ -4430,6 +4465,7 @@ void CChainState::CheckBlockIndex()
std::string CChainState::ToString()
{
+ AssertLockHeld(::cs_main);
CBlockIndex* tip = m_chain.Tip();
return strprintf("Chainstate [%s] @ height %d (%s)",
m_from_snapshot_blockhash ? "snapshot" : "ibd",
@@ -4438,6 +4474,7 @@ std::string CChainState::ToString()
bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
{
+ AssertLockHeld(::cs_main);
if (coinstip_size == m_coinstip_cache_size_bytes &&
coinsdb_size == m_coinsdb_cache_size_bytes) {
// Cache sizes are unchanged, no need to continue.
@@ -4662,6 +4699,7 @@ std::vector<CChainState*> ChainstateManager::GetAll()
CChainState& ChainstateManager::InitializeChainstate(
CTxMemPool* mempool, const std::optional<uint256>& snapshot_blockhash)
{
+ AssertLockHeld(::cs_main);
bool is_snapshot = snapshot_blockhash.has_value();
std::unique_ptr<CChainState>& to_modify =
is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate;
@@ -4999,6 +5037,7 @@ bool ChainstateManager::IsSnapshotActive() const
void ChainstateManager::Unload()
{
+ AssertLockHeld(::cs_main);
for (CChainState* chainstate : this->GetAll()) {
chainstate->m_chain.SetTip(nullptr);
chainstate->UnloadBlockIndex();
@@ -5020,6 +5059,7 @@ void ChainstateManager::Reset()
void ChainstateManager::MaybeRebalanceCaches()
{
+ AssertLockHeld(::cs_main);
if (m_ibd_chainstate && !m_snapshot_chainstate) {
LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n");
// Allocate everything to the IBD chainstate.
diff --git a/src/validation.h b/src/validation.h
index fdfd29d1f8..968f62aa9a 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -529,7 +529,9 @@ public:
//! @returns whether or not the CoinsViews object has been fully initialized and we can
//! safely flush this object to disk.
- bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
+ bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
+ {
+ AssertLockHeld(::cs_main);
return m_coins_views && m_coins_views->m_cacheview;
}
@@ -557,15 +559,17 @@ public:
std::set<CBlockIndex*, node::CBlockIndexWorkComparator> setBlockIndexCandidates;
//! @returns A reference to the in-memory cache of the UTXO set.
- CCoinsViewCache& CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+ CCoinsViewCache& CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
+ AssertLockHeld(::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() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+ CCoinsViewDB& CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
+ AssertLockHeld(::cs_main);
return m_coins_views->m_dbview;
}
@@ -577,8 +581,9 @@ public:
//! @returns A reference to a wrapped view of the in-memory UTXO set that
//! handles disk read errors gracefully.
- CCoinsViewErrorCatcher& CoinsErrorCatcher() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+ CCoinsViewErrorCatcher& CoinsErrorCatcher() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
+ AssertLockHeld(::cs_main);
return m_coins_views->m_catcherview;
}
@@ -924,6 +929,7 @@ public:
node::BlockMap& BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
+ AssertLockHeld(::cs_main);
return m_blockman.m_block_index;
}
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 8ef0d46c4f..7693c9c0e8 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -426,7 +426,7 @@ BOOST_AUTO_TEST_CASE(LoadReceiveRequests)
// Test some watch-only LegacyScriptPubKeyMan methods by the procedure of loading (LoadWatchOnly),
// checking (HaveWatchOnly), getting (GetWatchPubKey) and removing (RemoveWatchOnly) a
-// given PubKey, resp. its corresponding P2PK Script. Results of the the impact on
+// given PubKey, resp. its corresponding P2PK Script. Results of the impact on
// the address -> PubKey map is dependent on whether the PubKey is a point on the curve
static void TestWatchOnlyPubKey(LegacyScriptPubKeyMan* spk_man, const CPubKey& add_pubkey)
{