From af2dce3e651c80a5ea3c1462543097b66119df0b Mon Sep 17 00:00:00 2001 From: Luca Provini Date: Tue, 16 Apr 2024 12:50:17 +0200 Subject: [PATCH] P2P Sync e2e (#7529) Co-authored-by: Matthias Seitz --- Cargo.lock | 172 ++++++++------- crates/node-e2e-tests/Cargo.toml | 6 + .../node-e2e-tests/src/chain_spec_builder.rs | 31 --- crates/node-e2e-tests/src/engine_api.rs | 66 ++++++ crates/node-e2e-tests/src/lib.rs | 18 +- crates/node-e2e-tests/src/network.rs | 44 ++++ crates/node-e2e-tests/src/node.rs | 125 +++++++++++ crates/node-e2e-tests/src/payload.rs | 85 +++++++ crates/node-e2e-tests/src/test_suite.rs | 41 ---- crates/node-e2e-tests/src/wallet.rs | 18 +- crates/node-e2e-tests/tests/it/eth.rs | 208 ++++++------------ crates/node-e2e-tests/tests/it/main.rs | 1 + crates/node-e2e-tests/tests/it/p2p.rs | 76 +++++++ crates/payload/builder/src/events.rs | 5 +- 14 files changed, 586 insertions(+), 310 deletions(-) delete mode 100644 crates/node-e2e-tests/src/chain_spec_builder.rs create mode 100644 crates/node-e2e-tests/src/engine_api.rs create mode 100644 crates/node-e2e-tests/src/network.rs create mode 100644 crates/node-e2e-tests/src/node.rs create mode 100644 crates/node-e2e-tests/src/payload.rs delete mode 100644 crates/node-e2e-tests/src/test_suite.rs create mode 100644 crates/node-e2e-tests/tests/it/p2p.rs diff --git a/Cargo.lock b/Cargo.lock index 72cb77b76..3b209fd4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,7 +332,7 @@ checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -471,7 +471,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", "syn-solidity", "tiny-keccak", ] @@ -489,7 +489,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.58", + "syn 2.0.57", "syn-solidity", ] @@ -652,7 +652,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -825,9 +825,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.8" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60" +checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" dependencies = [ "brotli", "flate2", @@ -872,7 +872,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -883,7 +883,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -915,7 +915,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -1043,7 +1043,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.58", + "syn 2.0.57", "which", ] @@ -1240,7 +1240,7 @@ checksum = "6be9c93793b60dac381af475b98634d4b451e28336e72218cad9a20176218dbc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", "synstructure", ] @@ -1280,9 +1280,9 @@ dependencies = [ [[package]] name = "brotli" -version = "4.0.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125740193d7fee5cc63ab9e16c2fdc4e07c74ba755cc53b327d6ea029e9fc569" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1291,9 +1291,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "3.0.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65622a320492e09b5e0ac436b14c54ff68199bac392d0e89a6832c4518eea525" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1349,7 +1349,7 @@ checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -1541,7 +1541,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim 0.11.0", ] [[package]] @@ -1553,7 +1553,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -1630,13 +1630,13 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "7.1.1" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" +checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" dependencies = [ "crossterm", - "strum 0.26.2", - "strum_macros 0.26.2", + "strum 0.25.0", + "strum_macros 0.25.3", "unicode-width", ] @@ -1990,7 +1990,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -2147,7 +2147,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -2180,7 +2180,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core 0.20.8", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -2249,9 +2249,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "zeroize", @@ -2286,7 +2286,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -2437,7 +2437,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -2634,7 +2634,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -2647,7 +2647,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -2658,7 +2658,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -2970,7 +2970,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -3169,9 +3169,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" dependencies = [ "cfg-if", "crunchy", @@ -3462,7 +3462,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -3561,7 +3561,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -3711,7 +3711,7 @@ checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -4092,7 +4092,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -4388,12 +4388,13 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.3" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ "bitflags 2.5.0", "libc", + "redox_syscall 0.4.1", ] [[package]] @@ -4638,7 +4639,7 @@ checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -4778,7 +4779,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -4893,15 +4894,20 @@ dependencies = [ "alloy-signer-wallet", "eyre", "futures-util", + "jsonrpsee", "rand 0.8.5", "reth", + "reth-db", "reth-node-core", "reth-node-ethereum", + "reth-payload-builder", "reth-primitives", + "reth-rpc", "reth-tracing", "secp256k1 0.27.0", "serde_json", "tokio", + "tokio-stream", ] [[package]] @@ -5045,7 +5051,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -5283,9 +5289,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.9" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" +checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" dependencies = [ "memchr", "thiserror", @@ -5335,7 +5341,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -5364,7 +5370,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -5544,7 +5550,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" dependencies = [ "proc-macro2", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -5902,9 +5908,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom 0.2.14", "libredox", @@ -5957,9 +5963,9 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "regress" -version = "0.9.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eae2a1ebfecc58aff952ef8ccd364329abe627762f5bf09ff42eb9d98522479" +checksum = "d06f9a1f7cd8473611ba1a480cf35f9c5cffc2954336ba90a982fdb7e7d7f51e" dependencies = [ "hashbrown 0.14.3", "memchr", @@ -6261,7 +6267,7 @@ dependencies = [ "proc-macro2", "quote", "similar-asserts", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -6705,7 +6711,7 @@ dependencies = [ "quote", "regex", "serial_test", - "syn 2.0.58", + "syn 2.0.57", "trybuild", ] @@ -7923,9 +7929,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rusty-fork" @@ -8142,7 +8148,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8216,7 +8222,7 @@ dependencies = [ "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8241,7 +8247,7 @@ checksum = "b93fb4adc70021ac1b47f7d45e8cc4169baaa7ea58483bc5b721d19a26202212" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8551,9 +8557,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "strum" @@ -8583,7 +8589,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8596,7 +8602,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8664,9 +8670,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" dependencies = [ "proc-macro2", "quote", @@ -8682,7 +8688,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8699,7 +8705,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8791,7 +8797,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8830,7 +8836,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -8988,7 +8994,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -9201,7 +9207,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -9664,7 +9670,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", "wasm-bindgen-shared", ] @@ -9698,7 +9704,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9761,9 +9767,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.1.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "winapi" @@ -10024,9 +10030,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.20" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" [[package]] name = "xmltree" @@ -10057,7 +10063,7 @@ checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", "synstructure", ] @@ -10078,7 +10084,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -10098,7 +10104,7 @@ checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", "synstructure", ] @@ -10119,7 +10125,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] @@ -10141,7 +10147,7 @@ checksum = "7b4e5997cbf58990550ef1f0e5124a05e47e1ebd33a84af25739be6031a62c20" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.57", ] [[package]] diff --git a/crates/node-e2e-tests/Cargo.toml b/crates/node-e2e-tests/Cargo.toml index ff84a8943..d3811f5f5 100644 --- a/crates/node-e2e-tests/Cargo.toml +++ b/crates/node-e2e-tests/Cargo.toml @@ -12,10 +12,16 @@ reth-node-core.workspace = true reth-primitives.workspace = true reth-node-ethereum.workspace = true reth-tracing.workspace = true +reth-db.workspace = true +reth-rpc.workspace = true +reth-payload-builder = { workspace = true, features = ["test-utils"] } + +jsonrpsee.workspace = true futures-util.workspace = true eyre.workspace = true tokio.workspace = true +tokio-stream.workspace = true serde_json.workspace = true rand.workspace = true secp256k1.workspace = true diff --git a/crates/node-e2e-tests/src/chain_spec_builder.rs b/crates/node-e2e-tests/src/chain_spec_builder.rs deleted file mode 100644 index d0adc624c..000000000 --- a/crates/node-e2e-tests/src/chain_spec_builder.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::sync::Arc; - -use reth_primitives::{ChainSpec, Genesis}; - -/// Helper struct to configure the chain spec as needed for e2e tests -#[must_use = "call `build` to construct the chainspec"] -pub struct ChainSpecBuilder { - chain_spec: ChainSpec, -} - -impl ChainSpecBuilder { - /// Creates a new chain spec builder with the static genesis.json - pub fn new() -> Self { - let genesis: Genesis = - serde_json::from_str(include_str!("../assets/genesis.json")).unwrap(); - - Self { chain_spec: genesis.into() } - } - - /// Overrides the genesis block with the given one - #[allow(unused)] - pub fn with_genesis(mut self, genesis: Genesis) -> Self { - self.chain_spec.genesis = genesis; - self - } - - /// Builds the chain spec - pub fn build(self) -> Arc { - Arc::new(self.chain_spec) - } -} diff --git a/crates/node-e2e-tests/src/engine_api.rs b/crates/node-e2e-tests/src/engine_api.rs new file mode 100644 index 000000000..06c9afa31 --- /dev/null +++ b/crates/node-e2e-tests/src/engine_api.rs @@ -0,0 +1,66 @@ +use jsonrpsee::http_client::HttpClient; +use reth::{ + providers::CanonStateNotificationStream, + rpc::{ + api::EngineApiClient, + types::engine::{ExecutionPayloadEnvelopeV3, ForkchoiceState}, + }, +}; +use reth_node_ethereum::EthEngineTypes; +use reth_payload_builder::{EthBuiltPayload, EthPayloadBuilderAttributes, PayloadId}; +use reth_primitives::B256; + +/// Helper for engine api operations +pub struct EngineApiHelper { + pub canonical_stream: CanonStateNotificationStream, + pub engine_api_client: HttpClient, +} + +impl EngineApiHelper { + /// Retrieves a v3 payload from the engine api + pub async fn get_payload_v3( + &self, + payload_id: PayloadId, + ) -> eyre::Result { + Ok(EngineApiClient::::get_payload_v3(&self.engine_api_client, payload_id) + .await?) + } + + /// Submits a payload to the engine api + pub async fn submit_payload( + &self, + payload: EthBuiltPayload, + eth_attr: EthPayloadBuilderAttributes, + ) -> eyre::Result { + // setup payload for submission + let envelope_v3 = ExecutionPayloadEnvelopeV3::from(payload); + let payload_v3 = envelope_v3.execution_payload; + + // submit payload to engine api + let submission = EngineApiClient::::new_payload_v3( + &self.engine_api_client, + payload_v3, + vec![], + eth_attr.parent_beacon_block_root.unwrap(), + ) + .await?; + assert!(submission.is_valid()); + Ok(submission.latest_valid_hash.unwrap()) + } + + /// Sends forkchoice update to the engine api + pub async fn update_forkchoice(&self, hash: B256) -> eyre::Result<()> { + EngineApiClient::::fork_choice_updated_v2( + &self.engine_api_client, + ForkchoiceState { + head_block_hash: hash, + safe_block_hash: hash, + finalized_block_hash: hash, + }, + None, + ) + .await?; + + Ok(()) + } +} diff --git a/crates/node-e2e-tests/src/lib.rs b/crates/node-e2e-tests/src/lib.rs index 7448d3364..2799c4fe3 100644 --- a/crates/node-e2e-tests/src/lib.rs +++ b/crates/node-e2e-tests/src/lib.rs @@ -1,6 +1,14 @@ -/// Helper type to configure the chain spec as needed for e2e tests -mod chain_spec_builder; -/// Test suite for e2e tests -pub mod test_suite; +/// Wrapper type to create test nodes +pub mod node; + /// Helper type to yield accounts from mnemonic -mod wallet; +pub mod wallet; + +/// Helper for payload operations +mod payload; + +/// Helper for network operations +mod network; + +/// Helper for engine api operations +mod engine_api; diff --git a/crates/node-e2e-tests/src/network.rs b/crates/node-e2e-tests/src/network.rs new file mode 100644 index 000000000..341b0d7d0 --- /dev/null +++ b/crates/node-e2e-tests/src/network.rs @@ -0,0 +1,44 @@ +use futures_util::StreamExt; +use reth::network::{NetworkEvent, NetworkEvents, NetworkHandle, PeersInfo}; +use reth_primitives::NodeRecord; +use reth_tracing::tracing::info; +use tokio_stream::wrappers::UnboundedReceiverStream; + +/// Helper for network operations +pub struct NetworkHelper { + network_events: UnboundedReceiverStream, + network: NetworkHandle, +} + +impl NetworkHelper { + /// Creates a new network helper + pub fn new(network: NetworkHandle) -> Self { + let network_events = network.event_listener(); + Self { network_events, network } + } + + /// Adds a peer to the network node via network handle + pub async fn add_peer(&mut self, node_record: NodeRecord) { + self.network.peers_handle().add_peer(node_record.id, node_record.tcp_addr()); + + match self.network_events.next().await { + Some(NetworkEvent::PeerAdded(_)) => (), + _ => panic!("Expected a peer added event"), + } + } + + /// Returns the network node record + pub fn record(&self) -> NodeRecord { + self.network.local_node_record() + } + + /// Expects a session to be established + pub async fn expect_session(&mut self) { + match self.network_events.next().await { + Some(NetworkEvent::SessionEstablished { remote_addr, .. }) => { + info!(?remote_addr, "Session established") + } + _ => panic!("Expected session established event"), + } + } +} diff --git a/crates/node-e2e-tests/src/node.rs b/crates/node-e2e-tests/src/node.rs new file mode 100644 index 000000000..f4e94b4ae --- /dev/null +++ b/crates/node-e2e-tests/src/node.rs @@ -0,0 +1,125 @@ +use crate::{engine_api::EngineApiHelper, network::NetworkHelper, payload::PayloadHelper}; +use alloy_rpc_types::BlockNumberOrTag; +use eyre::Ok; +use reth::{ + api::FullNodeComponents, + builder::FullNode, + providers::{BlockReaderIdExt, CanonStateSubscriptions}, + rpc::{ + eth::{error::EthResult, EthTransactions}, + types::engine::PayloadAttributes, + }, +}; + +use reth_node_ethereum::EthEngineTypes; +use reth_payload_builder::EthPayloadBuilderAttributes; +use reth_primitives::{Address, Bytes, B256}; + +use std::time::{SystemTime, UNIX_EPOCH}; +use tokio_stream::StreamExt; + +/// An helper struct to handle node actions +pub struct NodeHelper +where + Node: FullNodeComponents, +{ + pub inner: FullNode, + payload: PayloadHelper, + pub network: NetworkHelper, + pub engine_api: EngineApiHelper, +} + +impl NodeHelper +where + Node: FullNodeComponents, +{ + /// Creates a new test node + pub async fn new(node: FullNode) -> eyre::Result { + let builder = node.payload_builder.clone(); + + Ok(Self { + inner: node.clone(), + network: NetworkHelper::new(node.network.clone()), + payload: PayloadHelper::new(builder).await?, + engine_api: EngineApiHelper { + engine_api_client: node.auth_server_handle().http_client(), + canonical_stream: node.provider.canonical_state_stream(), + }, + }) + } + + /// Advances the node forward + pub async fn advance(&mut self, raw_tx: Bytes) -> eyre::Result<(B256, B256)> { + // push tx into pool via RPC server + let tx_hash = self.inject_tx(raw_tx).await?; + + // trigger new payload building draining the pool + let eth_attr = self.payload.new_payload().await.unwrap(); + + // first event is the payload attributes + self.payload.expect_attr_event(eth_attr.clone()).await?; + + // wait for the payload builder to have finished building + self.payload.wait_for_built_payload(eth_attr.payload_id()).await; + + // trigger resolve payload via engine api + self.engine_api.get_payload_v3(eth_attr.payload_id()).await?; + + // ensure we're also receiving the built payload as event + let payload = self.payload.expect_built_payload().await?; + + // submit payload via engine api + let block_hash = self.engine_api.submit_payload(payload, eth_attr.clone()).await?; + + // trigger forkchoice update via engine api to commit the block to the blockchain + self.engine_api.update_forkchoice(block_hash).await?; + + // assert the block has been committed to the blockchain + self.assert_new_block(tx_hash, block_hash).await?; + Ok((block_hash, tx_hash)) + } + + /// Injects a raw transaction into the node tx pool via RPC server + async fn inject_tx(&mut self, raw_tx: Bytes) -> EthResult { + let eth_api = self.inner.rpc_registry.eth_api(); + eth_api.send_raw_transaction(raw_tx).await + } + + /// Asserts that a new block has been added to the blockchain + /// and the tx has been included in the block + pub async fn assert_new_block( + &mut self, + tip_tx_hash: B256, + block_hash: B256, + ) -> eyre::Result<()> { + // get head block from notifications stream and verify the tx has been pushed to the + // pool is actually present in the canonical block + let head = self.engine_api.canonical_stream.next().await.unwrap(); + let tx = head.tip().transactions().next(); + assert_eq!(tx.unwrap().hash().as_slice(), tip_tx_hash.as_slice()); + + // wait for the block to commit + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + + // make sure the block hash we submitted via FCU engine api is the new latest block + // using an RPC call + let latest_block = + self.inner.provider.block_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap(); + assert_eq!(latest_block.hash_slow(), block_hash); + Ok(()) + } +} + +/// Helper function to create a new eth payload attributes +pub fn eth_payload_attributes() -> EthPayloadBuilderAttributes { + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + + let attributes = PayloadAttributes { + timestamp, + prev_randao: B256::ZERO, + suggested_fee_recipient: Address::ZERO, + withdrawals: Some(vec![]), + parent_beacon_block_root: Some(B256::ZERO), + }; + EthPayloadBuilderAttributes::new(B256::ZERO, attributes) +} diff --git a/crates/node-e2e-tests/src/payload.rs b/crates/node-e2e-tests/src/payload.rs new file mode 100644 index 000000000..a23f7225f --- /dev/null +++ b/crates/node-e2e-tests/src/payload.rs @@ -0,0 +1,85 @@ +use std::time::{SystemTime, UNIX_EPOCH}; + +use futures_util::StreamExt; +use reth::{ + api::{EngineTypes, PayloadBuilderAttributes}, + rpc::types::engine::PayloadAttributes, +}; +use reth_node_ethereum::EthEngineTypes; +use reth_payload_builder::{ + EthBuiltPayload, EthPayloadBuilderAttributes, Events, PayloadBuilderHandle, PayloadId, +}; +use reth_primitives::{Address, B256}; +use tokio_stream::wrappers::BroadcastStream; + +/// Helper for payload operations +pub struct PayloadHelper { + pub payload_event_stream: BroadcastStream>, + payload_builder: PayloadBuilderHandle, +} + +impl PayloadHelper { + /// Creates a new payload helper + pub async fn new(payload_builder: PayloadBuilderHandle) -> eyre::Result { + let payload_events = payload_builder.subscribe().await?; + let payload_event_stream = payload_events.into_stream(); + Ok(Self { payload_event_stream, payload_builder }) + } + + /// Creates a new payload job from static attributes + pub async fn new_payload(&self) -> eyre::Result { + let attributes = eth_payload_attributes(); + self.payload_builder.new_payload(attributes.clone()).await.unwrap(); + Ok(attributes) + } + + /// Asserts that the next event is a payload attributes event + pub async fn expect_attr_event( + &mut self, + attrs: EthPayloadBuilderAttributes, + ) -> eyre::Result<()> { + let first_event = self.payload_event_stream.next().await.unwrap()?; + if let reth::payload::Events::Attributes(attr) = first_event { + assert_eq!(attrs.timestamp, attr.timestamp()); + } else { + panic!("Expect first event as payload attributes.") + } + Ok(()) + } + + /// Wait until the best built payload is ready + pub async fn wait_for_built_payload(&self, payload_id: PayloadId) { + loop { + let payload = self.payload_builder.best_payload(payload_id).await.unwrap().unwrap(); + if payload.block().body.is_empty() { + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + continue; + } + break; + } + } + + /// Expects the next event to be a built payload event or panics + pub async fn expect_built_payload(&mut self) -> eyre::Result { + let second_event = self.payload_event_stream.next().await.unwrap()?; + if let reth::payload::Events::BuiltPayload(payload) = second_event { + Ok(payload) + } else { + panic!("Expect a built payload event."); + } + } +} + +/// Helper function to create a new eth payload attributes +fn eth_payload_attributes() -> EthPayloadBuilderAttributes { + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + + let attributes = PayloadAttributes { + timestamp, + prev_randao: B256::ZERO, + suggested_fee_recipient: Address::ZERO, + withdrawals: Some(vec![]), + parent_beacon_block_root: Some(B256::ZERO), + }; + EthPayloadBuilderAttributes::new(B256::ZERO, attributes) +} diff --git a/crates/node-e2e-tests/src/test_suite.rs b/crates/node-e2e-tests/src/test_suite.rs deleted file mode 100644 index c656e3d6c..000000000 --- a/crates/node-e2e-tests/src/test_suite.rs +++ /dev/null @@ -1,41 +0,0 @@ -use crate::{chain_spec_builder::ChainSpecBuilder, wallet::Wallet}; -use alloy_network::eip2718::Encodable2718; -use reth_primitives::{Bytes, ChainSpec, B256}; -use std::sync::Arc; - -/// Mnemonic used to derive the test accounts -const TEST_MNEMONIC: &str = "test test test test test test test test test test test junk"; - -/// Helper struct to customize the chain spec during e2e tests -pub struct TestSuite { - wallet: Wallet, -} - -impl Default for TestSuite { - fn default() -> Self { - Self::new() - } -} - -impl TestSuite { - /// Creates a new e2e test suite with a test account prefunded with 10_000 ETH from genesis - /// allocations and the eth mainnet latest chainspec. - pub fn new() -> Self { - let wallet = Wallet::new(TEST_MNEMONIC); - Self { wallet } - } - - /// Creates a signed transfer tx and returns its hash and raw bytes - pub async fn transfer_tx(&self) -> (B256, Bytes) { - let tx = self.wallet.transfer_tx().await; - (tx.trie_hash(), tx.encoded_2718().into()) - } - - /// Chain spec for e2e eth tests - /// - /// Includes 20 prefunded accounts with 10_000 ETH each derived from mnemonic "test test test - /// test test test test test test test test junk". - pub fn chain_spec(&self) -> Arc { - ChainSpecBuilder::new().build() - } -} diff --git a/crates/node-e2e-tests/src/wallet.rs b/crates/node-e2e-tests/src/wallet.rs index 80800e27e..2351d0a0b 100644 --- a/crates/node-e2e-tests/src/wallet.rs +++ b/crates/node-e2e-tests/src/wallet.rs @@ -1,9 +1,7 @@ -use alloy_consensus::TxEnvelope; -use alloy_network::{EthereumSigner, TransactionBuilder}; +use alloy_network::{eip2718::Encodable2718, EthereumSigner, TransactionBuilder}; use alloy_rpc_types::TransactionRequest; use alloy_signer_wallet::{coins_bip39::English, LocalWallet, MnemonicBuilder}; -use reth_primitives::{Address, U256}; - +use reth_primitives::{Address, Bytes, U256}; /// One of the accounts of the genesis allocations. pub struct Wallet { inner: LocalWallet, @@ -17,7 +15,7 @@ impl Wallet { } /// Creates a static transfer and signs it - pub(crate) async fn transfer_tx(&self) -> TxEnvelope { + pub async fn transfer_tx(&self) -> Bytes { let tx = TransactionRequest { nonce: Some(0), value: Some(U256::from(100)), @@ -28,6 +26,14 @@ impl Wallet { ..Default::default() }; let signer = EthereumSigner::from(self.inner.clone()); - tx.build(&signer).await.unwrap() + tx.build(&signer).await.unwrap().encoded_2718().into() + } +} + +const TEST_MNEMONIC: &str = "test test test test test test test test test test test junk"; + +impl Default for Wallet { + fn default() -> Self { + Wallet::new(TEST_MNEMONIC) } } diff --git a/crates/node-e2e-tests/tests/it/eth.rs b/crates/node-e2e-tests/tests/it/eth.rs index 5a0bae95b..5686c6e18 100644 --- a/crates/node-e2e-tests/tests/it/eth.rs +++ b/crates/node-e2e-tests/tests/it/eth.rs @@ -1,117 +1,50 @@ -use futures_util::StreamExt; -use node_e2e_tests::test_suite::TestSuite; +use node_e2e_tests::{node::NodeHelper, wallet::Wallet}; use reth::{ - builder::{NodeBuilder, NodeHandle}, - payload::EthPayloadBuilderAttributes, - providers::{BlockReaderIdExt, CanonStateSubscriptions}, - rpc::{ - api::EngineApiClient, - eth::EthTransactions, - types::engine::{ExecutionPayloadEnvelopeV3, ForkchoiceState, PayloadAttributes}, - }, + self, + args::RpcServerArgs, + builder::{NodeBuilder, NodeConfig, NodeHandle}, tasks::TaskManager, }; -use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig}; use reth_node_ethereum::EthereumNode; -use reth_primitives::{Address, BlockNumberOrTag, B256}; -use std::time::{SystemTime, UNIX_EPOCH}; +use reth_primitives::{ChainSpecBuilder, Genesis, MAINNET}; +use std::sync::Arc; #[tokio::test] async fn can_run_eth_node() -> eyre::Result<()> { reth_tracing::init_test_tracing(); - let tasks = TaskManager::current(); - let test_suite = TestSuite::new(); + + let exec = TaskManager::current(); + let exec = exec.executor(); + + // Chain spec with test allocs + let genesis: Genesis = serde_json::from_str(include_str!("../../assets/genesis.json")).unwrap(); + let chain_spec = Arc::new( + ChainSpecBuilder::default() + .chain(MAINNET.chain) + .genesis(genesis) + .cancun_activated() + .build(), + ); // Node setup let node_config = NodeConfig::test() - .with_chain(test_suite.chain_spec()) + .with_chain(chain_spec) + .with_unused_ports() .with_rpc(RpcServerArgs::default().with_unused_ports().with_http()); - let NodeHandle { mut node, node_exit_future: _ } = NodeBuilder::new(node_config) - .testing_node(tasks.executor()) + let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config) + .testing_node(exec) .node(EthereumNode::default()) .launch() .await?; + let mut node = NodeHelper::new(node).await?; - // setup engine api events and payload service events - let mut notifications = node.provider.canonical_state_stream(); - let payload_events = node.payload_builder.subscribe().await?; - let mut payload_event_stream = payload_events.into_stream(); + // Configure wallet from test mnemonic and create dummy transfer tx + let wallet = Wallet::default(); + let raw_tx = wallet.transfer_tx().await; - // push tx into pool via RPC server - let eth_api = node.rpc_registry.eth_api(); - let (expected_hash, raw_tx) = test_suite.transfer_tx().await; - - eth_api.send_raw_transaction(raw_tx).await?; - - // trigger new payload building draining the pool - let eth_attr = eth_payload_attributes(); - let payload_id = node.payload_builder.new_payload(eth_attr.clone()).await?; - - // first event is the payload attributes - let first_event = payload_event_stream.next().await.unwrap()?; - if let reth::payload::Events::Attributes(attr) = first_event { - assert_eq!(eth_attr.timestamp, attr.timestamp); - } else { - panic!("Expect first event as payload attributes.") - } - - // wait until an actual payload is built before we resolve it via engine api - loop { - let payload = node.payload_builder.best_payload(payload_id).await.unwrap().unwrap(); - if payload.block().body.is_empty() { - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - continue; - } - break; - } - - let client = node.engine_http_client(); - // trigger resolve payload via engine api - let _ = client.get_payload_v3(payload_id).await?; - - // ensure we're also receiving the built payload as event - let second_event = payload_event_stream.next().await.unwrap()?; - if let reth::payload::Events::BuiltPayload(payload) = second_event { - // setup payload for submission - let envelope_v3 = ExecutionPayloadEnvelopeV3::from(payload); - let payload_v3 = envelope_v3.execution_payload; - - // submit payload to engine api - let submission = client - .new_payload_v3(payload_v3, vec![], eth_attr.parent_beacon_block_root.unwrap()) - .await?; - assert!(submission.is_valid()); - - // get latest valid hash from blockchain tree - let hash = submission.latest_valid_hash.unwrap(); - - // trigger forkchoice update via engine api to commit the block to the blockchain - let fcu = client - .fork_choice_updated_v2( - ForkchoiceState { - head_block_hash: hash, - safe_block_hash: hash, - finalized_block_hash: hash, - }, - None, - ) - .await?; - assert!(fcu.is_valid()); - - // get head block from notifications stream and verify the tx has been pushed to the pool - // is actually present in the canonical block - let head = notifications.next().await.unwrap(); - let tx = head.tip().transactions().next(); - assert_eq!(tx.unwrap().hash().as_slice(), expected_hash.as_slice()); - - // make sure the block hash we submitted via FCU engine api is the new latest block using an - // RPC call - let latest_block = node.provider.block_by_number_or_tag(BlockNumberOrTag::Latest)?.unwrap(); - assert_eq!(latest_block.hash_slow(), hash); - } else { - panic!("Expect a built payload event."); - } + // make the node advance + node.advance(raw_tx).await?; Ok(()) } @@ -120,42 +53,37 @@ async fn can_run_eth_node() -> eyre::Result<()> { #[cfg(unix)] async fn can_run_eth_node_with_auth_engine_api_over_ipc() -> eyre::Result<()> { reth_tracing::init_test_tracing(); - let tasks = TaskManager::current(); - let test_suite = TestSuite::new(); + let exec = TaskManager::current(); + let exec = exec.executor(); + + // Chain spec with test allocs + let genesis: Genesis = serde_json::from_str(include_str!("../../assets/genesis.json")).unwrap(); + let chain_spec = Arc::new( + ChainSpecBuilder::default() + .chain(MAINNET.chain) + .genesis(genesis) + .cancun_activated() + .build(), + ); // Node setup let node_config = NodeConfig::test() - .with_chain(test_suite.chain_spec()) + .with_chain(chain_spec) .with_rpc(RpcServerArgs::default().with_unused_ports().with_http().with_auth_ipc()); - let NodeHandle { mut node, node_exit_future: _ } = NodeBuilder::new(node_config) - .testing_node(tasks.executor()) + let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config) + .testing_node(exec) .node(EthereumNode::default()) .launch() .await?; + let mut node = NodeHelper::new(node).await?; - // setup engine api events and payload service events - let _notifications = node.provider.canonical_state_stream(); - let payload_events = node.payload_builder.subscribe().await?; - let mut payload_event_stream = payload_events.into_stream(); + // Configure wallet from test mnemonic and create dummy transfer tx + let wallet = Wallet::default(); + let raw_tx = wallet.transfer_tx().await; - // push tx into pool via RPC server - let eth_api = node.rpc_registry.eth_api(); - let (_expected_hash, raw_tx) = test_suite.transfer_tx().await; - - eth_api.send_raw_transaction(raw_tx).await?; - - // trigger new payload building draining the pool - let eth_attr = eth_payload_attributes(); - let _payload_id = node.payload_builder.new_payload(eth_attr.clone()).await?; - - // first event is the payload attributes - let first_event = payload_event_stream.next().await.unwrap()?; - if let reth::payload::Events::Attributes(attr) = first_event { - assert_eq!(eth_attr.timestamp, attr.timestamp); - } else { - panic!("Expect first event as payload attributes.") - } + // make the node advance + node.advance(raw_tx).await?; Ok(()) } @@ -164,32 +92,32 @@ async fn can_run_eth_node_with_auth_engine_api_over_ipc() -> eyre::Result<()> { #[cfg(unix)] async fn test_failed_run_eth_node_with_no_auth_engine_api_over_ipc_opts() -> eyre::Result<()> { reth_tracing::init_test_tracing(); - let tasks = TaskManager::current(); - let test_suite = TestSuite::new(); + let exec = TaskManager::current(); + let exec = exec.executor(); + + // Chain spec with test allocs + let genesis: Genesis = serde_json::from_str(include_str!("../../assets/genesis.json")).unwrap(); + let chain_spec = Arc::new( + ChainSpecBuilder::default() + .chain(MAINNET.chain) + .genesis(genesis) + .cancun_activated() + .build(), + ); // Node setup - let node_config = NodeConfig::test().with_chain(test_suite.chain_spec()); - + let node_config = NodeConfig::test().with_chain(chain_spec); let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config) - .testing_node(tasks.executor()) + .testing_node(exec) .node(EthereumNode::default()) .launch() .await?; - let client = node.engine_ipc_client().await; + let node = NodeHelper::new(node).await?; + + // Ensure that the engine api client is not available + let client = node.inner.engine_ipc_client().await; assert!(client.is_none(), "ipc auth should be disabled by default"); Ok(()) } -fn eth_payload_attributes() -> EthPayloadBuilderAttributes { - let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); - - let attributes = PayloadAttributes { - timestamp, - prev_randao: B256::ZERO, - suggested_fee_recipient: Address::ZERO, - withdrawals: Some(vec![]), - parent_beacon_block_root: Some(B256::ZERO), - }; - EthPayloadBuilderAttributes::new(B256::ZERO, attributes) -} diff --git a/crates/node-e2e-tests/tests/it/main.rs b/crates/node-e2e-tests/tests/it/main.rs index 915230777..ba1303464 100644 --- a/crates/node-e2e-tests/tests/it/main.rs +++ b/crates/node-e2e-tests/tests/it/main.rs @@ -1,4 +1,5 @@ mod dev; mod eth; +mod p2p; fn main() {} diff --git a/crates/node-e2e-tests/tests/it/p2p.rs b/crates/node-e2e-tests/tests/it/p2p.rs new file mode 100644 index 000000000..d0a2716f5 --- /dev/null +++ b/crates/node-e2e-tests/tests/it/p2p.rs @@ -0,0 +1,76 @@ +use std::sync::Arc; + +use node_e2e_tests::{node::NodeHelper, wallet::Wallet}; +use reth::{ + args::{DiscoveryArgs, NetworkArgs, RpcServerArgs}, + builder::{NodeBuilder, NodeConfig, NodeHandle}, + tasks::TaskManager, +}; +use reth_node_ethereum::EthereumNode; +use reth_primitives::{ChainSpecBuilder, Genesis, MAINNET}; + +#[tokio::test] +async fn can_sync() -> eyre::Result<()> { + reth_tracing::init_test_tracing(); + + let tasks = TaskManager::current(); + let exec = tasks.executor(); + + let genesis: Genesis = serde_json::from_str(include_str!("../../assets/genesis.json")).unwrap(); + let chain_spec = Arc::new( + ChainSpecBuilder::default() + .chain(MAINNET.chain) + .genesis(genesis) + .cancun_activated() + .build(), + ); + + let network_config = NetworkArgs { + discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() }, + ..NetworkArgs::default() + }; + + let node_config = NodeConfig::test() + .with_chain(chain_spec) + .with_network(network_config) + .with_unused_ports() + .with_rpc(RpcServerArgs::default().with_unused_ports().with_http()); + + let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone()) + .testing_node(exec.clone()) + .node(EthereumNode::default()) + .launch() + .await?; + + let mut first_node = NodeHelper::new(node.clone()).await?; + + let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config) + .testing_node(exec) + .node(EthereumNode::default()) + .launch() + .await?; + + let mut second_node = NodeHelper::new(node).await?; + + let wallet = Wallet::default(); + let raw_tx = wallet.transfer_tx().await; + + // Make them peer + first_node.network.add_peer(second_node.network.record()).await; + second_node.network.add_peer(first_node.network.record()).await; + + // Make sure they establish a new session + first_node.network.expect_session().await; + second_node.network.expect_session().await; + + // Make the first node advance + let (block_hash, tx_hash) = first_node.advance(raw_tx.clone()).await?; + + // only send forkchoice update to second node + second_node.engine_api.update_forkchoice(block_hash).await?; + + // expect second node advanced via p2p gossip + second_node.assert_new_block(tx_hash, block_hash).await?; + + Ok(()) +} diff --git a/crates/payload/builder/src/events.rs b/crates/payload/builder/src/events.rs index 66f299bbb..4df81030f 100644 --- a/crates/payload/builder/src/events.rs +++ b/crates/payload/builder/src/events.rs @@ -1,4 +1,3 @@ -use futures_util::Stream; use reth_engine_primitives::EngineTypes; use tokio::sync::broadcast; use tokio_stream::{ @@ -26,9 +25,7 @@ pub struct PayloadEvents { impl PayloadEvents { // Convert this receiver into a stream of PayloadEvents. - pub fn into_stream( - self, - ) -> impl Stream, BroadcastStreamRecvError>> { + pub fn into_stream(self) -> BroadcastStream> { BroadcastStream::new(self.receiver) } /// Asynchronously receives the next payload event.