@@ -342,8 +342,8 @@ impl SimplifiedP2P {
342342
343343 println ! ( "[P2P] 📊 Successfully parsed {}/{} bootstrap peers" , successful_parses, peers. len( ) ) ;
344344
345- // Try to establish connections
346- self . establish_regional_connections ( ) ;
345+ // STARTUP FIX: Establish connections asynchronously to prevent blocking startup
346+ self . start_regional_connection_establishment ( ) ;
347347 }
348348
349349 /// Add discovered peers to running P2P system (dynamic peer injection)
@@ -2048,124 +2048,256 @@ impl SimplifiedP2P {
20482048 . push ( peer) ;
20492049 }
20502050
2051- /// Establish connections within region and backups
2052- fn establish_regional_connections ( & self ) {
2053- let regional_peers = match self . regional_peers . lock ( ) {
2054- Ok ( peers) => peers,
2055- Err ( poisoned) => {
2056- println ! ( "[P2P] ⚠️ Regional peers mutex poisoned during connection establishment" ) ;
2057- poisoned. into_inner ( )
2058- }
2059- } ;
2060- let mut connected = match self . connected_peers . lock ( ) {
2061- Ok ( peers) => peers,
2062- Err ( poisoned) => {
2063- println ! ( "[P2P] ⚠️ Connected peers mutex poisoned during connection establishment" ) ;
2064- poisoned. into_inner ( )
2065- }
2066- } ;
2051+ /// STARTUP FIX: Start regional connection establishment asynchronously (non-blocking startup)
2052+ fn start_regional_connection_establishment ( & self ) {
2053+ let regional_peers = self . regional_peers . clone ( ) ;
2054+ let connected_peers = self . connected_peers . clone ( ) ;
2055+ let primary_region = self . primary_region . clone ( ) ;
2056+ let backup_regions = self . backup_regions . clone ( ) ;
20672057
2068- // Connect to primary region first - WITH REAL connectivity validation
2069- if let Some ( peers) = regional_peers. get ( & self . primary_region ) {
2070- // DYNAMIC: Use flexible connection limits based on network conditions
2071- let is_bootstrap_node = std:: env:: var ( "QNET_BOOTSTRAP_ID" ) . is_ok ( ) ;
2072- let active_peers = connected. len ( ) ;
2073- let is_small_network = active_peers < 10 ;
2074- let use_all_peers = is_bootstrap_node || is_small_network;
2058+ // EXISTING PATTERN: Use tokio::spawn like search_internet_peers for non-blocking startup
2059+ tokio:: spawn ( async move {
2060+ println ! ( "[P2P] 🔧 Starting regional connection establishment (background)..." ) ;
20752061
2076- // ROBUST: Connect to ALL peers during bootstrap or small network formation
2077- let peer_limit = if use_all_peers { peers. len ( ) } else { 5 } ;
2078- for peer in peers. iter ( ) . take ( peer_limit) {
2079- // Use previously defined is_genesis_startup variable
2080-
2081- let ip = peer. addr . split ( ':' ) . next ( ) . unwrap_or ( "" ) ;
2082- let is_genesis_peer = is_genesis_node_ip ( ip) ;
2083-
2084- // EXISTING: All peers use same validation logic for consistency
2085- if self . is_peer_actually_connected ( & peer. addr ) {
2086- connected. push ( peer. clone ( ) ) ;
2087- println ! ( "[P2P] ✅ Added {} to connection pool from {:?} (REAL connection verified)" , peer. id, peer. region) ;
2088- } else {
2089- // DIAGNOSTIC: Log why peer was skipped
2090- println ! ( "[P2P] ❌ Skipped {} from {:?} (connection failed)" , peer. id, peer. region) ;
2091- println ! ( "[P2P] 🔍 DIAGNOSTIC: Genesis peer: {}" , is_genesis_peer) ;
2062+ let regional_peers_data = match regional_peers. lock ( ) {
2063+ Ok ( peers) => peers. clone ( ) , // Clone the data to avoid lifetime issues
2064+ Err ( poisoned) => {
2065+ println ! ( "[P2P] ⚠️ Regional peers mutex poisoned during connection establishment" ) ;
2066+ poisoned. into_inner ( ) . clone ( )
20922067 }
2093- }
2094- }
2095-
2096- // DYNAMIC: For bootstrap nodes or small networks, connect to ALL Genesis nodes regardless of region
2097- let is_bootstrap_node = std:: env:: var ( "QNET_BOOTSTRAP_ID" ) . is_ok ( ) ;
2098- let active_peers = connected. len ( ) ;
2099- let is_small_network = active_peers < 10 ;
2100- let should_connect_all_genesis = is_bootstrap_node || is_small_network;
2101-
2102- if should_connect_all_genesis {
2103- println ! ( "[P2P] 🌟 GENESIS MODE: Attempting to connect to all Genesis peers regardless of region" ) ;
2068+ } ;
21042069
2105- // Try all regions for Genesis peers
2106- for ( region, peers_in_region) in regional_peers. iter ( ) {
2107- for peer in peers_in_region. iter ( ) . take ( 5 ) {
2070+ let mut connected_data = match connected_peers. lock ( ) {
2071+ Ok ( peers) => peers. clone ( ) , // Clone the data
2072+ Err ( poisoned) => {
2073+ println ! ( "[P2P] ⚠️ Connected peers mutex poisoned during connection establishment" ) ;
2074+ poisoned. into_inner ( ) . clone ( )
2075+ }
2076+ } ;
2077+
2078+ // Connect to primary region first - WITH REAL connectivity validation
2079+ if let Some ( peers) = regional_peers_data. get ( & primary_region) {
2080+ // DYNAMIC: Use flexible connection limits based on network conditions
2081+ let is_bootstrap_node = std:: env:: var ( "QNET_BOOTSTRAP_ID" ) . is_ok ( ) ;
2082+ let active_peers = connected_data. len ( ) ;
2083+ let is_small_network = active_peers < 10 ;
2084+ let use_all_peers = is_bootstrap_node || is_small_network;
2085+
2086+ // ROBUST: Connect to ALL peers during bootstrap or small network formation
2087+ let peer_limit = if use_all_peers { peers. len ( ) } else { 5 } ;
2088+ for peer in peers. iter ( ) . take ( peer_limit) {
2089+ // Use previously defined is_genesis_startup variable
2090+
21082091 let ip = peer. addr . split ( ':' ) . next ( ) . unwrap_or ( "" ) ;
21092092 let is_genesis_peer = is_genesis_node_ip ( ip) ;
21102093
2111- if is_genesis_peer {
2112- // Skip if already connected
2113- let already_connected = connected. iter ( ) . any ( |p| p. addr == peer. addr ) ;
2114- if !already_connected {
2115- connected. push ( peer. clone ( ) ) ;
2116- println ! ( "[P2P] 🌟 Added Genesis peer {} from region {:?} (startup mode)" , peer. addr, region) ;
2117- }
2094+ // EXISTING: Use static connectivity check for async context
2095+ if Self :: is_peer_actually_connected_static ( & peer. addr , active_peers) {
2096+ connected_data. push ( peer. clone ( ) ) ;
2097+ println ! ( "[P2P] ✅ Added {} to connection pool from {:?} (REAL connection verified)" , peer. id, peer. region) ;
2098+ } else {
2099+ // DIAGNOSTIC: Log why peer was skipped
2100+ println ! ( "[P2P] ❌ Skipped {} from {:?} (connection failed)" , peer. id, peer. region) ;
2101+ println ! ( "[P2P] 🔍 DIAGNOSTIC: Genesis peer: {}" , is_genesis_peer) ;
21182102 }
21192103 }
2120- }
21212104 }
21222105
2123- // If not enough peers, try backup regions - WITH REAL connectivity validation
2124- if connected. len ( ) < 3 {
2125- // DYNAMIC: For backup regions, use flexible limits based on network conditions
2106+ // DYNAMIC: For bootstrap nodes or small networks, connect to ALL Genesis nodes regardless of region
21262107 let is_bootstrap_node = std:: env:: var ( "QNET_BOOTSTRAP_ID" ) . is_ok ( ) ;
2127- let current_peers = connected . len ( ) ;
2128- let is_small_network = current_peers < 10 ;
2129- let use_all_backup_peers = is_bootstrap_node || is_small_network;
2108+ let active_peers = connected_data . len ( ) ;
2109+ let is_small_network = active_peers < 10 ;
2110+ let should_connect_all_genesis = is_bootstrap_node || is_small_network;
21302111
2131- for backup_region in & self . backup_regions {
2132- if let Some ( peers) = regional_peers. get ( backup_region) {
2112+ if should_connect_all_genesis {
2113+ println ! ( "[P2P] 🌟 GENESIS MODE: Attempting to connect to all Genesis peers regardless of region" ) ;
2114+
2115+ // Try all regions for Genesis peers
2116+ for ( region, peers_in_region) in regional_peers_data. iter ( ) {
2117+ for peer in peers_in_region. iter ( ) . take ( 5 ) {
2118+ let ip = peer. addr . split ( ':' ) . next ( ) . unwrap_or ( "" ) ;
2119+ let is_genesis_peer = is_genesis_node_ip ( ip) ;
2120+
2121+ if is_genesis_peer {
2122+ // Skip if already connected
2123+ let already_connected = connected_data. iter ( ) . any ( |p| p. addr == peer. addr ) ;
2124+ if !already_connected {
2125+ connected_data. push ( peer. clone ( ) ) ;
2126+ println ! ( "[P2P] 🌟 Added Genesis peer {} from region {:?} (startup mode)" , peer. addr, region) ;
2127+ }
2128+ }
2129+ }
2130+ }
2131+ }
2132+
2133+ // If not enough peers, try backup regions - WITH REAL connectivity validation
2134+ if connected_data. len ( ) < 3 {
2135+ // DYNAMIC: For backup regions, use flexible limits based on network conditions
2136+ let is_bootstrap_node = std:: env:: var ( "QNET_BOOTSTRAP_ID" ) . is_ok ( ) ;
2137+ let current_peers = connected_data. len ( ) ;
2138+ let is_small_network = current_peers < 10 ;
2139+ let use_all_backup_peers = is_bootstrap_node || is_small_network;
2140+
2141+ for backup_region in & backup_regions {
2142+ if let Some ( peers) = regional_peers_data. get ( backup_region) {
21332143 // ROBUST: Connect to ALL backup peers during bootstrap or small network formation
21342144 let backup_limit = if use_all_backup_peers { peers. len ( ) } else { 2 } ;
21352145 for peer in peers. iter ( ) . take ( backup_limit) {
2136- // DYNAMIC: Remove connection limit for small networks or bootstrap nodes
2137- let should_connect = if use_all_backup_peers { true } else { connected . len ( ) < 5 } ;
2146+ // DYNAMIC: Remove connection limit for small networks or bootstrap nodes
2147+ let should_connect = if use_all_backup_peers { true } else { connected_data . len ( ) < 5 } ;
21382148 if should_connect {
21392149 let ip = peer. addr . split ( ':' ) . next ( ) . unwrap_or ( "" ) ;
21402150 let is_genesis_peer = is_genesis_node_ip ( ip) ;
21412151
2142- // FIXED: Genesis peers ALWAYS use relaxed validation (no time dependency)
2143- if is_genesis_peer {
2144- connected. push ( peer. clone ( ) ) ;
2145- println ! ( "[P2P] ✅ Added Genesis backup {} (bootstrap trust)" , peer. addr) ;
2146- } else if self . is_peer_actually_connected ( & peer. addr ) {
2147- connected. push ( peer. clone ( ) ) ;
2148- println ! ( "[P2P] ✅ Added {} to backup pool from {:?} (REAL connection verified)" ,
2152+ // FIXED: Genesis peers ALWAYS use relaxed validation (no time dependency)
2153+ if is_genesis_peer {
2154+ connected_data. push ( peer. clone ( ) ) ;
2155+ println ! ( "[P2P] ✅ Added Genesis backup {} (bootstrap trust)" , peer. addr) ;
2156+ } else if Self :: is_peer_actually_connected_static ( & peer. addr , current_peers) {
2157+ connected_data. push ( peer. clone ( ) ) ;
2158+ println ! ( "[P2P] ✅ Added {} to backup pool from {:?} (REAL connection verified)" ,
2159+ peer. id, peer. region) ;
2160+ } else {
2161+ println ! ( "[P2P] ❌ Skipped backup peer {} from {:?} (connection failed)" ,
21492162 peer. id, peer. region) ;
2150- } else {
2151- println ! ( "[P2P] ❌ Skipped backup peer {} from {:?} (connection failed)" ,
2152- peer. id, peer. region) ;
2153- }
2163+ }
21542164 }
21552165 }
21562166 }
2167+ }
21572168 }
2158- }
2169+
2170+ // Update real connected_peers with results from background establishment
2171+ if let Ok ( mut connected) = connected_peers. lock ( ) {
2172+ * connected = connected_data;
2173+ println ! ( "[P2P] 📋 Regional connection establishment completed: {} peers connected" , connected. len( ) ) ;
2174+ } else {
2175+ println ! ( "[P2P] ⚠️ Failed to update connected_peers after establishment" ) ;
2176+ }
2177+ } ) ;
21592178
2160- * self . connection_count . lock ( ) . unwrap ( ) = connected. len ( ) ;
2179+ println ! ( "[P2P] ⚡ Regional connection establishment started (non-blocking startup)" ) ;
2180+ }
2181+
2182+ /// STATIC VERSION: Check if peer is actually connected (async-safe)
2183+ fn is_peer_actually_connected_static ( peer_addr : & str , active_peers : usize ) -> bool {
2184+ // PRODUCTION: Real connectivity check using EXISTING static methods
2185+ let ip = peer_addr. split ( ':' ) . next ( ) . unwrap_or ( "" ) ;
2186+ let is_genesis = is_genesis_node_ip ( ip) ;
21612187
2162- if connected. is_empty ( ) {
2163- println ! ( "[P2P] ⚠️ No peers in bootstrap pool - running in standalone mode" ) ;
2188+ // DYNAMIC: Use relaxed validation for Genesis peers in small networks
2189+ let is_bootstrap_node = std:: env:: var ( "QNET_BOOTSTRAP_ID" ) . is_ok ( ) ;
2190+ let is_small_network = active_peers < 10 ;
2191+ let use_relaxed_validation = is_bootstrap_node || is_small_network;
2192+
2193+ // DIAGNOSTIC: Log detailed validation process to debug phantom peers
2194+ println ! ( "[DEBUG-PHANTOM] 🔍 Static validating peer: {} (IP: {}, Genesis: {}, Small network: {}, Bootstrap: {})" ,
2195+ peer_addr, ip, is_genesis, is_small_network, is_bootstrap_node) ;
2196+
2197+ if is_genesis {
2198+ // EXISTING: Use FAST TCP connectivity check (same as instance method)
2199+ let is_connected = Self :: test_peer_connectivity_static ( peer_addr) ;
2200+
2201+ if is_connected {
2202+ println ! ( "[P2P] ✅ Genesis peer {} - FAST TCP connection verified" , peer_addr) ;
2203+ true
2204+ } else {
2205+ if use_relaxed_validation {
2206+ println ! ( "[P2P] ⏳ Genesis peer {} - using relaxed validation for network formation" , peer_addr) ;
2207+ true // Allow for bootstrap/small networks
2208+ } else {
2209+ println ! ( "[P2P] ❌ Genesis peer {} - TCP connection failed, excluding from consensus" , peer_addr) ;
2210+ false
2211+ }
2212+ }
21642213 } else {
2165- println ! ( "[P2P] 📋 Bootstrap pool populated with {} peers (pending validation)" , connected. len( ) ) ;
2214+ // For non-genesis: use existing query_peer_height_http through static methods
2215+ println ! ( "[DEBUG-PHANTOM] 🔍 Non-Genesis peer validation for: {}" , peer_addr) ;
2216+
2217+ // EXISTING: Use same pattern as query_peer_height but static
2218+ let api_endpoints = vec ! [
2219+ format!( "http://{}:8001/api/v1/height" , ip) , // EXISTING: Same endpoint as query_peer_height
2220+ ] ;
2221+
2222+ for endpoint in api_endpoints {
2223+ match Self :: query_peer_height_http_static ( & endpoint) {
2224+ Ok ( _height) => {
2225+ println ! ( "[DEBUG-PHANTOM] ✅ Non-Genesis peer {} height query OK" , peer_addr) ;
2226+ return true ;
2227+ }
2228+ Err ( e) => {
2229+ println ! ( "[DEBUG-PHANTOM] ❌ Non-Genesis peer {} height query failed: {}" , peer_addr, e) ;
2230+ continue ;
2231+ }
2232+ }
2233+ }
2234+
2235+ if use_relaxed_validation {
2236+ println ! ( "[DEBUG-PHANTOM] 🚨 PHANTOM NON-GENESIS ALLOWED: {} (relaxed validation)" , peer_addr) ;
2237+ true // Tolerate during network formation
2238+ } else {
2239+ println ! ( "[DEBUG-PHANTOM] ✅ PHANTOM NON-GENESIS BLOCKED: {} (strict validation)" , peer_addr) ;
2240+ false
2241+ }
21662242 }
21672243 }
21682244
2245+ /// STATIC VERSION: Query peer height via HTTP (async-safe, same logic as instance method)
2246+ fn query_peer_height_http_static ( endpoint : & str ) -> Result < u64 , String > {
2247+ use std:: time:: Duration ;
2248+
2249+ // EXISTING: Use same quick timeouts as check_api_readiness_static for microblock compatibility
2250+ let client = reqwest:: blocking:: Client :: builder ( )
2251+ . timeout ( Duration :: from_secs ( 5 ) ) // EXISTING: Same as check_api_readiness_static (quick API checks)
2252+ . connect_timeout ( Duration :: from_secs ( 3 ) ) // EXISTING: Same as check_api_readiness_static (quick connect)
2253+ . tcp_keepalive ( Duration :: from_secs ( 30 ) ) // Keep connections alive
2254+ . build ( )
2255+ . map_err ( |e| format ! ( "HTTP client error: {}" , e) ) ?;
2256+
2257+ // EXISTING: Use same single-attempt pattern as check_api_readiness_static for microblock speed
2258+ let max_attempts = 1 ; // EXISTING: Single attempt (same as check_api_readiness_static)
2259+ let retry_delay = Duration :: from_secs ( 0 ) ; // EXISTING: No delays for quick operations
2260+
2261+ for attempt in 1 ..=max_attempts {
2262+ match client. get ( endpoint) . send ( ) {
2263+ Ok ( response) if response. status ( ) . is_success ( ) => {
2264+ match response. json :: < serde_json:: Value > ( ) {
2265+ Ok ( json) => {
2266+ if let Some ( height) = json. get ( "height" ) . and_then ( |h| h. as_u64 ( ) ) {
2267+ return Ok ( height) ;
2268+ } else {
2269+ return Err ( "Invalid height format in response" . to_string ( ) ) ;
2270+ }
2271+ }
2272+ Err ( e) => {
2273+ if attempt < max_attempts {
2274+ // EXISTING: No delays for single-attempt quick operations
2275+ continue ;
2276+ }
2277+ return Err ( format ! ( "JSON parse error: {}" , e) ) ;
2278+ }
2279+ }
2280+ }
2281+ Ok ( response) => {
2282+ if attempt < max_attempts {
2283+ // EXISTING: No delays for single-attempt quick operations
2284+ continue ;
2285+ }
2286+ return Err ( format ! ( "HTTP error: {}" , response. status( ) ) ) ;
2287+ }
2288+ Err ( e) => {
2289+ if attempt < max_attempts {
2290+ // EXISTING: No delays for single-attempt quick operations
2291+ continue ;
2292+ }
2293+ return Err ( format ! ( "Request failed: {}" , e) ) ;
2294+ }
2295+ }
2296+ }
2297+
2298+ Err ( "All retry attempts failed" . to_string ( ) )
2299+ }
2300+
21692301 /// Intelligent peer selection with load balancing
21702302 pub fn select_optimal_peers ( & self , required_count : usize ) -> Vec < PeerInfo > {
21712303 let regional_peers = self . regional_peers . lock ( ) . unwrap ( ) ;
0 commit comments