mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-08 06:53:54 -05:00
feat: add helpers for testing rpc requests with prestate (#19790)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -3049,7 +3049,7 @@ dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users 0.5.2",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3379,7 +3379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4728,7 +4728,7 @@ dependencies = [
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.62.2",
|
||||
"windows-core 0.57.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5073,7 +5073,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5982,7 +5982,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7013,7 +7013,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2 0.6.1",
|
||||
"tracing",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9185,6 +9185,7 @@ dependencies = [
|
||||
"alloy-rpc-types-beacon",
|
||||
"alloy-rpc-types-engine",
|
||||
"alloy-rpc-types-eth",
|
||||
"alloy-rpc-types-trace",
|
||||
"alloy-signer",
|
||||
"alloy-sol-types",
|
||||
"eyre",
|
||||
@@ -9217,10 +9218,13 @@ dependencies = [
|
||||
"reth-rpc-eth-types",
|
||||
"reth-rpc-server-types",
|
||||
"reth-tasks",
|
||||
"reth-testing-utils",
|
||||
"reth-tracing",
|
||||
"reth-transaction-pool",
|
||||
"revm",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"similar-asserts",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@@ -11459,7 +11463,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.11.0",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12350,7 +12354,7 @@ dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"rustix 1.1.2",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13565,7 +13569,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -496,7 +496,7 @@ alloy-genesis = { version = "1.0.41", default-features = false }
|
||||
alloy-json-rpc = { version = "1.0.41", default-features = false }
|
||||
alloy-network = { version = "1.0.41", default-features = false }
|
||||
alloy-network-primitives = { version = "1.0.41", default-features = false }
|
||||
alloy-provider = { version = "1.0.41", features = ["reqwest"], default-features = false }
|
||||
alloy-provider = { version = "1.0.41", features = ["reqwest", "debug-api"], default-features = false }
|
||||
alloy-pubsub = { version = "1.0.41", default-features = false }
|
||||
alloy-rpc-client = { version = "1.0.41", default-features = false }
|
||||
alloy-rpc-types = { version = "1.0.41", features = ["eth"], default-features = false }
|
||||
|
||||
@@ -60,6 +60,7 @@ reth-exex.workspace = true
|
||||
reth-node-core.workspace = true
|
||||
reth-e2e-test-utils.workspace = true
|
||||
reth-tasks.workspace = true
|
||||
reth-testing-utils.workspace = true
|
||||
|
||||
alloy-primitives.workspace = true
|
||||
alloy-provider.workspace = true
|
||||
@@ -74,6 +75,9 @@ futures.workspace = true
|
||||
tokio.workspace = true
|
||||
serde_json.workspace = true
|
||||
rand.workspace = true
|
||||
serde.workspace = true
|
||||
alloy-rpc-types-trace.workspace = true
|
||||
similar-asserts.workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -5,6 +5,7 @@ mod dev;
|
||||
mod eth;
|
||||
mod p2p;
|
||||
mod pool;
|
||||
mod prestate;
|
||||
mod rpc;
|
||||
mod utils;
|
||||
|
||||
|
||||
132
crates/ethereum/node/tests/e2e/prestate.rs
Normal file
132
crates/ethereum/node/tests/e2e/prestate.rs
Normal file
@@ -0,0 +1,132 @@
|
||||
use alloy_eips::BlockId;
|
||||
use alloy_genesis::{Genesis, GenesisAccount};
|
||||
use alloy_primitives::address;
|
||||
use alloy_provider::ext::DebugApi;
|
||||
use alloy_rpc_types_eth::{Transaction, TransactionRequest};
|
||||
use alloy_rpc_types_trace::geth::{
|
||||
AccountState, GethDebugTracingOptions, PreStateConfig, PreStateFrame,
|
||||
};
|
||||
use eyre::{eyre, Result};
|
||||
use reth_chainspec::{ChainSpecBuilder, MAINNET};
|
||||
use reth_node_builder::{NodeBuilder, NodeHandle};
|
||||
use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};
|
||||
use reth_node_ethereum::EthereumNode;
|
||||
use reth_rpc_server_types::RpcModuleSelection;
|
||||
use reth_tasks::TaskManager;
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
|
||||
const PRESTATE_SNAPSHOT: &str =
|
||||
include_str!("../../../../../testing/prestate/tx-selfdestruct-prestate.json");
|
||||
|
||||
/// Replays the selfdestruct transaction via `debug_traceCall` and ensures Reth's prestate matches
|
||||
/// Geth's captured snapshot.
|
||||
// <https://github.com/paradigmxyz/reth/issues/19703>
|
||||
#[tokio::test]
|
||||
async fn debug_trace_call_matches_geth_prestate_snapshot() -> Result<()> {
|
||||
reth_tracing::init_test_tracing();
|
||||
|
||||
let mut genesis: Genesis = MAINNET.genesis().clone();
|
||||
genesis.coinbase = address!("0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5");
|
||||
|
||||
let exec = TaskManager::current();
|
||||
let exec = exec.executor();
|
||||
|
||||
let expected_frame = expected_snapshot_frame()?;
|
||||
let prestate_mode = match &expected_frame {
|
||||
PreStateFrame::Default(mode) => mode.clone(),
|
||||
_ => return Err(eyre!("snapshot must contain default prestate frame")),
|
||||
};
|
||||
|
||||
genesis.alloc.extend(
|
||||
prestate_mode
|
||||
.0
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(addr, state)| (addr, account_state_to_genesis(state))),
|
||||
);
|
||||
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::default()
|
||||
.chain(MAINNET.chain)
|
||||
.genesis(genesis)
|
||||
.cancun_activated()
|
||||
.prague_activated()
|
||||
.build(),
|
||||
);
|
||||
|
||||
let node_config = NodeConfig::test().with_chain(chain_spec).with_rpc(
|
||||
RpcServerArgs::default()
|
||||
.with_unused_ports()
|
||||
.with_http()
|
||||
.with_http_api(RpcModuleSelection::all_modules().into()),
|
||||
);
|
||||
|
||||
let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config)
|
||||
.testing_node(exec)
|
||||
.node(EthereumNode::default())
|
||||
.launch()
|
||||
.await?;
|
||||
|
||||
let provider = node.rpc_server_handle().eth_http_provider().unwrap();
|
||||
|
||||
// <https://etherscan.io/tx/0x391f4b6a382d3bcc3120adc2ea8c62003e604e487d97281129156fd284a1a89d>
|
||||
let tx = r#"{
|
||||
"type": "0x2",
|
||||
"chainId": "0x1",
|
||||
"nonce": "0x39af8",
|
||||
"gas": "0x249f0",
|
||||
"maxFeePerGas": "0xc6432e2d7",
|
||||
"maxPriorityFeePerGas": "0x68889c2b",
|
||||
"to": "0xc77ad0a71008d7094a62cfbd250a2eb2afdf2776",
|
||||
"value": "0x0",
|
||||
"accessList": [],
|
||||
"input": "0xf3fef3a3000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000f6b64",
|
||||
"r": "0x40ab901a8262d5e6fe9b6513996cd5df412526580cab7410c13acc9dd9f6ec93",
|
||||
"s": "0x6b76354c8cb1c1d6dbebfd555be9053170f02a648c4b36740e3fd7c6e9499572",
|
||||
"yParity": "0x1",
|
||||
"v": "0x1",
|
||||
"hash": "0x391f4b6a382d3bcc3120adc2ea8c62003e604e487d97281129156fd284a1a89d",
|
||||
"blockHash": "0xf9b77bcf8c69544304dff34129f3bdc71f00fdf766c1522ed6ac1382726ead82",
|
||||
"blockNumber": "0x1294fd2",
|
||||
"transactionIndex": "0x3a",
|
||||
"from": "0xa7fb5ca286fc3fd67525629048a4de3ba24cba2e",
|
||||
"gasPrice": "0x7c5bcc0e0"
|
||||
}"#;
|
||||
let tx = serde_json::from_str::<Transaction>(tx).unwrap();
|
||||
let request = TransactionRequest::from_recovered_transaction(tx.into_recovered());
|
||||
|
||||
let trace: PreStateFrame = provider
|
||||
.debug_trace_call_prestate(
|
||||
request,
|
||||
BlockId::latest(),
|
||||
GethDebugTracingOptions::prestate_tracer(PreStateConfig::default()).into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
similar_asserts::assert_eq!(trace, expected_frame);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn expected_snapshot_frame() -> Result<PreStateFrame> {
|
||||
#[derive(Deserialize)]
|
||||
struct Snapshot {
|
||||
result: serde_json::Value,
|
||||
}
|
||||
|
||||
let snapshot: Snapshot = serde_json::from_str(PRESTATE_SNAPSHOT)?;
|
||||
Ok(serde_json::from_value(snapshot.result)?)
|
||||
}
|
||||
|
||||
fn account_state_to_genesis(value: AccountState) -> GenesisAccount {
|
||||
let balance = value.balance.unwrap_or_default();
|
||||
let code = value.code.filter(|code| !code.is_empty());
|
||||
let storage = (!value.storage.is_empty()).then_some(value.storage);
|
||||
|
||||
GenesisAccount::default()
|
||||
.with_balance(balance)
|
||||
.with_nonce(value.nonce)
|
||||
.with_code(code)
|
||||
.with_storage(storage)
|
||||
}
|
||||
43
testing/prestate/tx-selfdestruct-prestate.json
Normal file
43
testing/prestate/tx-selfdestruct-prestate.json
Normal file
File diff suppressed because one or more lines are too long
@@ -8,8 +8,7 @@
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
|
||||
pub mod generators;
|
||||
pub mod genesis_allocator;
|
||||
|
||||
pub use genesis_allocator::GenesisAllocator;
|
||||
|
||||
pub mod generators;
|
||||
|
||||
Reference in New Issue
Block a user