feat: on-disk reorg E2E test (#12977)

This commit is contained in:
Arsenii Kulikov
2024-11-29 16:41:46 +04:00
committed by GitHub
parent 1f1671ad8c
commit b6b8c474ab
5 changed files with 253 additions and 107 deletions

View File

@ -53,7 +53,7 @@ pub async fn setup<N>(
chain_spec: Arc<N::ChainSpec>,
is_dev: bool,
attributes_generator: impl Fn(u64) -> <<N as NodeTypesWithEngine>::Engine as PayloadTypes>::PayloadBuilderAttributes + Copy + 'static,
) -> eyre::Result<(Vec<NodeHelperType<N, N::AddOns>>, TaskManager, Wallet)>
) -> eyre::Result<(Vec<NodeHelperType<N>>, TaskManager, Wallet)>
where
N: Default + Node<TmpNodeAdapter<N>> + NodeTypesForTree + NodeTypesWithEngine,
N::ComponentsBuilder: NodeComponentsBuilder<
@ -115,7 +115,7 @@ pub async fn setup_engine<N>(
is_dev: bool,
attributes_generator: impl Fn(u64) -> <<N as NodeTypesWithEngine>::Engine as PayloadTypes>::PayloadBuilderAttributes + Copy + 'static,
) -> eyre::Result<(
Vec<NodeHelperType<N, N::AddOns, BlockchainProvider2<NodeTypesWithDBAdapter<N, TmpDB>>>>,
Vec<NodeHelperType<N, BlockchainProvider2<NodeTypesWithDBAdapter<N, TmpDB>>>>,
TaskManager,
Wallet,
)>
@ -183,6 +183,9 @@ where
let mut node = NodeTestContext::new(node, attributes_generator).await?;
let genesis = node.block_hash(0);
node.engine_api.update_forkchoice(genesis, genesis).await?;
// Connect each node in a chain.
if let Some(previous_node) = nodes.last_mut() {
previous_node.connect(&mut node).await;
@ -203,7 +206,8 @@ where
// Type aliases
type TmpDB = Arc<TempDatabase<DatabaseEnv>>;
/// Testing database
pub type TmpDB = Arc<TempDatabase<DatabaseEnv>>;
type TmpNodeAdapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
FullNodeTypesAdapter<NodeTypesWithDBAdapter<N, TmpDB>, Provider>;
@ -216,5 +220,5 @@ pub type Adapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpD
>;
/// Type alias for a type of `NodeHelper`
pub type NodeHelperType<N, AO, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
NodeTestContext<Adapter<N, Provider>, AO>;
pub type NodeHelperType<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
NodeTestContext<Adapter<N, Provider>, <N as Node<TmpNodeAdapter<N, Provider>>>::AddOns>;

View File

@ -3,6 +3,7 @@ use crate::{
rpc::RpcTestContext, traits::PayloadEnvelopeExt,
};
use alloy_consensus::BlockHeader;
use alloy_eips::BlockId;
use alloy_primitives::{BlockHash, BlockNumber, Bytes, B256};
use alloy_rpc_types_engine::PayloadStatusEnum;
use alloy_rpc_types_eth::BlockNumberOrTag;
@ -134,8 +135,8 @@ where
Ok((self.payload.expect_built_payload().await?, eth_attr))
}
/// Advances the node forward one block
pub async fn advance_block(
/// Triggers payload building job and submits it to the engine.
pub async fn build_and_submit_payload(
&mut self,
) -> eyre::Result<(Engine::BuiltPayload, Engine::PayloadBuilderAttributes)>
where
@ -146,13 +147,27 @@ where
{
let (payload, eth_attr) = self.new_payload().await?;
let block_hash = self
.engine_api
self.engine_api
.submit_payload(payload.clone(), eth_attr.clone(), PayloadStatusEnum::Valid)
.await?;
Ok((payload, eth_attr))
}
/// Advances the node forward one block
pub async fn advance_block(
&mut self,
) -> eyre::Result<(Engine::BuiltPayload, Engine::PayloadBuilderAttributes)>
where
<Engine as EngineTypes>::ExecutionPayloadEnvelopeV3:
From<Engine::BuiltPayload> + PayloadEnvelopeExt,
<Engine as EngineTypes>::ExecutionPayloadEnvelopeV4:
From<Engine::BuiltPayload> + PayloadEnvelopeExt,
{
let (payload, eth_attr) = self.build_and_submit_payload().await?;
// trigger forkchoice update via engine api to commit the block to the blockchain
self.engine_api.update_forkchoice(block_hash, block_hash).await?;
self.engine_api.update_forkchoice(payload.block().hash(), payload.block().hash()).await?;
Ok((payload, eth_attr))
}
@ -238,6 +253,41 @@ where
Ok(())
}
/// Gets block hash by number.
pub fn block_hash(&self, number: u64) -> BlockHash {
self.inner
.provider
.sealed_header_by_number_or_tag(BlockNumberOrTag::Number(number))
.unwrap()
.unwrap()
.hash()
}
/// Sends FCU and waits for the node to sync to the given block.
pub async fn sync_to(&self, block: BlockHash) -> eyre::Result<()> {
self.engine_api.update_forkchoice(block, block).await?;
let start = std::time::Instant::now();
while self
.inner
.provider
.sealed_header_by_id(BlockId::Number(BlockNumberOrTag::Latest))?
.is_none_or(|h| h.hash() != block)
{
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
assert!(start.elapsed() <= std::time::Duration::from_secs(10), "timed out");
}
// Hack to make sure that all components have time to process canonical state update.
// Otherwise, this might result in e.g "nonce too low" errors when advancing chain further,
// making tests flaky.
tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
Ok(())
}
/// Returns the RPC URL.
pub fn rpc_url(&self) -> Url {
let addr = self.inner.rpc_server_handle().http_local_addr().unwrap();