Bitcoin Core 30.99.0
P2P Digital Currency
net.h
Go to the documentation of this file.
1// Copyright (c) 2009-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#ifndef BITCOIN_TEST_FUZZ_UTIL_NET_H
6#define BITCOIN_TEST_FUZZ_UTIL_NET_H
7
8#include <addrman.h>
9#include <addrman_impl.h>
10#include <net.h>
11#include <net_permissions.h>
12#include <netaddress.h>
14#include <node/eviction.h>
15#include <protocol.h>
17#include <test/fuzz/util.h>
18#include <test/util/net.h>
19#include <threadsafety.h>
20#include <util/asmap.h>
21#include <util/sock.h>
22
23#include <chrono>
24#include <cstddef>
25#include <cstdint>
26#include <limits>
27#include <memory>
28#include <optional>
29#include <string>
30
40
42{
43public:
44 explicit AddrManDeterministic(const NetGroupManager& netgroupman, FuzzedDataProvider& fuzzed_data_provider, int32_t check_ratio)
45 : AddrMan(netgroupman, /*deterministic=*/true, check_ratio)
46 {
47 WITH_LOCK(m_impl->cs, m_impl->insecure_rand.Reseed(ConsumeUInt256(fuzzed_data_provider)));
48 }
49
57 bool operator==(const AddrManDeterministic& other) const
58 {
59 LOCK2(m_impl->cs, other.m_impl->cs);
60
61 if (m_impl->mapInfo.size() != other.m_impl->mapInfo.size() || m_impl->nNew != other.m_impl->nNew ||
62 m_impl->nTried != other.m_impl->nTried) {
63 return false;
64 }
65
66 // Check that all values in `mapInfo` are equal to all values in `other.mapInfo`.
67 // Keys may be different.
68
69 auto addrinfo_hasher = [](const AddrInfo& a) {
70 CSipHasher hasher(0, 0);
71 auto addr_key = a.GetKey();
72 auto source_key = a.source.GetAddrBytes();
73 hasher.Write(TicksSinceEpoch<std::chrono::seconds>(a.m_last_success));
74 hasher.Write(a.nAttempts);
75 hasher.Write(a.nRefCount);
76 hasher.Write(a.fInTried);
77 hasher.Write(a.GetNetwork());
78 hasher.Write(a.source.GetNetwork());
79 hasher.Write(addr_key.size());
80 hasher.Write(source_key.size());
81 hasher.Write(addr_key);
82 hasher.Write(source_key);
83 return (size_t)hasher.Finalize();
84 };
85
86 auto addrinfo_eq = [](const AddrInfo& lhs, const AddrInfo& rhs) {
87 return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.m_last_success, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
88 std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.m_last_success, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
89 };
90
91 using Addresses = std::unordered_set<AddrInfo, decltype(addrinfo_hasher), decltype(addrinfo_eq)>;
92
93 const size_t num_addresses{m_impl->mapInfo.size()};
94
95 Addresses addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
96 for (const auto& [id, addr] : m_impl->mapInfo) {
97 addresses.insert(addr);
98 }
99
100 Addresses other_addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
101 for (const auto& [id, addr] : other.m_impl->mapInfo) {
102 other_addresses.insert(addr);
103 }
104
105 if (addresses != other_addresses) {
106 return false;
107 }
108
109 auto IdsReferToSameAddress = [&](nid_type id, nid_type other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
110 if (id == -1 && other_id == -1) {
111 return true;
112 }
113 if ((id == -1 && other_id != -1) || (id != -1 && other_id == -1)) {
114 return false;
115 }
116 return m_impl->mapInfo.at(id) == other.m_impl->mapInfo.at(other_id);
117 };
118
119 // Check that `vvNew` contains the same addresses as `other.vvNew`. Notice - `vvNew[i][j]`
120 // contains just an id and the address is to be found in `mapInfo.at(id)`. The ids
121 // themselves may differ between `vvNew` and `other.vvNew`.
122 for (size_t i = 0; i < ADDRMAN_NEW_BUCKET_COUNT; ++i) {
123 for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
124 if (!IdsReferToSameAddress(m_impl->vvNew[i][j], other.m_impl->vvNew[i][j])) {
125 return false;
126 }
127 }
128 }
129
130 // Same for `vvTried`.
131 for (size_t i = 0; i < ADDRMAN_TRIED_BUCKET_COUNT; ++i) {
132 for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
133 if (!IdsReferToSameAddress(m_impl->vvTried[i][j], other.m_impl->vvTried[i][j])) {
134 return false;
135 }
136 }
137 }
138
139 return true;
140 }
141};
142
144{
145public:
147
148 virtual void InitializeNode(const CNode&, ServiceFlags) override {}
149
150 virtual void FinalizeNode(const CNode&) override {}
151
152 virtual bool HasAllDesirableServiceFlags(ServiceFlags) const override { return m_fdp.ConsumeBool(); }
153
154 virtual bool ProcessMessages(CNode&, std::atomic<bool>&) override { return m_fdp.ConsumeBool(); }
155
156 virtual bool SendMessages(CNode&) override { return m_fdp.ConsumeBool(); }
157
158private:
160};
161
162class FuzzedSock : public Sock
163{
165
171 mutable std::vector<uint8_t> m_peek_data;
172
178 const bool m_selectable;
179
183 mutable std::chrono::milliseconds m_time;
184
188 void ElapseTime(std::chrono::milliseconds duration) const;
189
190public:
192
193 ~FuzzedSock() override;
194
195 FuzzedSock& operator=(Sock&& other) override;
196
197 ssize_t Send(const void* data, size_t len, int flags) const override;
198
199 ssize_t Recv(void* buf, size_t len, int flags) const override;
200
201 int Connect(const sockaddr*, socklen_t) const override;
202
203 int Bind(const sockaddr*, socklen_t) const override;
204
205 int Listen(int backlog) const override;
206
207 std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
208
209 int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override;
210
211 int SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt_len) const override;
212
213 int GetSockName(sockaddr* name, socklen_t* name_len) const override;
214
215 bool SetNonBlocking() const override;
216
217 bool IsSelectable() const override;
218
219 bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override;
220
221 bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override;
222
223 bool IsConnected(std::string& errmsg) const override;
224};
225
226[[nodiscard]] inline FuzzedNetEvents ConsumeNetEvents(FuzzedDataProvider& fdp) noexcept
227{
228 return FuzzedNetEvents{fdp};
229}
230
232{
234}
235
237{
238 std::vector<std::byte> asmap{ConsumeRandomLengthByteVector<std::byte>(fuzzed_data_provider)};
239 if (!CheckStandardAsmap(asmap)) {
241 }
242 return NetGroupManager::WithLoadedAsmap(std::move(asmap));
243}
244
246{
248}
249
251{
253}
254
256 size_t max_vector_size = 5) noexcept
257{
258 std::vector<CService> ret;
259 const size_t size = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
260 ret.reserve(size);
261 for (size_t i = 0; i < size; ++i) {
263 }
264 return ret;
265}
266
268
269template <bool ReturnUniquePtr = false>
270auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<NodeId>& node_id_in = std::nullopt) noexcept
271{
272 const NodeId node_id = node_id_in.value_or(fuzzed_data_provider.ConsumeIntegralInRange<NodeId>(0, std::numeric_limits<NodeId>::max()));
273 const auto sock = std::make_shared<FuzzedSock>(fuzzed_data_provider);
275 const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
276 const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
278 const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64);
280 const bool inbound_onion{conn_type == ConnectionType::INBOUND ? fuzzed_data_provider.ConsumeBool() : false};
281 const uint64_t network_id = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
282
284 if constexpr (ReturnUniquePtr) {
285 return std::make_unique<CNode>(node_id,
286 sock,
287 address,
288 keyed_net_group,
289 local_host_nonce,
290 addr_bind,
291 addr_name,
292 conn_type,
293 inbound_onion,
294 network_id,
295 CNodeOptions{ .permission_flags = permission_flags });
296 } else {
297 return CNode{node_id,
298 sock,
299 address,
300 keyed_net_group,
301 local_host_nonce,
302 addr_bind,
303 addr_name,
304 conn_type,
305 inbound_onion,
306 network_id,
307 CNodeOptions{ .permission_flags = permission_flags }};
308 }
309}
310inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, const std::optional<NodeId>& node_id_in = std::nullopt) { return ConsumeNode<true>(fdp, node_id_in); }
311
313
314#endif // BITCOIN_TEST_FUZZ_UTIL_NET_H
static constexpr int ADDRMAN_TRIED_BUCKET_COUNT
Definition: addrman_impl.h:27
static constexpr int ADDRMAN_BUCKET_SIZE
Definition: addrman_impl.h:33
int64_t nid_type
User-defined type for the internally used nIds This used to be int, making it feasible for attackers ...
Definition: addrman_impl.h:40
static constexpr int ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman_impl.h:30
int ret
int flags
Definition: bitcoin-tx.cpp:529
Extended statistics about a CAddress.
Definition: addrman_impl.h:46
CNetAddr source
where knowledge about this address first came from
Definition: addrman_impl.h:55
bool fInTried
in tried set? (memory only)
Definition: addrman_impl.h:67
NodeSeconds m_last_success
last successful connection by us
Definition: addrman_impl.h:58
int nRefCount
reference count in new sets (memory only)
Definition: addrman_impl.h:64
int nAttempts
connection attempts since last successful attempt
Definition: addrman_impl.h:61
AddrManDeterministic(const NetGroupManager &netgroupman, FuzzedDataProvider &fuzzed_data_provider, int32_t check_ratio)
Definition: net.h:44
bool operator==(const AddrManDeterministic &other) const
Compare with another AddrMan.
Definition: net.h:57
Stochastic address manager.
Definition: addrman.h:89
const std::unique_ptr< AddrManImpl > m_impl
Definition: addrman.h:91
A CService with information about it as peer.
Definition: protocol.h:367
Network address.
Definition: netaddress.h:113
Information about a peer.
Definition: net.h:680
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:530
General SipHash-2-4 implementation.
Definition: siphash.h:27
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Definition: siphash.cpp:73
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
Definition: siphash.cpp:24
Fast randomness source.
Definition: random.h:386
std::string ConsumeRandomLengthString(size_t max_length)
T ConsumeIntegralInRange(T min, T max)
T PickValueInArray(const T(&array)[size])
virtual bool ProcessMessages(CNode &, std::atomic< bool > &) override
Process protocol messages received from a given node.
Definition: net.h:154
virtual void InitializeNode(const CNode &, ServiceFlags) override
Initialize a peer (setup state)
Definition: net.h:148
virtual bool SendMessages(CNode &) override
Send queued protocol messages to a given node.
Definition: net.h:156
FuzzedDataProvider & m_fdp
Definition: net.h:159
FuzzedNetEvents(FuzzedDataProvider &fdp)
Definition: net.h:146
virtual bool HasAllDesirableServiceFlags(ServiceFlags) const override
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
Definition: net.h:152
virtual void FinalizeNode(const CNode &) override
Handle removal of a peer (clear state)
Definition: net.h:150
std::unique_ptr< Sock > Accept(sockaddr *addr, socklen_t *addr_len) const override
accept(2) wrapper.
Definition: net.cpp:305
int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const override
getsockopt(2) wrapper.
Definition: net.cpp:346
bool Wait(std::chrono::milliseconds timeout, Event requested, Event *occurred=nullptr) const override
Wait for readiness for input (recv) or output (send).
Definition: net.cpp:414
int Listen(int backlog) const override
listen(2) wrapper.
Definition: net.cpp:286
const bool m_selectable
Whether to pretend that the socket is select(2)-able.
Definition: net.h:178
bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock &events_per_sock) const override
Same as Wait(), but wait on many sockets within the same timeout.
Definition: net.cpp:435
void ElapseTime(std::chrono::milliseconds duration) const
Set the value of the mocked steady clock such as that many ms have passed.
Definition: net.cpp:132
bool IsConnected(std::string &errmsg) const override
Check if still connected.
Definition: net.cpp:448
int Connect(const sockaddr *, socklen_t) const override
connect(2) wrapper.
Definition: net.cpp:244
ssize_t Send(const void *data, size_t len, int flags) const override
send(2) wrapper.
Definition: net.cpp:144
std::vector< uint8_t > m_peek_data
Data to return when MSG_PEEK is used as a Recv() flag.
Definition: net.h:171
FuzzedSock & operator=(Sock &&other) override
Move assignment operator, grab the socket from another object and close ours (if set).
Definition: net.cpp:138
FuzzedDataProvider & m_fuzzed_data_provider
Definition: net.h:164
bool IsSelectable() const override
Check if the underlying socket can be used for select(2) (or the Wait() method).
Definition: net.cpp:409
bool SetNonBlocking() const override
Set the non-blocking option on the socket.
Definition: net.cpp:396
int SetSockOpt(int level, int opt_name, const void *opt_val, socklen_t opt_len) const override
setsockopt(2) wrapper.
Definition: net.cpp:365
ssize_t Recv(void *buf, size_t len, int flags) const override
recv(2) wrapper.
Definition: net.cpp:176
~FuzzedSock() override
Definition: net.cpp:123
int GetSockName(sockaddr *name, socklen_t *name_len) const override
getsockname(2) wrapper.
Definition: net.cpp:378
std::chrono::milliseconds m_time
Used to mock the steady clock in methods waiting for a given duration.
Definition: net.h:183
FuzzedSock(FuzzedDataProvider &fuzzed_data_provider)
Definition: net.cpp:114
int Bind(const sockaddr *, socklen_t) const override
bind(2) wrapper.
Definition: net.cpp:266
Interface for message handling.
Definition: net.h:1028
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
Definition: net.h:1031
Netgroup manager.
Definition: netgroup.h:17
static NetGroupManager NoAsmap()
Definition: netgroup.h:32
static NetGroupManager WithLoadedAsmap(std::vector< std::byte > &&asmap)
Definition: netgroup.h:28
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
Definition: sock.h:27
uint8_t Event
Definition: sock.h:138
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
Definition: sock.h:208
ConnectionType
Different types of connections to a peer.
@ INBOUND
Inbound connections are those initiated by a peer.
Definition: messages.h:21
int64_t NodeId
Definition: net.h:103
NetPermissionFlags
ServiceFlags
nServices flags
Definition: protocol.h:309
const char * name
Definition: rest.cpp:48
NetPermissionFlags permission_flags
Definition: net.h:671
#define LOCK2(cs1, cs2)
Definition: sync.h:260
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:290
void FillNode(FuzzedDataProvider &fuzzed_data_provider, ConnmanTestMsg &connman, CNode &node) noexcept
Definition: net.cpp:457
CService ConsumeService(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:250
CSubNet ConsumeSubNet(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:245
NetGroupManager ConsumeNetGroupManager(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:236
std::unique_ptr< CNode > ConsumeNodeAsUniquePtr(FuzzedDataProvider &fdp, const std::optional< NodeId > &node_id_in=std::nullopt)
Definition: net.h:310
CNetAddr ConsumeNetAddr(FuzzedDataProvider &fuzzed_data_provider, FastRandomContext *rand=nullptr) noexcept
Create a CNetAddr.
Definition: net.cpp:29
std::vector< CService > ConsumeServiceVector(FuzzedDataProvider &fuzzed_data_provider, size_t max_vector_size=5) noexcept
Definition: net.h:255
auto ConsumeNode(FuzzedDataProvider &fuzzed_data_provider, const std::optional< NodeId > &node_id_in=std::nullopt) noexcept
Definition: net.h:270
CAddress ConsumeAddress(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.cpp:88
FuzzedNetEvents ConsumeNetEvents(FuzzedDataProvider &fdp) noexcept
Definition: net.h:226
FuzzedSock ConsumeSock(FuzzedDataProvider &fuzzed_data_provider)
Definition: net.h:231
WeakEnumType ConsumeWeakEnum(FuzzedDataProvider &fuzzed_data_provider, const WeakEnumType(&all_types)[size]) noexcept
Definition: util.h:128
uint256 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: util.h:167
constexpr ConnectionType ALL_CONNECTION_TYPES[]
Definition: net.h:141
constexpr NetPermissionFlags ALL_NET_PERMISSION_FLAGS[]
Definition: net.h:128
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
bool CheckStandardAsmap(const std::span< const std::byte > data)
Provides a safe interface for validating ASMap data before use.
Definition: asmap.cpp:310
FuzzedDataProvider & fuzzed_data_provider
Definition: fees.cpp:38