diff --git a/crates/blockchain/dev/block_producer.rs b/crates/blockchain/dev/block_producer.rs index 5937a1b972c..c32e58a6031 100644 --- a/crates/blockchain/dev/block_producer.rs +++ b/crates/blockchain/dev/block_producer.rs @@ -3,7 +3,7 @@ use ethereum_types::{Address, H256}; use ethrex_rpc::clients::{EngineClient, EngineClientError}; use ethrex_rpc::types::fork_choice::{ForkChoiceState, PayloadAttributesV3}; use sha2::{Digest, Sha256}; -use std::time::{SystemTime, UNIX_EPOCH}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; pub async fn start_block_producer( execution_client_auth_url: String, @@ -15,6 +15,11 @@ pub async fn start_block_producer( ) -> Result<(), EngineClientError> { let engine_client = EngineClient::new(&execution_client_auth_url, jwt_secret); + let mut ticker = tokio::time::interval(Duration::from_millis(block_production_interval_ms)); + + // Sleep until the first tick to avoid timestamp collision with the genesis block. + ticker.tick().await; + let mut head_block_hash: H256 = head_block_hash; let parent_beacon_block_root = H256::zero(); let mut tries = 0; @@ -53,6 +58,11 @@ pub async fn start_block_producer( let payload_id = fork_choice_response .payload_id .expect("Failed to produce block: payload_id is None in ForkChoiceResponse"); + + // Wait for the next tick to retrieve the payload. + // Note that this makes getPayload failures result in skipped blocks. + ticker.tick().await; + let execution_payload_response = match engine_client.engine_get_payload_v5(payload_id).await { Ok(response) => { @@ -113,11 +123,6 @@ pub async fn start_block_producer( tracing::info!("Produced block {produced_block_hash:#x}"); head_block_hash = produced_block_hash; - - tokio::time::sleep(tokio::time::Duration::from_millis( - block_production_interval_ms, - )) - .await; } Err(EngineClientError::SystemFailed(format!("{max_tries}"))) }