Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2020-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <addrman.h>6#include <chainparams.h>7#include <common/args.h>8#include <net.h>9#include <net_processing.h>10#include <netaddress.h>11#include <protocol.h>12#include <test/fuzz/FuzzedDataProvider.h>13#include <test/fuzz/fuzz.h>14#include <test/fuzz/util.h>15#include <test/fuzz/util/net.h>16#include <test/fuzz/util/threadinterrupt.h>17#include <test/util/setup_common.h>18#include <test/util/time.h>19#include <util/translation.h>21#include <cstdint>22#include <vector>24namespace {25const TestingSetup* g_setup;27int32_t GetCheckRatio()28{29return std::clamp<int32_t>(g_setup->m_node.args->GetIntArg("-checkaddrman", 0), 0, 1000000);30}32} // namespace34void initialize_connman()35{36static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();37g_setup = testing_setup.get();38}40FUZZ_TARGET(connman, .init = initialize_connman)41{42SeedRandomStateForTest(SeedRand::ZEROS);43FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};44FakeNodeClock clock{ConsumeTime(fuzzed_data_provider)};45FakeSteadyClock steady_clock;46auto netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};47auto addr_man_ptr{std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio())};48if (fuzzed_data_provider.ConsumeBool()) {49const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};50DataStream ds{serialized_data};51try {52ds >> *addr_man_ptr;53} catch (const std::ios_base::failure&) {54addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio());55}56}57AddrManDeterministic& addr_man{*addr_man_ptr};58auto net_events{ConsumeNetEvents(fuzzed_data_provider)};60// Mock CreateSock() to create FuzzedSock.61auto CreateSockOrig = CreateSock;62CreateSock = [&fuzzed_data_provider, &steady_clock](int, int, int) {63return std::make_unique<FuzzedSock>(fuzzed_data_provider, steady_clock);64};66// Mock g_dns_lookup() to return a fuzzed address.67auto g_dns_lookup_orig = g_dns_lookup;68g_dns_lookup = [&fuzzed_data_provider](const std::string&, bool) {69return std::vector<CNetAddr>{ConsumeNetAddr(fuzzed_data_provider)};70};72ConnmanTestMsg connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(),73fuzzed_data_provider.ConsumeIntegral<uint64_t>(),74addr_man,75netgroupman,76Params(),77fuzzed_data_provider.ConsumeBool(),78ConsumeThreadInterrupt(fuzzed_data_provider)};80const uint64_t max_outbound_limit{fuzzed_data_provider.ConsumeIntegral<uint64_t>()};81CConnman::Options options;82options.m_msgproc = &net_events;83options.nMaxOutboundLimit = max_outbound_limit;85const auto local_services{ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS)};86options.m_local_services = local_services;88const auto use_addrman_outgoing{fuzzed_data_provider.ConsumeBool()};89options.m_use_addrman_outgoing = use_addrman_outgoing;90options.m_max_automatic_connections = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1000);92auto consume_whitelist = [&]() {93std::vector<NetWhitelistPermissions> result(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 3));94for (auto& entry : result) {95entry.m_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);96entry.m_subnet = ConsumeSubNet(fuzzed_data_provider);97}98return result;99};100options.vWhitelistedRangeIncoming = consume_whitelist();101options.vWhitelistedRangeOutgoing = consume_whitelist();103connman.Init(options);105const uint64_t total_bytes_recv_initial{connman.GetTotalBytesRecv()};106const uint64_t total_bytes_sent_initial{connman.GetTotalBytesSent()};108CNetAddr random_netaddr;109CAddress random_address;110CNode random_node = ConsumeNode(fuzzed_data_provider, steady_clock);111CSubNet random_subnet;112std::string random_string;113std::vector<NodeId> node_ids;114std::vector<std::string> node_addr_names;116LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 100) {117CNode& p2p_node{*ConsumeNodeAsUniquePtr(fuzzed_data_provider, steady_clock).release()};118// Simulate post-handshake state.119p2p_node.fSuccessfullyConnected = true;120connman.AddTestNode(p2p_node);121node_ids.push_back(p2p_node.GetId());122node_addr_names.push_back(p2p_node.m_addr_name);123}125LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 10000) {126CallOneOf(127fuzzed_data_provider,128[&] {129random_netaddr = ConsumeNetAddr(fuzzed_data_provider);130},131[&] {132random_address = ConsumeAddress(fuzzed_data_provider);133},134[&] {135random_subnet = ConsumeSubNet(fuzzed_data_provider);136},137[&] {138random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);139},140[&] {141const std::string& node_str = (!node_addr_names.empty() && fuzzed_data_provider.ConsumeBool())142? PickValue(fuzzed_data_provider, node_addr_names)143: random_string;144const auto added_node_info{connman.GetAddedNodeInfo(/*include_connected=*/true)};145const auto add_node{connman.AddNode({node_str, /*use_v2transport=*/fuzzed_data_provider.ConsumeBool()})};146if (add_node) {147assert(!connman.AddNode({node_str, /*use_v2transport=*/fuzzed_data_provider.ConsumeBool()}));148assert(added_node_info.size() < connman.GetAddedNodeInfo(/*include_connected=*/true).size());149const auto remove{fuzzed_data_provider.ConsumeBool()};150if (remove) {151assert(connman.RemoveAddedNode(node_str));152assert(added_node_info.size() == connman.GetAddedNodeInfo(/*include_connected=*/true).size());153}154}155},156[&] {157(void)connman.RemoveAddedNode(random_string);158},159[&] {160connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>());161},162[&] {163connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>());164},165[&] {166connman.DisconnectNode(random_netaddr);167},168[&] {169connman.DisconnectNode(random_string);170},171[&] {172connman.DisconnectNode(random_subnet);173},174[&] {175NodeId id = node_ids.empty() || fuzzed_data_provider.ConsumeBool()176? fuzzed_data_provider.ConsumeIntegral<NodeId>()177: PickValue(fuzzed_data_provider, node_ids);178(void)connman.ForNode(id, [&](CNode* pnode) {179(void)pnode->GetId();180(void)pnode->IsInboundConn();181(void)pnode->IsFullOutboundConn();182return true;183});184},185[&] {186auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>();187auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);188auto filtered = fuzzed_data_provider.ConsumeBool();189(void)connman.GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt, filtered);190},191[&] {192auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>();193auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);194(void)connman.GetAddresses(/*requestor=*/random_node, max_addresses, max_pct);195},196[&] {197(void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>());198},199[&] {200(void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({ConnectionDirection::None, ConnectionDirection::In, ConnectionDirection::Out, ConnectionDirection::Both}));201},202[&] {203(void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool());204},205[&] {206CSerializedNetMsg serialized_net_msg;207serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::MESSAGE_TYPE_SIZE);208serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);209connman.PushMessage(&random_node, std::move(serialized_net_msg));210},211[&] {212const auto set_active{fuzzed_data_provider.ConsumeBool()};213connman.SetNetworkActive(set_active);214assert(connman.GetNetworkActive() == set_active);215},216[&] {217connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool());218},219[&] {220const auto services{ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS)};221const auto before{connman.GetLocalServices()};222if (fuzzed_data_provider.ConsumeBool()) {223connman.AddLocalServices(services);224assert((connman.GetLocalServices() & services) == services);225// Restore by clearing only the bits that weren't already set.226connman.RemoveLocalServices(ServiceFlags(services & ~before));227} else {228connman.RemoveLocalServices(services);229assert((connman.GetLocalServices() & services) == 0);230// Restore by re-adding only the bits that were previously set.231connman.AddLocalServices(ServiceFlags(services & before));232}233assert(connman.GetLocalServices() == before);234},235[&] {236ConnectionType conn_type{237fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES)};238if (conn_type == ConnectionType::INBOUND) { // INBOUND is not allowed239conn_type = ConnectionType::OUTBOUND_FULL_RELAY;240}242std::optional<Proxy> proxy_override;243if (conn_type == ConnectionType::PRIVATE_BROADCAST || fuzzed_data_provider.ConsumeBool()) {244proxy_override.emplace(ConsumeService(fuzzed_data_provider));245}247connman.OpenNetworkConnection(248/*addrConnect=*/random_address,249/*fCountFailure=*/fuzzed_data_provider.ConsumeBool(),250/*grant_outbound=*/{},
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.