Skip to content

Commit 9fd2094

Browse files
committed
fix: critical Genesis consensus issues - reputation consistency and producer override timing
1 parent bee14e3 commit 9fd2094

1 file changed

Lines changed: 24 additions & 33 deletions

File tree

  • development/qnet-integration/src

development/qnet-integration/src/node.rs

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -771,15 +771,24 @@ impl BlockchainNode {
771771
.as_secs();
772772

773773
if current_time >= QNET_GENESIS_TIMESTAMP {
774-
// DEADLOCK FIX: Allow selected producer to start even with <4 nodes
775-
// Microblocks only need producer signature, not full consensus
776-
if is_selected_producer {
777-
println!("[MICROBLOCK] 🎯 PRODUCER OVERRIDE: Starting as selected producer with {} nodes (microblock production only)", active_node_count);
774+
// CONSERVATIVE PRODUCER OVERRIDE: Allow selected producer to start ONLY after grace period
775+
// This prevents premature block creation with insufficient network connectivity
776+
let grace_period_seconds = 300; // 5 minutes grace period for network formation
777+
let network_ready_time = QNET_GENESIS_TIMESTAMP + grace_period_seconds;
778+
779+
if is_selected_producer && current_time >= network_ready_time {
780+
println!("[MICROBLOCK] 🎯 PRODUCER OVERRIDE: Starting as selected producer with {} nodes (after {}min grace period)", active_node_count, grace_period_seconds / 60);
778781
println!("[MICROBLOCK] ⚡ Producer can create blocks without full Byzantine consensus for microblocks");
779-
// Continue to production - producer can work with reduced nodes
782+
// Continue to production - producer can work with reduced nodes after grace period
780783
} else if active_node_count >= 4 {
781784
println!("[MICROBLOCK] 🚀 COORDINATED START: Genesis time reached, starting with {} nodes (Byzantine safe)", active_node_count);
782785
// Continue to production with proper Byzantine safety
786+
} else if is_selected_producer {
787+
let remaining_grace = network_ready_time.saturating_sub(current_time);
788+
println!("[MICROBLOCK] ⏳ Producer waiting for grace period: {}s remaining before override allowed", remaining_grace);
789+
println!("[MICROBLOCK] 🛡️ Grace period prevents premature block creation with insufficient network");
790+
tokio::time::sleep(Duration::from_secs(5)).await;
791+
continue;
783792
} else {
784793
println!("[MICROBLOCK] ⏳ Genesis coordinated start: insufficient nodes for Byzantine safety: {}/4", active_node_count);
785794
println!("[MICROBLOCK] 🛡️ Waiting for minimum 4 Genesis nodes before network start (not producer)");
@@ -1392,38 +1401,20 @@ impl BlockchainNode {
13921401
async fn initialize_genesis_reputations(p2p: &SimplifiedP2P) {
13931402
println!("[REPUTATION] 🔐 Initializing ACTIVE Genesis node reputations...");
13941403

1395-
// PRODUCTION: Wait briefly for P2P discovery to find active Genesis nodes
1396-
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
1397-
1398-
// Get currently active peers from P2P discovery
1399-
let active_peers = p2p.get_validated_active_peers();
1400-
let mut genesis_nodes_found = 0;
1401-
1402-
println!("[REPUTATION] 🔍 Scanning {} active peers for Genesis nodes", active_peers.len());
1404+
// CRITICAL FIX: Initialize ALL Genesis nodes deterministically regardless of discovery status
1405+
// This ensures consistent candidate lists across all nodes for Byzantine consensus
1406+
let genesis_ips = crate::unified_p2p::get_genesis_bootstrap_ips();
14031407

1404-
for peer in active_peers {
1405-
let peer_ip = peer.addr.split(':').next().unwrap_or(&peer.addr);
1408+
for (i, _genesis_ip) in genesis_ips.iter().enumerate() {
1409+
let genesis_id = format!("genesis_node_{:03}", i + 1);
14061410

1407-
// Check if this peer is a Genesis node using IP mapping
1408-
if let Some(genesis_id_suffix) = crate::genesis_constants::get_genesis_id_by_ip(peer_ip) {
1409-
let genesis_id = format!("genesis_node_{}", genesis_id_suffix);
1410-
1411-
println!("[DIAGNOSTIC] 🔧 Setting reputation for Genesis node: {} -> 90.0", genesis_id);
1412-
// Set reputation only for DISCOVERED Genesis nodes
1413-
p2p.set_node_reputation(&genesis_id, 90.0);
1414-
1415-
let final_reputation = match p2p.get_reputation_system().lock() {
1416-
Ok(reputation) => reputation.get_reputation(&genesis_id),
1417-
Err(_) => 90.0,
1418-
};
1419-
1420-
println!("[REPUTATION] 🔐 ACTIVE Genesis {} set to {}% reputation ({})",
1421-
genesis_id, final_reputation, peer.addr);
1422-
genesis_nodes_found += 1;
1423-
}
1411+
// Set 90% reputation for ALL Genesis nodes on ALL nodes
1412+
p2p.set_node_reputation(&genesis_id, 90.0);
1413+
1414+
println!("[REPUTATION] 🔐 Genesis {} initialized to 90% reputation (deterministic)", genesis_id);
14241415
}
14251416

1426-
println!("[REPUTATION] ✅ Initialized {} ACTIVE Genesis nodes (no phantom reputation)", genesis_nodes_found);
1417+
println!("[REPUTATION] ✅ All 5 Genesis nodes initialized with 90% reputation on ALL nodes");
14271418

14281419
// CRITICAL FIX: Set own Genesis reputation to 90%
14291420
if let Ok(bootstrap_id) = std::env::var("QNET_BOOTSTRAP_ID") {

0 commit comments

Comments
 (0)