diff --git a/beacon_node/execution_layer/src/engine_api.rs b/beacon_node/execution_layer/src/engine_api.rs index aa2b2227f2..4d34628f95 100644 --- a/beacon_node/execution_layer/src/engine_api.rs +++ b/beacon_node/execution_layer/src/engine_api.rs @@ -22,6 +22,7 @@ pub enum Error { IsSyncing, ExecutionBlockNotFound(Hash256), ExecutionHeadBlockNotFound, + ParentHashEqualsBlockHash(Hash256), } impl From for Error { diff --git a/beacon_node/execution_layer/src/lib.rs b/beacon_node/execution_layer/src/lib.rs index 77b0b3058f..2173acf355 100644 --- a/beacon_node/execution_layer/src/lib.rs +++ b/beacon_node/execution_layer/src/lib.rs @@ -309,16 +309,25 @@ impl ExecutionLayer { self.execution_blocks().await.put(block.block_hash, block); + // TODO(merge): This function can theoretically loop indefinitely, as per the + // specification. We should consider how to fix this. See discussion: + // + // https://discord.com/channels/595666850260713488/692062809701482577/892307257205878785 loop { if block.total_difficulty >= self.terminal_total_difficulty() { ttd_exceeding_block = Some(block.block_hash); + // Try to prevent infinite loops. + if block.block_hash == block.parent_hash { + return Err(ApiError::ParentHashEqualsBlockHash(block.block_hash)); + } + block = self .get_pow_block(engine, block.parent_hash) .await? .ok_or(ApiError::ExecutionBlockNotFound(block.parent_hash))?; } else { - return Ok::<_, ApiError>(ttd_exceeding_block); + return Ok(ttd_exceeding_block); } } })