Skip to content

perf: cache x11 block header hash, reduce reindex hashes from 4->2 per block#6610

Closed
PastaPastaPasta wants to merge 2 commits into
dashpay:developfrom
PastaPastaPasta:perf-cache-header-hash
Closed

perf: cache x11 block header hash, reduce reindex hashes from 4->2 per block#6610
PastaPastaPasta wants to merge 2 commits into
dashpay:developfrom
PastaPastaPasta:perf-cache-header-hash

Conversation

@PastaPastaPasta
Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

We currently hash the header up to 4 times per block we are loading from disk; drop this down to 2 times

before:
./src/dashd --printtoconsole --testnet --nowallet --reindex --stopatheight=1 76.34s user 6.15s system 95% cpu 1:25.98 total
image

after:

./src/dashd --printtoconsole --testnet --nowallet --reindex --stopatheight=1 62.87s user 5.70s system 95% cpu 1:11.52 total
image

Shaves ~20-25% off of header reindex times.
Calculated as ((76.34-62.87)/76.34)=17.6%, but this includes the overhead of startup / shutdown, so it's likely higher.

What was done?

How Has This Been Tested?

Reindex headers; should probably do a full reindex

Breaking Changes

Checklist:

Go over all the following points, and put an x in all the boxes that apply.

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@PastaPastaPasta PastaPastaPasta added this to the 23 milestone Mar 6, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 6, 2025

Walkthrough

The changes introduce an optional caching mechanism for block header hashes within the CBlockHeader class. A new mutable member variable, cached_hash, is added to store the computed hash in memory. The GetHash method's signature is updated to accept a boolean parameter use_cache, defaulting to true. When use_cache is false or the cache is empty, the hash is recalculated and stored; otherwise, the cached value is returned. The cache is reset during serialization and when SetNull() is called. Several mining, validation, and test routines are updated to explicitly disable caching by passing use_cache=false during proof-of-work loops, ensuring fresh hash computation on each iteration. Additionally, when loading blocks from external files, the precomputed hash is stored in the cache to avoid redundant calculations. No changes are made to the serialized data structures or exported/public API entities beyond the method signature updates and the addition of the cache variable.

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10b0bc8c4db109d3dfbd7c20e8d8e9476e1ab0b7 and 3e760e2.

📒 Files selected for processing (10)
  • src/chainparams.cpp (1 hunks)
  • src/primitives/block.cpp (1 hunks)
  • src/primitives/block.h (3 hunks)
  • src/rpc/mining.cpp (1 hunks)
  • src/test/blockencodings_tests.cpp (2 hunks)
  • src/test/blockfilter_index_tests.cpp (1 hunks)
  • src/test/miner_tests.cpp (1 hunks)
  • src/test/util/mining.cpp (2 hunks)
  • src/test/util/setup_common.cpp (1 hunks)
  • src/test/validation_block_tests.cpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/test/validation_block_tests.cpp
  • src/test/miner_tests.cpp
  • src/rpc/mining.cpp
  • src/test/blockencodings_tests.cpp
  • src/test/blockfilter_index_tests.cpp
  • src/primitives/block.cpp
  • src/test/util/setup_common.cpp
  • src/test/util/mining.cpp
  • src/primitives/block.h
  • src/chainparams.cpp

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@UdjinM6
Copy link
Copy Markdown

UdjinM6 commented Mar 7, 2025

Nice! 👍

Could also avoid resetting cached_hash on writes and squeeze a bit more out of it:
nvm

develop:
119.50s user 13.16s system 98% cpu 2:14.32 total

This PR:
101.09s user 12.94s system 97% cpu 1:56.42 total

@UdjinM6
Copy link
Copy Markdown

UdjinM6 commented Mar 19, 2025

How about 1628c17 instead of 10b0bc8c4db109d3dfbd7c20e8d8e9476e1ab0b7?

@PastaPastaPasta PastaPastaPasta force-pushed the perf-cache-header-hash branch from 10b0bc8 to 3e760e2 Compare April 15, 2025 14:15
Comment thread src/primitives/block.h
SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
SERIALIZE_METHODS(CBlockHeader, obj) {
READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce);
obj.cached_hash.SetNull();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may reset only in case of read event

@knst
Copy link
Copy Markdown
Collaborator

knst commented Apr 23, 2025

See tsan error: https://gitlab.com/dashpay/dash/-/jobs/9770587678

 node0 stderr ==================
WARNING: ThreadSanitizer: data race (pid=13740)
  Write of size 8 at 0x722800040f20 by thread T33 (mutexes: write M0, write M1, write M2):
    #0 __tsan_memset <null> (dashd+0xd3b3d) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 __gnu_cxx::__enable_if<__is_scalar<int>::__value, void>::__type std::__fill_a1<unsigned char*, int>(unsigned char*, unsigned char*, int const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_algobase.h:952:11 (dashd+0x3f31ee) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #2 void std::__fill_a<unsigned char*, int>(unsigned char*, unsigned char*, int const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_algobase.h:998:7 (dashd+0x3f31ee)
    #3 void std::fill<unsigned char*, int>(unsigned char*, unsigned char*, int const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_algobase.h:1029:7 (dashd+0x3f31ee)
    #4 base_blob<256u>::SetNull() src/./uint256.h:52:9 (dashd+0x3f31ee)
    #5 void CBlockHeader::SerializationOps<CVectorWriter, CBlockHeader const, CSerActionSerialize>(CBlockHeader const&, CVectorWriter&, CSerActionSerialize) src/./primitives/block.h:44:25 (dashd+0x3f31ee)
    #6 void CBlockHeader::Ser<CVectorWriter>(CVectorWriter&, CBlockHeader const&) src/./primitives/block.h:42:5 (dashd+0x3f31ee)
    #7 void CBlockHeader::Serialize<CVectorWriter>(CVectorWriter&) const src/./primitives/block.h:42:5 (dashd+0x3f31ee)
    #8 void Serialize<CVectorWriter, CBlockHeader, (void*)0>(CVectorWriter&, CBlockHeader const&) src/./serialize.h:890:7 (dashd+0x3f31ee)
    #9 void SerializeMany<CVectorWriter, CBlockHeader>(CVectorWriter&, CBlockHeader const&) src/./serialize.h:1379:6 (dashd+0x3f31ee)
    #10 void SerReadWriteMany<CVectorWriter, CBlockHeader>(CVectorWriter&, CSerActionSerialize, CBlockHeader const&) src/./serialize.h:1391:5 (dashd+0x3f31ee)
    #11 void CBlock::SerializationOps<CVectorWriter, CBlock const, CSerActionSerialize>(CBlock const&, CVectorWriter&, CSerActionSerialize) src/./primitives/block.h:215:9 (dashd+0x3f31ee)
    #12 void CBlock::Ser<CVectorWriter>(CVectorWriter&, CBlock const&) src/./primitives/block.h:213:5 (dashd+0x3f31ee)
    #13 void CBlock::Serialize<CVectorWriter>(CVectorWriter&) const src/./primitives/block.h:213:5 (dashd+0x3f31ee)
    #14 void Serialize<CVectorWriter, CBlock, (void*)0>(CVectorWriter&, CBlock const&) src/./serialize.h:890:7 (dashd+0x3f31ee)
    #15 void SerializeMany<CVectorWriter, CBlock>(CVectorWriter&, CBlock const&) src/./serialize.h:1379:6 (dashd+0x3f31ee)
    #16 CVectorWriter::CVectorWriter<CBlock const&>(int, int, std::vector<unsigned char, std::allocator<unsigned char>>&, unsigned long, CBlock const&) src/./streams.h:96:9 (dashd+0x3f31ee)
    #17 CSerializedNetMsg CNetMsgMaker::Make<CBlock const&>(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, CBlock const&) const src/./netmessagemaker.h:23:9 (dashd+0x3f3098) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #18 CSerializedNetMsg CNetMsgMaker::Make<CBlock const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, CBlock const&) const src/./netmessagemaker.h:31:16 (dashd+0x3bcab4) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #19 (anonymous namespace)::PeerManagerImpl::ProcessGetBlockData(CNode&, (anonymous namespace)::Peer&, CInv const&, llmq::CInstantSendManager&) src/net_processing.cpp:2590:52 (dashd+0x3bcab4)
    #20 (anonymous namespace)::PeerManagerImpl::ProcessGetData(CNode&, (anonymous namespace)::Peer&, std::atomic<bool> const&) src/net_processing.cpp:2892:13 (dashd+0x3bcab4)
    #21 (anonymous namespace)::PeerManagerImpl::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, CDataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l>>, std::atomic<bool> const&) src/net_processing.cpp:4202:13 (dashd+0x38a4b5) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #22 (anonymous namespace)::PeerManagerImpl::ProcessMessages(CNode*, std::atomic<bool>&) src/net_processing.cpp:5399:9 (dashd+0x3998a3) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #23 non-virtual thunk to (anonymous namespace)::PeerManagerImpl::ProcessMessages(CNode*, std::atomic<bool>&) src/net_processing.cpp (dashd+0x3a2fde) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #24 CConnman::ThreadMessageHandler() src/net.cpp:3979:45 (dashd+0x33edc8) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #25 CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6::operator()() const src/net.cpp:4361:80 (dashd+0x351eb2) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #26 void std::__invoke_impl<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>(std::__invoke_other, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x351eb2)
    #27 std::enable_if<is_invocable_r_v<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>, void>::type std::__invoke_r<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>(CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:111:2 (dashd+0x351eb2)
    #28 std::_Function_handler<void (), CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0x351eb2)
    #29 std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0xf3b669) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #30 util::TraceThread(char const*, std::function<void ()>) src/util/thread.cpp:18:9 (dashd+0xf3b669)
    #31 void std::__invoke_impl<void, void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>(std::__invoke_other, void (*&&)(char const*, std::function<void ()>), char const*&&, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x351def) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #32 std::__invoke_result<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>::type std::__invoke<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>(void (*&&)(char const*, std::function<void ()>), char const*&&, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:96:14 (dashd+0x351def)
    #33 void std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:301:13 (dashd+0x351def)
    #34 std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:308:11 (dashd+0x351def)
    #35 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>>::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:253:13 (dashd+0x351def)
    #36 <null> <null> (libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
  Previous read of size 8 at 0x722800040f20 by thread T8:
    #0 __tsan_memcpy <null> (dashd+0xd3a2f) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 CBlockHeader::GetHash(bool) const src/primitives/block.cpp:21:12 (dashd+0xf67a06) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #2 CWallet::blockConnected(CBlock const&, int) src/wallet/wallet.cpp:1313:39 (dashd+0xcaee37) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #3 non-virtual thunk to CWallet::blockConnected(CBlock const&, int) src/wallet/wallet.cpp (dashd+0xcaf3ec) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #4 node::(anonymous namespace)::NotificationsProxy::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*) src/node/interfaces.cpp:631:26 (dashd+0x442886) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #5 CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_1::operator()() const::'lambda'(CValidationInterface&)::operator()(CValidationInterface&) const src/validationinterface.cpp:229:79 (dashd+0x8492ee) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #6 void MainSignalsInstance::Iterate<CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_1::operator()() const::'lambda'(CValidationInterface&)>(CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_1::operator()() const::'lambda'(CValidationInterface&)&&) src/validationinterface.cpp:88:17 (dashd+0x8492ee)
    #7 CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_1::operator()() const src/validationinterface.cpp:229:22 (dashd+0x8492ee)
    #8 CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_0::operator()() const src/validationinterface.cpp:231:5 (dashd+0x8492ee)
    #9 void std::__invoke_impl<void, CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_0&>(std::__invoke_other, CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_0&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x8492ee)
    #10 std::enable_if<is_invocable_r_v<void, CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_0&>, void>::type std::__invoke_r<void, CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_0&>(CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_0&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:111:2 (dashd+0x8492ee)
    #11 std::_Function_handler<void (), CMainSignals::BlockConnected(std::shared_ptr<CBlock const> const&, CBlockIndex const*)::$_0>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0x8492ee)
    #12 std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0xe15cdc) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #13 SingleThreadedSchedulerClient::ProcessQueue() src/scheduler.cpp:175:5 (dashd+0xe15cdc)
    #14 SingleThreadedSchedulerClient::MaybeScheduleProcessQueue()::$_0::operator()() const src/scheduler.cpp:144:41 (dashd+0xe172a2) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #15 void std::__invoke_impl<void, SingleThreadedSchedulerClient::MaybeScheduleProcessQueue()::$_0&>(std::__invoke_other, SingleThreadedSchedulerClient::MaybeScheduleProcessQueue()::$_0&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0xe172a2)
    #16 std::enable_if<is_invocable_r_v<void, SingleThreadedSchedulerClient::MaybeScheduleProcessQueue()::$_0&>, void>::type std::__invoke_r<void, SingleThreadedSchedulerClient::MaybeScheduleProcessQueue()::$_0&>(SingleThreadedSchedulerClient::MaybeScheduleProcessQueue()::$_0&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:111:2 (dashd+0xe172a2)
    #17 std::_Function_handler<void (), SingleThreadedSchedulerClient::MaybeScheduleProcessQueue()::$_0>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0xe172a2)
    #18 std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0xe14ab3) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #19 CScheduler::serviceQueue() src/scheduler.cpp:62:17 (dashd+0xe14ab3)
    #20 AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6::operator()() const src/init.cpp:1497:106 (dashd+0x193d55) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #21 void std::__invoke_impl<void, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6&>(std::__invoke_other, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x193d55)
    #22 std::enable_if<is_invocable_r_v<void, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6&>, void>::type std::__invoke_r<void, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6&>(AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:111:2 (dashd+0x193d55)
    #23 std::_Function_handler<void (), AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0x193d55)
    #24 std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0xf3b669) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #25 util::TraceThread(char const*, std::function<void ()>) src/util/thread.cpp:18:9 (dashd+0xf3b669)
    #26 void std::__invoke_impl<void, void (*)(char const*, std::function<void ()>), char const*, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6>(std::__invoke_other, void (*&&)(char const*, std::function<void ()>), char const*&&, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x193c7f) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #27 std::__invoke_result<void (*)(char const*, std::function<void ()>), char const*, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6>::type std::__invoke<void (*)(char const*, std::function<void ()>), char const*, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6>(void (*&&)(char const*, std::function<void ()>), char const*&&, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:96:14 (dashd+0x193c7f)
    #28 void std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6>>::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:301:13 (dashd+0x193c7f)
    #29 std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6>>::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:308:11 (dashd+0x193c7f)
    #30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_6>>>::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:253:13 (dashd+0x193c7f)
    #31 <null> <null> (libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
  Location is heap block of size 160 at 0x722800040ec0 allocated by thread T12:
    #0 operator new(unsigned long) <null> (dashd+0x15707b) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 std::__new_allocator<std::_Sp_counted_ptr_inplace<CBlock const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>::allocate(unsigned long, void const*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/new_allocator.h:151:27 (dashd+0x6210df) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #2 std::allocator<std::_Sp_counted_ptr_inplace<CBlock const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>::allocate(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/allocator.h:196:32 (dashd+0x6210df)
    #3 std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<CBlock const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>>::allocate(std::allocator<std::_Sp_counted_ptr_inplace<CBlock const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>&, unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/alloc_traits.h:478:20 (dashd+0x6210df)
    #4 std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<CBlock const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>> std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<CBlock const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>>(std::allocator<std::_Sp_counted_ptr_inplace<CBlock const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/allocated_ptr.h:98:21 (dashd+0x6210df)
    #5 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<CBlock const, std::allocator<void>, CBlock&>(CBlock const*&, std::_Sp_alloc_shared_tag<std::allocator<void>>, CBlock&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/shared_ptr_base.h:967:19 (dashd+0x6210df)
    #6 std::__shared_ptr<CBlock const, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, CBlock&>(std::_Sp_alloc_shared_tag<std::allocator<void>>, CBlock&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/shared_ptr_base.h:1713:14 (dashd+0x61b23a) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #7 std::shared_ptr<CBlock const>::shared_ptr<std::allocator<void>, CBlock&>(std::_Sp_alloc_shared_tag<std::allocator<void>>, CBlock&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/shared_ptr.h:463:4 (dashd+0x61b23a)
    #8 std::shared_ptr<CBlock const> std::make_shared<CBlock const, CBlock&>(CBlock&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/shared_ptr.h:1007:14 (dashd+0x61b23a)
    #9 GenerateBlock(ChainstateManager&, CBlock&, unsigned long&, unsigned int&, uint256&) src/rpc/mining.cpp:146:51 (dashd+0x61b23a)
    #10 generateBlocks(ChainstateManager&, NodeContext const&, CTxMemPool const&, CScript const&, int, unsigned long) src/rpc/mining.cpp:178:14 (dashd+0x61acae) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #11 generatetoaddress()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const src/rpc/mining.cpp:297:12 (dashd+0x61a7ec) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #12 UniValue std::__invoke_impl<UniValue, generatetoaddress()::$_0&, RPCHelpMan const&, JSONRPCRequest const&>(std::__invoke_other, generatetoaddress()::$_0&, RPCHelpMan const&, JSONRPCRequest const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x61a7ec)
    #13 std::enable_if<is_invocable_r_v<UniValue, generatetoaddress()::$_0&, RPCHelpMan const&, JSONRPCRequest const&>, UniValue>::type std::__invoke_r<UniValue, generatetoaddress()::$_0&, RPCHelpMan const&, JSONRPCRequest const&>(generatetoaddress()::$_0&, RPCHelpMan const&, JSONRPCRequest const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:114:9 (dashd+0x61a7ec)
    #14 std::_Function_handler<UniValue (RPCHelpMan const&, JSONRPCRequest const&), generatetoaddress()::$_0>::_M_invoke(std::_Any_data const&, RPCHelpMan const&, JSONRPCRequest const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0x61a7ec)
    #15 std::function<UniValue (RPCHelpMan const&, JSONRPCRequest const&)>::operator()(RPCHelpMan const&, JSONRPCRequest const&) const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0xe06fb9) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #16 RPCHelpMan::HandleRequest(JSONRPCRequest const&) const src/rpc/util.cpp:540:12 (dashd+0xe06fb9)
    #17 CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, RPCHelpMan (*)())::'lambda'(JSONRPCRequest const&, UniValue&, bool)::operator()(JSONRPCRequest const&, UniValue&, bool) const src/./rpc/server.h:107:91 (dashd+0x540577) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #18 bool std::__invoke_impl<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, RPCHelpMan (*)())::'lambda'(JSONRPCRequest const&, UniValue&, bool)&, JSONRPCRequest const&, UniValue&, bool>(std::__invoke_other, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, RPCHelpMan (*)())::'lambda'(JSONRPCRequest const&, UniValue&, bool)&, JSONRPCRequest const&, UniValue&, bool&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x54043d) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #19 std::enable_if<is_invocable_r_v<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, RPCHelpMan (*)())::'lambda'(JSONRPCRequest const&, UniValue&, bool)&, JSONRPCRequest const&, UniValue&, bool>, bool>::type std::__invoke_r<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, RPCHelpMan (*)())::'lambda'(JSONRPCRequest const&, UniValue&, bool)&, JSONRPCRequest const&, UniValue&, bool>(CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, RPCHelpMan (*)())::'lambda'(JSONRPCRequest const&, UniValue&, bool)&, JSONRPCRequest const&, UniValue&, bool&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:114:9 (dashd+0x54043d)
    #20 std::_Function_handler<bool (JSONRPCRequest const&, UniValue&, bool), CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, RPCHelpMan (*)())::'lambda'(JSONRPCRequest const&, UniValue&, bool)>::_M_invoke(std::_Any_data const&, JSONRPCRequest const&, UniValue&, bool&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0x54043d)
    #21 std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0x72de9a) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #22 ExecuteCommand(CRPCCommand const&, JSONRPCRequest const&, UniValue&, bool) src/rpc/server.cpp:536:20 (dashd+0x72de9a)
    #23 ExecuteCommands(std::vector<CRPCCommand const*, std::allocator<CRPCCommand const*>> const&, JSONRPCRequest const&, UniValue&) src/rpc/server.cpp:490:13 (dashd+0x72de9a)
    #24 CRPCTable::execute(JSONRPCRequest const&) const src/rpc/server.cpp:522:13 (dashd+0x72cf08) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #25 HTTPReq_JSONRPC(std::variant<std::monostate, std::reference_wrapper<ArgsManager>, std::reference_wrapper<NodeContext>, std::reference_wrapper<WalletContext>, std::reference_wrapper<CTxMemPool>, std::reference_wrapper<ChainstateManager>, std::reference_wrapper<CBlockPolicyEstimator>, std::reference_wrapper<LLMQContext>> const&, HTTPRequest*) src/httprpc.cpp:242:40 (dashd+0x9ff0e5) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #26 StartHTTPRPC(std::variant<std::monostate, std::reference_wrapper<ArgsManager>, std::reference_wrapper<NodeContext>, std::reference_wrapper<WalletContext>, std::reference_wrapper<CTxMemPool>, std::reference_wrapper<ChainstateManager>, std::reference_wrapper<CBlockPolicyEstimator>, std::reference_wrapper<LLMQContext>> const&)::$_0::operator()(HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) const src/httprpc.cpp:336:80 (dashd+0x9ff0e5)
    #27 bool std::__invoke_impl<bool, StartHTTPRPC(std::variant<std::monostate, std::reference_wrapper<ArgsManager>, std::reference_wrapper<NodeContext>, std::reference_wrapper<WalletContext>, std::reference_wrapper<CTxMemPool>, std::reference_wrapper<ChainstateManager>, std::reference_wrapper<CBlockPolicyEstimator>, std::reference_wrapper<LLMQContext>> const&)::$_0&, HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&>(std::__invoke_other, StartHTTPRPC(std::variant<std::monostate, std::reference_wrapper<ArgsManager>, std::reference_wrapper<NodeContext>, std::reference_wrapper<WalletContext>, std::reference_wrapper<CTxMemPool>, std::reference_wrapper<ChainstateManager>, std::reference_wrapper<CBlockPolicyEstimator>, std::reference_wrapper<LLMQContext>> const&)::$_0&, HTTPRequest*&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x9ff0e5)
    #28 std::enable_if<is_invocable_r_v<bool, StartHTTPRPC(std::variant<std::monostate, std::reference_wrapper<ArgsManager>, std::reference_wrapper<NodeContext>, std::reference_wrapper<WalletContext>, std::reference_wrapper<CTxMemPool>, std::reference_wrapper<ChainstateManager>, std::reference_wrapper<CBlockPolicyEstimator>, std::reference_wrapper<LLMQContext>> const&)::$_0&, HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&>, bool>::type std::__invoke_r<bool, StartHTTPRPC(std::variant<std::monostate, std::reference_wrapper<ArgsManager>, std::reference_wrapper<NodeContext>, std::reference_wrapper<WalletContext>, std::reference_wrapper<CTxMemPool>, std::reference_wrapper<ChainstateManager>, std::reference_wrapper<CBlockPolicyEstimator>, std::reference_wrapper<LLMQContext>> const&)::$_0&, HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&>(StartHTTPRPC(std::variant<std::monostate, std::reference_wrapper<ArgsManager>, std::reference_wrapper<NodeContext>, std::reference_wrapper<WalletContext>, std::reference_wrapper<CTxMemPool>, std::reference_wrapper<ChainstateManager>, std::reference_wrapper<CBlockPolicyEstimator>, std::reference_wrapper<LLMQContext>> const&)::$_0&, HTTPRequest*&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:114:9 (dashd+0x9ff0e5)
    #29 std::_Function_handler<bool (HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&), StartHTTPRPC(std::variant<std::monostate, std::reference_wrapper<ArgsManager>, std::reference_wrapper<NodeContext>, std::reference_wrapper<WalletContext>, std::reference_wrapper<CTxMemPool>, std::reference_wrapper<ChainstateManager>, std::reference_wrapper<CBlockPolicyEstimator>, std::reference_wrapper<LLMQContext>> const&)::$_0>::_M_invoke(std::_Any_data const&, HTTPRequest*&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0x9ff0e5)
    #30 std::function<bool (HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)>::operator()(HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0xa11b51) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #31 HTTPWorkItem::operator()() src/httpserver.cpp:52:9 (dashd+0xa11b51)
    #32 WorkQueue<HTTPClosure>::Run() src/httpserver.cpp:124:13 (dashd+0xa13092) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #33 HTTPWorkQueueRun(WorkQueue<HTTPClosure>*, int) src/httpserver.cpp:371:12 (dashd+0xa0c2ab) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #34 void std::__invoke_impl<void, void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>(std::__invoke_other, void (*&&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0xa12f4d) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #35 std::__invoke_result<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>::type std::__invoke<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>(void (*&&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:96:14 (dashd+0xa12f4d)
    #36 void std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>>::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:301:13 (dashd+0xa12f4d)
    #37 std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>>::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:308:11 (dashd+0xa12f4d)
    #38 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>>>::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:253:13 (dashd+0xa12f4d)
    #39 <null> <null> (libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
  Mutex M0 (0x55d8edf020e8) created at:
    #0 pthread_mutex_trylock <null> (dashd+0xd97fe) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 __gthread_mutex_trylock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:771:12 (dashd+0x1aac1e) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #2 std::mutex::try_lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_mutex.h:125:15 (dashd+0x1aac1e)
    #3 std::unique_lock<std::mutex>::try_lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:162:27 (dashd+0x1aac1e)
    #4 UniqueLock<AnnotatedMixin<std::mutex>, std::unique_lock<std::mutex>>::Enter(char const*, char const*, int) src/./sync.h:168:19 (dashd+0x1aac1e)
    #5 UniqueLock<AnnotatedMixin<std::mutex>, std::unique_lock<std::mutex>>::UniqueLock(AnnotatedMixin<std::mutex>&, char const*, char const*, int, bool) src/./sync.h:190:13 (dashd+0x33ec1f) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #6 CConnman::ThreadMessageHandler() src/net.cpp:3954:5 (dashd+0x33ec1f)
    #7 CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6::operator()() const src/net.cpp:4361:80 (dashd+0x351eb2) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #8 void std::__invoke_impl<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>(std::__invoke_other, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x351eb2)
    #9 std::enable_if<is_invocable_r_v<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>, void>::type std::__invoke_r<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>(CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:111:2 (dashd+0x351eb2)
    #10 std::_Function_handler<void (), CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0x351eb2)
    #11 std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0xf3b669) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #12 util::TraceThread(char const*, std::function<void ()>) src/util/thread.cpp:18:9 (dashd+0xf3b669)
    #13 void std::__invoke_impl<void, void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>(std::__invoke_other, void (*&&)(char const*, std::function<void ()>), char const*&&, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x351def) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #14 std::__invoke_result<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>::type std::__invoke<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>(void (*&&)(char const*, std::function<void ()>), char const*&&, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:96:14 (dashd+0x351def)
    #15 void std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:301:13 (dashd+0x351def)
    #16 std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:308:11 (dashd+0x351def)
    #17 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>>::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:253:13 (dashd+0x351def)
    #18 <null> <null> (libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
  Mutex M1 (0x7254000c0238) created at:
    #0 pthread_mutex_trylock <null> (dashd+0xd97fe) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 __gthread_mutex_trylock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:771:12 (dashd+0x1aac1e) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #2 std::mutex::try_lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_mutex.h:125:15 (dashd+0x1aac1e)
    #3 std::unique_lock<std::mutex>::try_lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:162:27 (dashd+0x1aac1e)
    #4 UniqueLock<AnnotatedMixin<std::mutex>, std::unique_lock<std::mutex>>::Enter(char const*, char const*, int) src/./sync.h:168:19 (dashd+0x1aac1e)
    #5 UniqueLock<AnnotatedMixin<std::mutex>, std::unique_lock<std::mutex>>::UniqueLock(AnnotatedMixin<std::mutex>&, char const*, char const*, int, bool) src/./sync.h:190:13 (dashd+0x3993b7) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #6 (anonymous namespace)::PeerManagerImpl::ProcessMessages(CNode*, std::atomic<bool>&) src/net_processing.cpp:5343:9 (dashd+0x3993b7)
    #7 non-virtual thunk to (anonymous namespace)::PeerManagerImpl::ProcessMessages(CNode*, std::atomic<bool>&) src/net_processing.cpp (dashd+0x3a2fde) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #8 CConnman::ThreadMessageHandler() src/net.cpp:3979:45 (dashd+0x33edc8) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #9 CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6::operator()() const src/net.cpp:4361:80 (dashd+0x351eb2) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #10 void std::__invoke_impl<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>(std::__invoke_other, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x351eb2)
    #11 std::enable_if<is_invocable_r_v<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>, void>::type std::__invoke_r<void, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&>(CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:111:2 (dashd+0x351eb2)
    #12 std::_Function_handler<void (), CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:290:9 (dashd+0x351eb2)
    #13 std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_function.h:591:9 (dashd+0xf3b669) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #14 util::TraceThread(char const*, std::function<void ()>) src/util/thread.cpp:18:9 (dashd+0xf3b669)
    #15 void std::__invoke_impl<void, void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>(std::__invoke_other, void (*&&)(char const*, std::function<void ()>), char const*&&, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:61:14 (dashd+0x351def) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #16 std::__invoke_result<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>::type std::__invoke<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>(void (*&&)(char const*, std::function<void ()>), char const*&&, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/invoke.h:96:14 (dashd+0x351def)
    #17 void std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:301:13 (dashd+0x351def)
    #18 std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:308:11 (dashd+0x351def)
    #19 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, CConnman::Start(CDeterministicMNManager&, CMasternodeMetaMan&, CMasternodeSync&, CScheduler&, CConnman::Options const&)::$_6>>>::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_thread.h:253:13 (dashd+0x351def)
    #20 <null> <null> (libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
  Mutex M2 (0x55d8ecb0fe38) created at:
    #0 pthread_mutex_trylock <null> (dashd+0xd97fe) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 __gthread_mutex_trylock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:771:12 (dashd+0x1a98ae) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #2 __gthread_recursive_mutex_trylock(pthread_mutex_t*) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:830:10 (dashd+0x1a98ae)
    #3 std::recursive_mutex::try_lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/mutex:137:15 (dashd+0x1a98ae)
    #4 std::unique_lock<std::recursive_mutex>::try_lock() /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:162:27 (dashd+0x1a98ae)
    #5 UniqueLock<AnnotatedMixin<std::recursive_mutex>, std::unique_lock<std::recursive_mutex>>::Enter(char const*, char const*, int) src/./sync.h:168:19 (dashd+0x1a98ae)
    #6 UniqueLock<AnnotatedMixin<std::recursive_mutex>, std::unique_lock<std::recursive_mutex>>::UniqueLock(AnnotatedMixin<std::recursive_mutex>&, char const*, char const*, int, bool) src/./sync.h:190:13 (dashd+0x426cdb) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #7 LoadChainstate(bool, ChainstateManager&, CGovernanceManager&, CMasternodeMetaMan&, CMasternodeSync&, CSporkManager&, std::unique_ptr<CActiveMasternodeManager, std::default_delete<CActiveMasternodeManager>>&, std::unique_ptr<CChainstateHelper, std::default_delete<CChainstateHelper>>&, std::unique_ptr<CCreditPoolManager, std::default_delete<CCreditPoolManager>>&, std::unique_ptr<CDeterministicMNManager, std::default_delete<CDeterministicMNManager>>&, std::unique_ptr<CEvoDB, std::default_delete<CEvoDB>>&, std::unique_ptr<CMNHFManager, std::default_delete<CMNHFManager>>&, std::unique_ptr<LLMQContext, std::default_delete<LLMQContext>>&, CTxMemPool*, bool, bool, bool, bool, bool, bool, Consensus::Params const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool, long, long, long, bool, bool, std::function<bool ()>, std::function<void ()>) src/node/chainstate.cpp:55:5 (dashd+0x426cdb)
    #8 AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*) src/init.cpp:1863:32 (dashd+0x184f9d) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #9 AppInit(NodeContext&, int, char**) src/bitcoind.cpp:237:43 (dashd+0x158f8c) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #10 main src/bitcoind.cpp:280:13 (dashd+0x158f8c)
  Thread T33 'd-msghand' (tid=13808, running) created by main thread at:
    #0 pthread_create <null> (dashd+0xd7aff) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State>>, void (*)()) <null> (libstdc++.so.6+0xeceb0) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #2 AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*) src/init.cpp:2417:24 (dashd+0x18a169) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #3 AppInit(NodeContext&, int, char**) src/bitcoind.cpp:237:43 (dashd+0x158f8c) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #4 main src/bitcoind.cpp:280:13 (dashd+0x158f8c)
  Thread T8 'd-scheduler' (tid=13769, running) created by main thread at:
    #0 pthread_create <null> (dashd+0xd7aff) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State>>, void (*)()) <null> (libstdc++.so.6+0xeceb0) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #2 AppInit(NodeContext&, int, char**) src/bitcoind.cpp:237:43 (dashd+0x158f8c) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #3 main src/bitcoind.cpp:280:13 (dashd+0x158f8c)
  Thread T12 'd-httpworker.2' (tid=13778, running) created by main thread at:
    #0 pthread_create <null> (dashd+0xd7aff) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State>>, void (*)()) <null> (libstdc++.so.6+0xeceb0) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #2 std::thread& std::vector<std::thread, std::allocator<std::thread>>::emplace_back<void (&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int&>(void (&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&) /usr/bin/../lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/vector.tcc:123:4 (dashd+0xa105b8) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #3 StartHTTPServer() src/httpserver.cpp:475:31 (dashd+0xa0bbd3) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #4 AppInitServers(NodeContext&) src/init.cpp:895:5 (dashd+0x1815b5) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #5 AppInitMain(NodeContext&, interfaces::BlockAndHeaderTipInfo*) src/init.cpp:1548:14 (dashd+0x1815b5)
    #6 AppInit(NodeContext&, int, char**) src/bitcoind.cpp:237:43 (dashd+0x158f8c) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df)
    #7 main src/bitcoind.cpp:280:13 (dashd+0x158f8c)
SUMMARY: ThreadSanitizer: data race (/builds/dashpay/dash/build-ci/dashcore-linux64_tsan/src/dashd+0xd3b3d) (BuildId: 958fa0f841126396be6d3f72a5d4185ba899e3df) in __tsan_memset
================== Early exiting after test failure

PastaPastaPasta added a commit that referenced this pull request Jul 24, 2025
…shing sources

0c5e295 chore: retain only Skein512, remove other variants (Kittywhiskers Van Gogh)
6fa5ddc chore: retain only Simd512, remove other variants (Kittywhiskers Van Gogh)
2c5b641 chore: retain only Shavite512, remove other variants (Kittywhiskers Van Gogh)
9035b5f chore: retain only Luffa512, remove other variants (Kittywhiskers Van Gogh)
11c0517 chore: retain only Keccak512, remove other variants (Kittywhiskers Van Gogh)
9fa0bc9 chore: retain only Jh512, remove other variants (Kittywhiskers Van Gogh)
9229220 chore: retain only Groestl512, remove other variants (Kittywhiskers Van Gogh)
822e75d chore: retain only Echo512, remove other variants (Kittywhiskers Van Gogh)
79f3078 chore: retain only Cubehash512, remove other variants (Kittywhiskers Van Gogh)
05e53e6 chore: retain only Bmw512, remove other variants (Kittywhiskers Van Gogh)
974b330 chore: retain only Blake512, remove other variants (Kittywhiskers Van Gogh)
4a31cfb chore: remove unused big-endian AES tables (Kittywhiskers Van Gogh)
d0f94c3 chore: remove Doxygen macro blocks (Kittywhiskers Van Gogh)
79b9c87 chore: remove commented out code (Kittywhiskers Van Gogh)

Pull request description:

  ## Motivation

  Dash utilizes a daisy-chain of 11 hash algorithms for its proof of work termed X11. The library that provided the implementation of the underlying hash algorithms is `sphlib` by Thomas Pornin ([source](https://web.archive.org/web/20180428002946/http://www.saphir2.com/sphlib/), Internet Archive). The library has been a part of Dash Core since inception (f164aea) and does what it says on the tin quite well.

  Though, it's been a solid decade since and performance profiling has shown that proof of work hashing takes up a not-insignificant amount of time. As an alternative to (or alongside) [dash#6610](#6610), we intend to work on improving the performance of X11 while maintaining readability and auditability.

  To begin with that, we are removing variants that Dash _doesn't_ use, namely, non 512-bit variants of the constituent algorithms used and subsequent pull requests will be integrating the library's contents with primitives available in Dash Core to allow for attributable and reasonable performance improvements.

  ## Breaking Changes

  None expected.

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)**
  - [x] I have added or updated relevant unit/integration/functional/e2e tests **(note: N/A)**
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  PastaPastaPasta:
    utACK 0c5e295
  UdjinM6:
    utACK 0c5e295
  knst:
    utACK 0c5e295

Tree-SHA512: fb6cd94bcb01b9434d83c35509f5bd2ed902c918bf58d7027af87643abcd62a937aa94070d73c7a2c4e9177809194369b71630e353df87e0432dac503e8e0d72
@UdjinM6 UdjinM6 removed this from the 23 milestone Nov 13, 2025
@thepastaclaw
Copy link
Copy Markdown

thepastaclaw commented Mar 30, 2026

Review Gate

Commit: 4434123d

  • Debounce: 53070m ago (need 30m)

  • CI checks: build failure: linux64_tsan-build / Build source, linux64_sqlite-build / Build source

  • CodeRabbit review: comment found

  • Off-peak hours: peak window (5am-11am PT) — currently 06:57 AM PT Tuesday

  • Run review now (check to override)

Copy link
Copy Markdown

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The X11 hash caching achieves a meaningful reindex speedup, but the implementation has two fundamental issues: the mutable cache introduces an unsynchronized write in a const method (data race under concurrent GetHash() calls), and cache invalidation is incomplete because use_cache=false still writes the cache and header fields remain publicly mutable without clearing it.

Reviewed commit: 3e760e2

🔴 2 blocking

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/primitives/block.cpp`:
- [BLOCKING] lines 13-21: Unsynchronized mutable write in const GetHash() — data race
  `GetHash()` is a `const` method that writes `cached_hash` (a `mutable uint256`) with no lock or atomic protection. Before this PR, `GetHash()` was pure and concurrent calls on the same header were safe. Now, two threads calling `GetHash()` on the same `CBlockHeader` for the first time race on a 32-byte write — undefined behavior per C++.

Since `CBlock`/`CBlockHeader` instances are routinely shared (including via `shared_ptr<const CBlock>`), this is a real regression. Consider using `std::atomic` with a flag, or `std::call_once`, or external synchronization.
- [BLOCKING] lines 15-20: `use_cache=false` still writes the cache — stale hashes after header mutation
  `GetHash(false)` bypasses the cache *read* but still assigns `cached_hash` on line 19. Callers using `use_cache=false` during nonce search (to get a fresh hash after mutating `nNonce`) still poison the cache with each iteration's hash. After the loop, a plain `GetHash()` returns the stale cached value from the last nonce tried, not the final header state.

The same issue affects `getblocktemplate` which mutates `nTime`/`nNonce`/`nVersion` on a cached template without clearing the hash. `CBlock::GetBlockHeader()` also copies `cached_hash` into the returned header, propagating stale state.

Fix: `use_cache=false` should compute and return without writing the cache, or header mutation should clear the cache.

Comment thread src/primitives/block.cpp
Comment on lines +13 to +21
uint256 CBlockHeader::GetHash(bool use_cache) const
{
std::vector<unsigned char> vch(80);
CVectorWriter ss(SER_GETHASH, PROTOCOL_VERSION, vch, 0);
ss << *this;
return HashX11((const char *)vch.data(), (const char *)vch.data() + vch.size());
if (!use_cache || cached_hash.IsNull()) {
std::vector<unsigned char> vch(80);
CVectorWriter ss(SER_GETHASH, PROTOCOL_VERSION, vch, 0);
ss << *this;
cached_hash = HashX11((const char *)vch.data(), (const char *)vch.data() + vch.size());
}
return cached_hash;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocking: Unsynchronized mutable write in const GetHash() — data race

GetHash() is a const method that writes cached_hash (a mutable uint256) with no lock or atomic protection. Before this PR, GetHash() was pure and concurrent calls on the same header were safe. Now, two threads calling GetHash() on the same CBlockHeader for the first time race on a 32-byte write — undefined behavior per C++.

Since CBlock/CBlockHeader instances are routinely shared (including via shared_ptr<const CBlock>), this is a real regression. Consider using std::atomic with a flag, or std::call_once, or external synchronization.

source: ['codex']

🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/primitives/block.cpp`:
- [BLOCKING] lines 13-21: Unsynchronized mutable write in const GetHash() — data race
  `GetHash()` is a `const` method that writes `cached_hash` (a `mutable uint256`) with no lock or atomic protection. Before this PR, `GetHash()` was pure and concurrent calls on the same header were safe. Now, two threads calling `GetHash()` on the same `CBlockHeader` for the first time race on a 32-byte write — undefined behavior per C++.

Since `CBlock`/`CBlockHeader` instances are routinely shared (including via `shared_ptr<const CBlock>`), this is a real regression. Consider using `std::atomic` with a flag, or `std::call_once`, or external synchronization.

Comment thread src/primitives/block.cpp
Comment on lines +15 to +20
if (!use_cache || cached_hash.IsNull()) {
std::vector<unsigned char> vch(80);
CVectorWriter ss(SER_GETHASH, PROTOCOL_VERSION, vch, 0);
ss << *this;
cached_hash = HashX11((const char *)vch.data(), (const char *)vch.data() + vch.size());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocking: use_cache=false still writes the cache — stale hashes after header mutation

GetHash(false) bypasses the cache read but still assigns cached_hash on line 19. Callers using use_cache=false during nonce search (to get a fresh hash after mutating nNonce) still poison the cache with each iteration's hash. After the loop, a plain GetHash() returns the stale cached value from the last nonce tried, not the final header state.

The same issue affects getblocktemplate which mutates nTime/nNonce/nVersion on a cached template without clearing the hash. CBlock::GetBlockHeader() also copies cached_hash into the returned header, propagating stale state.

Fix: use_cache=false should compute and return without writing the cache, or header mutation should clear the cache.

source: ['codex']

🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/primitives/block.cpp`:
- [BLOCKING] lines 15-20: `use_cache=false` still writes the cache — stale hashes after header mutation
  `GetHash(false)` bypasses the cache *read* but still assigns `cached_hash` on line 19. Callers using `use_cache=false` during nonce search (to get a fresh hash after mutating `nNonce`) still poison the cache with each iteration's hash. After the loop, a plain `GetHash()` returns the stale cached value from the last nonce tried, not the final header state.

The same issue affects `getblocktemplate` which mutates `nTime`/`nNonce`/`nVersion` on a cached template without clearing the hash. `CBlock::GetBlockHeader()` also copies `cached_hash` into the returned header, propagating stale state.

Fix: `use_cache=false` should compute and return without writing the cache, or header mutation should clear the cache.

@PastaPastaPasta PastaPastaPasta force-pushed the perf-cache-header-hash branch from 3e760e2 to 4434123 Compare April 5, 2026 17:27
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 5, 2026

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@UdjinM6
Copy link
Copy Markdown

UdjinM6 commented Apr 6, 2026

Pls see f6faab6, ae3f6a6 and d8c6891. This should fix tsan. But I'm not sure if all this extra complexity in such a critical part is a good tradeoff for performance gains. How about an alternative approach UdjinM6@f7c43a2? Headers only reindex on testnet finishes in basically the same time as this PR for me.

@PastaPastaPasta
Copy link
Copy Markdown
Member Author

Do you want to make you own PR for UdjinM6@f7c43a2? that approach seems fine

@UdjinM6
Copy link
Copy Markdown

UdjinM6 commented Apr 7, 2026

See #7272

PastaPastaPasta added a commit that referenced this pull request Apr 11, 2026
…to avoid redundant X11 computations

6e138f0 review: document known_hash safety and fix test to exercise reindex path (UdjinM6)
01af278 refactor: return std::optional<uint256> from ReadBlockFromDisk(FlatFilePos) (UdjinM6)
89d8c45 assert: use ASSERT_IF_DEBUG for known_hash invariants (UdjinM6)
01e72cb test: exercise CheckBlock and AcceptBlock with pre-computed known_hash (UdjinM6)
ec87196 assert: add debug-only invariant to verify known_hash matches block hash (UdjinM6)
f7c43a2 perf: pass pre-computed block hash through reindex path to avoid redundant X11 (UdjinM6)

Pull request description:

  ## Issue being fixed or feature implemented
  During reindex, the X11 block header hash was computed multiple times for the same block: once in `LoadExternalBlockFile`, again in `AcceptBlockHeader`, again in `CheckBlock`, and more for out-of-order blocks.

  See #6610 for more info.

  ## What was done?
  Thread the already-computed hash through `AcceptBlock`, `AcceptBlockHeader`, `CheckBlock`, and `ReadBlockFromDisk` to eliminate redundant X11 computations (from 3-5 per block down to 1).

  ## How Has This Been Tested?
  Reindexed on testnet with `--stopatheight=1` to confirm performance is on par with #6610. Then competed reindex on testnet with no issues. Tests are green too.

  ## Breaking Changes
  n/a

  ## Checklist:
  - [ ] I have performed a self-review of my own code
  - [ ] I have commented my code, particularly in hard-to-understand areas
  - [ ] I have added or updated relevant unit/integration/functional/e2e tests
  - [ ] I have made corresponding changes to the documentation
  - [ ] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

Top commit has no ACKs.

Tree-SHA512: 473fb7bf177c721f8d0f50e04394015554e779b26b1f004e52efb7803d267a13692a0f6a31426f084f1fbc25d2db44a56b0621fe7ed1b65c9c49ed322d98f1e9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants