Skip to content

Commit 353a3fd

Browse files
vasilddongcarl
andcommittedOct 9, 2020
net: advertise support for ADDRv2 via new message
Introduce a new message `sendaddrv2` to signal support for ADDRv2. Send the new message immediately after sending the `VERACK` message. Add support for receiving and parsing ADDRv2 messages. Send ADDRv2 messages (instead of ADDR) to a peer if he has advertised support for it. Co-authored-by: Carl Dong <[email protected]>
1 parent 201a459 commit 353a3fd

12 files changed

+392
-23
lines changed
 

‎src/net.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,11 @@ class CNode
868868
bool m_legacyWhitelisted{false};
869869
bool fClient{false}; // set by version message
870870
bool m_limited_node{false}; //after BIP159, set by version message
871+
/**
872+
* Whether the peer has signaled support for receiving ADDRv2 (BIP155)
873+
* messages, implying a preference to receive ADDRv2 instead of ADDR ones.
874+
*/
875+
std::atomic_bool m_wants_addrv2{false};
871876
std::atomic_bool fSuccessfullyConnected{false};
872877
// Setting fDisconnect to true will cause the node to be disconnected the
873878
// next time DisconnectNodes() runs
@@ -1115,11 +1120,16 @@ class CNode
11151120

11161121
void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand)
11171122
{
1123+
// Whether the peer supports the address in `_addr`. For example,
1124+
// nodes that do not implement BIP155 cannot receive Tor v3 addresses
1125+
// because they require ADDRv2 (BIP155) encoding.
1126+
const bool addr_format_supported = m_wants_addrv2 || _addr.IsAddrV1Compatible();
1127+
11181128
// Known checking here is only to save space from duplicates.
11191129
// SendMessages will filter it again for knowns that were added
11201130
// after addresses were pushed.
11211131
assert(m_addr_known);
1122-
if (_addr.IsValid() && !m_addr_known->contains(_addr.GetKey())) {
1132+
if (_addr.IsValid() && !m_addr_known->contains(_addr.GetKey()) && addr_format_supported) {
11231133
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
11241134
vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr;
11251135
} else {

‎src/net_processing.cpp

+38-7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <random.h>
2424
#include <reverse_iterator.h>
2525
#include <scheduler.h>
26+
#include <streams.h>
2627
#include <tinyformat.h>
2728
#include <txmempool.h>
2829
#include <util/check.h> // For NDEBUG compile time check
@@ -2408,11 +2409,16 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
24082409
pfrom.SetCommonVersion(greatest_common_version);
24092410
pfrom.nVersion = nVersion;
24102411

2412+
const CNetMsgMaker msg_maker(greatest_common_version);
2413+
24112414
if (greatest_common_version >= WTXID_RELAY_VERSION) {
2412-
m_connman.PushMessage(&pfrom, CNetMsgMaker(greatest_common_version).Make(NetMsgType::WTXIDRELAY));
2415+
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::WTXIDRELAY));
24132416
}
24142417

2415-
m_connman.PushMessage(&pfrom, CNetMsgMaker(greatest_common_version).Make(NetMsgType::VERACK));
2418+
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
2419+
2420+
// Signal ADDRv2 support (BIP155).
2421+
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
24162422

24172423
pfrom.nServices = nServices;
24182424
pfrom.SetAddrLocal(addrMe);
@@ -2582,16 +2588,25 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
25822588
return;
25832589
}
25842590

2585-
if (msg_type == NetMsgType::ADDR) {
2591+
if (msg_type == NetMsgType::ADDR || msg_type == NetMsgType::ADDRV2) {
2592+
int stream_version = vRecv.GetVersion();
2593+
if (msg_type == NetMsgType::ADDRV2) {
2594+
// Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
2595+
// unserialize methods know that an address in v2 format is coming.
2596+
stream_version |= ADDRV2_FORMAT;
2597+
}
2598+
2599+
OverrideStream<CDataStream> s(&vRecv, vRecv.GetType(), stream_version);
25862600
std::vector<CAddress> vAddr;
2587-
vRecv >> vAddr;
2601+
2602+
s >> vAddr;
25882603

25892604
if (!pfrom.RelayAddrsWithConn()) {
25902605
return;
25912606
}
25922607
if (vAddr.size() > MAX_ADDR_TO_SEND)
25932608
{
2594-
Misbehaving(pfrom.GetId(), 20, strprintf("addr message size = %u", vAddr.size()));
2609+
Misbehaving(pfrom.GetId(), 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
25952610
return;
25962611
}
25972612

@@ -2635,6 +2650,11 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
26352650
return;
26362651
}
26372652

2653+
if (msg_type == NetMsgType::SENDADDRV2) {
2654+
pfrom.m_wants_addrv2 = true;
2655+
return;
2656+
}
2657+
26382658
if (msg_type == NetMsgType::SENDHEADERS) {
26392659
LOCK(cs_main);
26402660
State(pfrom.GetId())->fPreferHeaders = true;
@@ -4095,6 +4115,17 @@ bool PeerManager::SendMessages(CNode* pto)
40954115
std::vector<CAddress> vAddr;
40964116
vAddr.reserve(pto->vAddrToSend.size());
40974117
assert(pto->m_addr_known);
4118+
4119+
const char* msg_type;
4120+
int make_flags;
4121+
if (pto->m_wants_addrv2) {
4122+
msg_type = NetMsgType::ADDRV2;
4123+
make_flags = ADDRV2_FORMAT;
4124+
} else {
4125+
msg_type = NetMsgType::ADDR;
4126+
make_flags = 0;
4127+
}
4128+
40984129
for (const CAddress& addr : pto->vAddrToSend)
40994130
{
41004131
if (!pto->m_addr_known->contains(addr.GetKey()))
@@ -4104,14 +4135,14 @@ bool PeerManager::SendMessages(CNode* pto)
41044135
// receiver rejects addr messages larger than MAX_ADDR_TO_SEND
41054136
if (vAddr.size() >= MAX_ADDR_TO_SEND)
41064137
{
4107-
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
4138+
m_connman.PushMessage(pto, msgMaker.Make(make_flags, msg_type, vAddr));
41084139
vAddr.clear();
41094140
}
41104141
}
41114142
}
41124143
pto->vAddrToSend.clear();
41134144
if (!vAddr.empty())
4114-
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
4145+
m_connman.PushMessage(pto, msgMaker.Make(make_flags, msg_type, vAddr));
41154146
// we only send the big addr message once
41164147
if (pto->vAddrToSend.capacity() > 40)
41174148
pto->vAddrToSend.shrink_to_fit();

‎src/netaddress.cpp

+26-3
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,26 @@ bool CNetAddr::IsInternal() const
474474
return m_net == NET_INTERNAL;
475475
}
476476

477+
bool CNetAddr::IsAddrV1Compatible() const
478+
{
479+
switch (m_net) {
480+
case NET_IPV4:
481+
case NET_IPV6:
482+
case NET_INTERNAL:
483+
return true;
484+
case NET_ONION:
485+
return m_addr.size() == ADDR_TORV2_SIZE;
486+
case NET_I2P:
487+
case NET_CJDNS:
488+
return false;
489+
case NET_UNROUTABLE: // m_net is never and should not be set to NET_UNROUTABLE
490+
case NET_MAX: // m_net is never and should not be set to NET_MAX
491+
assert(false);
492+
} // no default case, so the compiler can warn about missing cases
493+
494+
assert(false);
495+
}
496+
477497
enum Network CNetAddr::GetNetwork() const
478498
{
479499
if (IsInternal())
@@ -744,9 +764,12 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
744764

745765
std::vector<unsigned char> CNetAddr::GetAddrBytes() const
746766
{
747-
uint8_t serialized[V1_SERIALIZATION_SIZE];
748-
SerializeV1Array(serialized);
749-
return {std::begin(serialized), std::end(serialized)};
767+
if (IsAddrV1Compatible()) {
768+
uint8_t serialized[V1_SERIALIZATION_SIZE];
769+
SerializeV1Array(serialized);
770+
return {std::begin(serialized), std::end(serialized)};
771+
}
772+
return std::vector<unsigned char>(m_addr.begin(), m_addr.end());
750773
}
751774

752775
uint64_t CNetAddr::GetHash() const

‎src/netaddress.h

+6
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ class CNetAddr
173173
bool IsRoutable() const;
174174
bool IsInternal() const;
175175
bool IsValid() const;
176+
177+
/**
178+
* Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
179+
*/
180+
bool IsAddrV1Compatible() const;
181+
176182
enum Network GetNetwork() const;
177183
std::string ToString() const;
178184
std::string ToStringIP() const;

‎src/protocol.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace NetMsgType {
1414
const char *VERSION="version";
1515
const char *VERACK="verack";
1616
const char *ADDR="addr";
17+
const char *ADDRV2="addrv2";
18+
const char *SENDADDRV2="sendaddrv2";
1719
const char *INV="inv";
1820
const char *GETDATA="getdata";
1921
const char *MERKLEBLOCK="merkleblock";
@@ -52,6 +54,8 @@ const static std::string allNetMessageTypes[] = {
5254
NetMsgType::VERSION,
5355
NetMsgType::VERACK,
5456
NetMsgType::ADDR,
57+
NetMsgType::ADDRV2,
58+
NetMsgType::SENDADDRV2,
5559
NetMsgType::INV,
5660
NetMsgType::GETDATA,
5761
NetMsgType::MERKLEBLOCK,

‎src/protocol.h

+12
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ extern const char* VERACK;
7676
* network.
7777
*/
7878
extern const char* ADDR;
79+
/**
80+
* The addrv2 message relays connection information for peers on the network just
81+
* like the addr message, but is extended to allow gossiping of longer node
82+
* addresses (see BIP155).
83+
*/
84+
extern const char *ADDRV2;
85+
/**
86+
* The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
87+
* It also implies that its sender can encode as ADDRV2 and would send ADDRV2
88+
* instead of ADDR to a peer that has signaled ADDRV2 support by sending SENDADDRV2.
89+
*/
90+
extern const char *SENDADDRV2;
7991
/**
8092
* The inv message (inventory message) transmits one or more inventories of
8193
* objects known to the transmitting peer.

‎src/test/net_tests.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
212212
BOOST_REQUIRE(addr.IsIPv4());
213213

214214
BOOST_CHECK(addr.IsBindAny());
215+
BOOST_CHECK(addr.IsAddrV1Compatible());
215216
BOOST_CHECK_EQUAL(addr.ToString(), "0.0.0.0");
216217

217218
// IPv4, INADDR_NONE
@@ -220,6 +221,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
220221
BOOST_REQUIRE(addr.IsIPv4());
221222

222223
BOOST_CHECK(!addr.IsBindAny());
224+
BOOST_CHECK(addr.IsAddrV1Compatible());
223225
BOOST_CHECK_EQUAL(addr.ToString(), "255.255.255.255");
224226

225227
// IPv4, casual
@@ -228,6 +230,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
228230
BOOST_REQUIRE(addr.IsIPv4());
229231

230232
BOOST_CHECK(!addr.IsBindAny());
233+
BOOST_CHECK(addr.IsAddrV1Compatible());
231234
BOOST_CHECK_EQUAL(addr.ToString(), "12.34.56.78");
232235

233236
// IPv6, in6addr_any
@@ -236,6 +239,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
236239
BOOST_REQUIRE(addr.IsIPv6());
237240

238241
BOOST_CHECK(addr.IsBindAny());
242+
BOOST_CHECK(addr.IsAddrV1Compatible());
239243
BOOST_CHECK_EQUAL(addr.ToString(), "::");
240244

241245
// IPv6, casual
@@ -244,6 +248,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
244248
BOOST_REQUIRE(addr.IsIPv6());
245249

246250
BOOST_CHECK(!addr.IsBindAny());
251+
BOOST_CHECK(addr.IsAddrV1Compatible());
247252
BOOST_CHECK_EQUAL(addr.ToString(), "1122:3344:5566:7788:9900:aabb:ccdd:eeff");
248253

249254
// TORv2
@@ -252,6 +257,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
252257
BOOST_REQUIRE(addr.IsTor());
253258

254259
BOOST_CHECK(!addr.IsBindAny());
260+
BOOST_CHECK(addr.IsAddrV1Compatible());
255261
BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion");
256262

257263
// TORv3
@@ -261,6 +267,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
261267
BOOST_REQUIRE(addr.IsTor());
262268

263269
BOOST_CHECK(!addr.IsBindAny());
270+
BOOST_CHECK(!addr.IsAddrV1Compatible());
264271
BOOST_CHECK_EQUAL(addr.ToString(), torv3_addr);
265272

266273
// TORv3, broken, with wrong checksum
@@ -285,6 +292,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
285292
BOOST_REQUIRE(addr.IsInternal());
286293

287294
BOOST_CHECK(!addr.IsBindAny());
295+
BOOST_CHECK(addr.IsAddrV1Compatible());
288296
BOOST_CHECK_EQUAL(addr.ToString(), "esffpvrt3wpeaygy.internal");
289297

290298
// Totally bogus
@@ -379,6 +387,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
379387
s >> addr;
380388
BOOST_CHECK(addr.IsValid());
381389
BOOST_CHECK(addr.IsIPv4());
390+
BOOST_CHECK(addr.IsAddrV1Compatible());
382391
BOOST_CHECK_EQUAL(addr.ToString(), "1.2.3.4");
383392
BOOST_REQUIRE(s.empty());
384393

@@ -415,6 +424,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
415424
s >> addr;
416425
BOOST_CHECK(addr.IsValid());
417426
BOOST_CHECK(addr.IsIPv6());
427+
BOOST_CHECK(addr.IsAddrV1Compatible());
418428
BOOST_CHECK_EQUAL(addr.ToString(), "102:304:506:708:90a:b0c:d0e:f10");
419429
BOOST_REQUIRE(s.empty());
420430

@@ -426,6 +436,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
426436
// sha256(name)[0:10]
427437
s >> addr;
428438
BOOST_CHECK(addr.IsInternal());
439+
BOOST_CHECK(addr.IsAddrV1Compatible());
429440
BOOST_CHECK_EQUAL(addr.ToString(), "zklycewkdo64v6wc.internal");
430441
BOOST_REQUIRE(s.empty());
431442

@@ -461,6 +472,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
461472
s >> addr;
462473
BOOST_CHECK(addr.IsValid());
463474
BOOST_CHECK(addr.IsTor());
475+
BOOST_CHECK(addr.IsAddrV1Compatible());
464476
BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion");
465477
BOOST_REQUIRE(s.empty());
466478

@@ -482,6 +494,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
482494
s >> addr;
483495
BOOST_CHECK(addr.IsValid());
484496
BOOST_CHECK(addr.IsTor());
497+
BOOST_CHECK(!addr.IsAddrV1Compatible());
485498
BOOST_CHECK_EQUAL(addr.ToString(),
486499
"pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion");
487500
BOOST_REQUIRE(s.empty());
@@ -503,6 +516,8 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
503516
"f98232ae42d4b6fd2fa81952dfe36a87"));
504517
s >> addr;
505518
BOOST_CHECK(addr.IsValid());
519+
BOOST_CHECK(addr.IsI2P());
520+
BOOST_CHECK(!addr.IsAddrV1Compatible());
506521
BOOST_CHECK_EQUAL(addr.ToString(),
507522
"ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p");
508523
BOOST_REQUIRE(s.empty());
@@ -524,6 +539,8 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
524539
));
525540
s >> addr;
526541
BOOST_CHECK(addr.IsValid());
542+
BOOST_CHECK(addr.IsCJDNS());
543+
BOOST_CHECK(!addr.IsAddrV1Compatible());
527544
BOOST_CHECK_EQUAL(addr.ToString(), "fc00:1:2:3:4:5:6:7");
528545
BOOST_REQUIRE(s.empty());
529546

0 commit comments

Comments
 (0)
Please sign in to comment.