Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
.idea/
testnet/
.vscode/*
.nvim.lua
30 changes: 30 additions & 0 deletions finalizer/src/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,36 @@ impl<
}))
.await;

// Send initial forkchoice to the execution client so it knows the chain
// head and can start P2P sync. Then wait for sync to complete before
// replaying any blocks. Without this, catch-up blocks fail because the
// execution client doesn't have them yet.
{
let forkchoice = self.canonical_state.forkchoice;
if !forkchoice.head_block_hash.is_zero() {
info!(
head = %forkchoice.head_block_hash,
"sending initial forkchoice update to execution client, waiting for sync..."
);
loop {
let status = self.engine_client.commit_hash_with_status(forkchoice).await;
if status.is_valid() {
info!("execution client synced to checkpoint head, ready to replay blocks");
break;
} else if status.is_syncing() {
info!("execution client still syncing, waiting 5s...");
self.context.sleep(std::time::Duration::from_secs(5)).await;
} else {
warn!(
?status,
"unexpected response to initial forkchoice update, proceeding anyway"
);
break;
}
}
}
}

loop {
if self.validator_exit
&& is_first_block_of_epoch(
Expand Down
16 changes: 15 additions & 1 deletion finalizer/src/tests/mocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
use alloy_primitives::{Address, FixedBytes, U256};
use alloy_rpc_types_engine::{
ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, ExecutionPayloadV1, ExecutionPayloadV2,
ExecutionPayloadV3, ForkchoiceState, PayloadId, PayloadStatus, PayloadStatusEnum,
ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus,
PayloadStatusEnum,
};
use commonware_consensus::simplex::scheme::bls12381_multisig;
use commonware_consensus::simplex::types::{Finalization, Finalize, Proposal};
Expand Down Expand Up @@ -136,6 +137,19 @@ impl EngineClient for MockEngineClient {
}

async fn commit_hash(&mut self, _fork_choice_state: ForkchoiceState) {}

async fn commit_hash_with_status(
&mut self,
_fork_choice_state: ForkchoiceState,
) -> ForkchoiceUpdated {
ForkchoiceUpdated {
payload_status: PayloadStatus {
status: PayloadStatusEnum::Valid,
latest_valid_hash: Some([0u8; 32].into()),
},
payload_id: None,
}
}
}

/// Minimal mock NetworkOracle
Expand Down
2 changes: 1 addition & 1 deletion node/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub const BLOCKS_PER_EPOCH: u64 = 50;
#[cfg(debug_assertions)]
pub const BLOCKS_PER_EPOCH: u64 = 10;
#[cfg(all(not(debug_assertions), not(feature = "e2e")))]
const BLOCKS_PER_EPOCH: u64 = 10000;
const BLOCKS_PER_EPOCH: u64 = 50;
const VALIDATOR_MAX_WITHDRAWALS_PER_BLOCK: usize = 16;
//

Expand Down
15 changes: 13 additions & 2 deletions node/src/test_harness/mock_engine_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use alloy_primitives::hex;
use alloy_primitives::{Address, B256, Bloom, Bytes, FixedBytes, U256};
use alloy_rpc_types_engine::{
BlobsBundleV1, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, ExecutionPayloadV1,
ExecutionPayloadV2, ExecutionPayloadV3, ForkchoiceState, PayloadId, PayloadStatus,
PayloadStatusEnum,
ExecutionPayloadV2, ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadId,
PayloadStatus, PayloadStatusEnum,
};
use rand::RngCore;
use std::collections::HashMap;
Expand Down Expand Up @@ -469,6 +469,17 @@ impl EngineClient for MockEngineClient {
}
}
}

async fn commit_hash_with_status(
&mut self,
fork_choice_state: ForkchoiceState,
) -> ForkchoiceUpdated {
self.commit_hash(fork_choice_state).await;
ForkchoiceUpdated {
payload_status: PayloadStatus::new(PayloadStatusEnum::Valid, Some(fork_choice_state.head_block_hash)),
payload_id: None,
}
}
}

pub struct MockEngineNetworkBuilder {
Expand Down
62 changes: 60 additions & 2 deletions types/src/engine_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use alloy_eips::eip4895::Withdrawal;
use alloy_primitives::{Address, FixedBytes};
use alloy_provider::{ProviderBuilder, RootProvider, ext::EngineApi};
use alloy_rpc_types_engine::{
ExecutionPayloadEnvelopeV4, ForkchoiceState, PayloadAttributes, PayloadId, PayloadStatus,
ExecutionPayloadEnvelopeV4, ForkchoiceState, ForkchoiceUpdated, PayloadAttributes, PayloadId,
PayloadStatus,
};
use tracing::{error, warn};

Expand Down Expand Up @@ -51,6 +52,11 @@ pub trait EngineClient: Clone + Send + Sync + 'static {
&mut self,
fork_choice_state: ForkchoiceState,
) -> impl Future<Output = ()> + Send;

fn commit_hash_with_status(
&mut self,
fork_choice_state: ForkchoiceState,
) -> impl Future<Output = ForkchoiceUpdated> + Send;
}

#[derive(Clone)]
Expand Down Expand Up @@ -192,6 +198,27 @@ impl EngineClient for RethEngineClient {
Err(_) => panic!("Unable to get a response"),
};
}

async fn commit_hash_with_status(
&mut self,
fork_choice_state: ForkchoiceState,
) -> ForkchoiceUpdated {
match self
.provider
.fork_choice_updated_v3(fork_choice_state, None)
.await
{
Ok(res) => res,
Err(e) if e.is_transport_error() => {
self.wait_until_reconnect_available().await;
self.provider
.fork_choice_updated_v3(fork_choice_state, None)
.await
.expect("Failed to commit hash after reconnect")
}
Err(_) => panic!("Unable to get a response"),
}
}
}

#[cfg(feature = "bad-blocks")]
Expand Down Expand Up @@ -345,6 +372,27 @@ impl EngineClient for BadBlockEngineClient {
Err(_) => panic!("Unable to get a response"),
};
}

async fn commit_hash_with_status(
&mut self,
fork_choice_state: ForkchoiceState,
) -> ForkchoiceUpdated {
match self
.provider
.fork_choice_updated_v3(fork_choice_state, None)
.await
{
Ok(res) => res,
Err(e) if e.is_transport_error() => {
self.wait_until_reconnect_available().await;
self.provider
.fork_choice_updated_v3(fork_choice_state, None)
.await
.expect("Failed to commit hash after reconnect")
}
Err(_) => panic!("Unable to get a response"),
}
}
}

#[cfg(feature = "bench")]
Expand All @@ -357,7 +405,7 @@ pub mod benchmarking {
use alloy_provider::{ProviderBuilder, RootProvider, ext::EngineApi};
use alloy_rpc_types_engine::{
ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, ExecutionPayloadV3,
ForkchoiceState, PayloadId, PayloadStatus,
ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus,
};
use alloy_transport_ipc::IpcConnect;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -441,6 +489,16 @@ pub mod benchmarking {
.await
.unwrap();
}

async fn commit_hash_with_status(
&mut self,
fork_choice_state: ForkchoiceState,
) -> ForkchoiceUpdated {
self.provider
.fork_choice_updated_v3(fork_choice_state, None)
.await
.unwrap()
}
}

#[derive(Debug, Serialize, Deserialize)]
Expand Down