feat: improve e2e tests API + feeHistory test (#12058)

This commit is contained in:
Arsenii Kulikov
2024-10-25 09:01:44 +04:00
committed by GitHub
parent c3182f2a64
commit d9889787a7
16 changed files with 202 additions and 62 deletions

View File

@ -55,6 +55,9 @@ alloy-consensus.workspace = true
alloy-provider.workspace = true
rand.workspace = true
alloy-signer.workspace = true
alloy-eips.workspace = true
alloy-sol-types.workspace = true
alloy-contract.workspace = true
[features]
default = []

View File

@ -41,7 +41,7 @@ async fn can_handle_blobs() -> eyre::Result<()> {
.launch()
.await?;
let mut node = NodeTestContext::new(node).await?;
let mut node = NodeTestContext::new(node, eth_payload_attributes).await?;
let wallets = Wallet::new(2).gen();
let blob_wallet = wallets.first().unwrap();
@ -51,7 +51,7 @@ async fn can_handle_blobs() -> eyre::Result<()> {
let raw_tx = TransactionTestContext::transfer_tx_bytes(1, second_wallet.clone()).await;
let tx_hash = node.rpc.inject_tx(raw_tx).await?;
// build payload with normal tx
let (payload, attributes) = node.new_payload(eth_payload_attributes).await?;
let (payload, attributes) = node.new_payload().await?;
// clean the pool
node.inner.pool.remove_transactions(vec![tx_hash]);
@ -64,16 +64,14 @@ async fn can_handle_blobs() -> eyre::Result<()> {
// fetch it from rpc
let envelope = node.rpc.envelope_by_hash(blob_tx_hash).await?;
// validate sidecar
let versioned_hashes = TransactionTestContext::validate_sidecar(envelope);
TransactionTestContext::validate_sidecar(envelope);
// build a payload
let (blob_payload, blob_attr) = node.new_payload(eth_payload_attributes).await?;
let (blob_payload, blob_attr) = node.new_payload().await?;
// submit the blob payload
let blob_block_hash = node
.engine_api
.submit_payload(blob_payload, blob_attr, PayloadStatusEnum::Valid, versioned_hashes.clone())
.await?;
let blob_block_hash =
node.engine_api.submit_payload(blob_payload, blob_attr, PayloadStatusEnum::Valid).await?;
let (_, _) = tokio::join!(
// send fcu with blob hash
@ -83,7 +81,7 @@ async fn can_handle_blobs() -> eyre::Result<()> {
);
// submit normal payload
node.engine_api.submit_payload(payload, attributes, PayloadStatusEnum::Valid, vec![]).await?;
node.engine_api.submit_payload(payload, attributes, PayloadStatusEnum::Valid).await?;
tokio::time::sleep(std::time::Duration::from_secs(3)).await;

View File

@ -1,5 +1,6 @@
use std::sync::Arc;
use crate::utils::eth_payload_attributes;
use alloy_genesis::Genesis;
use alloy_primitives::{b256, hex};
use futures::StreamExt;
@ -17,7 +18,8 @@ use reth_tasks::TaskManager;
#[tokio::test]
async fn can_run_dev_node() -> eyre::Result<()> {
reth_tracing::init_test_tracing();
let (mut nodes, _tasks, _) = setup::<EthereumNode>(1, custom_chain(), true).await?;
let (mut nodes, _tasks, _) =
setup::<EthereumNode>(1, custom_chain(), true, eth_payload_attributes).await?;
assert_chain_advances(nodes.pop().unwrap().inner).await;
Ok(())

View File

@ -26,6 +26,7 @@ async fn can_run_eth_node() -> eyre::Result<()> {
.build(),
),
false,
eth_payload_attributes,
)
.await?;
@ -36,7 +37,7 @@ async fn can_run_eth_node() -> eyre::Result<()> {
let tx_hash = node.rpc.inject_tx(raw_tx).await?;
// make the node advance
let (payload, _) = node.advance_block(vec![], eth_payload_attributes).await?;
let (payload, _) = node.advance_block().await?;
let block_hash = payload.block().hash();
let block_number = payload.block().number;
@ -74,7 +75,7 @@ async fn can_run_eth_node_with_auth_engine_api_over_ipc() -> eyre::Result<()> {
.node(EthereumNode::default())
.launch()
.await?;
let mut node = NodeTestContext::new(node).await?;
let mut node = NodeTestContext::new(node, eth_payload_attributes).await?;
// Configure wallet from test mnemonic and create dummy transfer tx
let wallet = Wallet::default();
@ -84,7 +85,7 @@ async fn can_run_eth_node_with_auth_engine_api_over_ipc() -> eyre::Result<()> {
let tx_hash = node.rpc.inject_tx(raw_tx).await?;
// make the node advance
let (payload, _) = node.advance_block(vec![], eth_payload_attributes).await?;
let (payload, _) = node.advance_block().await?;
let block_hash = payload.block().hash();
let block_number = payload.block().number;
@ -120,7 +121,7 @@ async fn test_failed_run_eth_node_with_no_auth_engine_api_over_ipc_opts() -> eyr
.launch()
.await?;
let node = NodeTestContext::new(node).await?;
let node = NodeTestContext::new(node, eth_payload_attributes).await?;
// Ensure that the engine api client is not available
let client = node.inner.engine_ipc_client().await;

View File

@ -4,6 +4,7 @@ mod blobs;
mod dev;
mod eth;
mod p2p;
mod rpc;
mod utils;
const fn main() {}

View File

@ -30,6 +30,7 @@ async fn can_sync() -> eyre::Result<()> {
.build(),
),
false,
eth_payload_attributes,
)
.await?;
@ -41,7 +42,7 @@ async fn can_sync() -> eyre::Result<()> {
let tx_hash = first_node.rpc.inject_tx(raw_tx).await?;
// make the node advance
let (payload, _) = first_node.advance_block(vec![], eth_payload_attributes).await?;
let (payload, _) = first_node.advance_block().await?;
let block_hash = payload.block().hash();
let block_number = payload.block().number;
@ -76,7 +77,7 @@ async fn e2e_test_send_transactions() -> eyre::Result<()> {
);
let (mut nodes, _tasks, wallet) =
setup_engine::<EthereumNode>(2, chain_spec.clone(), false).await?;
setup_engine::<EthereumNode>(2, chain_spec.clone(), false, eth_payload_attributes).await?;
let mut node = nodes.pop().unwrap();
let signers = wallet.gen();
let provider = ProviderBuilder::new().with_recommended_fillers().on_http(node.rpc_url());
@ -139,7 +140,7 @@ async fn e2e_test_send_transactions() -> eyre::Result<()> {
pending.push(provider.send_tx_envelope(tx).await?);
}
let (payload, _) = node.advance_block(vec![], eth_payload_attributes).await?;
let (payload, _) = node.advance_block().await?;
assert!(payload.block().raw_transactions().len() == tx_count);
for pending in pending {

View File

@ -0,0 +1,109 @@
use crate::utils::eth_payload_attributes;
use alloy_eips::calc_next_block_base_fee;
use alloy_primitives::U256;
use alloy_provider::{network::EthereumWallet, Provider, ProviderBuilder};
use rand::{rngs::StdRng, Rng, SeedableRng};
use reth_chainspec::{ChainSpecBuilder, MAINNET};
use reth_e2e_test_utils::setup_engine;
use reth_node_ethereum::EthereumNode;
use std::sync::Arc;
alloy_sol_types::sol! {
#[sol(rpc, bytecode = "6080604052348015600f57600080fd5b5060405160db38038060db833981016040819052602a91607a565b60005b818110156074576040805143602082015290810182905260009060600160408051601f19818403018152919052805160209091012080555080606d816092565b915050602d565b505060b8565b600060208284031215608b57600080fd5b5051919050565b60006001820160b157634e487b7160e01b600052601160045260246000fd5b5060010190565b60168060c56000396000f3fe6080604052600080fdfea164736f6c6343000810000a")]
contract GasWaster {
constructor(uint256 iterations) {
for (uint256 i = 0; i < iterations; i++) {
bytes32 slot = keccak256(abi.encode(block.number, i));
assembly {
sstore(slot, slot)
}
}
}
}
}
#[tokio::test]
async fn test_fee_history() -> eyre::Result<()> {
reth_tracing::init_test_tracing();
let seed: [u8; 32] = rand::thread_rng().gen();
let mut rng = StdRng::from_seed(seed);
println!("Seed: {:?}", seed);
let chain_spec = Arc::new(
ChainSpecBuilder::default()
.chain(MAINNET.chain)
.genesis(serde_json::from_str(include_str!("../assets/genesis.json")).unwrap())
.cancun_activated()
.build(),
);
let (mut nodes, _tasks, wallet) =
setup_engine::<EthereumNode>(1, chain_spec.clone(), false, eth_payload_attributes).await?;
let mut node = nodes.pop().unwrap();
let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(EthereumWallet::new(wallet.gen().swap_remove(0)))
.on_http(node.rpc_url());
let fee_history = provider.get_fee_history(10, 0_u64.into(), &[]).await?;
let genesis_base_fee = chain_spec.initial_base_fee().unwrap() as u128;
let expected_first_base_fee = genesis_base_fee -
genesis_base_fee / chain_spec.base_fee_params_at_block(0).max_change_denominator;
assert_eq!(fee_history.base_fee_per_gas[0], genesis_base_fee);
assert_eq!(fee_history.base_fee_per_gas[1], expected_first_base_fee,);
// Spend some gas
let builder = GasWaster::deploy_builder(&provider, U256::from(500)).send().await?;
node.advance_block().await?;
let receipt = builder.get_receipt().await?;
assert!(receipt.status());
let block = provider.get_block_by_number(1.into(), false).await?.unwrap();
assert_eq!(block.header.gas_used as u128, receipt.gas_used,);
assert_eq!(block.header.base_fee_per_gas.unwrap(), expected_first_base_fee as u64);
for _ in 0..100 {
let _ =
GasWaster::deploy_builder(&provider, U256::from(rng.gen_range(0..1000))).send().await?;
node.advance_block().await?;
}
let latest_block = provider.get_block_number().await?;
for _ in 0..100 {
let latest_block = rng.gen_range(0..=latest_block);
let block_count = rng.gen_range(1..=(latest_block + 1));
let fee_history = provider.get_fee_history(block_count, latest_block.into(), &[]).await?;
let mut prev_header = provider
.get_block_by_number((latest_block + 1 - block_count).into(), false)
.await?
.unwrap()
.header;
for block in (latest_block + 2 - block_count)..=latest_block {
let expected_base_fee = calc_next_block_base_fee(
prev_header.gas_used,
prev_header.gas_limit,
prev_header.base_fee_per_gas.unwrap(),
chain_spec.base_fee_params_at_block(block),
);
let header = provider.get_block_by_number(block.into(), false).await?.unwrap().header;
assert_eq!(header.base_fee_per_gas.unwrap(), expected_base_fee as u64);
assert_eq!(
header.base_fee_per_gas.unwrap(),
fee_history.base_fee_per_gas[(block + block_count - 1 - latest_block) as usize]
as u64
);
prev_header = header;
}
}
Ok(())
}