/root/bitcoin/src/test/fuzz/process_messages.cpp
Line | Count | Source |
1 | | // Copyright (c) 2020-present The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | | |
5 | | #include <addrman.h> |
6 | | #include <banman.h> |
7 | | #include <consensus/consensus.h> |
8 | | #include <kernel/chainparams.h> |
9 | | #include <net.h> |
10 | | #include <net_processing.h> |
11 | | #include <node/mining_types.h> |
12 | | #include <primitives/block.h> |
13 | | #include <primitives/transaction.h> |
14 | | #include <protocol.h> |
15 | | #include <sync.h> |
16 | | #include <test/fuzz/FuzzedDataProvider.h> |
17 | | #include <test/fuzz/fuzz.h> |
18 | | #include <test/fuzz/util.h> |
19 | | #include <test/fuzz/util/net.h> |
20 | | #include <test/util/mining.h> |
21 | | #include <test/util/net.h> |
22 | | #include <test/util/random.h> |
23 | | #include <test/util/setup_common.h> |
24 | | #include <test/util/time.h> |
25 | | #include <test/util/validation.h> |
26 | | #include <util/time.h> |
27 | | #include <validation.h> |
28 | | #include <validationinterface.h> |
29 | | |
30 | | #include <functional> |
31 | | #include <ios> |
32 | | #include <memory> |
33 | | #include <optional> |
34 | | #include <string> |
35 | | #include <utility> |
36 | | #include <vector> |
37 | | |
38 | | namespace { |
39 | | TestingSetup* g_setup; |
40 | | |
41 | | void ResetChainman(TestingSetup& setup) |
42 | 0 | { |
43 | 0 | SetMockTime(setup.m_node.chainman->GetParams().GenesisBlock().Time()); |
44 | 0 | setup.m_node.chainman.reset(); |
45 | 0 | setup.m_make_chainman(); |
46 | 0 | setup.LoadVerifyActivateChainstate(); |
47 | 0 | node::BlockCreateOptions options; |
48 | 0 | for (int i = 0; i < 2 * COINBASE_MATURITY; i++) { Branch (48:21): [True: 0, False: 0]
|
49 | 0 | MineBlock(setup.m_node, options); |
50 | 0 | } |
51 | 0 | } |
52 | | } // namespace |
53 | | |
54 | | void initialize_process_messages() |
55 | 0 | { |
56 | 0 | static const auto testing_setup{ |
57 | 0 | MakeNoLogFileContext<TestingSetup>( |
58 | 0 | /*chain_type=*/ChainType::REGTEST, |
59 | 0 | {}), |
60 | 0 | }; |
61 | 0 | g_setup = testing_setup.get(); |
62 | 0 | ResetChainman(*g_setup); |
63 | 0 | } |
64 | | |
65 | | FUZZ_TARGET(process_messages, .init = initialize_process_messages) |
66 | 0 | { |
67 | 0 | SeedRandomStateForTest(SeedRand::ZEROS); |
68 | 0 | FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); |
69 | |
|
70 | 0 | auto& node{g_setup->m_node}; |
71 | 0 | auto& connman{static_cast<ConnmanTestMsg&>(*node.connman)}; |
72 | 0 | connman.Reset(); |
73 | 0 | auto& chainman{static_cast<TestChainstateManager&>(*node.chainman)}; |
74 | 0 | const auto block_index_size{WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())}; |
75 | 0 | FakeNodeClock clock{1610000000s}; // any time to successfully reset ibd |
76 | 0 | FakeSteadyClock steady_clock; |
77 | 0 | chainman.ResetIbd(); |
78 | 0 | chainman.DisableNextWrite(); |
79 | | |
80 | | // Reset, so that dangling pointers can be detected by sanitizers. |
81 | 0 | node.banman.reset(); |
82 | 0 | node.addrman.reset(); |
83 | 0 | node.peerman.reset(); |
84 | 0 | node.addrman = std::make_unique<AddrMan>(*node.netgroupman, /*deterministic=*/true, /*consistency_check_ratio=*/0); |
85 | 0 | node.peerman = PeerManager::make(connman, *node.addrman, |
86 | 0 | /*banman=*/nullptr, chainman, |
87 | 0 | *node.mempool, *node.warnings, |
88 | 0 | PeerManager::Options{ |
89 | 0 | .reconcile_txs = true, |
90 | 0 | .deterministic_rng = true, |
91 | 0 | }); |
92 | 0 | connman.SetMsgProc(node.peerman.get()); |
93 | 0 | connman.SetAddrman(*node.addrman); |
94 | |
|
95 | 0 | node.validation_signals->RegisterValidationInterface(node.peerman.get()); |
96 | |
|
97 | 0 | LOCK(NetEventsInterface::g_msgproc_mutex); |
98 | |
|
99 | 0 | std::vector<CNode*> peers; |
100 | 0 | const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3); |
101 | 0 | for (int i = 0; i < num_peers_to_add; ++i) { Branch (101:21): [True: 0, False: 0]
|
102 | 0 | peers.push_back(ConsumeNodeAsUniquePtr(fuzzed_data_provider, steady_clock, i).release()); |
103 | 0 | CNode& p2p_node = *peers.back(); |
104 | |
|
105 | 0 | FillNode(fuzzed_data_provider, connman, p2p_node); |
106 | |
|
107 | 0 | connman.AddTestNode(p2p_node); |
108 | 0 | } |
109 | |
|
110 | 0 | LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 30) |
111 | 0 | { |
112 | 0 | const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::MESSAGE_TYPE_SIZE).c_str()}; |
113 | |
|
114 | 0 | clock.set(ConsumeTime(fuzzed_data_provider)); |
115 | |
|
116 | 0 | CSerializedNetMsg net_msg; |
117 | 0 | net_msg.m_type = random_message_type; |
118 | 0 | net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider, MAX_PROTOCOL_MESSAGE_LENGTH); |
119 | |
|
120 | 0 | CNode& random_node = *PickValue(fuzzed_data_provider, peers); |
121 | |
|
122 | 0 | connman.FlushSendBuffer(random_node); |
123 | 0 | (void)connman.ReceiveMsgFrom(random_node, std::move(net_msg)); |
124 | |
|
125 | 0 | bool more_work{true}; |
126 | 0 | while (more_work) { // Ensure that every message is eventually processed in some way or another Branch (126:16): [True: 0, False: 0]
|
127 | 0 | random_node.fPauseSend = false; |
128 | |
|
129 | 0 | try { |
130 | 0 | more_work = connman.ProcessMessagesOnce(random_node); |
131 | 0 | } catch (const std::ios_base::failure&) { |
132 | 0 | } |
133 | 0 | node.peerman->SendMessages(random_node); |
134 | 0 | } |
135 | 0 | } |
136 | 0 | node.validation_signals->SyncWithValidationInterfaceQueue(); |
137 | 0 | node.validation_signals->UnregisterValidationInterface(node.peerman.get()); |
138 | 0 | node.connman->StopNodes(); |
139 | 0 | if (block_index_size != WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())) { Branch (139:9): [True: 0, False: 0]
|
140 | | // Reuse the global chainman, but reset it when it is dirty |
141 | 0 | ResetChainman(*g_setup); |
142 | 0 | } |
143 | 0 | } |