mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-15 09:48:20 +00:00
Refactor payload_attestation_service and add payload attestation test to validator client (#9357)
Co-Authored-By: Tan Chee Keong <tanck@sigmaprime.io>
This commit is contained in:
@@ -4,18 +4,23 @@ use mockito::{Matcher, Mock, Server, ServerGuard};
|
||||
use regex::Regex;
|
||||
use reqwest::StatusCode;
|
||||
use sensitive_url::SensitiveUrl;
|
||||
use ssz::Decode;
|
||||
use std::marker::PhantomData;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
use tracing::info;
|
||||
use types::{ChainSpec, ConfigAndPreset, EthSpec, SignedBlindedBeaconBlock};
|
||||
use types::{
|
||||
ChainSpec, ConfigAndPreset, EthSpec, ForkName, PayloadAttestationData,
|
||||
PayloadAttestationMessage, SignedBlindedBeaconBlock, Slot,
|
||||
};
|
||||
|
||||
pub struct MockBeaconNode<E: EthSpec> {
|
||||
server: ServerGuard,
|
||||
pub beacon_api_client: BeaconNodeHttpClient,
|
||||
_phantom: PhantomData<E>,
|
||||
pub received_blocks: Arc<Mutex<Vec<SignedBlindedBeaconBlock<E>>>>,
|
||||
pub payload_attestation_message: Arc<Mutex<Vec<PayloadAttestationMessage>>>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> MockBeaconNode<E> {
|
||||
@@ -31,6 +36,7 @@ impl<E: EthSpec> MockBeaconNode<E> {
|
||||
beacon_api_client,
|
||||
_phantom: PhantomData,
|
||||
received_blocks: Arc::new(Mutex::new(Vec::new())),
|
||||
payload_attestation_message: Arc::new(Mutex::new(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,4 +130,112 @@ impl<E: EthSpec> MockBeaconNode<E> {
|
||||
)
|
||||
.create()
|
||||
}
|
||||
|
||||
/// Mocks `GET /eth/v1/validator/payload_attestations_data/{slot}`
|
||||
pub fn mock_get_validator_payload_attestation_data(
|
||||
&mut self,
|
||||
data: &PayloadAttestationData,
|
||||
fork_name: ForkName,
|
||||
slot: Slot,
|
||||
) -> Mock {
|
||||
let path_pattern = Regex::new(&format!(
|
||||
r"^/eth/v1/validator/payload_attestation_data/{}$",
|
||||
slot.as_u64()
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let body = serde_json::json!({
|
||||
"version": fork_name.to_string(),
|
||||
"data": data,
|
||||
});
|
||||
|
||||
self.server
|
||||
.mock("GET", Matcher::Regex(path_pattern.to_string()))
|
||||
.with_status(200)
|
||||
.with_header("content-type", "application/json")
|
||||
.with_body(serde_json::to_string(&body).unwrap())
|
||||
.create()
|
||||
}
|
||||
|
||||
/// Mocks `GET /eth/v1/validator/payload_attestation_data/{slot}` returning error
|
||||
pub fn mock_get_validator_payload_attestation_data_error(&mut self, slot: Slot) -> Mock {
|
||||
let path_pattern = Regex::new(&format!(
|
||||
r"^/eth/v1/validator/payload_attestation_data/{}$",
|
||||
slot.as_u64()
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
self.server
|
||||
.mock("GET", Matcher::Regex(path_pattern.to_string()))
|
||||
.with_status(500)
|
||||
.with_header("content-type", "application/json")
|
||||
.with_body(r#"{"message":"Internal server error"}"#)
|
||||
.create()
|
||||
}
|
||||
|
||||
/// Mocks `POST /eth/v1/beacon/pool/payload_attestations`
|
||||
pub fn mock_post_beacon_pool_payload_attestations(&mut self) -> Mock {
|
||||
let path_pattern = Regex::new(r"^/eth/v1/beacon/pool/payload_attestations$").unwrap();
|
||||
let payload_attestation_message = Arc::clone(&self.payload_attestation_message);
|
||||
|
||||
self.server
|
||||
.mock("POST", Matcher::Regex(path_pattern.to_string()))
|
||||
.match_header("content-type", "application/json")
|
||||
.with_status(200)
|
||||
.with_body_from_request(move |request| {
|
||||
let body = request.body().expect("Failed to get request body");
|
||||
let message: Vec<PayloadAttestationMessage> = serde_json::from_slice(body)
|
||||
.expect("Failed to deserialize payload attestations");
|
||||
payload_attestation_message.lock().unwrap().extend(message);
|
||||
vec![]
|
||||
})
|
||||
.create()
|
||||
}
|
||||
|
||||
/// Mocks `POST /eth/v1/beacon/pool/payload_attestations` (SSZ) with an optional `delay`.
|
||||
pub fn mock_post_beacon_pool_payload_attestations_ssz(&mut self, delay: Duration) -> Mock {
|
||||
let path_pattern = Regex::new(r"^/eth/v1/beacon/pool/payload_attestations$").unwrap();
|
||||
let url = self.server.url();
|
||||
|
||||
let payload_attestation_message = Arc::clone(&self.payload_attestation_message);
|
||||
|
||||
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!(
|
||||
"Received payload attestation SSZ on server {} with delay {} ms",
|
||||
url,
|
||||
delay.as_secs(),
|
||||
);
|
||||
let body = request.body().expect("Failed to get request body");
|
||||
|
||||
let chunk_size = <PayloadAttestationMessage>::ssz_fixed_len();
|
||||
let messages: Vec<PayloadAttestationMessage> = body
|
||||
.chunks(chunk_size)
|
||||
.map(|chunk| {
|
||||
PayloadAttestationMessage::from_ssz_bytes(chunk)
|
||||
.expect("Failed to deserialize PayloadAttestationMessage from SSZ")
|
||||
})
|
||||
.collect();
|
||||
|
||||
payload_attestation_message.lock().unwrap().extend(messages);
|
||||
std::thread::sleep(delay);
|
||||
vec![]
|
||||
})
|
||||
.create()
|
||||
}
|
||||
|
||||
/// Mocks `POST /eth/v1/beacon/pool/payload_attestations` (SSZ) returning error
|
||||
pub fn mock_post_beacon_pool_payload_attestations_ssz_error(&mut self) -> Mock {
|
||||
let path_pattern = Regex::new(r"^/eth/v1/beacon/pool/payload_attestations$").unwrap();
|
||||
|
||||
self.server
|
||||
.mock("POST", Matcher::Regex(path_pattern.to_string()))
|
||||
.match_header("content-type", "application/octet-stream")
|
||||
.with_status(500)
|
||||
.with_body(r#"{"message":"Internal server error"}"#)
|
||||
.create()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user