mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-07 14:18:18 +02:00
faea12ecd9test: Fixup docs for NodeClockContext and SteadyClockContext (MarcoFalke)eeeeb2a0b9fuzz: Use NodeClockContext (MarcoFalke)fa4fae6227test: Add NodeClockContext (MarcoFalke) Pull request description: Iterating over fuzz inputs will usually be done in the same process. As the mocktime is global, it can theoretically leak from one fuzz input run into the next run, making it less deterministic. Fix this issue, by adding and using a context manager to handle the mocktime and reset it before the end. This refactor should not change any behavior. ACKs for top commit: seduless: re-ACKfaea12ecd9dergoegge: utACKfaea12ecd9brunoerg: code review ACKfaea12ecd9Tree-SHA512: e222c4e4217a504d058b30f1e975dfdfff019363c82385bd62f368b16fb029c46a5d1b43cd773dbdd9efcd7f968d46dbe2c75812971696b1b879b8f081fc6b1b
137 lines
4.8 KiB
C++
137 lines
4.8 KiB
C++
// Copyright (c) 2020-present The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <banman.h>
|
|
#include <consensus/consensus.h>
|
|
#include <net.h>
|
|
#include <net_processing.h>
|
|
#include <node/warnings.h>
|
|
#include <primitives/transaction.h>
|
|
#include <protocol.h>
|
|
#include <script/script.h>
|
|
#include <sync.h>
|
|
#include <test/fuzz/FuzzedDataProvider.h>
|
|
#include <test/fuzz/fuzz.h>
|
|
#include <test/fuzz/util.h>
|
|
#include <test/fuzz/util/net.h>
|
|
#include <test/util/mining.h>
|
|
#include <test/util/net.h>
|
|
#include <test/util/setup_common.h>
|
|
#include <test/util/time.h>
|
|
#include <test/util/validation.h>
|
|
#include <util/check.h>
|
|
#include <util/time.h>
|
|
#include <validationinterface.h>
|
|
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
TestingSetup* g_setup;
|
|
std::string_view LIMIT_TO_MESSAGE_TYPE{};
|
|
|
|
void ResetChainman(TestingSetup& setup)
|
|
{
|
|
SetMockTime(setup.m_node.chainman->GetParams().GenesisBlock().Time());
|
|
setup.m_node.chainman.reset();
|
|
setup.m_make_chainman();
|
|
setup.LoadVerifyActivateChainstate();
|
|
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
|
|
node::BlockAssembler::Options options;
|
|
options.include_dummy_extranonce = true;
|
|
MineBlock(setup.m_node, options);
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
void initialize_process_message()
|
|
{
|
|
if (const auto val{std::getenv("LIMIT_TO_MESSAGE_TYPE")}) {
|
|
LIMIT_TO_MESSAGE_TYPE = val;
|
|
Assert(std::count(ALL_NET_MESSAGE_TYPES.begin(), ALL_NET_MESSAGE_TYPES.end(), LIMIT_TO_MESSAGE_TYPE)); // Unknown message type passed
|
|
}
|
|
|
|
static const auto testing_setup{
|
|
MakeNoLogFileContext<TestingSetup>(
|
|
/*chain_type=*/ChainType::REGTEST,
|
|
{}),
|
|
};
|
|
g_setup = testing_setup.get();
|
|
ResetChainman(*g_setup);
|
|
}
|
|
|
|
FUZZ_TARGET(process_message, .init = initialize_process_message)
|
|
{
|
|
SeedRandomStateForTest(SeedRand::ZEROS);
|
|
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
|
|
|
auto& node{g_setup->m_node};
|
|
auto& connman{static_cast<ConnmanTestMsg&>(*node.connman)};
|
|
connman.Reset();
|
|
auto& chainman{static_cast<TestChainstateManager&>(*node.chainman)};
|
|
const auto block_index_size{WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())};
|
|
NodeClockContext clock_ctx{1610000000s}; // any time to successfully reset ibd
|
|
chainman.ResetIbd();
|
|
chainman.DisableNextWrite();
|
|
|
|
// Reset, so that dangling pointers can be detected by sanitizers.
|
|
node.banman.reset();
|
|
node.addrman.reset();
|
|
node.peerman.reset();
|
|
node.addrman = std::make_unique<AddrMan>(*node.netgroupman, /*deterministic=*/true, /*consistency_check_ratio=*/0);
|
|
node.peerman = PeerManager::make(connman, *node.addrman,
|
|
/*banman=*/nullptr, chainman,
|
|
*node.mempool, *node.warnings,
|
|
PeerManager::Options{
|
|
.reconcile_txs = true,
|
|
.deterministic_rng = true,
|
|
});
|
|
|
|
connman.SetMsgProc(node.peerman.get());
|
|
connman.SetAddrman(*node.addrman);
|
|
LOCK(NetEventsInterface::g_msgproc_mutex);
|
|
|
|
const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::MESSAGE_TYPE_SIZE).c_str()};
|
|
if (!LIMIT_TO_MESSAGE_TYPE.empty() && random_message_type != LIMIT_TO_MESSAGE_TYPE) {
|
|
return;
|
|
}
|
|
|
|
node.validation_signals->RegisterValidationInterface(node.peerman.get());
|
|
|
|
CNode& p2p_node = *ConsumeNodeAsUniquePtr(fuzzed_data_provider).release();
|
|
|
|
connman.AddTestNode(p2p_node);
|
|
FillNode(fuzzed_data_provider, connman, p2p_node);
|
|
|
|
clock_ctx.set(ConsumeTime(fuzzed_data_provider));
|
|
|
|
CSerializedNetMsg net_msg;
|
|
net_msg.m_type = random_message_type;
|
|
net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider, MAX_PROTOCOL_MESSAGE_LENGTH);
|
|
|
|
connman.FlushSendBuffer(p2p_node);
|
|
(void)connman.ReceiveMsgFrom(p2p_node, std::move(net_msg));
|
|
|
|
bool more_work{true};
|
|
while (more_work) {
|
|
p2p_node.fPauseSend = false;
|
|
try {
|
|
more_work = connman.ProcessMessagesOnce(p2p_node);
|
|
} catch (const std::ios_base::failure&) {
|
|
}
|
|
node.peerman->SendMessages(p2p_node);
|
|
}
|
|
node.validation_signals->SyncWithValidationInterfaceQueue();
|
|
node.validation_signals->UnregisterValidationInterface(node.peerman.get());
|
|
node.connman->StopNodes();
|
|
if (block_index_size != WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())) {
|
|
// Reuse the global chainman, but reset it when it is dirty
|
|
ResetChainman(*g_setup);
|
|
}
|
|
}
|