diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1681,11 +1681,6 @@ }); } -static bool isAvalancheOutboundOrManual(const CNode *pnode) { - return pnode->IsAvalancheOutboundConnection() || - (pnode->IsManualConn() && (pnode->nServices & NODE_AVALANCHE)); -} - void PeerManagerImpl::AvalanchePeriodicNetworking(CScheduler &scheduler) const { const auto now = GetTime(); std::vector avanode_outbound_ids; @@ -1697,7 +1692,7 @@ m_connman.ForEachNode([&](CNode *pnode) { // Build a list of the avalanche manual or outbound peers nodeids - if (isAvalancheOutboundOrManual(pnode)) { + if (!pnode->IsInboundConn() && pnode->sendAvaVersion > 0) { avanode_outbound_ids.push_back(pnode->GetId()); } @@ -3739,38 +3734,6 @@ msgMaker.Make(NetMsgType::SENDAVA, AVALANCHE_SENDAVA_VERSION)); } - - if (g_avalanche->sendHello(&pfrom)) { - LogPrint(BCLog::AVALANCHE, "Send avahello to peer %d\n", - pfrom.GetId()); - - auto localProof = g_avalanche->getLocalProof(); - // If we sent a hello message, we should have a proof - assert(localProof); - - // Add our proof id to the list or the recently announced proof - // INVs to this peer. This is used for filtering which INV can - // be requested for download. - LOCK(cs_main); - State(pfrom.GetId()) - ->m_recently_announced_proofs.insert(localProof->getId()); - } - - // Send getavaaddr and getavaproofs to our avalanche outbound or - // manual connections - if (isAvalancheOutboundOrManual(&pfrom)) { - m_connman.PushMessage(&pfrom, - msgMaker.Make(NetMsgType::GETAVAADDR)); - WITH_LOCK(peer->m_addr_token_bucket_mutex, - peer->m_addr_token_bucket += GetMaxAddrToSend()); - - if (pfrom.m_proof_relay && - !m_chainman.ActiveChainstate().IsInitialBlockDownload()) { - m_connman.PushMessage( - &pfrom, msgMaker.Make(NetMsgType::GETAVAPROOFS)); - pfrom.m_proof_relay->compactproofs_requested = true; - } - } } pfrom.fSuccessfullyConnected = true; @@ -4945,6 +4908,38 @@ pfrom.sendAvaVersion = version; + if (g_avalanche->sendHello(&pfrom)) { + LogPrint(BCLog::AVALANCHE, "Send avahello to peer %d\n", + pfrom.GetId()); + + auto localProof = g_avalanche->getLocalProof(); + // If we sent a hello message, we should have a proof + assert(localProof); + + // Add our proof id to the list or the recently announced proof + // INVs to this peer. This is used for filtering which INV can + // be requested for download. + LOCK(cs_main); + State(pfrom.GetId()) + ->m_recently_announced_proofs.insert(localProof->getId()); + } + + // Send getavaaddr and getavaproofs to our avalanche outbound or + // manual connections + if (!pfrom.IsInboundConn()) { + m_connman.PushMessage(&pfrom, + msgMaker.Make(NetMsgType::GETAVAADDR)); + WITH_LOCK(peer->m_addr_token_bucket_mutex, + peer->m_addr_token_bucket += GetMaxAddrToSend()); + + if (pfrom.m_proof_relay && + !m_chainman.ActiveChainstate().IsInitialBlockDownload()) { + m_connman.PushMessage(&pfrom, + msgMaker.Make(NetMsgType::GETAVAPROOFS)); + pfrom.m_proof_relay->compactproofs_requested = true; + } + } + return; } diff --git a/test/functional/abc_p2p_compactproofs.py b/test/functional/abc_p2p_compactproofs.py --- a/test/functional/abc_p2p_compactproofs.py +++ b/test/functional/abc_p2p_compactproofs.py @@ -73,7 +73,7 @@ p2p_idx = 0 non_avapeers = [] - for i in range(4): + for _ in range(4): peer = P2PInterface() node.add_outbound_p2p_connection( peer, @@ -89,8 +89,9 @@ AvaP2PInterface()) for _ in range(4)] outbound_avapeers = [] - for i in range(4): - peer = P2PInterface() + # With the service bit set + for _ in range(4): + peer = AvaP2PInterface() node.add_outbound_p2p_connection( peer, p2p_idx=p2p_idx, @@ -99,6 +100,17 @@ ) outbound_avapeers.append(peer) p2p_idx += 1 + # Without the service bit set + for _ in range(4): + peer = AvaP2PInterface() + node.add_outbound_p2p_connection( + peer, + p2p_idx=p2p_idx, + connection_type="outbound-full-relay", + services=NODE_NETWORK, + ) + outbound_avapeers.append(peer) + p2p_idx += 1 def all_peers_received_getavaproofs(): with p2p_lock: @@ -138,7 +150,7 @@ self.log.info( "After the first avaproofs has been received, all the peers are requested periodically") - responding_outbound_avapeer = P2PInterface() + responding_outbound_avapeer = AvaP2PInterface() node.add_outbound_p2p_connection( responding_outbound_avapeer, p2p_idx=p2p_idx, @@ -298,7 +310,7 @@ def add_avalanche_p2p_outbound(): nonlocal p2p_idx - peer = P2PInterface() + peer = AvaP2PInterface() node.add_outbound_p2p_connection( peer, p2p_idx=p2p_idx, diff --git a/test/functional/abc_p2p_getavaaddr.py b/test/functional/abc_p2p_getavaaddr.py --- a/test/functional/abc_p2p_getavaaddr.py +++ b/test/functional/abc_p2p_getavaaddr.py @@ -242,7 +242,7 @@ avapeers = [] for i in range(16): - avapeer = P2PInterface() + avapeer = AvaP2PInterface() node.add_outbound_p2p_connection( avapeer, p2p_idx=i, diff --git a/test/functional/abc_p2p_sendava.py b/test/functional/abc_p2p_sendava.py --- a/test/functional/abc_p2p_sendava.py +++ b/test/functional/abc_p2p_sendava.py @@ -4,10 +4,12 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test version message behavior""" +from test_framework.avatools import gen_proof from test_framework.messages import msg_sendava, msg_version from test_framework.p2p import P2P_SUBVERSION, P2PInterface, p2p_lock from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal +from test_framework.wallet_util import bytes_to_wif # Extracted from version.h SENDAVA_VERSION = 70017 @@ -51,20 +53,44 @@ sendava_version_peer.message_count.get( "sendava", 0), 0) - self.restart_node(0, extra_args=['-enableavalanche=1']) + privkey, proof = gen_proof(node) + self.restart_node(0, extra_args=[ + '-enableavalanche=1', + f'-avamasterkey={bytes_to_wif(privkey.get_bytes())}', + f'-avaproof={proof.serialize().hex()}', + ]) low_version_peer = CustomVersionP2PInterface(SENDAVA_VERSION - 1) - node.add_p2p_connection(low_version_peer) + node.add_outbound_p2p_connection( + low_version_peer, + p2p_idx=0, + ) low_version_peer.sync_with_ping() with p2p_lock: assert_equal(low_version_peer.message_count.get("sendava", 0), 0) sendava_version_peer = CustomVersionP2PInterface(SENDAVA_VERSION) - node.add_p2p_connection(sendava_version_peer) + node.add_outbound_p2p_connection( + sendava_version_peer, + p2p_idx=1, + ) sendava_version_peer.wait_until( lambda: sendava_version_peer.last_message.get("sendava")) + for peer in [low_version_peer, sendava_version_peer]: + with p2p_lock: + assert_equal(peer.message_count.get("avahello", 0), 0) + assert_equal(peer.message_count.get("getavaaddr", 0), 0) + assert_equal(peer.message_count.get("getavaproofs", 0), 0) + + peer.send_message(msg_sendava()) + peer.wait_until( + lambda: + peer.message_count.get("avahello", 0) > 0 and + peer.message_count.get("getavaaddr", 0) > 0 and + peer.message_count.get("getavaproofs", 0) > 0) + duplicated_sendava_peer = CustomVersionP2PInterface(SENDAVA_VERSION) node.add_p2p_connection(duplicated_sendava_peer) duplicated_sendava_peer.send_message(msg_sendava()) diff --git a/test/functional/test_framework/avatools.py b/test/functional/test_framework/avatools.py --- a/test/functional/test_framework/avatools.py +++ b/test/functional/test_framework/avatools.py @@ -29,6 +29,7 @@ msg_avapoll, msg_avaproof, msg_avaproofs, + msg_sendava, msg_tcpavaresponse, ) from .p2p import P2PInterface, p2p_lock @@ -206,6 +207,8 @@ self.remote_nonce = message.nNonce self.remote_extra_entropy = message.nExtraEntropy + self.send_message(msg_sendava()) + def on_avaresponse(self, message): self.avaresponses.append(message.response)