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.
251constexpr auto MINIMUM_CONNECT_TIME{30s};252CConnman::Options options;253options.m_max_automatic_connections = DEFAULT_MAX_PEER_CONNECTIONS;255connman->Init(options);256std::vector<CNode*> vNodes;258// Add block-relay-only peers up to the limit259for (int i = 0; i < max_outbound_block_relay; ++i) {260AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::BLOCK_RELAY);261}262peerLogic->CheckForStaleTipAndEvictPeers();264for (int i = 0; i < max_outbound_block_relay; ++i) {265BOOST_CHECK(vNodes[i]->fDisconnect == false);266}268// Add an extra block-relay-only peer breaking the limit (mocks logic in ThreadOpenConnections)269AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::BLOCK_RELAY);270peerLogic->CheckForStaleTipAndEvictPeers();272// The extra peer should only get marked for eviction after MINIMUM_CONNECT_TIME273for (int i = 0; i < max_outbound_block_relay; ++i) {274BOOST_CHECK(vNodes[i]->fDisconnect == false);275}276BOOST_CHECK(vNodes.back()->fDisconnect == false);278clock += MINIMUM_CONNECT_TIME;279peerLogic->CheckForStaleTipAndEvictPeers();280for (int i = 0; i < max_outbound_block_relay; ++i) {281BOOST_CHECK(vNodes[i]->fDisconnect == false);282}283BOOST_CHECK(vNodes.back()->fDisconnect == true);285// Update the last block time for the extra peer,286// and check that the next youngest peer gets evicted.287vNodes.back()->fDisconnect = false;288vNodes.back()->m_last_block_time = GetTime<std::chrono::seconds>();290peerLogic->CheckForStaleTipAndEvictPeers();291for (int i = 0; i < max_outbound_block_relay - 1; ++i) {292BOOST_CHECK(vNodes[i]->fDisconnect == false);293}294BOOST_CHECK(vNodes[max_outbound_block_relay - 1]->fDisconnect == true);295BOOST_CHECK(vNodes.back()->fDisconnect == false);297for (const CNode* node : vNodes) {298peerLogic->FinalizeNode(*node);299}300connman->ClearTestNodes();301}303BOOST_AUTO_TEST_CASE(peer_discouragement)304{305LOCK(NetEventsInterface::g_msgproc_mutex);307auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);308auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params());309auto peerLogic = PeerManager::make(*connman, *m_node.addrman, banman.get(), *m_node.chainman, *m_node.mempool, *m_node.warnings, {});311CNetAddr tor_netaddr;312BOOST_REQUIRE(313tor_netaddr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));314const CService tor_service{tor_netaddr, Params().GetDefaultPort()};316const std::array<CAddress, 3> addr{CAddress{ip(0xa0b0c001), NODE_NONE},317CAddress{ip(0xa0b0c002), NODE_NONE},318CAddress{tor_service, NODE_NONE}};320const CNetAddr other_addr{ip(0xa0b0ff01)}; // Not any of addr[].322std::array<CNode*, 5> nodes;324banman->ClearBanned();325NodeId id{0};326nodes[0] = new CNode{id++,327/*sock=*/nullptr,328addr[0],329/*nKeyedNetGroupIn=*/0,330/*nLocalHostNonceIn=*/0,331CAddress(),332/*addrNameIn=*/"",333ConnectionType::INBOUND,334/*inbound_onion=*/false,335/*network_key=*/1};336nodes[0]->SetCommonVersion(PROTOCOL_VERSION);337peerLogic->InitializeNode(*nodes[0], NODE_NETWORK);338nodes[0]->fSuccessfullyConnected = true;339connman->AddTestNode(*nodes[0]);340peerLogic->UnitTestMisbehaving(nodes[0]->GetId()); // Should be discouraged341BOOST_CHECK(peerLogic->SendMessages(*nodes[0]));343BOOST_CHECK(banman->IsDiscouraged(addr[0]));344BOOST_CHECK(nodes[0]->fDisconnect);345BOOST_CHECK(!banman->IsDiscouraged(other_addr)); // Different address, not discouraged347nodes[1] = new CNode{id++,348/*sock=*/nullptr,349addr[1],350/*nKeyedNetGroupIn=*/1,351/*nLocalHostNonceIn=*/1,352CAddress(),353/*addrNameIn=*/"",354ConnectionType::INBOUND,355/*inbound_onion=*/false,356/*network_key=*/1};357nodes[1]->SetCommonVersion(PROTOCOL_VERSION);358peerLogic->InitializeNode(*nodes[1], NODE_NETWORK);359nodes[1]->fSuccessfullyConnected = true;360connman->AddTestNode(*nodes[1]);361BOOST_CHECK(peerLogic->SendMessages(*nodes[1]));362// [0] is still discouraged/disconnected.363BOOST_CHECK(banman->IsDiscouraged(addr[0]));364BOOST_CHECK(nodes[0]->fDisconnect);365// [1] is not discouraged/disconnected yet.366BOOST_CHECK(!banman->IsDiscouraged(addr[1]));367BOOST_CHECK(!nodes[1]->fDisconnect);368peerLogic->UnitTestMisbehaving(nodes[1]->GetId());369BOOST_CHECK(peerLogic->SendMessages(*nodes[1]));370// Expect both [0] and [1] to be discouraged/disconnected now.371BOOST_CHECK(banman->IsDiscouraged(addr[0]));372BOOST_CHECK(nodes[0]->fDisconnect);373BOOST_CHECK(banman->IsDiscouraged(addr[1]));374BOOST_CHECK(nodes[1]->fDisconnect);376// Make sure non-IP peers are discouraged and disconnected properly.378nodes[2] = new CNode{id++,379/*sock=*/nullptr,380addr[2],381/*nKeyedNetGroupIn=*/1,382/*nLocalHostNonceIn=*/1,383CAddress(),384/*addrNameIn=*/"",385ConnectionType::OUTBOUND_FULL_RELAY,386/*inbound_onion=*/false,387/*network_key=*/2};388nodes[2]->SetCommonVersion(PROTOCOL_VERSION);389peerLogic->InitializeNode(*nodes[2], NODE_NETWORK);390nodes[2]->fSuccessfullyConnected = true;391connman->AddTestNode(*nodes[2]);393nodes[3] = new CNode{/*id=*/id++,394/*sock=*/nullptr,395/*addrIn=*/addr[2],396/*nKeyedNetGroupIn=*/0,397/*nLocalHostNonceIn=*/0,398/*addrBindIn=*/CAddress{},399/*addrNameIn=*/"",400/*conn_type_in=*/ConnectionType::PRIVATE_BROADCAST,401/*inbound_onion=*/false,402/*network_key=*/0};403peerLogic->InitializeNode(*nodes[3], NODE_NETWORK);404connman->AddTestNode(*nodes[3]);406peerLogic->UnitTestMisbehaving(nodes[2]->GetId());407BOOST_CHECK(peerLogic->SendMessages(*nodes[2]));408BOOST_CHECK(banman->IsDiscouraged(addr[0]));409BOOST_CHECK(banman->IsDiscouraged(addr[1]));410BOOST_CHECK(banman->IsDiscouraged(addr[2]));411BOOST_CHECK(nodes[0]->fDisconnect);412BOOST_CHECK(nodes[1]->fDisconnect);413BOOST_CHECK(nodes[2]->fDisconnect);414BOOST_CHECK(!nodes[3]->fDisconnect);416nodes[4] = new CNode{/*id=*/id++,417/*sock=*/nullptr,418/*addrIn=*/CAddress{CService{other_addr, Params().GetDefaultPort()}, NODE_NONE},419/*nKeyedNetGroupIn=*/0,420/*nLocalHostNonceIn=*/0,421/*addrBindIn=*/CAddress{},422/*addrNameIn=*/"",423/*conn_type_in=*/ConnectionType::PRIVATE_BROADCAST,424/*inbound_onion=*/false,425/*network_key=*/0};426peerLogic->InitializeNode(*nodes[4], NODE_NETWORK);427connman->AddTestNode(*nodes[4]);429peerLogic->UnitTestMisbehaving(nodes[4]->GetId());430BOOST_CHECK(peerLogic->SendMessages(*nodes[4]));431BOOST_CHECK(nodes[4]->fDisconnect);432BOOST_CHECK(!banman->IsDiscouraged(other_addr));434for (CNode* node : nodes) {435peerLogic->FinalizeNode(*node);436}437connman->ClearTestNodes();438}440BOOST_AUTO_TEST_CASE(DoS_bantime)441{442LOCK(NetEventsInterface::g_msgproc_mutex);444auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);445auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params());446auto peerLogic = PeerManager::make(*connman, *m_node.addrman, banman.get(), *m_node.chainman, *m_node.mempool, *m_node.warnings, {});448banman->ClearBanned();449const FakeNodeClock clock{}; // keep mocktime constant451CAddress addr(ip(0xa0b0c001), NODE_NONE);452NodeId id{0};453CNode dummyNode{id++,454/*sock=*/nullptr,455addr,456/*nKeyedNetGroupIn=*/4,457/*nLocalHostNonceIn=*/4,458CAddress(),459/*addrNameIn=*/"",460ConnectionType::INBOUND,461/*inbound_onion=*/false,462/*network_key=*/1};463dummyNode.SetCommonVersion(PROTOCOL_VERSION);464peerLogic->InitializeNode(dummyNode, NODE_NETWORK);465dummyNode.fSuccessfullyConnected = true;467peerLogic->UnitTestMisbehaving(dummyNode.GetId());468BOOST_CHECK(peerLogic->SendMessages(dummyNode));469BOOST_CHECK(banman->IsDiscouraged(addr));471peerLogic->FinalizeNode(dummyNode);472}474BOOST_AUTO_TEST_SUITE_END()
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.