mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 18:04:18 +00:00
Merge remote-tracking branch 'origin/unstable' into tree-states
This commit is contained in:
@@ -518,22 +518,32 @@ pub mod deposit_methods {
|
||||
pub struct HttpJsonRpc {
|
||||
pub client: Client,
|
||||
pub url: SensitiveUrl,
|
||||
pub execution_timeout_multiplier: u32,
|
||||
auth: Option<Auth>,
|
||||
}
|
||||
|
||||
impl HttpJsonRpc {
|
||||
pub fn new(url: SensitiveUrl) -> Result<Self, Error> {
|
||||
pub fn new(
|
||||
url: SensitiveUrl,
|
||||
execution_timeout_multiplier: Option<u32>,
|
||||
) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
client: Client::builder().build()?,
|
||||
url,
|
||||
execution_timeout_multiplier: execution_timeout_multiplier.unwrap_or(1),
|
||||
auth: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_with_auth(url: SensitiveUrl, auth: Auth) -> Result<Self, Error> {
|
||||
pub fn new_with_auth(
|
||||
url: SensitiveUrl,
|
||||
auth: Auth,
|
||||
execution_timeout_multiplier: Option<u32>,
|
||||
) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
client: Client::builder().build()?,
|
||||
url,
|
||||
execution_timeout_multiplier: execution_timeout_multiplier.unwrap_or(1),
|
||||
auth: Some(auth),
|
||||
})
|
||||
}
|
||||
@@ -590,7 +600,11 @@ impl std::fmt::Display for HttpJsonRpc {
|
||||
impl HttpJsonRpc {
|
||||
pub async fn upcheck(&self) -> Result<(), Error> {
|
||||
let result: serde_json::Value = self
|
||||
.rpc_request(ETH_SYNCING, json!([]), ETH_SYNCING_TIMEOUT)
|
||||
.rpc_request(
|
||||
ETH_SYNCING,
|
||||
json!([]),
|
||||
ETH_SYNCING_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
|
||||
/*
|
||||
@@ -614,7 +628,7 @@ impl HttpJsonRpc {
|
||||
self.rpc_request(
|
||||
ETH_GET_BLOCK_BY_NUMBER,
|
||||
params,
|
||||
ETH_GET_BLOCK_BY_NUMBER_TIMEOUT,
|
||||
ETH_GET_BLOCK_BY_NUMBER_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -625,8 +639,12 @@ impl HttpJsonRpc {
|
||||
) -> Result<Option<ExecutionBlock>, Error> {
|
||||
let params = json!([block_hash, RETURN_FULL_TRANSACTION_OBJECTS]);
|
||||
|
||||
self.rpc_request(ETH_GET_BLOCK_BY_HASH, params, ETH_GET_BLOCK_BY_HASH_TIMEOUT)
|
||||
.await
|
||||
self.rpc_request(
|
||||
ETH_GET_BLOCK_BY_HASH,
|
||||
params,
|
||||
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_block_by_hash_with_txns<T: EthSpec>(
|
||||
@@ -634,8 +652,12 @@ impl HttpJsonRpc {
|
||||
block_hash: ExecutionBlockHash,
|
||||
) -> Result<Option<ExecutionBlockWithTransactions<T>>, Error> {
|
||||
let params = json!([block_hash, true]);
|
||||
self.rpc_request(ETH_GET_BLOCK_BY_HASH, params, ETH_GET_BLOCK_BY_HASH_TIMEOUT)
|
||||
.await
|
||||
self.rpc_request(
|
||||
ETH_GET_BLOCK_BY_HASH,
|
||||
params,
|
||||
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn new_payload_v1<T: EthSpec>(
|
||||
@@ -645,7 +667,11 @@ impl HttpJsonRpc {
|
||||
let params = json!([JsonExecutionPayloadV1::from(execution_payload)]);
|
||||
|
||||
let response: JsonPayloadStatusV1 = self
|
||||
.rpc_request(ENGINE_NEW_PAYLOAD_V1, params, ENGINE_NEW_PAYLOAD_TIMEOUT)
|
||||
.rpc_request(
|
||||
ENGINE_NEW_PAYLOAD_V1,
|
||||
params,
|
||||
ENGINE_NEW_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(response.into())
|
||||
@@ -658,7 +684,11 @@ impl HttpJsonRpc {
|
||||
let params = json!([JsonPayloadIdRequest::from(payload_id)]);
|
||||
|
||||
let response: JsonExecutionPayloadV1<T> = self
|
||||
.rpc_request(ENGINE_GET_PAYLOAD_V1, params, ENGINE_GET_PAYLOAD_TIMEOUT)
|
||||
.rpc_request(
|
||||
ENGINE_GET_PAYLOAD_V1,
|
||||
params,
|
||||
ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(response.into())
|
||||
@@ -678,7 +708,7 @@ impl HttpJsonRpc {
|
||||
.rpc_request(
|
||||
ENGINE_FORKCHOICE_UPDATED_V1,
|
||||
params,
|
||||
ENGINE_FORKCHOICE_UPDATED_TIMEOUT,
|
||||
ENGINE_FORKCHOICE_UPDATED_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -695,7 +725,8 @@ impl HttpJsonRpc {
|
||||
.rpc_request(
|
||||
ENGINE_EXCHANGE_TRANSITION_CONFIGURATION_V1,
|
||||
params,
|
||||
ENGINE_EXCHANGE_TRANSITION_CONFIGURATION_V1_TIMEOUT,
|
||||
ENGINE_EXCHANGE_TRANSITION_CONFIGURATION_V1_TIMEOUT
|
||||
* self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -732,13 +763,13 @@ mod test {
|
||||
let echo_auth =
|
||||
Auth::new(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap(), None, None);
|
||||
(
|
||||
Arc::new(HttpJsonRpc::new_with_auth(rpc_url, rpc_auth).unwrap()),
|
||||
Arc::new(HttpJsonRpc::new_with_auth(echo_url, echo_auth).unwrap()),
|
||||
Arc::new(HttpJsonRpc::new_with_auth(rpc_url, rpc_auth, None).unwrap()),
|
||||
Arc::new(HttpJsonRpc::new_with_auth(echo_url, echo_auth, None).unwrap()),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
Arc::new(HttpJsonRpc::new(rpc_url).unwrap()),
|
||||
Arc::new(HttpJsonRpc::new(echo_url).unwrap()),
|
||||
Arc::new(HttpJsonRpc::new(rpc_url, None).unwrap()),
|
||||
Arc::new(HttpJsonRpc::new(echo_url, None).unwrap()),
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use super::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_types::FixedVector;
|
||||
use types::{
|
||||
EthSpec, ExecutionBlockHash, ExecutionPayloadHeader, Transaction, Unsigned, VariableList,
|
||||
};
|
||||
use strum::EnumString;
|
||||
use types::{EthSpec, ExecutionBlockHash, Transaction, Unsigned, VariableList};
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -314,8 +313,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,
|
||||
|
||||
@@ -159,6 +159,7 @@ pub struct Config {
|
||||
pub default_datadir: PathBuf,
|
||||
/// The minimum value of an external payload for it to be considered in a proposal.
|
||||
pub builder_profit_threshold: u128,
|
||||
pub execution_timeout_multiplier: Option<u32>,
|
||||
}
|
||||
|
||||
/// Provides access to one execution engine and provides a neat interface for consumption by the
|
||||
@@ -180,6 +181,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
jwt_version,
|
||||
default_datadir,
|
||||
builder_profit_threshold,
|
||||
execution_timeout_multiplier,
|
||||
} = config;
|
||||
|
||||
if urls.len() > 1 {
|
||||
@@ -224,7 +226,8 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
let engine: Engine = {
|
||||
let auth = Auth::new(jwt_key, jwt_id, jwt_version);
|
||||
debug!(log, "Loaded execution endpoint"; "endpoint" => %execution_url, "jwt_path" => ?secret_file.as_path());
|
||||
let api = HttpJsonRpc::new_with_auth(execution_url, auth).map_err(Error::ApiError)?;
|
||||
let api = HttpJsonRpc::new_with_auth(execution_url, auth, execution_timeout_multiplier)
|
||||
.map_err(Error::ApiError)?;
|
||||
Engine::new(api, executor.clone(), &log)
|
||||
};
|
||||
|
||||
@@ -1393,12 +1396,13 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
|
||||
pub async fn propose_blinded_beacon_block(
|
||||
&self,
|
||||
block_root: Hash256,
|
||||
block: &SignedBeaconBlock<T, BlindedPayload<T>>,
|
||||
) -> Result<ExecutionPayload<T>, Error> {
|
||||
debug!(
|
||||
self.log(),
|
||||
"Sending block to builder";
|
||||
"root" => ?block.canonical_root(),
|
||||
"root" => ?block_root,
|
||||
);
|
||||
if let Some(builder) = self.builder() {
|
||||
builder
|
||||
|
||||
@@ -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