Skip to content

Commit

Permalink
Add test to beacon node fallback feature (#6568)
Browse files Browse the repository at this point in the history
  • Loading branch information
chong-he authored Feb 4, 2025
1 parent 56f201a commit 3d06bc2
Show file tree
Hide file tree
Showing 9 changed files with 405 additions and 13 deletions.
67 changes: 67 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ members = [
"testing/simulator",
"testing/state_transition_vectors",
"testing/test-test_logger",
"testing/validator_test_rig",
"testing/web3signer_tests",


"validator_client",
"validator_client/beacon_node_fallback",
"validator_client/doppelganger_service",
Expand Down Expand Up @@ -155,6 +157,7 @@ log = "0.4"
lru = "0.12"
maplit = "1"
milhouse = "0.3"
mockito = "1.5.0"
num_cpus = "1"
parking_lot = "0.12"
paste = "1"
Expand Down Expand Up @@ -261,6 +264,7 @@ malloc_utils = { path = "common/malloc_utils" }
merkle_proof = { path = "consensus/merkle_proof" }
monitoring_api = { path = "common/monitoring_api" }
network = { path = "beacon_node/network" }
node_test_rig = { path = "testing/node_test_rig" }
operation_pool = { path = "beacon_node/operation_pool" }
pretty_reqwest_error = { path = "common/pretty_reqwest_error" }
proto_array = { path = "consensus/proto_array" }
Expand All @@ -283,6 +287,7 @@ validator_http_api = { path = "validator_client/http_api" }
validator_http_metrics = { path = "validator_client/http_metrics" }
validator_metrics = { path = "validator_client/validator_metrics" }
validator_store = { path = "validator_client/validator_store" }
validator_test_rig = { path = "testing/validator_test_rig" }
warp_utils = { path = "common/warp_utils" }
xdelta3 = { git = "http://github.com/sigp/xdelta3-rs", rev = "50d63cdf1878e5cf3538e9aae5eed34a22c64e4a" }
zstd = "0.13"
Expand Down
14 changes: 14 additions & 0 deletions testing/validator_test_rig/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "validator_test_rig"
version = "0.1.0"
edition = { workspace = true }

[dependencies]
eth2 = { workspace = true }
logging = { workspace = true }
mockito = { workspace = true }
regex = { workspace = true }
sensitive_url = { workspace = true }
serde_json = { workspace = true }
slog = { workspace = true }
types = { workspace = true }
1 change: 1 addition & 0 deletions testing/validator_test_rig/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod mock_beacon_node;
132 changes: 132 additions & 0 deletions testing/validator_test_rig/src/mock_beacon_node.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use eth2::types::{GenericResponse, SyncingData};
use eth2::{BeaconNodeHttpClient, StatusCode, Timeouts};
use logging::test_logger;
use mockito::{Matcher, Mock, Server, ServerGuard};
use regex::Regex;
use sensitive_url::SensitiveUrl;
use slog::{info, Logger};
use std::marker::PhantomData;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use types::{ChainSpec, ConfigAndPreset, EthSpec, SignedBlindedBeaconBlock};

pub struct MockBeaconNode<E: EthSpec> {
server: ServerGuard,
pub beacon_api_client: BeaconNodeHttpClient,
log: Logger,
_phantom: PhantomData<E>,
pub received_blocks: Arc<Mutex<Vec<SignedBlindedBeaconBlock<E>>>>,
}

impl<E: EthSpec> MockBeaconNode<E> {
pub async fn new() -> Self {
// mock server logging
let server = Server::new_async().await;
let beacon_api_client = BeaconNodeHttpClient::new(
SensitiveUrl::from_str(&server.url()).unwrap(),
Timeouts::set_all(Duration::from_secs(1)),
);
let log = test_logger();
Self {
server,
beacon_api_client,
log,
_phantom: PhantomData,
received_blocks: Arc::new(Mutex::new(Vec::new())),
}
}

/// Resets all mocks
#[allow(dead_code)]
pub fn reset_mocks(&mut self) {
self.server.reset();
}

pub fn mock_config_spec(&mut self, spec: &ChainSpec) {
let path_pattern = Regex::new(r"^/eth/v1/config/spec$").unwrap();
let config_and_preset = ConfigAndPreset::from_chain_spec::<E>(spec, None);
let data = GenericResponse::from(config_and_preset);
self.server
.mock("GET", Matcher::Regex(path_pattern.to_string()))
.with_status(200)
.with_body(serde_json::to_string(&data).unwrap())
.create();
}

pub fn mock_get_node_syncing(&mut self, response: SyncingData) {
let path_pattern = Regex::new(r"^/eth/v1/node/syncing$").unwrap();

let data = GenericResponse::from(response);

self.server
.mock("GET", Matcher::Regex(path_pattern.to_string()))
.with_status(200)
.with_body(serde_json::to_string(&data).unwrap())
.create();
}

/// Mocks the `post_beacon_blinded_blocks_v2_ssz` response with an optional `delay`.
pub fn mock_post_beacon_blinded_blocks_v2_ssz(&mut self, delay: Duration) -> Mock {
let path_pattern = Regex::new(r"^/eth/v2/beacon/blinded_blocks$").unwrap();
let log = self.log.clone();
let url = self.server.url();

let received_blocks = Arc::clone(&self.received_blocks);

self.server
.mock("POST", Matcher::Regex(path_pattern.to_string()))
.match_header("content-type", "application/octet-stream")
.with_status(200)
.with_body_from_request(move |request| {
info!(
log,
"{}",
format!(
"Received published block request on server {} with delay {} s",
url,
delay.as_secs(),
)
);

let body = request.body().expect("Failed to get request body");
let block: SignedBlindedBeaconBlock<E> =
SignedBlindedBeaconBlock::any_from_ssz_bytes(body)
.expect("Failed to deserialize body as SignedBlindedBeaconBlock");

received_blocks.lock().unwrap().push(block);

std::thread::sleep(delay);
vec![]
})
.create()
}

pub fn mock_offline_node(&mut self) -> Mock {
let path_pattern = Regex::new(r"^/eth/v1/node/version$").unwrap();

self.server
.mock("GET", Matcher::Regex(path_pattern.to_string()))
.with_status(StatusCode::INTERNAL_SERVER_ERROR.as_u16() as usize)
.with_header("content-type", "application/json")
.with_body(r#"{"message":"Internal Server Error"}"#)
.create()
}

pub fn mock_online_node(&mut self) -> Mock {
let path_pattern = Regex::new(r"^/eth/v1/node/version$").unwrap();

self.server
.mock("GET", Matcher::Regex(path_pattern.to_string()))
.with_status(200)
.with_header("content-type", "application/json")
.with_body(
r#"{
"data": {
"version": "lighthouse-mock"
}
}"#,
)
.create()
}
}
3 changes: 0 additions & 3 deletions validator_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ edition = { workspace = true }
name = "validator_client"
path = "src/lib.rs"

[dev-dependencies]
tokio = { workspace = true }

[dependencies]
account_utils = { workspace = true }
beacon_node_fallback = { workspace = true }
Expand Down
4 changes: 4 additions & 0 deletions validator_client/beacon_node_fallback/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ strum = { workspace = true }
tokio = { workspace = true }
types = { workspace = true }
validator_metrics = { workspace = true }

[dev-dependencies]
logging = { workspace = true }
validator_test_rig = { workspace = true }
Loading

0 comments on commit 3d06bc2

Please # to comment.