From c011e3aa542631a8857039df796ebf13a653e8a6 Mon Sep 17 00:00:00 2001 From: Martin Zumsande Date: Fri, 5 Dec 2025 11:42:30 -0500 Subject: [PATCH] test: Wrap validation functions with TestChainstateManager This allows to access them in the fuzz test in the next commit without making them public. Co-authored-by: TheCharlatan --- src/node/blockstorage.h | 16 ++++++------ src/test/util/validation.cpp | 48 ++++++++++++++++++++++++++++++++++++ src/test/util/validation.h | 13 ++++++++++ src/validation.h | 4 ++- 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index c381d1c9226..bef99984644 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -248,7 +248,6 @@ private: ChainstateManager& chainman); RecursiveMutex cs_LastBlockFile; - std::vector m_blockfile_info; //! Since assumedvalid chainstates may be syncing a range of the chain that is very //! far away from the normal/background validation process, we should segment blockfiles @@ -283,12 +282,6 @@ private: const Obfuscation m_obfuscation; - /** Dirty block index entries. */ - std::set m_dirty_blockindex; - - /** Dirty block file entries. */ - std::set m_dirty_fileinfo; - /** * Map from external index name to oldest block that must not be pruned. * @@ -304,6 +297,15 @@ private: const FlatFileSeq m_block_file_seq; const FlatFileSeq m_undo_file_seq; +protected: + std::vector m_blockfile_info; + + /** Dirty block index entries. */ + std::set m_dirty_blockindex; + + /** Dirty block file entries. */ + std::set m_dirty_fileinfo; + public: using Options = kernel::BlockManagerOpts; using ReadRawBlockResult = util::Expected, ReadRawError>; diff --git a/src/test/util/validation.cpp b/src/test/util/validation.cpp index c199d912a38..b9f79f1d57a 100644 --- a/src/test/util/validation.cpp +++ b/src/test/util/validation.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -11,6 +12,13 @@ using kernel::ChainstateRole; +void TestBlockManager::CleanupForFuzzing() +{ + m_dirty_blockindex.clear(); + m_dirty_fileinfo.clear(); + m_blockfile_info.resize(1); +} + void TestChainstateManager::DisableNextWrite() { struct TestChainstate : public Chainstate { @@ -43,3 +51,43 @@ void ValidationInterfaceTest::BlockConnected( { obj.BlockConnected(role, block, pindex); } +void TestChainstateManager::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state) +{ + struct TestChainstate : public Chainstate { + void CallInvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main) + { + InvalidBlockFound(pindex, state); + } + }; + + static_cast(&ActiveChainstate())->CallInvalidBlockFound(pindex, state); +} + +void TestChainstateManager::InvalidChainFound(CBlockIndex* pindexNew) +{ + struct TestChainstate : public Chainstate { + void CallInvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main) + { + InvalidChainFound(pindexNew); + } + }; + + static_cast(&ActiveChainstate())->CallInvalidChainFound(pindexNew); +} + +CBlockIndex* TestChainstateManager::FindMostWorkChain() +{ + struct TestChainstate : public Chainstate { + CBlockIndex* CallFindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main) + { + return FindMostWorkChain(); + } + }; + + return static_cast(&ActiveChainstate())->CallFindMostWorkChain(); +} + +void TestChainstateManager::ResetBestInvalid() +{ + m_best_invalid = nullptr; +} diff --git a/src/test/util/validation.h b/src/test/util/validation.h index 4a24c97ed24..debad32d8d3 100644 --- a/src/test/util/validation.h +++ b/src/test/util/validation.h @@ -7,8 +7,16 @@ #include +namespace node { +class BlockManager; +} class CValidationInterface; +struct TestBlockManager : public node::BlockManager { + /** Test-only method to clear internal state for fuzzing */ + void CleanupForFuzzing(); +}; + struct TestChainstateManager : public ChainstateManager { /** Disable the next write of all chainstates */ void DisableNextWrite(); @@ -16,6 +24,11 @@ struct TestChainstateManager : public ChainstateManager { void ResetIbd(); /** Toggle IsInitialBlockDownload from true to false */ void JumpOutOfIbd(); + /** Wrappers that avoid making chainstatemanager internals public for tests */ + void InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + void InvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main); + void ResetBestInvalid() EXCLUSIVE_LOCKS_REQUIRED(cs_main); }; class ValidationInterfaceTest diff --git a/src/validation.h b/src/validation.h index 77958b53dd1..e4b1e555bdd 100644 --- a/src/validation.h +++ b/src/validation.h @@ -929,7 +929,6 @@ enum class SnapshotCompletionResult { class ChainstateManager { private: - CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr}; /** The last header for which a headerTip notification was issued. */ CBlockIndex* m_last_notified_header GUARDED_BY(GetMutex()){nullptr}; @@ -983,6 +982,9 @@ private: SteadyClock::duration GUARDED_BY(::cs_main) time_chainstate{}; SteadyClock::duration GUARDED_BY(::cs_main) time_post_connect{}; +protected: + CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr}; + public: using Options = kernel::ChainstateManagerOpts;