@@ -222,6 +222,10 @@ struct Peer {
222222 * Most peers use headers-first syncing, which doesn't use this mechanism */
223223 uint256 m_continuation_block GUARDED_BY (m_block_inv_mutex) {};
224224
225+ Mutex m_msgproc_mutex;
226+ /* * Set to true once initial VERSION message was sent (only relevant for outbound peers). */
227+ bool m_outbound_version_message_sent GUARDED_BY (m_msgproc_mutex){false };
228+
225229 /* * This peer's reported block height when we connected */
226230 std::atomic<int > m_starting_height{-1 };
227231
@@ -312,7 +316,7 @@ class PeerManagerImpl final : public PeerManager
312316 void NewPoWValidBlock (const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override ;
313317
314318 /* * Implement NetEventsInterface */
315- void InitializeNode (CNode* pnode) override ;
319+ void InitializeNode (const CNode* pnode) override ;
316320 void FinalizeNode (const CNode& node) override ;
317321 bool ProcessMessages (CNode* pfrom, std::atomic<bool >& interrupt) override ;
318322 bool SendMessages (CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
@@ -1189,7 +1193,7 @@ void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)
11891193 if (state) state->m_last_block_announcement = time_in_seconds;
11901194}
11911195
1192- void PeerManagerImpl::InitializeNode (CNode *pnode)
1196+ void PeerManagerImpl::InitializeNode (const CNode *pnode)
11931197{
11941198 NodeId nodeid = pnode->GetId ();
11951199 {
@@ -1202,9 +1206,6 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
12021206 LOCK (m_peer_mutex);
12031207 m_peer_map.emplace_hint (m_peer_map.end (), nodeid, std::move (peer));
12041208 }
1205- if (!pnode->IsInboundConn ()) {
1206- PushNodeVersion (*pnode);
1207- }
12081209}
12091210
12101211void PeerManagerImpl::ReattemptInitialBroadcast (CScheduler& scheduler)
@@ -4201,6 +4202,10 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
42014202 PeerRef peer = GetPeerRef (pfrom->GetId ());
42024203 if (peer == nullptr ) return false ;
42034204
4205+ // For outbound connections, ensure that the initial VERSION message
4206+ // has been sent first before processing any incoming messages
4207+ if (!pfrom->IsInboundConn () && WITH_LOCK (peer->m_msgproc_mutex , return !peer->m_outbound_version_message_sent )) return false ;
4208+
42044209 {
42054210 LOCK (peer->m_getdata_requests_mutex );
42064211 if (!peer->m_getdata_requests .empty ()) {
@@ -4660,6 +4665,13 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
46604665 // disconnect misbehaving peers even before the version handshake is complete.
46614666 if (MaybeDiscourageAndDisconnect (*pto, *peer)) return true ;
46624667
4668+ // Initiate version handshake for outbound connections
4669+ if (!pto->IsInboundConn () && WITH_LOCK (peer->m_msgproc_mutex , return !peer->m_outbound_version_message_sent )) {
4670+ LOCK (peer->m_msgproc_mutex );
4671+ PushNodeVersion (*pto);
4672+ peer->m_outbound_version_message_sent = true ;
4673+ }
4674+
46634675 // Don't send anything until the version handshake is complete
46644676 if (!pto->fSuccessfullyConnected || pto->fDisconnect )
46654677 return true ;
0 commit comments