Skip to content

Commit 74ebd4d

Browse files
committed
doc, test: Test and explain service flag handling
Service flags are handled differently, depending on whether validated (if received from the peer) or unvalidated (received via gossip relay).
1 parent b3b19be commit 74ebd4d

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

src/addrman.h

Lines changed: 4 additions & 1 deletion
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 27 additions & 1 deletion
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)