From 7daa67d25bf7075fab19d4c639af136be3570a12 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 6 Oct 2026 04:01:25 +0700 Subject: [PATCH 1/3] fix(test): assert the chain tip before dereferencing it in reward reallocation tests GetMnRewardEraAfter() accepts a null pindexPrev, so clang-tidy's static analyzer treats the tip as possibly null on the path into it and flags the tip->nBits dereference a few lines later in linux64_multiprocess CI. Wrap every tip lookup that feeds the era helper in Assert(): the chain is never empty here, and a fatal check in a unit test documents that. --- src/test/block_reward_reallocation_tests.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/test/block_reward_reallocation_tests.cpp b/src/test/block_reward_reallocation_tests.cpp index daface97824c..6c55b711b780 100644 --- a/src/test/block_reward_reallocation_tests.cpp +++ b/src/test/block_reward_reallocation_tests.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -108,7 +109,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS // This applies even if reallocation was activated right at superblock height like it does here. // next block should be signaling by default LOCK(cs_main); - const CBlockIndex* const tip{m_node.chainman->ActiveChain().Tip()}; + const CBlockIndex* const tip{Assert(m_node.chainman->ActiveChain().Tip())}; const MnRewardEra era{GetMnRewardEraAfter(tip, *m_node.chainman)}; const bool isV20Active{era != MnRewardEra::Classic}; dmnman.UpdatedBlockTip(tip); @@ -125,7 +126,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS { LOCK(cs_main); - const CBlockIndex* const tip{m_node.chainman->ActiveChain().Tip()}; + const CBlockIndex* const tip{Assert(m_node.chainman->ActiveChain().Tip())}; const MnRewardEra era{GetMnRewardEraAfter(tip, *m_node.chainman)}; const bool isV20Active{era != MnRewardEra::Classic}; const CAmount block_subsidy = GetBlockSubsidyInner(tip->nBits, tip->nHeight, consensus_params, isV20Active); @@ -143,7 +144,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS CreateAndProcessBlock({}, coinbasePubKey); } LOCK(cs_main); - const CBlockIndex* const tip{m_node.chainman->ActiveChain().Tip()}; + const CBlockIndex* const tip{Assert(m_node.chainman->ActiveChain().Tip())}; const MnRewardEra era{GetMnRewardEraAfter(tip, *m_node.chainman)}; const bool isV20Active{era != MnRewardEra::Classic}; const CAmount block_subsidy = GetBlockSubsidyInner(tip->nBits, tip->nHeight, consensus_params, isV20Active); @@ -157,7 +158,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS { // Reward split should reach ~75/25 after reallocation is done LOCK(cs_main); - const CBlockIndex* const tip{m_node.chainman->ActiveChain().Tip()}; + const CBlockIndex* const tip{Assert(m_node.chainman->ActiveChain().Tip())}; const MnRewardEra era{GetMnRewardEraAfter(tip, *m_node.chainman)}; const bool isV20Active{era != MnRewardEra::Classic}; const CAmount block_subsidy = GetBlockSubsidyInner(tip->nBits, tip->nHeight, consensus_params, isV20Active); @@ -182,7 +183,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS CreateAndProcessBlock({}, coinbasePubKey); } LOCK(cs_main); - const CBlockIndex* const tip{m_node.chainman->ActiveChain().Tip()}; + const CBlockIndex* const tip{Assert(m_node.chainman->ActiveChain().Tip())}; const MnRewardEra era{GetMnRewardEraAfter(tip, *m_node.chainman)}; const bool isV20Active{era != MnRewardEra::Classic}; const bool isMNRewardReallocated{era == MnRewardEra::EvoReward}; @@ -203,7 +204,7 @@ BOOST_FIXTURE_TEST_CASE(block_reward_reallocation, TestChainBRRBeforeActivationS { // At this moment Masternode reward should be reallocated to platform // Allocation of block subsidy is 60% MN, 20% miners and 20% treasury LOCK(cs_main); - const CBlockIndex* const tip{m_node.chainman->ActiveChain().Tip()}; + const CBlockIndex* const tip{Assert(m_node.chainman->ActiveChain().Tip())}; const MnRewardEra era{GetMnRewardEraAfter(tip, *m_node.chainman)}; const bool isV20Active{era != MnRewardEra::Classic}; const CAmount block_subsidy = GetBlockSubsidyInner(tip->nBits, tip->nHeight, consensus_params, isV20Active); From 9c6ccd0d34dba699bde588724a37595e6f3b1b83 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 6 Oct 2026 04:01:25 +0700 Subject: [PATCH 2/3] fix(qt): clear ItemIsEnabled through QFlags::setFlag in coin control test ~Qt::ItemIsEnabled is evaluated as a plain int of -33, and QFlags::operator& converts it to unsigned, which UBSan reports as an implicit sign change in the asan CI job. Use setFlag(Qt::ItemIsEnabled, false) so the mask never leaves the QFlags type. --- src/qt/test/coincontroltreewidgettests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/test/coincontroltreewidgettests.cpp b/src/qt/test/coincontroltreewidgettests.cpp index a1c0bdd5354b..c1813808d7f1 100644 --- a/src/qt/test/coincontroltreewidgettests.cpp +++ b/src/qt/test/coincontroltreewidgettests.cpp @@ -153,7 +153,7 @@ void CoinControlTreeWidgetTests::disabledCoinsSkipped() CoinControlTreeWidget tree; const auto coins{AddCoins(tree, 6)}; // CoinControlDialog disables locked coins - coins[2]->setFlags(coins[2]->flags() & ~Qt::ItemIsEnabled); + coins[2]->setFlags(coins[2]->flags().setFlag(Qt::ItemIsEnabled, false)); ShowTree(tree); ClickCheckbox(tree, coins[0]); From 92365cc8114799b28d78f608bf7c77a3a2b06ee5 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 6 Oct 2026 04:37:37 +0700 Subject: [PATCH 3/3] fix(qt): reserve the coin vector in the coin control test helper clang-tidy's performance-inefficient-vector-operation flags the push_back loop in AddCoins(), and src/.clang-tidy turns every warning into an error, so the linux64_multiprocess tidy step fails on this file. Reserve the final size before the loop. --- src/qt/test/coincontroltreewidgettests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/test/coincontroltreewidgettests.cpp b/src/qt/test/coincontroltreewidgettests.cpp index c1813808d7f1..ab3918075b6e 100644 --- a/src/qt/test/coincontroltreewidgettests.cpp +++ b/src/qt/test/coincontroltreewidgettests.cpp @@ -34,6 +34,7 @@ QTreeWidgetItem* AddCoin(CoinControlTreeWidget& tree, QTreeWidgetItem* group = n std::vector AddCoins(CoinControlTreeWidget& tree, int count, QTreeWidgetItem* group = nullptr) { std::vector coins; + coins.reserve(count); for (int i = 0; i < count; ++i) { coins.push_back(AddCoin(tree, group)); }