mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-17 02:38:34 +00:00
Merge branch 'unstable' into into-anchor
This commit is contained in:
@@ -829,7 +829,8 @@ impl HttpJsonRpc {
|
||||
Ok(response.into())
|
||||
}
|
||||
|
||||
pub async fn new_payload_v5_fulu<E: EthSpec>(
|
||||
// TODO(fulu): switch to v5 endpoint when the EL is ready for Fulu
|
||||
pub async fn new_payload_v4_fulu<E: EthSpec>(
|
||||
&self,
|
||||
new_payload_request_fulu: NewPayloadRequestFulu<'_, E>,
|
||||
) -> Result<PayloadStatusV1, Error> {
|
||||
@@ -844,7 +845,7 @@ impl HttpJsonRpc {
|
||||
|
||||
let response: JsonPayloadStatusV1 = self
|
||||
.rpc_request(
|
||||
ENGINE_NEW_PAYLOAD_V5,
|
||||
ENGINE_NEW_PAYLOAD_V4,
|
||||
params,
|
||||
ENGINE_NEW_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
@@ -962,6 +963,19 @@ impl HttpJsonRpc {
|
||||
.try_into()
|
||||
.map_err(Error::BadResponse)
|
||||
}
|
||||
// TODO(fulu): remove when v5 method is ready.
|
||||
ForkName::Fulu => {
|
||||
let response: JsonGetPayloadResponseV5<E> = self
|
||||
.rpc_request(
|
||||
ENGINE_GET_PAYLOAD_V4,
|
||||
params,
|
||||
ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
JsonGetPayloadResponse::V5(response)
|
||||
.try_into()
|
||||
.map_err(Error::BadResponse)
|
||||
}
|
||||
_ => Err(Error::UnsupportedForkVariant(format!(
|
||||
"called get_payload_v4 with {}",
|
||||
fork_name
|
||||
@@ -1263,10 +1277,11 @@ impl HttpJsonRpc {
|
||||
}
|
||||
}
|
||||
NewPayloadRequest::Fulu(new_payload_request_fulu) => {
|
||||
if engine_capabilities.new_payload_v5 {
|
||||
self.new_payload_v5_fulu(new_payload_request_fulu).await
|
||||
// TODO(fulu): switch to v5 endpoint when the EL is ready for Fulu
|
||||
if engine_capabilities.new_payload_v4 {
|
||||
self.new_payload_v4_fulu(new_payload_request_fulu).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_newPayloadV5"))
|
||||
Err(Error::RequiredMethodUnsupported("engine_newPayloadV4"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1305,8 +1320,9 @@ impl HttpJsonRpc {
|
||||
}
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
if engine_capabilities.get_payload_v5 {
|
||||
self.get_payload_v5(fork_name, payload_id).await
|
||||
// TODO(fulu): switch to v5 when the EL is ready
|
||||
if engine_capabilities.get_payload_v4 {
|
||||
self.get_payload_v4(fork_name, payload_id).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_getPayloadv5"))
|
||||
}
|
||||
|
||||
@@ -991,3 +991,154 @@ impl TryFrom<JsonClientVersionV1> for ClientVersionV1 {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ssz::Encode;
|
||||
use types::{
|
||||
ConsolidationRequest, DepositRequest, MainnetEthSpec, PublicKeyBytes, RequestType,
|
||||
SignatureBytes, WithdrawalRequest,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
fn create_request_string<T: Encode>(prefix: u8, request_bytes: &T) -> String {
|
||||
format!(
|
||||
"0x{:02x}{}",
|
||||
prefix,
|
||||
hex::encode(request_bytes.as_ssz_bytes())
|
||||
)
|
||||
}
|
||||
|
||||
/// Tests all error conditions except ssz decoding errors
|
||||
///
|
||||
/// ***
|
||||
/// Elements of the list MUST be ordered by request_type in ascending order.
|
||||
/// Elements with empty request_data MUST be excluded from the list.
|
||||
/// If any element is out of order, has a length of 1-byte or shorter,
|
||||
/// or more than one element has the same type byte, client software MUST return -32602: Invalid params error.
|
||||
/// ***
|
||||
#[test]
|
||||
fn test_invalid_execution_requests() {
|
||||
let deposit_request = DepositRequest {
|
||||
pubkey: PublicKeyBytes::empty(),
|
||||
withdrawal_credentials: Hash256::random(),
|
||||
amount: 32,
|
||||
signature: SignatureBytes::empty(),
|
||||
index: 0,
|
||||
};
|
||||
|
||||
let consolidation_request = ConsolidationRequest {
|
||||
source_address: Address::random(),
|
||||
source_pubkey: PublicKeyBytes::empty(),
|
||||
target_pubkey: PublicKeyBytes::empty(),
|
||||
};
|
||||
|
||||
let withdrawal_request = WithdrawalRequest {
|
||||
amount: 32,
|
||||
source_address: Address::random(),
|
||||
validator_pubkey: PublicKeyBytes::empty(),
|
||||
};
|
||||
|
||||
// First check a valid request with all requests
|
||||
assert!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Deposit.to_u8(), &deposit_request),
|
||||
create_request_string(RequestType::Withdrawal.to_u8(), &withdrawal_request),
|
||||
create_request_string(RequestType::Consolidation.to_u8(), &consolidation_request),
|
||||
]))
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
// Single requests
|
||||
assert!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Deposit.to_u8(), &deposit_request),
|
||||
]))
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
assert!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Withdrawal.to_u8(), &withdrawal_request),
|
||||
]))
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
assert!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Consolidation.to_u8(), &consolidation_request),
|
||||
]))
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
// Out of order
|
||||
assert!(matches!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Withdrawal.to_u8(), &withdrawal_request),
|
||||
create_request_string(RequestType::Deposit.to_u8(), &deposit_request),
|
||||
]))
|
||||
.unwrap_err(),
|
||||
RequestsError::InvalidOrdering
|
||||
));
|
||||
|
||||
assert!(matches!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Consolidation.to_u8(), &consolidation_request),
|
||||
create_request_string(RequestType::Withdrawal.to_u8(), &withdrawal_request),
|
||||
]))
|
||||
.unwrap_err(),
|
||||
RequestsError::InvalidOrdering
|
||||
));
|
||||
|
||||
assert!(matches!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Consolidation.to_u8(), &consolidation_request),
|
||||
create_request_string(RequestType::Deposit.to_u8(), &deposit_request),
|
||||
]))
|
||||
.unwrap_err(),
|
||||
RequestsError::InvalidOrdering
|
||||
));
|
||||
|
||||
// Multiple requests of same type
|
||||
assert!(matches!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Deposit.to_u8(), &deposit_request),
|
||||
create_request_string(RequestType::Deposit.to_u8(), &deposit_request),
|
||||
]))
|
||||
.unwrap_err(),
|
||||
RequestsError::InvalidOrdering
|
||||
));
|
||||
|
||||
// Invalid prefix
|
||||
assert!(matches!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(42, &deposit_request),
|
||||
]))
|
||||
.unwrap_err(),
|
||||
RequestsError::InvalidPrefix(42)
|
||||
));
|
||||
|
||||
// Prefix followed by no data
|
||||
assert!(matches!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Deposit.to_u8(), &deposit_request),
|
||||
create_request_string(
|
||||
RequestType::Consolidation.to_u8(),
|
||||
&Vec::<ConsolidationRequest>::new()
|
||||
),
|
||||
]))
|
||||
.unwrap_err(),
|
||||
RequestsError::EmptyRequest(1)
|
||||
));
|
||||
// Empty request
|
||||
assert!(matches!(
|
||||
ExecutionRequests::<MainnetEthSpec>::try_from(JsonExecutionRequests(vec![
|
||||
create_request_string(RequestType::Deposit.to_u8(), &deposit_request),
|
||||
"0x".to_string()
|
||||
]))
|
||||
.unwrap_err(),
|
||||
RequestsError::EmptyRequest(1)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,8 +121,7 @@ impl<E: EthSpec> TryFrom<BuilderBid<E>> for ProvenancedPayload<BlockProposalCont
|
||||
block_value: builder_bid.value,
|
||||
kzg_commitments: builder_bid.blob_kzg_commitments,
|
||||
blobs_and_proofs: None,
|
||||
// TODO(electra): update this with builder api returning the requests
|
||||
requests: None,
|
||||
requests: Some(builder_bid.execution_requests),
|
||||
},
|
||||
BuilderBid::Fulu(builder_bid) => BlockProposalContents::PayloadAndBlobs {
|
||||
payload: ExecutionPayloadHeader::Fulu(builder_bid.header).into(),
|
||||
@@ -159,6 +158,7 @@ pub enum Error {
|
||||
},
|
||||
ZeroLengthTransaction,
|
||||
PayloadBodiesByRangeNotSupported,
|
||||
GetBlobsNotSupported,
|
||||
InvalidJWTSecret(String),
|
||||
InvalidForkForPayload,
|
||||
InvalidPayloadBody(String),
|
||||
@@ -330,7 +330,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BlockProposalContents<E, Paylo
|
||||
|
||||
// This just groups together a bunch of parameters that commonly
|
||||
// get passed around together in calls to get_payload.
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct PayloadParameters<'a> {
|
||||
pub parent_hash: ExecutionBlockHash,
|
||||
pub parent_gas_limit: u64,
|
||||
@@ -1872,7 +1872,7 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
||||
.map_err(Box::new)
|
||||
.map_err(Error::EngineError)
|
||||
} else {
|
||||
Ok(vec![None; query.len()])
|
||||
Err(Error::GetBlobsNotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1901,11 +1901,18 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
||||
if let Some(builder) = self.builder() {
|
||||
let (payload_result, duration) =
|
||||
timed_future(metrics::POST_BLINDED_PAYLOAD_BUILDER, async {
|
||||
builder
|
||||
.post_builder_blinded_blocks(block)
|
||||
.await
|
||||
.map_err(Error::Builder)
|
||||
.map(|d| d.data)
|
||||
if builder.is_ssz_enabled() {
|
||||
builder
|
||||
.post_builder_blinded_blocks_ssz(block)
|
||||
.await
|
||||
.map_err(Error::Builder)
|
||||
} else {
|
||||
builder
|
||||
.post_builder_blinded_blocks(block)
|
||||
.await
|
||||
.map_err(Error::Builder)
|
||||
.map(|d| d.data)
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
||||
|
||||
@@ -230,7 +230,8 @@ pub async fn handle_rpc<E: EthSpec>(
|
||||
if method == ENGINE_NEW_PAYLOAD_V1
|
||||
|| method == ENGINE_NEW_PAYLOAD_V2
|
||||
|| method == ENGINE_NEW_PAYLOAD_V3
|
||||
|| method == ENGINE_NEW_PAYLOAD_V4
|
||||
// TODO(fulu): Uncomment this once v5 method is ready for Fulu
|
||||
// || method == ENGINE_NEW_PAYLOAD_V4
|
||||
{
|
||||
return Err((
|
||||
format!("{} called after Fulu fork!", method),
|
||||
@@ -264,15 +265,16 @@ pub async fn handle_rpc<E: EthSpec>(
|
||||
GENERIC_ERROR_CODE,
|
||||
));
|
||||
}
|
||||
if matches!(request, JsonExecutionPayload::V4(_)) {
|
||||
return Err((
|
||||
format!(
|
||||
"{} called with `ExecutionPayloadV4` after Fulu fork!",
|
||||
method
|
||||
),
|
||||
GENERIC_ERROR_CODE,
|
||||
));
|
||||
}
|
||||
// TODO(fulu): remove once we switch to v5
|
||||
// if matches!(request, JsonExecutionPayload::V4(_)) {
|
||||
// return Err((
|
||||
// format!(
|
||||
// "{} called with `ExecutionPayloadV4` after Fulu fork!",
|
||||
// method
|
||||
// ),
|
||||
// GENERIC_ERROR_CODE,
|
||||
// ));
|
||||
// }
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
@@ -381,8 +383,9 @@ pub async fn handle_rpc<E: EthSpec>(
|
||||
== ForkName::Fulu
|
||||
&& (method == ENGINE_GET_PAYLOAD_V1
|
||||
|| method == ENGINE_GET_PAYLOAD_V2
|
||||
|| method == ENGINE_GET_PAYLOAD_V3
|
||||
|| method == ENGINE_GET_PAYLOAD_V4)
|
||||
|| method == ENGINE_GET_PAYLOAD_V3)
|
||||
// TODO(fulu): Uncomment this once v5 method is ready for Fulu
|
||||
// || method == ENGINE_GET_PAYLOAD_V4)
|
||||
{
|
||||
return Err((
|
||||
format!("{} called after Fulu fork!", method),
|
||||
@@ -448,6 +451,22 @@ pub async fn handle_rpc<E: EthSpec>(
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
// TODO(fulu): remove this once we switch to v5 method
|
||||
JsonExecutionPayload::V5(execution_payload) => {
|
||||
serde_json::to_value(JsonGetPayloadResponseV5 {
|
||||
execution_payload,
|
||||
block_value: Uint256::from(DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI),
|
||||
blobs_bundle: maybe_blobs
|
||||
.ok_or((
|
||||
"No blobs returned despite V5 Payload".to_string(),
|
||||
GENERIC_ERROR_CODE,
|
||||
))?
|
||||
.into(),
|
||||
should_override_builder: false,
|
||||
execution_requests: Default::default(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}),
|
||||
ENGINE_GET_PAYLOAD_V5 => Ok(match JsonExecutionPayload::from(response) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user