Sorry, I don't understand.
The fuzzing setup here is a single global, so it is one datadir per process that does not change. Assuming 60 processes or so, 32 bits of randomness should be sufficient. Though, feel free to change it to 256 bits of randomness.
Why are the requirements different? There are different *TestingSetups to accommodate for different needs, but they are mostly inheriting from each other. Why is this not possible for FuzzingSetup? I can replace it with a plain RegTestingSetup and everything works just fine. Please explain the issues you are running into.
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index 3048b09564..ffb7a78b5b 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -28,6 +28,7 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/util/setup_common.h>
+#include <test/util/mining.h>
#include <txdb.h>
#include <txmempool.h>
#include <util/memory.h>
@@ -58,23 +59,6 @@ bool ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vR
namespace {
-size_t GetNumberOfScheduledTasks(const CScheduler& scheduler)
-{
- std::chrono::system_clock::time_point first, last;
- return scheduler.getQueueInfo(first, last);
-}
-
-void SleepUntilSchedulerCompletion(const CScheduler& scheduler, const size_t consider_completed_at_size = 0)
-{
- for (int i = 0; i < 10; ++i) {
- if (GetNumberOfScheduledTasks(scheduler) <= consider_completed_at_size) {
- return;
- }
- UninterruptibleSleep(std::chrono::milliseconds{10});
- }
- assert(false);
-}
-
#ifdef MESSAGE_TYPE
#define TO_STRING_(s) #s
#define TO_STRING(s) TO_STRING_(s)
@@ -83,94 +67,6 @@ const std::string LIMIT_TO_MESSAGE_TYPE{TO_STRING(MESSAGE_TYPE)};
const std::string LIMIT_TO_MESSAGE_TYPE;
#endif
-void CreateAndProcessNextBlock(const CTxMemPool& mempool)
-{
- std::unique_ptr<CBlockTemplate> block_template = BlockAssembler(mempool, Params()).CreateNewBlock(CScript() << OP_TRUE);
- CBlock& block = block_template->block;
- {
- LOCK(cs_main);
- unsigned int extra_nonce;
- IncrementExtraNonce(&block, ChainActive().Tip(), extra_nonce);
- }
- while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) {
- ++block.nNonce;
- }
- ProcessNewBlock(Params(), std::make_shared<const CBlock>(block), true, nullptr);
-}
-
-template <typename T>
-std::string ToString(const T t)
-{
- std::ostringstream oss;
- oss.imbue(std::locale::classic());
- oss << t;
- return oss.str();
-}
-
-class FuzzingSetup
-{
- boost::thread_group m_thread_group;
- const fs::path m_path;
- std::unique_ptr<PeerLogicValidation> m_peer_logic_validation;
-
-public:
- CScheduler m_scheduler;
- NodeContext m_node_context;
- std::unique_ptr<CNode> m_dummy_p2p_node;
-
- FuzzingSetup(const std::string& fuzzer_name) : m_path{fs::temp_directory_path() / "fuzzers" / fuzzer_name / ToString(FastRandomContext().rand64())}
- {
- SelectParams(CBaseChainParams::REGTEST);
- fs::remove_all(m_path);
- fs::create_directories(m_path);
- ::gArgs.ForceSetArg("-datadir", m_path.string());
- InitLogging();
- LogInstance().m_print_to_console = false;
- LogInstance().StartLogging();
- ::g_chainstate = MakeUnique<CChainState>();
- ::pblocktree = MakeUnique<CBlockTreeDB>(1 << 20, true);
- m_dummy_p2p_node = MakeUnique<CNode>(0, ServiceFlags(NODE_NETWORK | NODE_WITNESS | NODE_BLOOM), 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, false);
- m_dummy_p2p_node->fSuccessfullyConnected = true;
- m_dummy_p2p_node->nVersion = PROTOCOL_VERSION;
- m_dummy_p2p_node->SetSendVersion(PROTOCOL_VERSION);
- m_node_context.mempool = &::mempool;
- m_node_context.mempool->setSanityCheck(1.0);
- m_node_context.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
- m_node_context.connman = MakeUnique<CConnman>(0x1337, 0x1337);
- m_thread_group.create_thread(std::bind(&CScheduler::serviceQueue, &m_scheduler));
- GetMainSignals().RegisterBackgroundSignalScheduler(m_scheduler);
- ChainstateActive().InitCoinsDB(1 << 23, true, false);
- ChainstateActive().InitCoinsCache();
- if (!LoadGenesisBlock(Params())) {
- throw std::runtime_error("LoadGenesisBlock(...) failed.");
- }
- BlockValidationState block_validation_state;
- if (!ActivateBestChain(block_validation_state, Params())) {
- throw std::runtime_error("ActivateBestChain(...) failed.");
- }
- for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
- CreateAndProcessNextBlock(*m_node_context.mempool);
- SleepUntilSchedulerCompletion(m_scheduler);
- }
- assert(ChainActive().Tip() != nullptr);
- m_peer_logic_validation = MakeUnique<PeerLogicValidation>(m_node_context.connman.get(), nullptr, m_scheduler);
- m_peer_logic_validation->InitializeNode(m_dummy_p2p_node.get());
- assert(GetMainSignals().CallbacksPending() == 0);
- SleepUntilSchedulerCompletion(m_scheduler, 1);
- LogInstance().m_print_to_console = true;
- }
-
- ~FuzzingSetup()
- {
- LogInstance().DisconnectTestLogger();
- fs::remove_all(m_path);
- m_thread_group.interrupt_all();
- m_thread_group.join_all();
- GetMainSignals().FlushBackgroundCallbacks();
- GetMainSignals().UnregisterBackgroundSignalScheduler();
- }
-};
-
const std::map<std::string, std::set<std::string>> EXPECTED_DESERIALIZATION_EXCEPTIONS = {
{"CDataStream::read(): end of data: iostream error", {"addr", "block", "blocktxn", "cmpctblock", "feefilter", "filteradd", "filterload", "getblocks", "getblocktxn", "getdata", "getheaders", "headers", "inv", "notfound", "ping", "sendcmpct", "tx"}},
{"index overflowed 16 bits: iostream error", {"getblocktxn"}},
@@ -182,12 +78,20 @@ const std::map<std::string, std::set<std::string>> EXPECTED_DESERIALIZATION_EXCE
{"Unknown transaction optional data: iostream error", {"block", "blocktxn", "cmpctblock", "tx"}},
};
-std::unique_ptr<FuzzingSetup> g_fuzzing_setup;
+std::unique_ptr<RegTestingSetup> g_fuzzing_setup;
} // namespace
void initialize()
{
- g_fuzzing_setup = MakeUnique<FuzzingSetup>("process_message-" + (LIMIT_TO_MESSAGE_TYPE.empty() ? "all" : LIMIT_TO_MESSAGE_TYPE));
+ g_fuzzing_setup = MakeUnique<RegTestingSetup>();
+
+ for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
+ MineBlock(g_fuzzing_setup->m_node, CScript() << OP_TRUE);
+ }
+ SyncWithValidationInterfaceQueue();
+ assert(ChainActive().Tip() != nullptr);
+ assert(GetMainSignals().CallbacksPending() == 0);
+ LogInstance().m_print_to_console = true;
}
void test_one_input(const std::vector<uint8_t>& buffer)
@@ -206,9 +110,13 @@ void test_one_input(const std::vector<uint8_t>& buffer)
return;
}
CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes<unsigned char>(), SER_NETWORK, PROTOCOL_VERSION};
- CNode& p2p_node = *g_fuzzing_setup->m_dummy_p2p_node;
+ CNode p2p_node{0, ServiceFlags(NODE_NETWORK | NODE_WITNESS | NODE_BLOOM), 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, false};
+ p2p_node.fSuccessfullyConnected = true;
+ p2p_node.nVersion = PROTOCOL_VERSION;
+ p2p_node.SetSendVersion(PROTOCOL_VERSION);
+ g_fuzzing_setup->m_node.peer_logic->InitializeNode(&p2p_node);
try {
- (void)ProcessMessage(&p2p_node, random_message_type, random_bytes_data_stream, GetTimeMillis(), Params(), g_fuzzing_setup->m_node_context.connman.get(), g_fuzzing_setup->m_node_context.banman.get(), std::atomic<bool>{false});
+ (void)ProcessMessage(&p2p_node, random_message_type, random_bytes_data_stream, GetTimeMillis(), Params(), g_fuzzing_setup->m_node.connman.get(), g_fuzzing_setup->m_node.banman.get(), std::atomic<bool>{false});
} catch (const std::ios_base::failure& e) {
const std::string exception_message{e.what()};
const auto p = EXPECTED_DESERIALIZATION_EXCEPTIONS.find(exception_message);
@@ -219,18 +127,6 @@ void test_one_input(const std::vector<uint8_t>& buffer)
} catch (...) {
assert(false);
}
- p2p_node.fDisconnect = false;
- p2p_node.fPauseSend = false;
- p2p_node.nSendSize = 0;
- {
- LOCK(p2p_node.cs_inventory);
- p2p_node.vInventoryBlockToSend.clear();
- }
- p2p_node.vRecvGetData.clear();
- {
- LOCK(p2p_node.cs_vSend);
- p2p_node.vSendMsg.clear();
- }
assert(GetMainSignals().CallbacksPending() == 0);
- SleepUntilSchedulerCompletion(g_fuzzing_setup->m_scheduler, 1);
+ SyncWithValidationInterfaceQueue();
}
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 53eb9ff43b..7fdbbdfd1d 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -7,6 +7,7 @@
#include <banman.h>
#include <chainparams.h>
#include <consensus/consensus.h>
+#include <net_processing.h>
#include <consensus/params.h>
#include <consensus/validation.h>
#include <crypto/sha256.h>
@@ -62,7 +63,7 @@ std::ostream& operator<<(std::ostream& os, const uint256& num)
}
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
- : m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / std::to_string(g_insecure_rand_ctx_temp_path.rand32())}
+ : m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / g_insecure_rand_ctx_temp_path.rand256().ToString()}
{
fs::create_directories(m_path_root);
gArgs.ForceSetArg("-datadir", m_path_root.string());
@@ -136,6 +137,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
m_node.mempool->setSanityCheck(1.0);
m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
+ m_node.peer_logic = MakeUnique<PeerLogicValidation>(m_node.connman.get(), m_node.banman.get(), *m_node.scheduler);
}
TestingSetup::~TestingSetup()