Make transactions in execution layer integration tests (#3320)
## Issue Addressed Resolves #3159 ## Proposed Changes Sends transactions to the EE before requesting for a payload in the `execution_integration_tests`. Made some changes to the integration tests in order to be able to sign and publish transactions to the EE: 1. `genesis.json` for both geth and nethermind was modified to include pre-funded accounts that we know private keys for 2. Using the unauthenticated port again in order to make `eth_sendTransaction` and calls from the `personal` namespace to import keys Also added a `fcu` call with `PayloadAttributes` before calling `getPayload` in order to give EEs sufficient time to pack transactions into the payload.
This commit is contained in:
parent
2ed51c364d
commit
da7b7a0f60
190
Cargo.lock
generated
190
Cargo.lock
generated
@ -189,6 +189,17 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async_io_stream"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"pharos",
|
||||
"rustc_version 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asynchronous-codec"
|
||||
version = "0.6.0"
|
||||
@ -224,6 +235,18 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "auto_impl"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.8"
|
||||
@ -1865,14 +1888,53 @@ dependencies = [
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethers-providers"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/gakonst/ethers-rs?rev=02ad93a1cfb7b62eb051c77c61dc4c0218428e4a#02ad93a1cfb7b62eb051c77c61dc4c0218428e4a"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"auto_impl",
|
||||
"base64",
|
||||
"ethers-core",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-timer",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"http",
|
||||
"once_cell",
|
||||
"parking_lot 0.11.2",
|
||||
"pin-project 1.0.11",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-tungstenite 0.17.1",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-timer",
|
||||
"web-sys",
|
||||
"ws_stream_wasm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "execution_engine_integration"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"deposit_contract",
|
||||
"environment",
|
||||
"ethers-core",
|
||||
"ethers-providers",
|
||||
"execution_layer",
|
||||
"exit-future",
|
||||
"futures",
|
||||
"hex",
|
||||
"reqwest",
|
||||
"sensitive_url",
|
||||
"serde_json",
|
||||
"task_executor",
|
||||
@ -2620,6 +2682,19 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac"
|
||||
dependencies = [
|
||||
"http",
|
||||
"hyper",
|
||||
"rustls 0.20.6",
|
||||
"tokio",
|
||||
"tokio-rustls 0.23.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
@ -2758,6 +2833,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4351,6 +4429,16 @@ dependencies = [
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pharos"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"rustc_version 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "0.4.30"
|
||||
@ -5038,6 +5126,7 @@ dependencies = [
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
@ -5047,17 +5136,21 @@ dependencies = [
|
||||
"native-tls",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.9",
|
||||
"rustls 0.20.6",
|
||||
"rustls-pemfile",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls 0.23.4",
|
||||
"tokio-util 0.7.3",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots",
|
||||
"winreg 0.10.1",
|
||||
]
|
||||
|
||||
@ -5219,6 +5312,15 @@ dependencies = [
|
||||
"webpki 0.22.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9"
|
||||
dependencies = [
|
||||
"base64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.7"
|
||||
@ -5437,6 +5539,12 @@ dependencies = [
|
||||
"pest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "send_wrapper"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "930c0acf610d3fdb5e2ab6213019aaa04e227ebe9547b0649ba599b16d788bd7"
|
||||
|
||||
[[package]]
|
||||
name = "sensitive_url"
|
||||
version = "0.1.0"
|
||||
@ -6398,6 +6506,17 @@ dependencies = [
|
||||
"webpki 0.21.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.23.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||
dependencies = [
|
||||
"rustls 0.20.6",
|
||||
"tokio",
|
||||
"webpki 0.22.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.9"
|
||||
@ -6420,7 +6539,23 @@ dependencies = [
|
||||
"log",
|
||||
"pin-project 1.0.11",
|
||||
"tokio",
|
||||
"tungstenite",
|
||||
"tungstenite 0.14.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06cda1232a49558c46f8a504d5b93101d42c0bf7f911f12a105ba48168f821ae"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"rustls 0.20.6",
|
||||
"tokio",
|
||||
"tokio-rustls 0.23.4",
|
||||
"tungstenite 0.17.2",
|
||||
"webpki 0.22.0",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6502,6 +6637,16 @@ dependencies = [
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-futures"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
|
||||
dependencies = [
|
||||
"pin-project 1.0.11",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.1.3"
|
||||
@ -6644,6 +6789,27 @@ dependencies = [
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"rustls 0.20.6",
|
||||
"sha-1 0.10.0",
|
||||
"thiserror",
|
||||
"url",
|
||||
"utf-8",
|
||||
"webpki 0.22.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "twoway"
|
||||
version = "0.1.8"
|
||||
@ -6991,9 +7157,9 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tokio-rustls 0.22.0",
|
||||
"tokio-stream",
|
||||
"tokio-tungstenite",
|
||||
"tokio-tungstenite 0.15.0",
|
||||
"tokio-util 0.6.10",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@ -7378,6 +7544,24 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ws_stream_wasm"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47ca1ab42f5afed7fc332b22b6e932ca5414b209465412c8cdf0ad23bc0de645"
|
||||
dependencies = [
|
||||
"async_io_stream",
|
||||
"futures",
|
||||
"js-sys",
|
||||
"pharos",
|
||||
"rustc_version 0.4.0",
|
||||
"send_wrapper",
|
||||
"thiserror",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.2.0"
|
||||
|
@ -15,3 +15,8 @@ execution_layer = { path = "../../beacon_node/execution_layer" }
|
||||
sensitive_url = { path = "../../common/sensitive_url" }
|
||||
types = { path = "../../consensus/types" }
|
||||
unused_port = { path = "../../common/unused_port" }
|
||||
ethers-core = { git = "https://github.com/gakonst/ethers-rs", rev = "02ad93a1cfb7b62eb051c77c61dc4c0218428e4a" }
|
||||
ethers-providers = { git = "https://github.com/gakonst/ethers-rs", rev = "02ad93a1cfb7b62eb051c77c61dc4c0218428e4a" }
|
||||
deposit_contract = { path = "../../common/deposit_contract" }
|
||||
reqwest = { version = "0.11.0", features = ["json"] }
|
||||
hex = "0.4.2"
|
||||
|
@ -1,3 +1,4 @@
|
||||
use ethers_providers::{Http, Provider};
|
||||
use execution_layer::DEFAULT_JWT_FILE;
|
||||
use sensitive_url::SensitiveUrl;
|
||||
use std::path::PathBuf;
|
||||
@ -5,6 +6,14 @@ use std::process::Child;
|
||||
use tempfile::TempDir;
|
||||
use unused_port::unused_tcp_port;
|
||||
|
||||
pub const KEYSTORE_PASSWORD: &str = "testpwd";
|
||||
pub const ACCOUNT1: &str = "7b8C3a386C0eea54693fFB0DA17373ffC9228139";
|
||||
pub const ACCOUNT2: &str = "dA2DD7560DB7e212B945fC72cEB54B7D8C886D77";
|
||||
pub const PRIVATE_KEYS: [&str; 2] = [
|
||||
"115fe42a60e5ef45f5490e599add1f03c73aeaca129c2c41451eca6cf8ff9e04",
|
||||
"6a692e710077d9000be1326acbe32f777b403902ac8779b19eb1398b849c99c3",
|
||||
];
|
||||
|
||||
/// Defined for each EE type (e.g., Geth, Nethermind, etc).
|
||||
pub trait GenericExecutionEngine: Clone {
|
||||
fn init_datadir() -> TempDir;
|
||||
@ -22,8 +31,10 @@ pub struct ExecutionEngine<E> {
|
||||
engine: E,
|
||||
#[allow(dead_code)]
|
||||
datadir: TempDir,
|
||||
http_port: u16,
|
||||
http_auth_port: u16,
|
||||
child: Child,
|
||||
pub provider: Provider<Http>,
|
||||
}
|
||||
|
||||
impl<E> Drop for ExecutionEngine<E> {
|
||||
@ -42,11 +53,15 @@ impl<E: GenericExecutionEngine> ExecutionEngine<E> {
|
||||
let http_port = unused_tcp_port().unwrap();
|
||||
let http_auth_port = unused_tcp_port().unwrap();
|
||||
let child = E::start_client(&datadir, http_port, http_auth_port, jwt_secret_path);
|
||||
let provider = Provider::<Http>::try_from(format!("http://localhost:{}", http_port))
|
||||
.expect("failed to instantiate ethers provider");
|
||||
Self {
|
||||
engine,
|
||||
datadir,
|
||||
http_port,
|
||||
http_auth_port,
|
||||
child,
|
||||
provider,
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +69,10 @@ impl<E: GenericExecutionEngine> ExecutionEngine<E> {
|
||||
SensitiveUrl::parse(&format!("http://127.0.0.1:{}", self.http_auth_port)).unwrap()
|
||||
}
|
||||
|
||||
pub fn http_url(&self) -> SensitiveUrl {
|
||||
SensitiveUrl::parse(&format!("http://127.0.0.1:{}", self.http_port)).unwrap()
|
||||
}
|
||||
|
||||
pub fn datadir(&self) -> PathBuf {
|
||||
self.datadir.path().to_path_buf()
|
||||
}
|
||||
|
@ -32,7 +32,12 @@ pub fn geth_genesis_json() -> Value {
|
||||
"mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase":"0x0000000000000000000000000000000000000000",
|
||||
"alloc":{
|
||||
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"}
|
||||
"0x7b8C3a386C0eea54693fFB0DA17373ffC9228139": {
|
||||
"balance": "10000000000000000000000000"
|
||||
},
|
||||
"0xdA2DD7560DB7e212B945fC72cEB54B7D8C886D77": {
|
||||
"balance": "10000000000000000000000000"
|
||||
},
|
||||
},
|
||||
"number":"0x0",
|
||||
"gasUsed":"0x0",
|
||||
@ -40,3 +45,87 @@ pub fn geth_genesis_json() -> Value {
|
||||
"baseFeePerGas":"0x7"
|
||||
})
|
||||
}
|
||||
|
||||
/// Modified kiln config
|
||||
pub fn nethermind_genesis_json() -> Value {
|
||||
json!(
|
||||
{
|
||||
"name": "lighthouse_test_network",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x20000",
|
||||
"difficultyBoundDivisor": "0x800",
|
||||
"durationLimit": "0xd",
|
||||
"blockReward": {
|
||||
"0x0": "0x1BC16D674EC80000"
|
||||
},
|
||||
"homesteadTransition": "0x0",
|
||||
"eip100bTransition": "0x0",
|
||||
"difficultyBombDelays": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x400",
|
||||
"registrar": "0x0000000000000000000000000000000000000000",
|
||||
"accountStartNonce": "0x0",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "0x1469ca",
|
||||
"MergeForkIdTransition": "0x3e8",
|
||||
"eip150Transition": "0x0",
|
||||
"eip158Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip1014Transition": "0x0",
|
||||
"eip1052Transition": "0x0",
|
||||
"eip1283Transition": "0x0",
|
||||
"eip1283DisableTransition": "0x0",
|
||||
"eip152Transition": "0x0",
|
||||
"eip1108Transition": "0x0",
|
||||
"eip1344Transition": "0x0",
|
||||
"eip1884Transition": "0x0",
|
||||
"eip2028Transition": "0x0",
|
||||
"eip2200Transition": "0x0",
|
||||
"eip2565Transition": "0x0",
|
||||
"eip2929Transition": "0x0",
|
||||
"eip2930Transition": "0x0",
|
||||
"eip1559Transition": "0x0",
|
||||
"eip3198Transition": "0x0",
|
||||
"eip3529Transition": "0x0",
|
||||
"eip3541Transition": "0x0"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x1234",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x01",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "",
|
||||
"gasLimit": "0x1C9C380"
|
||||
},
|
||||
"accounts": {
|
||||
"0x7b8C3a386C0eea54693fFB0DA17373ffC9228139": {
|
||||
"balance": "10000000000000000000000000"
|
||||
},
|
||||
"0xdA2DD7560DB7e212B945fC72cEB54B7D8C886D77": {
|
||||
"balance": "10000000000000000000000000"
|
||||
},
|
||||
},
|
||||
"nodes": []
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -90,13 +90,14 @@ impl GenericExecutionEngine for GethEngine {
|
||||
.arg(datadir.path().to_str().unwrap())
|
||||
.arg("--http")
|
||||
.arg("--http.api")
|
||||
.arg("engine,eth")
|
||||
.arg("engine,eth,personal")
|
||||
.arg("--http.port")
|
||||
.arg(http_port.to_string())
|
||||
.arg("--authrpc.port")
|
||||
.arg(http_auth_port.to_string())
|
||||
.arg("--port")
|
||||
.arg(network_port.to_string())
|
||||
.arg("--allow-insecure-unlock")
|
||||
.arg("--authrpc.jwtsecret")
|
||||
.arg(jwt_secret_path.as_path().to_str().unwrap())
|
||||
.stdout(build_utils::build_stdio())
|
||||
|
@ -1,3 +1,4 @@
|
||||
#![recursion_limit = "1024"]
|
||||
/// This binary runs integration tests between Lighthouse and execution engines.
|
||||
///
|
||||
/// It will first attempt to build any supported integration clients, then it will run tests.
|
||||
@ -9,6 +10,7 @@ mod genesis_json;
|
||||
mod geth;
|
||||
mod nethermind;
|
||||
mod test_rig;
|
||||
mod transactions;
|
||||
|
||||
use geth::GethEngine;
|
||||
use nethermind::NethermindEngine;
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::build_utils;
|
||||
use crate::execution_engine::GenericExecutionEngine;
|
||||
use crate::genesis_json::nethermind_genesis_json;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Child, Command, Output};
|
||||
use tempfile::TempDir;
|
||||
@ -69,33 +71,43 @@ impl NethermindEngine {
|
||||
|
||||
impl GenericExecutionEngine for NethermindEngine {
|
||||
fn init_datadir() -> TempDir {
|
||||
TempDir::new().unwrap()
|
||||
let datadir = TempDir::new().unwrap();
|
||||
let genesis_json_path = datadir.path().join("genesis.json");
|
||||
let mut file = File::create(&genesis_json_path).unwrap();
|
||||
let json = nethermind_genesis_json();
|
||||
serde_json::to_writer(&mut file, &json).unwrap();
|
||||
datadir
|
||||
}
|
||||
|
||||
fn start_client(
|
||||
datadir: &TempDir,
|
||||
_http_port: u16,
|
||||
http_port: u16,
|
||||
http_auth_port: u16,
|
||||
jwt_secret_path: PathBuf,
|
||||
) -> Child {
|
||||
let network_port = unused_tcp_port().unwrap();
|
||||
let genesis_json_path = datadir.path().join("genesis.json");
|
||||
|
||||
Command::new(Self::binary_path())
|
||||
.arg("--datadir")
|
||||
.arg(datadir.path().to_str().unwrap())
|
||||
.arg("--config")
|
||||
.arg("kiln")
|
||||
.arg("--Init.ChainSpecPath")
|
||||
.arg(genesis_json_path.to_str().unwrap())
|
||||
.arg("--Merge.TerminalTotalDifficulty")
|
||||
.arg("0")
|
||||
.arg("--JsonRpc.Enabled")
|
||||
.arg("true")
|
||||
.arg("--JsonRpc.EnabledModules")
|
||||
.arg("net,eth,subscribe,web3,admin,personal")
|
||||
.arg("--JsonRpc.Port")
|
||||
.arg(http_port.to_string())
|
||||
.arg("--JsonRpc.AdditionalRpcUrls")
|
||||
.arg(format!(
|
||||
"http://localhost:{}|http;ws|net;eth;subscribe;engine;web3;client",
|
||||
http_auth_port
|
||||
))
|
||||
.arg("--JsonRpc.EnabledModules")
|
||||
.arg("net,eth,subscribe,web3,admin,engine")
|
||||
.arg("--JsonRpc.Port")
|
||||
.arg(http_auth_port.to_string())
|
||||
.arg("--Network.DiscoveryPort")
|
||||
.arg(network_port.to_string())
|
||||
.arg("--Network.P2PPort")
|
||||
|
@ -1,5 +1,12 @@
|
||||
use crate::execution_engine::{ExecutionEngine, GenericExecutionEngine};
|
||||
use crate::execution_engine::{
|
||||
ExecutionEngine, GenericExecutionEngine, ACCOUNT1, ACCOUNT2, KEYSTORE_PASSWORD, PRIVATE_KEYS,
|
||||
};
|
||||
use crate::transactions::transactions;
|
||||
use ethers_providers::Middleware;
|
||||
use execution_layer::{ExecutionLayer, PayloadAttributes, PayloadStatus};
|
||||
use reqwest::{header::CONTENT_TYPE, Client};
|
||||
use sensitive_url::SensitiveUrl;
|
||||
use serde_json::{json, Value};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
use task_executor::TaskExecutor;
|
||||
@ -8,7 +15,6 @@ use types::{
|
||||
Address, ChainSpec, EthSpec, ExecutionBlockHash, ExecutionPayload, FullPayload, Hash256,
|
||||
MainnetEthSpec, Slot, Uint256,
|
||||
};
|
||||
|
||||
const EXECUTION_ENGINE_START_TIMEOUT: Duration = Duration::from_secs(20);
|
||||
|
||||
struct ExecutionPair<E, T: EthSpec> {
|
||||
@ -32,6 +38,63 @@ pub struct TestRig<E, T: EthSpec = MainnetEthSpec> {
|
||||
_runtime_shutdown: exit_future::Signal,
|
||||
}
|
||||
|
||||
/// Import a private key into the execution engine and unlock it so that we can
|
||||
/// make transactions with the corresponding account.
|
||||
async fn import_and_unlock(http_url: SensitiveUrl, priv_keys: &[&str], password: &str) {
|
||||
for priv_key in priv_keys {
|
||||
let body = json!(
|
||||
{
|
||||
"jsonrpc":"2.0",
|
||||
"method":"personal_importRawKey",
|
||||
"params":[priv_key, password],
|
||||
"id":1
|
||||
}
|
||||
);
|
||||
|
||||
let client = Client::builder().build().unwrap();
|
||||
let request = client
|
||||
.post(http_url.full.clone())
|
||||
.header(CONTENT_TYPE, "application/json")
|
||||
.json(&body);
|
||||
|
||||
let response: Value = request
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.error_for_status()
|
||||
.unwrap()
|
||||
.json()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let account = response.get("result").unwrap().as_str().unwrap();
|
||||
|
||||
let body = json!(
|
||||
{
|
||||
"jsonrpc":"2.0",
|
||||
"method":"personal_unlockAccount",
|
||||
"params":[account, password],
|
||||
"id":1
|
||||
}
|
||||
);
|
||||
|
||||
let request = client
|
||||
.post(http_url.full.clone())
|
||||
.header(CONTENT_TYPE, "application/json")
|
||||
.json(&body);
|
||||
|
||||
let _response: Value = request
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.error_for_status()
|
||||
.unwrap()
|
||||
.json()
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: GenericExecutionEngine> TestRig<E> {
|
||||
pub fn new(generic_engine: E) -> Self {
|
||||
let log = environment::null_logger().unwrap();
|
||||
@ -125,6 +188,20 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
||||
pub async fn perform_tests(&self) {
|
||||
self.wait_until_synced().await;
|
||||
|
||||
// Import and unlock all private keys to sign transactions
|
||||
let _ = futures::future::join_all([&self.ee_a, &self.ee_b].iter().map(|ee| {
|
||||
import_and_unlock(
|
||||
ee.execution_engine.http_url(),
|
||||
&PRIVATE_KEYS,
|
||||
KEYSTORE_PASSWORD,
|
||||
)
|
||||
}))
|
||||
.await;
|
||||
|
||||
// We hardcode the accounts here since some EEs start with a default unlocked account
|
||||
let account1 = ethers_core::types::Address::from_slice(&hex::decode(&ACCOUNT1).unwrap());
|
||||
let account2 = ethers_core::types::Address::from_slice(&hex::decode(&ACCOUNT2).unwrap());
|
||||
|
||||
/*
|
||||
* Check the transition config endpoint.
|
||||
*/
|
||||
@ -157,6 +234,17 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
// Submit transactions before getting payload
|
||||
let txs = transactions::<MainnetEthSpec>(account1, account2);
|
||||
for tx in txs.clone().into_iter() {
|
||||
self.ee_a
|
||||
.execution_engine
|
||||
.provider
|
||||
.send_transaction(tx, None)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/*
|
||||
* Execution Engine A:
|
||||
*
|
||||
@ -168,6 +256,45 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
||||
let prev_randao = Hash256::zero();
|
||||
let finalized_block_hash = ExecutionBlockHash::zero();
|
||||
let proposer_index = 0;
|
||||
|
||||
let prepared = self
|
||||
.ee_a
|
||||
.execution_layer
|
||||
.insert_proposer(
|
||||
Slot::new(1), // Insert proposer for the next slot
|
||||
Hash256::zero(),
|
||||
proposer_index,
|
||||
PayloadAttributes {
|
||||
timestamp,
|
||||
prev_randao,
|
||||
suggested_fee_recipient: Address::zero(),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(!prepared, "Inserting proposer for the first time");
|
||||
|
||||
// Make a fcu call with the PayloadAttributes that we inserted previously
|
||||
let prepare = self
|
||||
.ee_a
|
||||
.execution_layer
|
||||
.notify_forkchoice_updated(
|
||||
parent_hash,
|
||||
finalized_block_hash,
|
||||
Slot::new(0),
|
||||
Hash256::zero(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(prepare, PayloadStatus::Valid);
|
||||
|
||||
// Add a delay to give the EE sufficient time to pack the
|
||||
// submitted transactions into a payload.
|
||||
// This is required when running on under resourced nodes and
|
||||
// in CI.
|
||||
sleep(Duration::from_secs(3)).await;
|
||||
|
||||
let valid_payload = self
|
||||
.ee_a
|
||||
.execution_layer
|
||||
@ -184,6 +311,8 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
||||
.unwrap()
|
||||
.execution_payload;
|
||||
|
||||
assert_eq!(valid_payload.transactions.len(), txs.len());
|
||||
|
||||
/*
|
||||
* Execution Engine A:
|
||||
*
|
||||
|
87
testing/execution_engine_integration/src/transactions.rs
Normal file
87
testing/execution_engine_integration/src/transactions.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use deposit_contract::{encode_eth1_tx_data, BYTECODE, CONTRACT_DEPLOY_GAS, DEPOSIT_GAS};
|
||||
use ethers_core::types::{
|
||||
transaction::{eip2718::TypedTransaction, eip2930::AccessList},
|
||||
Address, Bytes, Eip1559TransactionRequest, TransactionRequest,
|
||||
};
|
||||
use types::{DepositData, EthSpec, Hash256, Keypair, Signature};
|
||||
|
||||
/// Hardcoded deposit contract address based on sender address and nonce
|
||||
pub const DEPOSIT_CONTRACT_ADDRESS: &str = "64f43BEc7F86526686C931d65362bB8698872F90";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Transaction {
|
||||
Transfer(Address, Address),
|
||||
TransferLegacy(Address, Address),
|
||||
TransferAccessList(Address, Address),
|
||||
DeployDepositContract(Address),
|
||||
DepositDepositContract {
|
||||
sender: Address,
|
||||
deposit_contract_address: Address,
|
||||
},
|
||||
}
|
||||
|
||||
/// Get a list of transactions to publish to the execution layer.
|
||||
pub fn transactions<E: EthSpec>(account1: Address, account2: Address) -> Vec<TypedTransaction> {
|
||||
vec![
|
||||
Transaction::Transfer(account1, account2).transaction::<E>(),
|
||||
Transaction::TransferLegacy(account1, account2).transaction::<E>(),
|
||||
Transaction::TransferAccessList(account1, account2).transaction::<E>(),
|
||||
Transaction::DeployDepositContract(account1).transaction::<E>(),
|
||||
Transaction::DepositDepositContract {
|
||||
sender: account1,
|
||||
deposit_contract_address: ethers_core::types::Address::from_slice(
|
||||
&hex::decode(&DEPOSIT_CONTRACT_ADDRESS).unwrap(),
|
||||
),
|
||||
}
|
||||
.transaction::<E>(),
|
||||
]
|
||||
}
|
||||
|
||||
impl Transaction {
|
||||
pub fn transaction<E: EthSpec>(&self) -> TypedTransaction {
|
||||
match &self {
|
||||
Self::TransferLegacy(from, to) => TransactionRequest::new()
|
||||
.from(*from)
|
||||
.to(*to)
|
||||
.value(1)
|
||||
.into(),
|
||||
Self::Transfer(from, to) => Eip1559TransactionRequest::new()
|
||||
.from(*from)
|
||||
.to(*to)
|
||||
.value(1)
|
||||
.into(),
|
||||
Self::TransferAccessList(from, to) => TransactionRequest::new()
|
||||
.from(*from)
|
||||
.to(*to)
|
||||
.value(1)
|
||||
.with_access_list(AccessList::default())
|
||||
.into(),
|
||||
Self::DeployDepositContract(addr) => TransactionRequest::new()
|
||||
.from(*addr)
|
||||
.data(Bytes::from(BYTECODE.to_vec()))
|
||||
.gas(CONTRACT_DEPLOY_GAS)
|
||||
.into(),
|
||||
Self::DepositDepositContract {
|
||||
sender,
|
||||
deposit_contract_address,
|
||||
} => {
|
||||
let keypair = Keypair::random();
|
||||
|
||||
let mut deposit = DepositData {
|
||||
pubkey: keypair.pk.into(),
|
||||
withdrawal_credentials: Hash256::zero(),
|
||||
amount: 32_000_000_000,
|
||||
signature: Signature::empty().into(),
|
||||
};
|
||||
|
||||
deposit.signature = deposit.create_signature(&keypair.sk, &E::default_spec());
|
||||
TransactionRequest::new()
|
||||
.from(*sender)
|
||||
.to(*deposit_contract_address)
|
||||
.data(Bytes::from(encode_eth1_tx_data(&deposit).unwrap()))
|
||||
.gas(DEPOSIT_GAS)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user