Skip to content

Commit 994aaaa

Browse files
committed
Merge bitcoin/bitcoin#23380: addrman: Fix AddrMan::Add() return semantics and logging
61ec053 [MOVEONLY] reorder functions in addrman_impl.h and addrman.cpp (John Newbery) 2095df7 [addrman] Add Add_() inner function, fix Add() return semantics (John Newbery) 2658eb6 [addrman] Rename Add_() to AddSingle() (John Newbery) e58598e [addrman] Add doxygen comment to AddrMan::Add() (John Newbery) Pull request description: Previously, Add() would return true if the function created a new AddressInfo object, even if that object could not be successfully entered into the new table and was deleted. That would happen if the new table position was already taken and the existing entry could not be removed. Instead, return true if the new AddressInfo object is successfully entered into the new table. This fixes a bug in the "Added %i addresses" log, which would not always accurately log how many addresses had been added. ACKs for top commit: naumenkogs: ACK 61ec053 mzumsande: ACK 61ec053 shaavan: ACK 61ec053 Tree-SHA512: 276f1e8297d4b6d411d05d06ffc7c176f6290a784da039926ab6c471a8ed8e9159ab4f56c893b1285737ae292954930f0d28012d89dfb3f2f825d7df41016feb
2 parents 7efc628 + 61ec053 commit 994aaaa

File tree

6 files changed

+87
-74
lines changed

6 files changed

+87
-74
lines changed

src/addrman.cpp

Lines changed: 72 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -537,69 +537,13 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
537537
info.fInTried = true;
538538
}
539539

540-
void AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nTime)
541-
{
542-
AssertLockHeld(cs);
543-
544-
int nId;
545-
546-
nLastGood = nTime;
547-
548-
AddrInfo* pinfo = Find(addr, &nId);
549-
550-
// if not found, bail out
551-
if (!pinfo)
552-
return;
553-
554-
AddrInfo& info = *pinfo;
555-
556-
// update info
557-
info.nLastSuccess = nTime;
558-
info.nLastTry = nTime;
559-
info.nAttempts = 0;
560-
// nTime is not updated here, to avoid leaking information about
561-
// currently-connected peers.
562-
563-
// if it is already in the tried set, don't do anything else
564-
if (info.fInTried)
565-
return;
566-
567-
// if it is not in new, something bad happened
568-
if (!Assume(info.nRefCount > 0)) {
569-
return;
570-
}
571-
572-
// which tried bucket to move the entry to
573-
int tried_bucket = info.GetTriedBucket(nKey, m_asmap);
574-
int tried_bucket_pos = info.GetBucketPosition(nKey, false, tried_bucket);
575-
576-
// Will moving this address into tried evict another entry?
577-
if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
578-
if (m_tried_collisions.size() < ADDRMAN_SET_TRIED_COLLISION_SIZE) {
579-
m_tried_collisions.insert(nId);
580-
}
581-
// Output the entry we'd be colliding with, for debugging purposes
582-
auto colliding_entry = mapInfo.find(vvTried[tried_bucket][tried_bucket_pos]);
583-
LogPrint(BCLog::ADDRMAN, "Collision with %s while attempting to move %s to tried table. Collisions=%d\n",
584-
colliding_entry != mapInfo.end() ? colliding_entry->second.ToString() : "",
585-
addr.ToString(),
586-
m_tried_collisions.size());
587-
} else {
588-
// move nId to the tried tables
589-
MakeTried(info, nId);
590-
LogPrint(BCLog::ADDRMAN, "Moved %s mapped to AS%i to tried[%i][%i]\n",
591-
addr.ToString(), addr.GetMappedAS(m_asmap), tried_bucket, tried_bucket_pos);
592-
}
593-
}
594-
595-
bool AddrManImpl::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
540+
bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
596541
{
597542
AssertLockHeld(cs);
598543

599544
if (!addr.IsRoutable())
600545
return false;
601546

602-
bool fNew = false;
603547
int nId;
604548
AddrInfo* pinfo = Find(addr, &nId);
605549

@@ -640,13 +584,12 @@ bool AddrManImpl::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTi
640584
pinfo = Create(addr, source, &nId);
641585
pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
642586
nNew++;
643-
fNew = true;
644587
}
645588

646589
int nUBucket = pinfo->GetNewBucket(nKey, source, m_asmap);
647590
int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
591+
bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
648592
if (vvNew[nUBucket][nUBucketPos] != nId) {
649-
bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
650593
if (!fInsert) {
651594
AddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
652595
if (infoExisting.IsTerrible() || (infoExisting.nRefCount > 1 && pinfo->nRefCount == 0)) {
@@ -666,7 +609,74 @@ bool AddrManImpl::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTi
666609
}
667610
}
668611
}
669-
return fNew;
612+
return fInsert;
613+
}
614+
615+
void AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nTime)
616+
{
617+
AssertLockHeld(cs);
618+
619+
int nId;
620+
621+
nLastGood = nTime;
622+
623+
AddrInfo* pinfo = Find(addr, &nId);
624+
625+
// if not found, bail out
626+
if (!pinfo)
627+
return;
628+
629+
AddrInfo& info = *pinfo;
630+
631+
// update info
632+
info.nLastSuccess = nTime;
633+
info.nLastTry = nTime;
634+
info.nAttempts = 0;
635+
// nTime is not updated here, to avoid leaking information about
636+
// currently-connected peers.
637+
638+
// if it is already in the tried set, don't do anything else
639+
if (info.fInTried)
640+
return;
641+
642+
// if it is not in new, something bad happened
643+
if (!Assume(info.nRefCount > 0)) {
644+
return;
645+
}
646+
647+
// which tried bucket to move the entry to
648+
int tried_bucket = info.GetTriedBucket(nKey, m_asmap);
649+
int tried_bucket_pos = info.GetBucketPosition(nKey, false, tried_bucket);
650+
651+
// Will moving this address into tried evict another entry?
652+
if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
653+
if (m_tried_collisions.size() < ADDRMAN_SET_TRIED_COLLISION_SIZE) {
654+
m_tried_collisions.insert(nId);
655+
}
656+
// Output the entry we'd be colliding with, for debugging purposes
657+
auto colliding_entry = mapInfo.find(vvTried[tried_bucket][tried_bucket_pos]);
658+
LogPrint(BCLog::ADDRMAN, "Collision with %s while attempting to move %s to tried table. Collisions=%d\n",
659+
colliding_entry != mapInfo.end() ? colliding_entry->second.ToString() : "",
660+
addr.ToString(),
661+
m_tried_collisions.size());
662+
} else {
663+
// move nId to the tried tables
664+
MakeTried(info, nId);
665+
LogPrint(BCLog::ADDRMAN, "Moved %s mapped to AS%i to tried[%i][%i]\n",
666+
addr.ToString(), addr.GetMappedAS(m_asmap), tried_bucket, tried_bucket_pos);
667+
}
668+
}
669+
670+
bool AddrManImpl::Add_(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty)
671+
{
672+
int added{0};
673+
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) {
674+
added += AddSingle(*it, source, nTimePenalty) ? 1 : 0;
675+
}
676+
if (added > 0) {
677+
LogPrint(BCLog::ADDRMAN, "Added %i addresses (of %i) from %s: %i tried, %i new\n", added, vAddr.size(), source.ToString(), nTried, nNew);
678+
}
679+
return added > 0;
670680
}
671681

672682
void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime)
@@ -1031,15 +1041,10 @@ size_t AddrManImpl::size() const
10311041
bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
10321042
{
10331043
LOCK(cs);
1034-
int nAdd = 0;
10351044
Check();
1036-
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
1037-
nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
1045+
auto ret = Add_(vAddr, source, nTimePenalty);
10381046
Check();
1039-
if (nAdd) {
1040-
LogPrint(BCLog::ADDRMAN, "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew);
1041-
}
1042-
return nAdd > 0;
1047+
return ret;
10431048
}
10441049

10451050
void AddrManImpl::Good(const CService& addr, int64_t nTime)

src/addrman.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,15 @@ class AddrMan
6969
//! Return the number of (unique) addresses in all tables.
7070
size_t size() const;
7171

72-
//! Add addresses to addrman's new table.
72+
/**
73+
* Attempt to add one or more addresses to addrman's new table.
74+
*
75+
* @param[in] vAddr Address records to attempt to add.
76+
* @param[in] source The address of the node that sent us these addr records.
77+
* @param[in] nTimePenalty A "time penalty" to apply to the address record's nTime. If a peer
78+
* sends us an address record with nTime=n, then we'll add it to our
79+
* addrman with nTime=(n - nTimePenalty).
80+
* @return true if at least one address is successfully added. */
7381
bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty = 0);
7482

7583
//! Mark an entry as accessible, possibly moving it from "new" to "tried".

src/addrman_impl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,13 @@ class AddrManImpl
243243
//! Move an entry from the "new" table(s) to the "tried" table
244244
void MakeTried(AddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
245245

246+
/** Attempt to add a single address to addrman's new table.
247+
* @see AddrMan::Add() for parameters. */
248+
bool AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
249+
246250
void Good_(const CService& addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
247251

248-
bool Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
252+
bool Add_(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
249253

250254
void Attempt_(const CService& addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
251255

src/test/addrman_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
347347
//Test: tried table collision!
348348
CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
349349
uint32_t collisions{1};
350-
BOOST_CHECK(addrman.Add({CAddress(addr1, NODE_NONE)}, source));
350+
BOOST_CHECK(!addrman.Add({CAddress(addr1, NODE_NONE)}, source));
351351
BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
352352

353353
CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));

test/functional/p2p_addr_relay.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ def relay_tests(self):
152152
msg = self.setup_addr_msg(num_ipv4_addrs)
153153
with self.nodes[0].assert_debug_log(
154154
[
155-
'Added {} addresses from 127.0.0.1: 0 tried'.format(num_ipv4_addrs),
156155
'received: addr (301 bytes) peer=1',
157156
]
158157
):

test/functional/p2p_addrv2_relay.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,6 @@ def run_test(self):
7272
addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
7373
msg.addrs = ADDRS
7474
with self.nodes[0].assert_debug_log([
75-
# The I2P address is not added to node's own addrman because it has no
76-
# I2P reachability (thus 10 - 1 = 9).
77-
'Added 9 addresses from 127.0.0.1: 0 tried',
7875
'received: addrv2 (159 bytes) peer=0',
7976
'sending addrv2 (159 bytes) peer=1',
8077
]):

0 commit comments

Comments
 (0)