mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-25 14:28:53 +02:00
Merge bitcoin/bitcoin#31533: fuzz: Add fuzz target for block index tree and related validation events
db2d39f642fuzz: add subtest for re-downloading a previously pruned block (Eugene Siegel)45f5b2dac3fuzz: Add fuzzer for block index (Martin Zumsande)c011e3aa54test: Wrap validation functions with TestChainstateManager (Martin Zumsande) Pull request description: This adds a fuzz target for the block index and various events in validation that interact with it. It can create arbitrary tree-like structure of block indexes, simulating (so far) the following events: - Adding a header - Receiving the full block (may be valid or not) - `ActivateBestChain()` - Reorging the chain to a new chain tip (possibly encountering invalid blocks on the way) - Pruning a block in the best chain - Receiving a previously pruned block again (`getblockfrompeer`) It might be interesting / possible to extend this to more events, such as dealing with more than one chainstate (assumeutxo). The test skips all actual validation of header/ block / transaction data by just simulating the outcome, and also doesn't interact with the data directory. The main goal is to ensure the integrity of the block index tree in all fuzzed constellations, by calling `CheckBlockIndex()` at the end of each iteration. Compared to #29158 this approach has a more limited scope (by skipping all actual validation), but it is fast - it doesn't do a full init sequence on each iteration, but "cleans up" after itself by resetting the global validation state after each iteration. ACKs for top commit: Crypt-iQ: reACKdb2d39f642maflcko: review ACKdb2d39f642🍶 sedited: Re-ACKdb2d39f642Tree-SHA512: 76cd5f8f4d7d7258620b46d7438bad4508c3bdc98825b48b60f694b5a9838e2b2cf4967c0ead181f86f66f4939ddfe552471851b9d18f84f584c03dd7e09fc43
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <test/util/validation.h>
|
||||
|
||||
#include <node/blockstorage.h>
|
||||
#include <util/check.h>
|
||||
#include <util/time.h>
|
||||
#include <validation.h>
|
||||
@@ -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<TestChainstate*>(&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<TestChainstate*>(&ActiveChainstate())->CallInvalidChainFound(pindexNew);
|
||||
}
|
||||
|
||||
CBlockIndex* TestChainstateManager::FindMostWorkChain()
|
||||
{
|
||||
struct TestChainstate : public Chainstate {
|
||||
CBlockIndex* CallFindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
return FindMostWorkChain();
|
||||
}
|
||||
};
|
||||
|
||||
return static_cast<TestChainstate*>(&ActiveChainstate())->CallFindMostWorkChain();
|
||||
}
|
||||
|
||||
void TestChainstateManager::ResetBestInvalid()
|
||||
{
|
||||
m_best_invalid = nullptr;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,16 @@
|
||||
|
||||
#include <validation.h>
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user