feat(test): rewrite test_engine_tree_valid_forks_with_older_canonical_head using e2e framework (#16699)

This commit is contained in:
Federico Gimenez
2025-06-06 12:29:21 +02:00
committed by GitHub
parent e869762caf
commit a04bd716a9
4 changed files with 130 additions and 76 deletions

View File

@@ -13,11 +13,20 @@ use reth_rpc_api::clients::EthApiClient;
use std::marker::PhantomData;
use tracing::debug;
/// Action to create a fork from a specified block number and produce blocks on top
/// Fork base target for fork creation
#[derive(Debug, Clone)]
pub enum ForkBase {
/// Block number
Number(u64),
/// Tagged block reference
Tag(String),
}
/// Action to create a fork from a specified block and produce blocks on top
#[derive(Debug)]
pub struct CreateFork<Engine> {
/// Block number to use as the base of the fork
pub fork_base_block: u64,
/// Fork base specification (either block number or tag)
pub fork_base: ForkBase,
/// Number of blocks to produce on top of the fork base
pub num_blocks: u64,
/// Tracks engine type
@@ -25,9 +34,18 @@ pub struct CreateFork<Engine> {
}
impl<Engine> CreateFork<Engine> {
/// Create a new `CreateFork` action
/// Create a new `CreateFork` action from a block number
pub fn new(fork_base_block: u64, num_blocks: u64) -> Self {
Self { fork_base_block, num_blocks, _phantom: Default::default() }
Self {
fork_base: ForkBase::Number(fork_base_block),
num_blocks,
_phantom: Default::default(),
}
}
/// Create a new `CreateFork` action from a tagged block
pub fn new_from_tag(tag: impl Into<String>, num_blocks: u64) -> Self {
Self { fork_base: ForkBase::Tag(tag.into()), num_blocks, _phantom: Default::default() }
}
}
@@ -40,18 +58,34 @@ where
{
fn execute<'a>(&'a mut self, env: &'a mut Environment<Engine>) -> BoxFuture<'a, Result<()>> {
Box::pin(async move {
// store the fork base for later validation
env.current_fork_base = Some(self.fork_base_block);
// resolve the fork base and execute the appropriate sequence
match &self.fork_base {
ForkBase::Number(block_number) => {
// store the fork base for later validation
env.current_fork_base = Some(*block_number);
let mut sequence = Sequence::new(vec![
Box::new(SetForkBase::new(self.fork_base_block)),
Box::new(ProduceBlocks::new(self.num_blocks)),
// Note: ValidateFork is not called here because fork blocks are not accessible
// via RPC until they are made canonical. Validation will be done automatically
// as part of MakeCanonical or ReorgTo actions.
]);
let mut sequence = Sequence::new(vec![
Box::new(SetForkBase::new(*block_number)),
Box::new(ProduceBlocks::new(self.num_blocks)),
]);
sequence.execute(env).await
}
ForkBase::Tag(tag) => {
let block_info =
env.block_registry.get(tag).copied().ok_or_else(|| {
eyre::eyre!("Block tag '{}' not found in registry", tag)
})?;
sequence.execute(env).await
// store the fork base for later validation
env.current_fork_base = Some(block_info.number);
let mut sequence = Sequence::new(vec![
Box::new(SetForkBaseFromBlockInfo::new(block_info)),
Box::new(ProduceBlocks::new(self.num_blocks)),
]);
sequence.execute(env).await
}
}
})
}
}
@@ -63,6 +97,13 @@ pub struct SetForkBase {
pub fork_base_block: u64,
}
/// Sub-action to set the fork base block from existing block info
#[derive(Debug)]
pub struct SetForkBaseFromBlockInfo {
/// Complete block info to use as the base of the fork
pub fork_base_info: BlockInfo,
}
impl SetForkBase {
/// Create a new `SetForkBase` action
pub const fn new(fork_base_block: u64) -> Self {
@@ -70,6 +111,13 @@ impl SetForkBase {
}
}
impl SetForkBaseFromBlockInfo {
/// Create a new `SetForkBaseFromBlockInfo` action
pub const fn new(fork_base_info: BlockInfo) -> Self {
Self { fork_base_info }
}
}
impl<Engine> Action<Engine> for SetForkBase
where
Engine: EngineTypes,
@@ -117,6 +165,37 @@ where
}
}
impl<Engine> Action<Engine> for SetForkBaseFromBlockInfo
where
Engine: EngineTypes,
{
fn execute<'a>(&'a mut self, env: &'a mut Environment<Engine>) -> BoxFuture<'a, Result<()>> {
Box::pin(async move {
let block_info = self.fork_base_info;
debug!(
"Set fork base from block info: block {} (hash: {})",
block_info.number, block_info.hash
);
// update environment to point to the fork base block
env.current_block_info = Some(block_info);
env.latest_header_time = block_info.timestamp;
// update fork choice state to the fork base
env.latest_fork_choice_state = ForkchoiceState {
head_block_hash: block_info.hash,
safe_block_hash: block_info.hash,
finalized_block_hash: block_info.hash,
};
debug!("Set fork base to block {} (hash: {})", block_info.number, block_info.hash);
Ok(())
})
}
}
/// Sub-action to validate that a fork was created correctly
#[derive(Debug)]
pub struct ValidateFork {

View File

@@ -12,7 +12,7 @@ pub mod fork;
pub mod produce_blocks;
pub mod reorg;
pub use fork::{CreateFork, SetForkBase, ValidateFork};
pub use fork::{CreateFork, ForkBase, SetForkBase, SetForkBaseFromBlockInfo, ValidateFork};
pub use produce_blocks::{
AssertMineBlock, BroadcastLatestForkchoice, BroadcastNextNewPayload, CheckPayloadAccepted,
GenerateNextPayload, GeneratePayloadAttributes, PickNextBlockProducer, ProduceBlocks,