diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/chainparams.cpp | 10 | ||||
-rw-r--r-- | src/chainparams.h | 9 | ||||
-rw-r--r-- | src/coins.h | 2 | ||||
-rw-r--r-- | src/index/base.cpp | 10 | ||||
-rw-r--r-- | src/index/base.h | 4 | ||||
-rw-r--r-- | src/init.cpp | 12 | ||||
-rw-r--r-- | src/net.cpp | 2 | ||||
-rw-r--r-- | src/protocol.cpp | 12 | ||||
-rw-r--r-- | src/protocol.h | 11 | ||||
-rw-r--r-- | src/script/standard.h | 65 | ||||
-rw-r--r-- | src/test/blockfilter_index_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/coinstatsindex_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/script_ops.cpp | 61 | ||||
-rw-r--r-- | src/test/txindex_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/validation_chainstatemanager_tests.cpp | 17 | ||||
-rw-r--r-- | src/test/validation_tests.cpp | 4 | ||||
-rw-r--r-- | src/util/hash_type.h | 72 | ||||
-rw-r--r-- | src/validation.cpp | 65 | ||||
-rw-r--r-- | src/validation.h | 8 | ||||
-rw-r--r-- | src/wallet/db.cpp | 7 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 3 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 9 | ||||
-rw-r--r-- | src/wallet/wallet.h | 2 |
24 files changed, 200 insertions, 192 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 41fab024c6..770bb76226 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -246,6 +246,7 @@ BITCOIN_CORE_H = \ util/fees.h \ util/getuniquepath.h \ util/golombrice.h \ + util/hash_type.h \ util/hasher.h \ util/macros.h \ util/message.h \ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 45d93ca014..fc5a9d84cc 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -451,11 +451,11 @@ public: m_assumeutxo_data = MapAssumeutxo{ { 110, - {uint256S("0x1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618"), 110}, + {AssumeutxoHash{uint256S("0x1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618")}, 110}, }, { 210, - {uint256S("0x9c5ed99ef98544b34f8920b6d1802f72ac28ae6e2bd2bd4c316ff10c230df3f2"), 210}, + {AssumeutxoHash{uint256S("0x9c5ed99ef98544b34f8920b6d1802f72ac28ae6e2bd2bd4c316ff10c230df3f2")}, 210}, }, }; @@ -559,9 +559,3 @@ void SelectParams(const std::string& network) SelectBaseParams(network); globalChainParams = CreateChainParams(gArgs, network); } - -std::ostream& operator<<(std::ostream& o, const AssumeutxoData& aud) -{ - o << strprintf("AssumeutxoData(%s, %s)", aud.hash_serialized.ToString(), aud.nChainTx); - return o; -} diff --git a/src/chainparams.h b/src/chainparams.h index 6f23199986..5c2351eea6 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -10,6 +10,7 @@ #include <consensus/params.h> #include <primitives/block.h> #include <protocol.h> +#include <util/hash_type.h> #include <memory> #include <vector> @@ -25,6 +26,10 @@ struct CCheckpointData { } }; +struct AssumeutxoHash : public BaseHash<uint256> { + explicit AssumeutxoHash(const uint256& hash) : BaseHash(hash) {} +}; + /** * Holds configuration for use during UTXO snapshot load and validation. The contents * here are security critical, since they dictate which UTXO snapshots are recognized @@ -32,7 +37,7 @@ struct CCheckpointData { */ struct AssumeutxoData { //! The expected hash of the deserialized UTXO set. - const uint256 hash_serialized; + const AssumeutxoHash hash_serialized; //! Used to populate the nChainTx value, which is used during BlockManager::LoadBlockIndex(). //! @@ -41,8 +46,6 @@ struct AssumeutxoData { const unsigned int nChainTx; }; -std::ostream& operator<<(std::ostream& o, const AssumeutxoData& aud); - using MapAssumeutxo = std::map<int, const AssumeutxoData>; /** diff --git a/src/coins.h b/src/coins.h index 5a6f73652b..816b4864a3 100644 --- a/src/coins.h +++ b/src/coins.h @@ -20,8 +20,6 @@ #include <functional> #include <unordered_map> -class ChainstateManager; - /** * A UTXO entry. * diff --git a/src/index/base.cpp b/src/index/base.cpp index 0ab49f8a37..4079fc4569 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -98,9 +98,7 @@ bool BaseIndex::Init() } } if (prune_violation) { - // throw error and graceful shutdown if we can't build the index - FatalError("%s: %s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)", __func__, GetName()); - return false; + return InitError(strprintf(Untranslated("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"), GetName())); } } return true; @@ -339,17 +337,17 @@ void BaseIndex::Interrupt() m_interrupt(); } -void BaseIndex::Start() +bool BaseIndex::Start() { // Need to register this ValidationInterface before running Init(), so that // callbacks are not missed if Init sets m_synced to true. RegisterValidationInterface(this); if (!Init()) { - FatalError("%s: %s failed to initialize", __func__, GetName()); - return; + return false; } m_thread_sync = std::thread(&util::TraceThread, GetName(), [this] { ThreadSync(); }); + return true; } void BaseIndex::Stop() diff --git a/src/index/base.h b/src/index/base.h index d887620524..59eefab29e 100644 --- a/src/index/base.h +++ b/src/index/base.h @@ -84,7 +84,7 @@ protected: const CBlockIndex* CurrentIndex() { return m_best_block_index.load(); }; /// Initialize internal state from the database and block index. - virtual bool Init(); + [[nodiscard]] virtual bool Init(); /// Write update index entries for a newly connected block. virtual bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) { return true; } @@ -117,7 +117,7 @@ public: /// Start initializes the sync state and registers the instance as a /// ValidationInterface so that it stays in sync with blockchain updates. - void Start(); + [[nodiscard]] bool Start(); /// Stops the instance from staying in sync with blockchain updates. void Stop(); diff --git a/src/init.cpp b/src/init.cpp index 481c3c7d63..89e152e56f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1550,17 +1550,23 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // ********************************************************* Step 8: start indexers if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex); - g_txindex->Start(); + if (!g_txindex->Start()) { + return false; + } } for (const auto& filter_type : g_enabled_filter_types) { InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex); - GetBlockFilterIndex(filter_type)->Start(); + if (!GetBlockFilterIndex(filter_type)->Start()) { + return false; + } } if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) { g_coin_stats_index = std::make_unique<CoinStatsIndex>(/* cache size */ 0, false, fReindex); - g_coin_stats_index->Start(); + if (!g_coin_stats_index->Start()) { + return false; + } } // ********************************************************* Step 9: load wallet diff --git a/src/net.cpp b/src/net.cpp index bbc0b81056..05588d7406 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2245,7 +2245,7 @@ void CConnman::ThreadI2PAcceptIncoming() } if (!advertising_listen_addr) { - AddLocal(conn.me, LOCAL_BIND); + AddLocal(conn.me, LOCAL_MANUAL); advertising_listen_addr = true; } diff --git a/src/protocol.cpp b/src/protocol.cpp index 0b893b9272..2e70b41e4c 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -87,26 +87,16 @@ const static std::string allNetMessageTypes[] = { }; const static std::vector<std::string> allNetMessageTypesVec(std::begin(allNetMessageTypes), std::end(allNetMessageTypes)); -CMessageHeader::CMessageHeader() -{ - memset(pchMessageStart, 0, MESSAGE_START_SIZE); - memset(pchCommand, 0, sizeof(pchCommand)); - nMessageSize = -1; - memset(pchChecksum, 0, CHECKSUM_SIZE); -} - CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn) { memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE); - // Copy the command name, zero-padding to COMMAND_SIZE bytes + // Copy the command name size_t i = 0; for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i]; assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE - for (; i < COMMAND_SIZE; ++i) pchCommand[i] = 0; nMessageSize = nMessageSizeIn; - memset(pchChecksum, 0, CHECKSUM_SIZE); } std::string CMessageHeader::GetCommand() const diff --git a/src/protocol.h b/src/protocol.h index f183db0501..aaa9f1df40 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -16,6 +16,7 @@ #include <uint256.h> #include <version.h> +#include <limits> #include <stdint.h> #include <string> @@ -37,7 +38,7 @@ public: static constexpr size_t HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE; typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; - explicit CMessageHeader(); + explicit CMessageHeader() = default; /** Construct a P2P message header from message-start characters, a command and the size of the message. * @note Passing in a `pszCommand` longer than COMMAND_SIZE will result in a run-time assertion error. @@ -49,10 +50,10 @@ public: SERIALIZE_METHODS(CMessageHeader, obj) { READWRITE(obj.pchMessageStart, obj.pchCommand, obj.nMessageSize, obj.pchChecksum); } - char pchMessageStart[MESSAGE_START_SIZE]; - char pchCommand[COMMAND_SIZE]; - uint32_t nMessageSize; - uint8_t pchChecksum[CHECKSUM_SIZE]; + char pchMessageStart[MESSAGE_START_SIZE]{}; + char pchCommand[COMMAND_SIZE]{}; + uint32_t nMessageSize{std::numeric_limits<uint32_t>::max()}; + uint8_t pchChecksum[CHECKSUM_SIZE]{}; }; /** diff --git a/src/script/standard.h b/src/script/standard.h index f2bf4a8af3..12ab9979a8 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -8,6 +8,7 @@ #include <script/interpreter.h> #include <uint256.h> +#include <util/hash_type.h> #include <string> #include <variant> @@ -18,70 +19,6 @@ class CKeyID; class CScript; struct ScriptHash; -template<typename HashType> -class BaseHash -{ -protected: - HashType m_hash; - -public: - BaseHash() : m_hash() {} - explicit BaseHash(const HashType& in) : m_hash(in) {} - - unsigned char* begin() - { - return m_hash.begin(); - } - - const unsigned char* begin() const - { - return m_hash.begin(); - } - - unsigned char* end() - { - return m_hash.end(); - } - - const unsigned char* end() const - { - return m_hash.end(); - } - - operator std::vector<unsigned char>() const - { - return std::vector<unsigned char>{m_hash.begin(), m_hash.end()}; - } - - std::string ToString() const - { - return m_hash.ToString(); - } - - bool operator==(const BaseHash<HashType>& other) const noexcept - { - return m_hash == other.m_hash; - } - - bool operator!=(const BaseHash<HashType>& other) const noexcept - { - return !(m_hash == other.m_hash); - } - - bool operator<(const BaseHash<HashType>& other) const noexcept - { - return m_hash < other.m_hash; - } - - size_t size() const - { - return m_hash.size(); - } - - unsigned char* data() { return m_hash.data(); } - const unsigned char* data() const { return m_hash.data(); } -}; - /** A reference to a CScript: the Hash160 of its serialization (see script.h) */ class CScriptID : public BaseHash<uint160> { diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index 9903ba75cb..1cb1c002f4 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -131,7 +131,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) // BlockUntilSyncedToCurrentChain should return false before index is started. BOOST_CHECK(!filter_index.BlockUntilSyncedToCurrentChain()); - filter_index.Start(); + BOOST_REQUIRE(filter_index.Start()); // Allow filter index to catch up with the block index. constexpr int64_t timeout_ms = 10 * 1000; diff --git a/src/test/coinstatsindex_tests.cpp b/src/test/coinstatsindex_tests.cpp index 3fc7b72077..bf7a80ae5c 100644 --- a/src/test/coinstatsindex_tests.cpp +++ b/src/test/coinstatsindex_tests.cpp @@ -32,7 +32,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup) // is started. BOOST_CHECK(!coin_stats_index.BlockUntilSyncedToCurrentChain()); - coin_stats_index.Start(); + BOOST_REQUIRE(coin_stats_index.Start()); // Allow the CoinStatsIndex to catch up with the block index that is syncing // in a background thread. diff --git a/src/test/fuzz/script_ops.cpp b/src/test/fuzz/script_ops.cpp index eb1c808a88..4bc709ed35 100644 --- a/src/test/fuzz/script_ops.cpp +++ b/src/test/fuzz/script_ops.cpp @@ -14,55 +14,54 @@ FUZZ_TARGET(script_ops) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - CScript script = ConsumeScript(fuzzed_data_provider); + CScript script_mut = ConsumeScript(fuzzed_data_provider); while (fuzzed_data_provider.remaining_bytes() > 0) { CallOneOf( fuzzed_data_provider, [&] { CScript s = ConsumeScript(fuzzed_data_provider); - script = std::move(s); + script_mut = std::move(s); }, [&] { const CScript& s = ConsumeScript(fuzzed_data_provider); - script = s; + script_mut = s; }, [&] { - script << fuzzed_data_provider.ConsumeIntegral<int64_t>(); + script_mut << fuzzed_data_provider.ConsumeIntegral<int64_t>(); }, [&] { - script << ConsumeOpcodeType(fuzzed_data_provider); + script_mut << ConsumeOpcodeType(fuzzed_data_provider); }, [&] { - script << ConsumeScriptNum(fuzzed_data_provider); + script_mut << ConsumeScriptNum(fuzzed_data_provider); }, [&] { - script << ConsumeRandomLengthByteVector(fuzzed_data_provider); + script_mut << ConsumeRandomLengthByteVector(fuzzed_data_provider); }, [&] { - script.clear(); - }, - [&] { - (void)script.GetSigOpCount(false); - (void)script.GetSigOpCount(true); - (void)script.GetSigOpCount(script); - (void)script.HasValidOps(); - (void)script.IsPayToScriptHash(); - (void)script.IsPayToWitnessScriptHash(); - (void)script.IsPushOnly(); - (void)script.IsUnspendable(); - { - CScript::const_iterator pc = script.begin(); - opcodetype opcode; - (void)script.GetOp(pc, opcode); - std::vector<uint8_t> data; - (void)script.GetOp(pc, opcode, data); - (void)script.IsPushOnly(pc); - } - { - int version; - std::vector<uint8_t> program; - (void)script.IsWitnessProgram(version, program); - } + script_mut.clear(); }); } + const CScript& script = script_mut; + (void)script.GetSigOpCount(false); + (void)script.GetSigOpCount(true); + (void)script.GetSigOpCount(script); + (void)script.HasValidOps(); + (void)script.IsPayToScriptHash(); + (void)script.IsPayToWitnessScriptHash(); + (void)script.IsPushOnly(); + (void)script.IsUnspendable(); + { + CScript::const_iterator pc = script.begin(); + opcodetype opcode; + (void)script.GetOp(pc, opcode); + std::vector<uint8_t> data; + (void)script.GetOp(pc, opcode, data); + (void)script.IsPushOnly(pc); + } + { + int version; + std::vector<uint8_t> program; + (void)script.IsWitnessProgram(version, program); + } } diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp index 5fc172ee86..082655d811 100644 --- a/src/test/txindex_tests.cpp +++ b/src/test/txindex_tests.cpp @@ -27,7 +27,7 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup) // BlockUntilSyncedToCurrentChain should return false before txindex is started. BOOST_CHECK(!txindex.BlockUntilSyncedToCurrentChain()); - txindex.Start(); + BOOST_REQUIRE(txindex.Start()); // Allow tx index to catch up with the block index. constexpr int64_t timeout_ms = 10 * 1000; diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index 82e70b5cdc..0b912acb08 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -226,10 +226,8 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup) // Snapshot should refuse to load at this height. BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(m_node, m_path_root)); - BOOST_CHECK(chainman.ActiveChainstate().m_from_snapshot_blockhash.IsNull()); - BOOST_CHECK_EQUAL( - chainman.ActiveChainstate().m_from_snapshot_blockhash, - chainman.SnapshotBlockhash().value_or(uint256())); + BOOST_CHECK(!chainman.ActiveChainstate().m_from_snapshot_blockhash); + BOOST_CHECK(!chainman.SnapshotBlockhash()); // Mine 10 more blocks, putting at us height 110 where a valid assumeutxo value can // be found. @@ -263,15 +261,20 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup) BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot( m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) { // Wrong hash + metadata.m_base_blockhash = uint256::ZERO; + })); + BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot( + m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) { + // Wrong hash metadata.m_base_blockhash = uint256::ONE; })); BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(m_node, m_path_root)); // Ensure our active chain is the snapshot chainstate. - BOOST_CHECK(!chainman.ActiveChainstate().m_from_snapshot_blockhash.IsNull()); + BOOST_CHECK(!chainman.ActiveChainstate().m_from_snapshot_blockhash->IsNull()); BOOST_CHECK_EQUAL( - chainman.ActiveChainstate().m_from_snapshot_blockhash, + *chainman.ActiveChainstate().m_from_snapshot_blockhash, *chainman.SnapshotBlockhash()); const AssumeutxoData& au_data = *ExpectedAssumeutxo(snapshot_height, ::Params()); @@ -347,7 +350,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup) // Snapshot blockhash should be unchanged. BOOST_CHECK_EQUAL( - chainman.ActiveChainstate().m_from_snapshot_blockhash, + *chainman.ActiveChainstate().m_from_snapshot_blockhash, loaded_snapshot_blockhash); } diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp index d0317aca0a..1e5baec01a 100644 --- a/src/test/validation_tests.cpp +++ b/src/test/validation_tests.cpp @@ -135,11 +135,11 @@ BOOST_AUTO_TEST_CASE(test_assumeutxo) } const auto out110 = *ExpectedAssumeutxo(110, *params); - BOOST_CHECK_EQUAL(out110.hash_serialized, uint256S("1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618")); + BOOST_CHECK_EQUAL(out110.hash_serialized.ToString(), "1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618"); BOOST_CHECK_EQUAL(out110.nChainTx, (unsigned int)110); const auto out210 = *ExpectedAssumeutxo(210, *params); - BOOST_CHECK_EQUAL(out210.hash_serialized, uint256S("9c5ed99ef98544b34f8920b6d1802f72ac28ae6e2bd2bd4c316ff10c230df3f2")); + BOOST_CHECK_EQUAL(out210.hash_serialized.ToString(), "9c5ed99ef98544b34f8920b6d1802f72ac28ae6e2bd2bd4c316ff10c230df3f2"); BOOST_CHECK_EQUAL(out210.nChainTx, (unsigned int)210); } diff --git a/src/util/hash_type.h b/src/util/hash_type.h new file mode 100644 index 0000000000..13b831cf19 --- /dev/null +++ b/src/util/hash_type.h @@ -0,0 +1,72 @@ +// Copyright (c) 2020-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_HASH_TYPE_H +#define BITCOIN_UTIL_HASH_TYPE_H + +template <typename HashType> +class BaseHash +{ +protected: + HashType m_hash; + +public: + BaseHash() : m_hash() {} + explicit BaseHash(const HashType& in) : m_hash(in) {} + + unsigned char* begin() + { + return m_hash.begin(); + } + + const unsigned char* begin() const + { + return m_hash.begin(); + } + + unsigned char* end() + { + return m_hash.end(); + } + + const unsigned char* end() const + { + return m_hash.end(); + } + + operator std::vector<unsigned char>() const + { + return std::vector<unsigned char>{m_hash.begin(), m_hash.end()}; + } + + std::string ToString() const + { + return m_hash.ToString(); + } + + bool operator==(const BaseHash<HashType>& other) const noexcept + { + return m_hash == other.m_hash; + } + + bool operator!=(const BaseHash<HashType>& other) const noexcept + { + return !(m_hash == other.m_hash); + } + + bool operator<(const BaseHash<HashType>& other) const noexcept + { + return m_hash < other.m_hash; + } + + size_t size() const + { + return m_hash.size(); + } + + unsigned char* data() { return m_hash.data(); } + const unsigned char* data() const { return m_hash.data(); } +}; + +#endif // BITCOIN_UTIL_HASH_TYPE_H diff --git a/src/validation.cpp b/src/validation.cpp index 639c1f6879..4f9b8687b7 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1158,7 +1158,7 @@ void CoinsViews::InitCache() m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview); } -CChainState::CChainState(CTxMemPool& mempool, BlockManager& blockman, uint256 from_snapshot_blockhash) +CChainState::CChainState(CTxMemPool& mempool, BlockManager& blockman, std::optional<uint256> from_snapshot_blockhash) : m_mempool(mempool), m_blockman(blockman), m_from_snapshot_blockhash(from_snapshot_blockhash) {} @@ -1169,8 +1169,8 @@ void CChainState::InitCoinsDB( bool should_wipe, std::string leveldb_name) { - if (!m_from_snapshot_blockhash.IsNull()) { - leveldb_name += "_" + m_from_snapshot_blockhash.ToString(); + if (m_from_snapshot_blockhash) { + leveldb_name += "_" + m_from_snapshot_blockhash->ToString(); } m_coins_views = std::make_unique<CoinsViews>( @@ -3877,7 +3877,7 @@ bool CVerifyDB::VerifyDB( int reportDone = 0; LogPrintf("[0%%]..."); /* Continued */ - bool is_snapshot_cs = !chainstate.m_from_snapshot_blockhash.IsNull(); + const bool is_snapshot_cs{!chainstate.m_from_snapshot_blockhash}; for (pindex = chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); @@ -4458,8 +4458,8 @@ std::string CChainState::ToString() { CBlockIndex* tip = m_chain.Tip(); return strprintf("Chainstate [%s] @ height %d (%s)", - m_from_snapshot_blockhash.IsNull() ? "ibd" : "snapshot", - tip ? tip->nHeight : -1, tip ? tip->GetBlockHash().ToString() : "null"); + m_from_snapshot_blockhash ? "snapshot" : "ibd", + tip ? tip->nHeight : -1, tip ? tip->GetBlockHash().ToString() : "null"); } bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size) @@ -4662,10 +4662,10 @@ double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pin return std::min<double>(pindex->nChainTx / fTxTotal, 1.0); } -std::optional<uint256> ChainstateManager::SnapshotBlockhash() const { +std::optional<uint256> ChainstateManager::SnapshotBlockhash() const +{ LOCK(::cs_main); - if (m_active_chainstate != nullptr && - !m_active_chainstate->m_from_snapshot_blockhash.IsNull()) { + if (m_active_chainstate && m_active_chainstate->m_from_snapshot_blockhash) { // If a snapshot chainstate exists, it will always be our active. return m_active_chainstate->m_from_snapshot_blockhash; } @@ -4688,9 +4688,9 @@ std::vector<CChainState*> ChainstateManager::GetAll() return out; } -CChainState& ChainstateManager::InitializeChainstate(CTxMemPool& mempool, const uint256& snapshot_blockhash) +CChainState& ChainstateManager::InitializeChainstate(CTxMemPool& mempool, const std::optional<uint256>& snapshot_blockhash) { - bool is_snapshot = !snapshot_blockhash.IsNull(); + bool is_snapshot = snapshot_blockhash.has_value(); std::unique_ptr<CChainState>& to_modify = is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate; @@ -4815,6 +4815,26 @@ bool ChainstateManager::PopulateAndValidateSnapshot( uint256 base_blockhash = metadata.m_base_blockhash; + CBlockIndex* snapshot_start_block = WITH_LOCK(::cs_main, return m_blockman.LookupBlockIndex(base_blockhash)); + + if (!snapshot_start_block) { + // Needed for GetUTXOStats and ExpectedAssumeutxo to determine the height and to avoid a crash when base_blockhash.IsNull() + LogPrintf("[snapshot] Did not find snapshot start blockheader %s\n", + base_blockhash.ToString()); + return false; + } + + int base_height = snapshot_start_block->nHeight; + auto maybe_au_data = ExpectedAssumeutxo(base_height, ::Params()); + + if (!maybe_au_data) { + LogPrintf("[snapshot] assumeutxo height in snapshot metadata not recognized " /* Continued */ + "(%d) - refusing to load snapshot\n", base_height); + return false; + } + + const AssumeutxoData& au_data = *maybe_au_data; + COutPoint outpoint; Coin coin; const uint64_t coins_count = metadata.m_coins_count; @@ -4905,15 +4925,6 @@ bool ChainstateManager::PopulateAndValidateSnapshot( assert(coins_cache.GetBestBlock() == base_blockhash); - CBlockIndex* snapshot_start_block = WITH_LOCK(::cs_main, return m_blockman.LookupBlockIndex(base_blockhash)); - - if (!snapshot_start_block) { - // Needed for GetUTXOStats to determine the height - LogPrintf("[snapshot] Did not find snapshot start blockheader %s\n", - base_blockhash.ToString()); - return false; - } - CCoinsStats stats{CoinStatsHashType::HASH_SERIALIZED}; auto breakpoint_fnc = [] { /* TODO insert breakpoint here? */ }; @@ -4927,19 +4938,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot( } // Assert that the deserialized chainstate contents match the expected assumeutxo value. - - int base_height = snapshot_start_block->nHeight; - auto maybe_au_data = ExpectedAssumeutxo(base_height, ::Params()); - - if (!maybe_au_data) { - LogPrintf("[snapshot] assumeutxo height in snapshot metadata not recognized " /* Continued */ - "(%d) - refusing to load snapshot\n", base_height); - return false; - } - - const AssumeutxoData& au_data = *maybe_au_data; - - if (stats.hashSerialized != au_data.hash_serialized) { + if (AssumeutxoHash{stats.hashSerialized} != au_data.hash_serialized) { LogPrintf("[snapshot] bad snapshot content hash: expected %s, got %s\n", au_data.hash_serialized.ToString(), stats.hashSerialized.ToString()); return false; diff --git a/src/validation.h b/src/validation.h index 8fa45c3f77..1b50644185 100644 --- a/src/validation.h +++ b/src/validation.h @@ -553,7 +553,7 @@ public: //! CChainState instances. BlockManager& m_blockman; - explicit CChainState(CTxMemPool& mempool, BlockManager& blockman, uint256 from_snapshot_blockhash = uint256()); + explicit CChainState(CTxMemPool& mempool, BlockManager& blockman, std::optional<uint256> from_snapshot_blockhash = std::nullopt); /** * Initialize the CoinsViews UTXO set database management data structures. The in-memory @@ -584,9 +584,9 @@ public: /** * The blockhash which is the base of the snapshot this chainstate was created from. * - * IsNull() if this chainstate was not created from a snapshot. + * std::nullopt if this chainstate was not created from a snapshot. */ - const uint256 m_from_snapshot_blockhash{}; + const std::optional<uint256> m_from_snapshot_blockhash; /** * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and @@ -866,7 +866,7 @@ public: // constructor //! @param[in] snapshot_blockhash If given, signify that this chainstate //! is based on a snapshot. - CChainState& InitializeChainstate(CTxMemPool& mempool, const uint256& snapshot_blockhash = uint256()) + CChainState& InitializeChainstate(CTxMemPool& mempool, const std::optional<uint256>& snapshot_blockhash = std::nullopt) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); //! Get all chainstates currently being used. diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index cd49baeb78..5bf037b222 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -18,7 +18,12 @@ std::vector<fs::path> ListDatabases(const fs::path& wallet_dir) for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) { if (ec) { - LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string()); + if (fs::is_directory(*it)) { + it.no_push(); + LogPrintf("%s: %s %s -- skipping.\n", __func__, ec.message(), it->path().string()); + } else { + LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string()); + } continue; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 326e183a7f..5567d183b6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2970,8 +2970,9 @@ static RPCHelpMan listunspent() cctl.m_avoid_address_reuse = false; cctl.m_min_depth = nMinDepth; cctl.m_max_depth = nMaxDepth; + cctl.m_include_unsafe_inputs = include_unsafe; LOCK(pwallet->cs_wallet); - pwallet->AvailableCoins(vecOutputs, !include_unsafe, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount); + pwallet->AvailableCoins(vecOutputs, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount); } LOCK(pwallet->cs_wallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 60d60d1e81..456c26ea31 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2197,7 +2197,7 @@ CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const CAmount balance = 0; std::vector<COutput> vCoins; - AvailableCoins(vCoins, true, coinControl); + AvailableCoins(vCoins, coinControl); for (const COutput& out : vCoins) { if (out.fSpendable) { balance += out.tx->tx->vout[out.i].nValue; @@ -2206,7 +2206,7 @@ CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const return balance; } -void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount) const +void CWallet::AvailableCoins(std::vector<COutput>& vCoins, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount) const { AssertLockHeld(cs_wallet); @@ -2217,6 +2217,7 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const bool allow_used_addresses = !IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE) || (coinControl && !coinControl->m_avoid_address_reuse); const int min_depth = {coinControl ? coinControl->m_min_depth : DEFAULT_MIN_DEPTH}; const int max_depth = {coinControl ? coinControl->m_max_depth : DEFAULT_MAX_DEPTH}; + const bool only_safe = {coinControl ? !coinControl->m_include_unsafe_inputs : true}; std::set<uint256> trusted_parents; for (const auto& entry : mapWallet) @@ -2273,7 +2274,7 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const safeTx = false; } - if (fOnlySafe && !safeTx) { + if (only_safe && !safeTx) { continue; } @@ -2843,7 +2844,7 @@ bool CWallet::CreateTransactionInternal( txNew.nLockTime = GetLocktimeForNewTransaction(chain(), GetLastBlockHash(), GetLastBlockHeight()); { std::vector<COutput> vAvailableCoins; - AvailableCoins(vAvailableCoins, !coin_control.m_include_unsafe_inputs, &coin_control, 1, MAX_MONEY, MAX_MONEY, 0); + AvailableCoins(vAvailableCoins, &coin_control, 1, MAX_MONEY, MAX_MONEY, 0); CoinSelectionParams coin_selection_params; // Parameters for coin selection, init with dummy coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 03adca7a89..5a36d92784 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -850,7 +850,7 @@ public: /** * populate vCoins with vector of available COutputs. */ - void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe = true, const CCoinControl* coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + void AvailableCoins(std::vector<COutput>& vCoins, const CCoinControl* coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); /** * Return list of available coins and locked coins grouped by non-change output address. |