Skip to content

Commit c9dd1e7

Browse files
committed
fix(node): handle case of multiple blocks with the same hash
1 parent 8fad0f5 commit c9dd1e7

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

node/src/actors/chain_manager/handlers.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -994,30 +994,41 @@ impl Handler<PeersBeacons> for ChainManager {
994994
} else {
995995
// Review candidates
996996
let consensus_block_hash = consensus_beacon.hash_prev_block;
997-
let candidate = self.candidates.remove(&consensus_block_hash);
997+
let candidates = self
998+
.candidates
999+
.remove(&consensus_block_hash)
1000+
.unwrap_or_default();
9981001
// Clear candidates, as they are only valid for one epoch
9991002
self.candidates.clear();
10001003
self.seen_candidates.clear();
1001-
// TODO: Be functional my friend
1002-
if let Some(consensus_block) = candidate {
1004+
1005+
if candidates.len() > 1 {
1006+
log::warn!(
1007+
"There are {} block candidates with the same hash",
1008+
candidates.len()
1009+
);
1010+
}
1011+
let mut consolidated_consensus_candidate = false;
1012+
for consensus_block in candidates {
10031013
match self.process_requested_block(ctx, consensus_block, false) {
10041014
Ok(()) => {
1015+
consolidated_consensus_candidate = true;
10051016
log::info!(
10061017
"Consolidate consensus candidate. AlmostSynced state"
10071018
);
1008-
StateMachine::AlmostSynced
1019+
break;
10091020
}
10101021
Err(e) => {
10111022
log::debug!(
10121023
"Failed to consolidate consensus candidate: {}",
10131024
e
10141025
);
1015-
1016-
self.request_blocks_batch(ctx);
1017-
1018-
StateMachine::Synchronizing
10191026
}
10201027
}
1028+
}
1029+
1030+
if consolidated_consensus_candidate {
1031+
StateMachine::AlmostSynced
10211032
} else {
10221033
self.request_blocks_batch(ctx);
10231034

node/src/actors/chain_manager/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ pub struct ChainManager {
182182
sync_waiting_for_add_blocks_since: Option<Epoch>,
183183
/// Map that stores candidate blocks for further validation and consolidation as tip of the blockchain
184184
/// (block_hash, block))
185-
candidates: HashMap<Hash, Block>,
185+
candidates: HashMap<Hash, Vec<Block>>,
186186
/// Best candidate
187187
best_candidate: Option<BlockCandidate>,
188188
/// Set that stores all the received candidates
@@ -541,7 +541,10 @@ impl ChainManager {
541541
if self.sm_state == StateMachine::WaitingConsensus
542542
|| self.sm_state == StateMachine::Synchronizing
543543
{
544-
self.candidates.insert(hash_block, block.clone());
544+
self.candidates
545+
.entry(hash_block)
546+
.or_default()
547+
.push(block.clone());
545548
// If the node is not synced, broadcast recent candidates without validating them
546549
self.broadcast_item(InventoryItem::Block(block));
547550

0 commit comments

Comments
 (0)