diff --git a/Cargo.lock b/Cargo.lock index c3f789cf8..c2f7b0f2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4512,6 +4512,20 @@ dependencies = [ "libc", ] +[[package]] +name = "node-e2e-tests" +version = "0.0.0" +dependencies = [ + "eyre", + "futures-util", + "reth", + "reth-node-core", + "reth-node-ethereum", + "reth-primitives", + "serde_json", + "tokio", +] + [[package]] name = "nom" version = "7.1.3" diff --git a/Cargo.toml b/Cargo.toml index 398739379..c8c8f84e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ members = [ "crates/node-optimism/", "crates/node-core/", "crates/node-api/", + "crates/node-e2e-tests/", "crates/stages/", "crates/static-file/", "crates/storage/codecs/", diff --git a/crates/node-e2e-tests/Cargo.toml b/crates/node-e2e-tests/Cargo.toml new file mode 100644 index 000000000..6210eaa02 --- /dev/null +++ b/crates/node-e2e-tests/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "node-e2e-tests" +version = "0.0.0" +publish = false +edition.workspace = true +license.workspace = true + + +[dependencies] +reth.workspace = true +reth-node-core.workspace = true +reth-primitives.workspace = true +reth-node-ethereum.workspace = true +futures-util.workspace = true + +eyre.workspace = true +tokio.workspace = true +serde_json.workspace = true diff --git a/crates/node-e2e-tests/tests/it/dev.rs b/crates/node-e2e-tests/tests/it/dev.rs new file mode 100644 index 000000000..923763038 --- /dev/null +++ b/crates/node-e2e-tests/tests/it/dev.rs @@ -0,0 +1,95 @@ +use futures_util::StreamExt; +use reth::{ + builder::{components::FullNodeComponents, FullNode, NodeBuilder, NodeHandle}, + providers::CanonStateSubscriptions, + rpc::eth::EthTransactions, + tasks::TaskManager, +}; +use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig}; +use reth_node_ethereum::EthereumNode; +use reth_primitives::{b256, hex, ChainSpec, Genesis}; +use std::sync::Arc; + +#[tokio::test] +async fn can_run_dev_node() -> eyre::Result<()> { + let tasks = TaskManager::current(); + + // create node config + let node_config = NodeConfig::test() + .dev() + .with_rpc(RpcServerArgs::default().with_http()) + .with_chain(custom_chain()); + + let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config) + .testing_node(tasks.executor()) + .node(EthereumNode::default()) + .launch() + .await?; + + assert_chain_advances(node).await; + Ok(()) +} + +async fn assert_chain_advances(mut node: FullNode) { + let mut notifications = node.provider.canonical_state_stream(); + + // submit tx through rpc + let raw_tx = hex!("02f876820a28808477359400847735940082520894ab0840c0e43688012c1adb0f5e3fc665188f83d28a029d394a5d630544000080c080a0a044076b7e67b5deecc63f61a8d7913fab86ca365b344b5759d1fe3563b4c39ea019eab979dd000da04dfc72bb0377c092d30fd9e1cab5ae487de49586cc8b0090"); + + let eth_api = node.rpc_registry.eth_api(); + + let hash = eth_api.send_raw_transaction(raw_tx.into()).await.unwrap(); + + let expected = b256!("b1c6512f4fc202c04355fbda66755e0e344b152e633010e8fd75ecec09b63398"); + + assert_eq!(hash, expected); + println!("submitted transaction: {hash}"); + + let head = notifications.next().await.unwrap(); + + let tx = head.tip().transactions().next().unwrap(); + assert_eq!(tx.hash(), hash); + println!("mined transaction: {hash}"); +} + +fn custom_chain() -> Arc { + let custom_genesis = r#" +{ + + "nonce": "0x42", + "timestamp": "0x0", + "extraData": "0x5343", + "gasLimit": "0x1388", + "difficulty": "0x400000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b": { + "balance": "0x4a47e3c12448f4ad000000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "config": { + "ethash": {}, + "chainId": 2600, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "terminalTotalDifficulty": 0, + "terminalTotalDifficultyPassed": true, + "shanghaiTime": 0 + } +} +"#; + let genesis: Genesis = serde_json::from_str(custom_genesis).unwrap(); + Arc::new(genesis.into()) +} diff --git a/crates/node-e2e-tests/tests/it/main.rs b/crates/node-e2e-tests/tests/it/main.rs new file mode 100644 index 000000000..77e27a5dc --- /dev/null +++ b/crates/node-e2e-tests/tests/it/main.rs @@ -0,0 +1,3 @@ +mod dev; + +fn main() {} diff --git a/examples/custom-dev-node/src/main.rs b/examples/custom-dev-node/src/main.rs index a1e3656d3..4788e02b8 100644 --- a/examples/custom-dev-node/src/main.rs +++ b/examples/custom-dev-node/src/main.rs @@ -25,7 +25,7 @@ async fn main() -> eyre::Result<()> { .with_rpc(RpcServerArgs::default().with_http()) .with_chain(custom_chain()); - let NodeHandle { mut node, node_exit_future } = NodeBuilder::new(node_config) + let NodeHandle { mut node, node_exit_future: _ } = NodeBuilder::new(node_config) .testing_node(tasks.executor()) .node(EthereumNode::default()) .launch() @@ -50,8 +50,7 @@ async fn main() -> eyre::Result<()> { let tx = head.tip().transactions().next().unwrap(); assert_eq!(tx.hash(), hash); println!("mined transaction: {hash}"); - - node_exit_future.await + Ok(()) } fn custom_chain() -> Arc {