@@ -2410,6 +2410,9 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
24102410
24112411 m_connman.PushMessage (&pfrom, CNetMsgMaker (INIT_PROTO_VERSION).Make (NetMsgType::VERACK));
24122412
2413+ // Signal ADDRv2 support (BIP155).
2414+ m_connman.PushMessage (&pfrom, CNetMsgMaker (INIT_PROTO_VERSION).Make (NetMsgType::SENDADDRv2));
2415+
24132416 pfrom.nServices = nServices;
24142417 pfrom.SetAddrLocal (addrMe);
24152418 {
@@ -2584,9 +2587,29 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
25842587 return ;
25852588 }
25862589
2587- if (msg_type == NetMsgType::ADDR) {
2590+ if (msg_type == NetMsgType::ADDR || msg_type == NetMsgType::ADDRv2) {
2591+ const auto version_orig = vRecv.GetVersion ();
2592+ if (msg_type == NetMsgType::ADDRv2) {
2593+ // Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
2594+ // unserialize methods know that an address in v2 format is coming.
2595+ vRecv.SetVersion (version_orig | ADDRV2_FORMAT);
2596+ }
25882597 std::vector<CAddress> vAddr;
2589- vRecv >> vAddr;
2598+
2599+ try {
2600+ vRecv >> vAddr;
2601+ } catch (const std::exception& e) {
2602+ vRecv.SetVersion (version_orig);
2603+
2604+ LOCK (cs_main);
2605+ Misbehaving (pfrom.GetId (), 20 ,
2606+ strprintf (
2607+ " Supplied us with a message that contains an unparsable address: %s" ,
2608+ e.what ()));
2609+ return ;
2610+ }
2611+
2612+ vRecv.SetVersion (version_orig);
25902613
25912614 if (!pfrom.RelayAddrsWithConn ()) {
25922615 return ;
@@ -2612,6 +2635,11 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
26122635 if (!MayHaveUsefulAddressDB (addr.nServices ) && !HasAllDesirableServiceFlags (addr.nServices ))
26132636 continue ;
26142637
2638+ // Skip invalid addresses, maybe a new BIP155 network id from the future.
2639+ if (!addr.IsValid ()) {
2640+ continue ;
2641+ }
2642+
26152643 if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60 )
26162644 addr.nTime = nNow - 5 * 24 * 60 * 60 ;
26172645 pfrom.AddAddressKnown (addr);
@@ -2637,6 +2665,11 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
26372665 return ;
26382666 }
26392667
2668+ if (msg_type == NetMsgType::SENDADDRv2) {
2669+ pfrom.m_wants_addrv2 = true ;
2670+ return ;
2671+ }
2672+
26402673 if (msg_type == NetMsgType::SENDHEADERS) {
26412674 LOCK (cs_main);
26422675 State (pfrom.GetId ())->fPreferHeaders = true ;
@@ -4134,6 +4167,7 @@ bool PeerManager::SendMessages(CNode* pto)
41344167 std::vector<CAddress> vAddr;
41354168 vAddr.reserve (pto->vAddrToSend .size ());
41364169 assert (pto->m_addr_known );
4170+ const auto & msg_type = pto->m_wants_addrv2 ? NetMsgType::ADDRv2 : NetMsgType::ADDR;
41374171 for (const CAddress& addr : pto->vAddrToSend )
41384172 {
41394173 if (!pto->m_addr_known ->contains (addr.GetKey ()))
@@ -4143,14 +4177,14 @@ bool PeerManager::SendMessages(CNode* pto)
41434177 // receiver rejects addr messages larger than MAX_ADDR_TO_SEND
41444178 if (vAddr.size () >= MAX_ADDR_TO_SEND)
41454179 {
4146- m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::ADDR , vAddr));
4180+ m_connman.PushMessage (pto, msgMaker.Make (msg_type , vAddr));
41474181 vAddr.clear ();
41484182 }
41494183 }
41504184 }
41514185 pto->vAddrToSend .clear ();
41524186 if (!vAddr.empty ())
4153- m_connman.PushMessage (pto, msgMaker.Make (NetMsgType::ADDR , vAddr));
4187+ m_connman.PushMessage (pto, msgMaker.Make (msg_type , vAddr));
41544188 // we only send the big addr message once
41554189 if (pto->vAddrToSend .capacity () > 40 )
41564190 pto->vAddrToSend .shrink_to_fit ();
0 commit comments