mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 20:22:02 +00:00
Optimistic sync spec tests (v1.2.0) (#3564)
## Issue Addressed Implements new optimistic sync test format from https://github.com/ethereum/consensus-specs/pull/2982. ## Proposed Changes - Add parsing and runner support for the new test format. - Extend the mock EL with a set of canned responses keyed by block hash. Although this doubles up on some of the existing functionality I think it's really nice to use compared to the `preloaded_responses` or static responses. I think we could write novel new opt sync tests using these primtives much more easily than the previous ones. Forks are natively supported, and different responses to `forkchoiceUpdated` and `newPayload` are also straight-forward. ## Additional Info Blocked on merge of the spec PR and release of new test vectors.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::EnumString;
|
||||
use types::{EthSpec, ExecutionBlockHash, FixedVector, Transaction, Unsigned, VariableList};
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
@@ -311,8 +312,9 @@ impl From<JsonForkChoiceStateV1> for ForkChoiceState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, EnumString)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum JsonPayloadStatusV1Status {
|
||||
Valid,
|
||||
Invalid,
|
||||
|
||||
@@ -77,6 +77,11 @@ pub async fn handle_rpc<T: EthSpec>(
|
||||
ENGINE_NEW_PAYLOAD_V1 => {
|
||||
let request: JsonExecutionPayloadV1<T> = get_param(params, 0)?;
|
||||
|
||||
// Canned responses set by block hash take priority.
|
||||
if let Some(status) = ctx.get_new_payload_status(&request.block_hash) {
|
||||
return Ok(serde_json::to_value(JsonPayloadStatusV1::from(status)).unwrap());
|
||||
}
|
||||
|
||||
let (static_response, should_import) =
|
||||
if let Some(mut response) = ctx.static_new_payload_response.lock().clone() {
|
||||
if response.status.status == PayloadStatusV1Status::Valid {
|
||||
@@ -120,6 +125,15 @@ pub async fn handle_rpc<T: EthSpec>(
|
||||
|
||||
let head_block_hash = forkchoice_state.head_block_hash;
|
||||
|
||||
// Canned responses set by block hash take priority.
|
||||
if let Some(status) = ctx.get_fcu_payload_status(&head_block_hash) {
|
||||
let response = JsonForkchoiceUpdatedV1Response {
|
||||
payload_status: JsonPayloadStatusV1::from(status),
|
||||
payload_id: None,
|
||||
};
|
||||
return Ok(serde_json::to_value(response).unwrap());
|
||||
}
|
||||
|
||||
let mut response = ctx
|
||||
.execution_block_generator
|
||||
.write()
|
||||
|
||||
@@ -12,6 +12,7 @@ use parking_lot::{Mutex, RwLock, RwLockWriteGuard};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use slog::{info, Logger};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::Infallible;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
@@ -98,6 +99,8 @@ impl<T: EthSpec> MockServer<T> {
|
||||
static_new_payload_response: <_>::default(),
|
||||
static_forkchoice_updated_response: <_>::default(),
|
||||
static_get_block_by_hash_response: <_>::default(),
|
||||
new_payload_statuses: <_>::default(),
|
||||
fcu_payload_statuses: <_>::default(),
|
||||
_phantom: PhantomData,
|
||||
});
|
||||
|
||||
@@ -370,6 +373,25 @@ impl<T: EthSpec> MockServer<T> {
|
||||
pub fn drop_all_blocks(&self) {
|
||||
self.ctx.execution_block_generator.write().drop_all_blocks()
|
||||
}
|
||||
|
||||
pub fn set_payload_statuses(&self, block_hash: ExecutionBlockHash, status: PayloadStatusV1) {
|
||||
self.set_new_payload_status(block_hash, status.clone());
|
||||
self.set_fcu_payload_status(block_hash, status);
|
||||
}
|
||||
|
||||
pub fn set_new_payload_status(&self, block_hash: ExecutionBlockHash, status: PayloadStatusV1) {
|
||||
self.ctx
|
||||
.new_payload_statuses
|
||||
.lock()
|
||||
.insert(block_hash, status);
|
||||
}
|
||||
|
||||
pub fn set_fcu_payload_status(&self, block_hash: ExecutionBlockHash, status: PayloadStatusV1) {
|
||||
self.ctx
|
||||
.fcu_payload_statuses
|
||||
.lock()
|
||||
.insert(block_hash, status);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -419,9 +441,33 @@ pub struct Context<T: EthSpec> {
|
||||
pub static_new_payload_response: Arc<Mutex<Option<StaticNewPayloadResponse>>>,
|
||||
pub static_forkchoice_updated_response: Arc<Mutex<Option<PayloadStatusV1>>>,
|
||||
pub static_get_block_by_hash_response: Arc<Mutex<Option<Option<ExecutionBlock>>>>,
|
||||
|
||||
// Canned responses by block hash.
|
||||
//
|
||||
// This is a more flexible and less stateful alternative to `static_new_payload_response`
|
||||
// and `preloaded_responses`.
|
||||
pub new_payload_statuses: Arc<Mutex<HashMap<ExecutionBlockHash, PayloadStatusV1>>>,
|
||||
pub fcu_payload_statuses: Arc<Mutex<HashMap<ExecutionBlockHash, PayloadStatusV1>>>,
|
||||
|
||||
pub _phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: EthSpec> Context<T> {
|
||||
pub fn get_new_payload_status(
|
||||
&self,
|
||||
block_hash: &ExecutionBlockHash,
|
||||
) -> Option<PayloadStatusV1> {
|
||||
self.new_payload_statuses.lock().get(block_hash).cloned()
|
||||
}
|
||||
|
||||
pub fn get_fcu_payload_status(
|
||||
&self,
|
||||
block_hash: &ExecutionBlockHash,
|
||||
) -> Option<PayloadStatusV1> {
|
||||
self.fcu_payload_statuses.lock().get(block_hash).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for the HTTP server.
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
|
||||
Reference in New Issue
Block a user