Skip to content

Commit ae01431

Browse files
committed
fix(v2/chain): use actual parent consensus hash instead of slot-derived value
The V2 block production pipeline was incorrectly setting ConsensusBlock.parent_hash to a slot-derived value (Hash256::from_low_u64_be(slot - 1)) instead of querying the actual parent block's consensus hash from storage. This caused block import failures with "Parent block not found" errors because: 1. Producer node creates block with fake derived parent hash (e.g., 0x0000...0b04) 2. Receiver node queries storage for parent by that hash 3. Storage lookup fails - the derived value doesn't match any real block hash 4. Block import rejected, breaking cross-node block propagation Changes: - Modified block production to capture both parent hashes from StorageActor: * parent_execution_hash: Used for Geth forkchoice (execution layer) * parent_consensus_hash: Used for ConsensusBlock.parent_hash (consensus layer) - Updated ConsensusBlock creation to use actual parent_consensus_hash - Matches V0 behavior where ConsensusBlock.parent_hash references real parent block Impact: - Fixes 100% block import failure rate between nodes - Enables proper blockchain synchronization in multi-node networks - Maintains correct parent-child relationships in consensus layer
1 parent 9eba73e commit ae01431

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

app/src/actors_v2/chain/handlers.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ impl Handler<ChainMessage> for ChainActor {
8686

8787
Box::pin(async move {
8888
// Step 2: Get parent block from storage
89-
let parent_hash = if let Some(ref storage_actor) = storage_actor {
89+
// Capture both execution hash (for Geth) and consensus hash (for ConsensusBlock.parent_hash)
90+
let (parent_execution_hash, parent_consensus_hash) = if let Some(ref storage_actor) = storage_actor {
9091
let get_head_msg =
9192
crate::actors_v2::storage::messages::GetChainHeadMessage {
9293
correlation_id: Some(correlation_id),
@@ -98,16 +99,17 @@ impl Handler<ChainMessage> for ChainActor {
9899
Ok(Some(head_ref)) => {
99100
info!(
100101
correlation_id = %correlation_id,
101-
parent_hash = ?head_ref.execution_hash,
102+
parent_execution_hash = ?head_ref.execution_hash,
103+
parent_consensus_hash = ?head_ref.hash,
102104
parent_height = head_ref.number,
103105
"Retrieved chain head for block production"
104106
);
105-
// Use execution hash for Geth (CRITICAL FIX)
106-
head_ref.execution_hash
107+
// Return both hashes: execution for Geth, consensus for parent_hash field
108+
(head_ref.execution_hash, head_ref.hash)
107109
}
108110
Ok(None) => {
109111
info!(correlation_id = %correlation_id, "No chain head found - producing genesis block (parent_hash will be None for Engine)");
110-
lighthouse_wrapper::types::ExecutionBlockHash::zero()
112+
(lighthouse_wrapper::types::ExecutionBlockHash::zero(), lighthouse_wrapper::types::Hash256::zero())
111113
}
112114
Err(e) => {
113115
error!(correlation_id = %correlation_id, error = ?e, "Failed to get chain head");
@@ -193,10 +195,10 @@ impl Handler<ChainMessage> for ChainActor {
193195

194196
// Step 5: Build execution payload via EngineActor
195197
// Convert zero hash to None for genesis (matches V0 behavior)
196-
let parent_hash_for_engine = if parent_hash.into_root().is_zero() {
198+
let parent_hash_for_engine = if parent_execution_hash.into_root().is_zero() {
197199
None
198200
} else {
199-
Some(parent_hash)
201+
Some(parent_execution_hash)
200202
};
201203

202204
let execution_payload = if let Some(ref engine_actor) = engine_actor {
@@ -268,9 +270,7 @@ impl Handler<ChainMessage> for ChainActor {
268270
};
269271

270272
let consensus_block = crate::block::ConsensusBlock {
271-
parent_hash: lighthouse_wrapper::types::Hash256::from_low_u64_be(
272-
slot.saturating_sub(1),
273-
),
273+
parent_hash: parent_consensus_hash, // Use actual parent consensus block hash, not derived from slot
274274
slot,
275275
auxpow_header: None, // Will be set by incorporate_auxpow if available
276276
execution_payload: capella_payload,

0 commit comments

Comments
 (0)