Skip to content

Commit 5711da6

Browse files
committed
Merge bitcoin/bitcoin#29213: doc, test: test and explain service flag handling
74ebd4d doc, test: Test and explain service flag handling (Martin Zumsande) Pull request description: Service flags received from the peer-to-peer network are handled differently, depending on how we receive them. If received directly from an outbound peer the flags belong to, they replace existing flags. If received via gossip relay (so that anyone could send them), new flags are added, but existing ones but cannot be overwritten. Document that and add test coverage for it. ACKs for top commit: achow101: ACK 74ebd4d furszy: ACK 74ebd4d brunoerg: utACK 74ebd4d Tree-SHA512: 604adc3304b8e3cb1a10dfd017025c10b029bebd3ef533f96bcb5856fee5d4396a9aed4949908b8e7ef267ad21320d1814dd80f88426330c5c9c2c529c497591
2 parents 27d935f + 74ebd4d commit 5711da6

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

src/addrman.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,16 @@ class AddrMan
111111

112112
/**
113113
* Attempt to add one or more addresses to addrman's new table.
114+
* If an address already exists in addrman, the existing entry may be updated
115+
* (e.g. adding additional service flags). If the existing entry is in the new table,
116+
* it may be added to more buckets, improving the probability of selection.
114117
*
115118
* @param[in] vAddr Address records to attempt to add.
116119
* @param[in] source The address of the node that sent us these addr records.
117120
* @param[in] time_penalty A "time penalty" to apply to the address record's nTime. If a peer
118121
* sends us an address record with nTime=n, then we'll add it to our
119122
* addrman with nTime=(n - time_penalty).
120-
* @return true if at least one address is successfully added. */
123+
* @return true if at least one address is successfully added, or added to an additional bucket. Unaffected by updates. */
121124
bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty = 0s);
122125

123126
/**

src/net_processing.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -3376,6 +3376,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
33763376
vRecv >> CNetAddr::V1(addrMe);
33773377
if (!pfrom.IsInboundConn())
33783378
{
3379+
// Overwrites potentially existing services. In contrast to this,
3380+
// unvalidated services received via gossip relay in ADDR/ADDRV2
3381+
// messages are only ever added but cannot replace existing ones.
33793382
m_addrman.SetServices(pfrom.addr, nServices);
33803383
}
33813384
if (pfrom.ExpectServicesFromConn() && !HasAllDesirableServiceFlags(nServices))

src/test/addrman_tests.cpp

+27-1
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
10681068

10691069
BOOST_AUTO_TEST_CASE(addrman_update_address)
10701070
{
1071-
// Tests updating nTime via Connected() and nServices via SetServices()
1071+
// Tests updating nTime via Connected() and nServices via SetServices() and Add()
10721072
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
10731073
CNetAddr source{ResolveIP("252.2.2.2")};
10741074
CAddress addr{CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE)};
@@ -1095,6 +1095,32 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
10951095
BOOST_CHECK_EQUAL(vAddr2.size(), 1U);
10961096
BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000s);
10971097
BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
1098+
1099+
// Updating an existing addr through Add() (used in gossip relay) can add additional services but can't remove existing ones.
1100+
CAddress addr_v2{CAddress(ResolveService("250.1.1.1", 8333), NODE_P2P_V2)};
1101+
addr_v2.nTime = start_time;
1102+
BOOST_CHECK(!addrman->Add({addr_v2}, source));
1103+
std::vector<CAddress> vAddr3{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1104+
BOOST_CHECK_EQUAL(vAddr3.size(), 1U);
1105+
BOOST_CHECK_EQUAL(vAddr3.at(0).nServices, NODE_P2P_V2 | NODE_NETWORK_LIMITED);
1106+
1107+
// SetServices() (used when we connected to them) overwrites existing service flags
1108+
addrman->SetServices(addr, NODE_NETWORK);
1109+
std::vector<CAddress> vAddr4{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1110+
BOOST_CHECK_EQUAL(vAddr4.size(), 1U);
1111+
BOOST_CHECK_EQUAL(vAddr4.at(0).nServices, NODE_NETWORK);
1112+
1113+
// Promoting to Tried does not affect the service flags
1114+
BOOST_CHECK(addrman->Good(addr)); // addr has NODE_NONE
1115+
std::vector<CAddress> vAddr5{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1116+
BOOST_CHECK_EQUAL(vAddr5.size(), 1U);
1117+
BOOST_CHECK_EQUAL(vAddr5.at(0).nServices, NODE_NETWORK);
1118+
1119+
// Adding service flags even works when the addr is in Tried
1120+
BOOST_CHECK(!addrman->Add({addr_v2}, source));
1121+
std::vector<CAddress> vAddr6{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1122+
BOOST_CHECK_EQUAL(vAddr6.size(), 1U);
1123+
BOOST_CHECK_EQUAL(vAddr6.at(0).nServices, NODE_NETWORK | NODE_P2P_V2);
10981124
}
10991125

11001126
BOOST_AUTO_TEST_CASE(addrman_size)

0 commit comments

Comments
 (0)