@@ -1318,10 +1318,12 @@ impl BlockchainNode {
13181318
13191319 println!("[PING] 📡 Processing ping signal: {} ({}ms)", node_id, response_time_ms);
13201320
1321- // TODO : Forward to reward manager when available in this context
1322- // For now, just log
1321+ // CRITICAL FIX : Forward to reward manager for tracking
1322+ // Note: In this context we only log, actual recording happens in RPC handler
13231323 if success {
1324- println!("[PING] ✅ Successful ping recorded for {}", node_id);
1324+ println!("[PING] ✅ Successful ping recorded for {} (will be processed by RPC)", node_id);
1325+ } else {
1326+ println!("[PING] ❌ Failed ping for {}", node_id);
13251327 }
13261328 }
13271329 }
@@ -1456,34 +1458,9 @@ impl BlockchainNode {
14561458 fork_producer == p2p.get_node_id()
14571459 } else { false };
14581460
1461+ // CRITICAL FIX: Always handle forks immediately, but rate limit to prevent DoS
14591462 if !own_fork && last_attempt.elapsed().as_secs() < FORK_ATTEMPT_COOLDOWN_SECS {
14601463 println!("[REORG] 🛡️ Fork attempt too soon - rate limited ({}s cooldown)", FORK_ATTEMPT_COOLDOWN_SECS);
1461-
1462- // CRITICAL FIX: If we detect our own blocks being rejected as forks,
1463- // we need to sync with the network majority
1464- if let Some(p2p) = &unified_p2p {
1465- let own_node_id = p2p.get_node_id();
1466- if fork_producer == own_node_id {
1467- println!("[REORG] ⚠️ Our blocks are being rejected! Forcing sync with network majority");
1468-
1469- // Force sync with network to get correct chain
1470- if let Ok(network_height) = p2p.sync_blockchain_height() {
1471- if network_height > *height.read().await {
1472- println!("[REORG] 📥 Network is ahead at height {} - syncing...", network_height);
1473-
1474- // Download missing blocks from network
1475- let local_height = *height.read().await;
1476- // Sync blocks from network
1477- if let Err(e) = p2p.sync_blocks(local_height + 1, network_height).await {
1478- println!("[REORG] ⚠️ Failed to sync blocks: {}", e);
1479- } else {
1480- *height.write().await = network_height;
1481- println!("[REORG] ✅ Synced to network height #{}", network_height);
1482- }
1483- }
1484- }
1485- }
1486- }
14871464 continue;
14881465 }
14891466
@@ -3018,10 +2995,9 @@ impl BlockchainNode {
30182995 println!("[SYNC] ⚠️ Node is {} blocks behind network (local: {}, network: {})",
30192996 height_difference, microblock_height, network_height);
30202997
3021- // For significant lag (>10 blocks), use fast sync
3022- if height_difference > 10 {
2998+
30232999 // RACE CONDITION FIX: Only start fast sync if not already running
3024- if !FAST_SYNC_IN_PROGRESS.swap(true, Ordering::SeqCst) {
3000+ if !FAST_SYNC_IN_PROGRESS.swap(true, Ordering::SeqCst) {
30253001 println!("[SYNC] ⚡ FAST SYNC MODE: {} blocks behind, catching up...", height_difference);
30263002
30273003 // CRITICAL FIX: Do NOT update height before syncing blocks!
@@ -3050,13 +3026,13 @@ impl BlockchainNode {
30503026 // PRODUCTION: Guard ensures flag is cleared even on panic/error
30513027 let _guard = FastSyncGuard;
30523028
3053- println!("[SYNC] 🚀 Fast downloading blocks {}-{}", sync_from_height, sync_to_height);
3029+ println!("[SYNC] 🚀 Fast downloading blocks {}-{}", sync_from_height, sync_to_height);
30543030
30553031 // TIMEOUT PROTECTION: Add 60-second timeout for entire sync operation
30563032 // PRODUCTION: Use parallel download for faster sync
30573033 let sync_result = tokio::time::timeout(
30583034 Duration::from_secs(60),
3059- p2p_clone.parallel_download_microblocks(&storage_clone, sync_from_height, sync_to_height)
3035+ p2p_clone.parallel_download_microblocks(&storage_clone, sync_from_height, sync_to_height)
30603036 ).await;
30613037
30623038 match sync_result {
@@ -3072,13 +3048,6 @@ impl BlockchainNode {
30723048 // Skip this production cycle to focus on syncing
30733049 tokio::time::sleep(Duration::from_millis(100)).await;
30743050 continue;
3075- }
3076- // For moderate lag (10-50 blocks), trigger normal background sync
3077- else {
3078- println!("[SYNC] 🔄 Triggering background sync for {} blocks lag", height_difference);
3079- // Background sync will handle it in the next cycle
3080- // Continue normal operation but log the situation
3081- }
30823051 }
30833052 }
30843053 // else: No cached height - continue with local production
@@ -4079,12 +4048,14 @@ impl BlockchainNode {
40794048 if let Some(ref p2p) = p2p_for_reward {
40804049 if blocks_created == ROTATION_INTERVAL_BLOCKS as u32 {
40814050 // Full rotation completed
4082- p2p.update_node_reputation(&rotation_producer, 30.0);
4083- println!("[ROTATION] ✅ {} completed full rotation ({}/30 blocks) +30.0 reputation",
4051+ // BALANCED: Reduced from +30% to +10% for gradual growth
4052+ p2p.update_node_reputation(&rotation_producer, 10.0);
4053+ println!("[ROTATION] ✅ {} completed full rotation ({}/30 blocks) +10.0 reputation",
40844054 rotation_producer, blocks_created);
40854055 } else {
40864056 // Partial rotation (failover occurred)
4087- let reward = (blocks_created as f64 / 30.0) * 30.0;
4057+ // BALANCED: Proportional to 10% max instead of 30%
4058+ let reward = (blocks_created as f64 / 30.0) * 10.0;
40884059 p2p.update_node_reputation(&rotation_producer, reward);
40894060 println!("[ROTATION] ⚠️ {} partial rotation ({}/30 blocks) +{:.1} reputation",
40904061 rotation_producer, blocks_created, reward);
@@ -4121,11 +4092,17 @@ impl BlockchainNode {
41214092 // TIMING: Measure broadcast time
41224093 let broadcast_start = std::time::Instant::now();
41234094
4124- // WORKING: From 669ca77 - use Turbine only for networks >10 peers
4125- // For small networks (≤10 peers) use direct broadcast - simpler and more reliable
4126- let result = if peer_count > 10 {
4127- // Turbine protocol: O(log n) complexity, fanout=3
4128- // Scales to millions of nodes
4095+ // OPTIMIZATION: Use direct broadcast for critical blocks (emergency, rotation, consensus)
4096+ let is_critical_block = is_emergency_producer ||
4097+ (height_for_broadcast > 1 && (height_for_broadcast - 1) % 30 == 0) || // Rotation
4098+ (height_for_broadcast % 90 >= 61 && height_for_broadcast % 90 <= 90); // Consensus
4099+
4100+ let result = if is_critical_block {
4101+ // CRITICAL: Direct broadcast for immediate delivery (<500ms)
4102+ println!("[P2P] ⚡ PRIORITY broadcast for critical block #{}", height_for_broadcast);
4103+ p2p_clone.broadcast_block(height_for_broadcast, broadcast_data)
4104+ } else if peer_count > 10 {
4105+ // Turbine protocol: O(log n) complexity for large networks
41294106 p2p_clone.broadcast_block_turbine(height_for_broadcast, broadcast_data)
41304107 } else {
41314108 // Direct broadcast: O(n) complexity, works well for ≤10 peers
@@ -4204,13 +4181,13 @@ impl BlockchainNode {
42044181
42054182 if let Some(p2p) = &unified_p2p {
42064183 if blocks_created == ROTATION_INTERVAL_BLOCKS as u32 {
4207- // Full rotation: +30 reputation
4208- p2p.update_node_reputation(&rotation_producer, 30 .0);
4209- println!("[ROTATION] ✅ {} completed full rotation #{} ({}/30 blocks) +30 .0 reputation",
4184+ // Full rotation: BALANCED +10 reputation (was +30)
4185+ p2p.update_node_reputation(&rotation_producer, 10 .0);
4186+ println!("[ROTATION] ✅ {} completed full rotation #{} ({}/30 blocks) +10 .0 reputation",
42104187 rotation_producer, microblock.height / 30, blocks_created);
42114188 } else {
4212- // Partial rotation: proportional reward
4213- let reward = (blocks_created as f64 / 30.0) * 30 .0;
4189+ // Partial rotation: proportional reward (max 10%)
4190+ let reward = (blocks_created as f64 / 30.0) * 10 .0;
42144191 p2p.update_node_reputation(&rotation_producer, reward);
42154192 println!("[ROTATION] ⚠️ {} partial rotation #{} ({}/30 blocks) +{:.1} reputation",
42164193 rotation_producer, microblock.height / 30, blocks_created, reward);
@@ -4405,10 +4382,9 @@ impl BlockchainNode {
44054382 // Check if we were significantly behind (>50 blocks)
44064383 if network_height > current_height + 50 {
44074384 // Node successfully caught up after being behind
4408- // Give significant reputation boost for recovery
4409- // This will help nodes that fell behind to rejoin consensus
4410- p2p_clone.update_node_reputation(&node_id_for_sync, 40.0);
4411- println!("[REPUTATION] 🔄 Node {} recovered from {} block lag! +40.0 reputation boost",
4385+ // BALANCED: Reduced from +40% to +10% for gradual recovery
4386+ p2p_clone.update_node_reputation(&node_id_for_sync, 10.0);
4387+ println!("[REPUTATION] 🔄 Node {} recovered from {} block lag! +10.0 reputation boost",
44124388 node_id_for_sync, network_height - current_height);
44134389 }
44144390 }
@@ -4529,7 +4505,7 @@ impl BlockchainNode {
45294505 } else if is_consensus_period {
45304506 15 // During consensus: more tolerance (was causing false emergencies)
45314507 } else {
4532- 7 // Normal operation: 7 seconds
4508+ 7 // Normal operation: 7 seconds (network optimized for fast broadcast)
45334509 };
45344510
45354511 // Special logging for rotation boundaries
@@ -5629,8 +5605,9 @@ impl BlockchainNode {
56295605 let peer_node_id = format!("genesis_node_{:03}", i + 1);
56305606 if peer_node_id != failed_producer {
56315607 // Give emergency reputation boost to enable recovery
5632- p2p.update_node_reputation(&peer_node_id, 30.0);
5633- println!("[EMERGENCY] 💊 Emergency boost +30% to {} for recovery", peer_node_id);
5608+ // BALANCED: Reduced from +30% to +15% for gradual recovery
5609+ p2p.update_node_reputation(&peer_node_id, 15.0);
5610+ println!("[EMERGENCY] 💊 Emergency boost +15% to {} for recovery", peer_node_id);
56345611
56355612 // Check if now eligible
56365613 let new_reputation = Self::get_node_reputation_score(&peer_node_id, p2p).await;
@@ -5700,8 +5677,9 @@ impl BlockchainNode {
57005677 if !peers.is_empty() {
57015678 // Boost first available peer
57025679 let emergency_peer = &peers[0];
5703- p2p.update_node_reputation(&emergency_peer.id, 50.0);
5704- println!("[EMERGENCY] 💊 Critical boost +50% to {} for network recovery", emergency_peer.id);
5680+ // BALANCED: Reduced from +50% to +20% to prevent instant max reputation
5681+ p2p.update_node_reputation(&emergency_peer.id, 20.0);
5682+ println!("[EMERGENCY] 💊 Critical boost +20% to {} for network recovery", emergency_peer.id);
57055683 return emergency_peer.id.clone();
57065684 }
57075685
@@ -7539,7 +7517,8 @@ impl BlockchainNode {
75397517
75407518 // For new blocks, use light compression (they're hot data)
75417519 // They will be recompressed later with stronger levels as they age
7542- let compressed = zstd::encode_all(&serialized[..], 3) // Level 3 for new blocks
7520+ // OPTIMIZATION: Use level 1 for fastest compression (still good ratio)
7521+ let compressed = zstd::encode_all(&serialized[..], 1) // Level 1 for speed
75437522 .map_err(|e| format!("Zstd compression error: {}", e))?;
75447523
75457524 // Only use compression if it actually reduces size significantly
@@ -7881,16 +7860,18 @@ impl BlockchainNode {
78817860
78827861 // PRODUCTION: Distribute reputation rewards for successful macroblock consensus
78837862 // According to config.ini and ReputationConfig documentation
7884- // Reward consensus leader (+10 reputation)
7885- p2p.update_node_reputation(&consensus_data.leader_id, 10.0);
7886- println!("[REPUTATION] 🏆 Consensus leader {} rewarded: +10.0 reputation", consensus_data.leader_id);
7863+ // Reward consensus leader
7864+ // BALANCED: Reduced from +10% to +5% for gradual growth
7865+ p2p.update_node_reputation(&consensus_data.leader_id, 5.0);
7866+ println!("[REPUTATION] 🏆 Consensus leader {} rewarded: +5.0 reputation", consensus_data.leader_id);
78877867
78887868 // Reward all participants (+5 reputation each)
78897869 for participant_id in &consensus_data.participants {
78907870 // Don't double-reward the leader
78917871 if participant_id != &consensus_data.leader_id {
7892- p2p.update_node_reputation(participant_id, 5.0);
7893- println!("[REPUTATION] ✅ Consensus participant {} rewarded: +5.0 reputation", participant_id);
7872+ // BALANCED: Reduced from +5% to +2% for gradual growth
7873+ p2p.update_node_reputation(participant_id, 2.0);
7874+ println!("[REPUTATION] ✅ Consensus participant {} rewarded: +2.0 reputation", participant_id);
78947875 }
78957876 }
78967877
0 commit comments