From 3bfdcbd7ee494c613deac0840ca6997fcc078c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Thu, 16 Jul 2026 16:39:05 -0700 Subject: [PATCH] coins: reuse cache hasher for txid set Use `SaltedCoinsCacheHasher` for the temporary set of earlier txids in `CoinsViewOverlay`, and in existing overlay tests to exercise the new `Txid` overload. Every entry is a computed transaction hash, and the set is limited to a few thousand elements per block, satisfying the SipHash-1-3-UJ jumbo-input requirements. Co-authored-by: Andrew Toth --- src/coins.cpp | 3 +-- src/coins.h | 6 ++++++ src/test/coinsviewoverlay_tests.cpp | 7 +++---- src/test/fuzz/coins_view.cpp | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 50e1aa05ab2..3d3e63fa4b8 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -384,7 +383,7 @@ CCoinsViewCache::ResetGuard CoinsViewOverlay::StartFetching(const CBlock& block // Loop through the block inputs and set their prevouts in the queue. // Filter inputs that spend outputs created earlier in the same block. These outputs will be created // directly in the cache from the tx that creates them, so they will not be requested from a base view. - std::unordered_set earlier_txids; + std::unordered_set earlier_txids; earlier_txids.reserve(block.vtx.size()); for (const auto& tx : block.vtx | std::views::drop(1)) { for (const auto& input : tx->vin) { diff --git a/src/coins.h b/src/coins.h index 71dff015c3e..c854893bcbc 100644 --- a/src/coins.h +++ b/src/coins.h @@ -243,6 +243,12 @@ class SaltedCoinsCacheHasher public: SaltedCoinsCacheHasher(bool deterministic = false); + /** Hash a transaction ID, itself a cryptographic hash, as one jumbo block. */ + size_t operator()(const Txid& id) const noexcept + { + return m_hasher.Hash(id.ToUint256()); + } + /** Hash an outpoint as its txid jumbo block followed by the zero-extended index as one normal block. */ size_t operator()(const COutPoint& id) const noexcept { diff --git a/src/test/coinsviewoverlay_tests.cpp b/src/test/coinsviewoverlay_tests.cpp index df497131f13..b63807da31e 100644 --- a/src/test/coinsviewoverlay_tests.cpp +++ b/src/test/coinsviewoverlay_tests.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -57,7 +56,7 @@ void PopulateView(const CBlock& block, CCoinsView& view, bool spent = false) CCoinsViewCache cache{&view}; cache.SetBestBlock(uint256::ONE); - std::unordered_set txids{}; + std::unordered_set txids{}; txids.reserve(block.vtx.size() - 1); for (const auto& tx : block.vtx | std::views::drop(1)) { for (const auto& in : tx->vin) { @@ -75,7 +74,7 @@ void PopulateView(const CBlock& block, CCoinsView& view, bool spent = false) void CheckCache(const CBlock& block, const CCoinsViewCache& cache) { uint32_t counter{0}; - std::unordered_set txids{}; + std::unordered_set txids{}; txids.reserve(block.vtx.size() - 1); for (const auto& tx : block.vtx) { @@ -225,7 +224,7 @@ BOOST_AUTO_TEST_CASE(fetch_out_of_order_input_uses_normal_lookup) PopulateView(block, main_cache); std::vector fetched_inputs; - std::unordered_set txids; + std::unordered_set txids; txids.reserve(block.vtx.size() - 1); for (const auto& tx : block.vtx | std::views::drop(1)) { for (const auto& input : tx->vin) { diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index 10c29ef7f73..6f5dbd62414 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -429,7 +429,7 @@ FUZZ_TARGET(coins_view_db, .init = initialize_coins_view) // called. FUZZ_TARGET(coins_view_overlay, .init = initialize_coins_view) { - SeedRandomStateForTest(SeedRand::ZEROS); // for SaltedTxidHasher + SeedRandomStateForTest(SeedRand::ZEROS); // for SaltedCoinsCacheHasher StartPoolIfNeeded(); FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; MutationGuardCoinsViewCache backend_cache{&CoinsViewEmpty::Get(), /*deterministic=*/true}; @@ -441,7 +441,7 @@ FUZZ_TARGET(coins_view_overlay, .init = initialize_coins_view) FUZZ_TARGET(coins_view_stacked, .init = initialize_coins_view) { - SeedRandomStateForTest(SeedRand::ZEROS); // for SaltedTxidHasher + SeedRandomStateForTest(SeedRand::ZEROS); // for SaltedCoinsCacheHasher StartPoolIfNeeded(); FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; auto db_params = DBParams{