mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 16:55:46 +00:00
Exclude empty requests and add back prefix
This commit is contained in:
@@ -7,7 +7,7 @@ use superstruct::superstruct;
|
|||||||
use types::beacon_block_body::KzgCommitments;
|
use types::beacon_block_body::KzgCommitments;
|
||||||
use types::blob_sidecar::BlobsList;
|
use types::blob_sidecar::BlobsList;
|
||||||
use types::execution_requests::{
|
use types::execution_requests::{
|
||||||
ConsolidationRequests, DepositRequests, RequestPrefix, WithdrawalRequests,
|
ConsolidationRequests, DepositRequests, RequestType, WithdrawalRequests,
|
||||||
};
|
};
|
||||||
use types::{Blob, FixedVector, KzgProof, Unsigned};
|
use types::{Blob, FixedVector, KzgProof, Unsigned};
|
||||||
|
|
||||||
@@ -341,6 +341,15 @@ impl<E: EthSpec> From<JsonExecutionPayload<E>> for ExecutionPayload<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum RequestsError {
|
||||||
|
InvalidHex(hex::FromHexError),
|
||||||
|
EmptyRequest(usize),
|
||||||
|
InvalidOrdering,
|
||||||
|
InvalidPrefix(u8),
|
||||||
|
DecodeError(String),
|
||||||
|
}
|
||||||
|
|
||||||
/// Format of `ExecutionRequests` received over the engine api.
|
/// Format of `ExecutionRequests` received over the engine api.
|
||||||
///
|
///
|
||||||
/// Array of ssz-encoded requests list encoded as hex bytes.
|
/// Array of ssz-encoded requests list encoded as hex bytes.
|
||||||
@@ -355,33 +364,62 @@ impl<E: EthSpec> From<JsonExecutionPayload<E>> for ExecutionPayload<E> {
|
|||||||
pub struct JsonExecutionRequests(pub Vec<String>);
|
pub struct JsonExecutionRequests(pub Vec<String>);
|
||||||
|
|
||||||
impl<E: EthSpec> TryFrom<JsonExecutionRequests> for ExecutionRequests<E> {
|
impl<E: EthSpec> TryFrom<JsonExecutionRequests> for ExecutionRequests<E> {
|
||||||
type Error = String;
|
type Error = RequestsError;
|
||||||
|
|
||||||
fn try_from(value: JsonExecutionRequests) -> Result<Self, Self::Error> {
|
fn try_from(value: JsonExecutionRequests) -> Result<Self, Self::Error> {
|
||||||
let mut requests = ExecutionRequests::default();
|
let mut requests = ExecutionRequests::default();
|
||||||
|
let mut prev_prefix: Option<RequestType> = None;
|
||||||
for (i, request) in value.0.into_iter().enumerate() {
|
for (i, request) in value.0.into_iter().enumerate() {
|
||||||
// hex string
|
// hex string
|
||||||
let decoded_bytes = hex::decode(request.strip_prefix("0x").unwrap_or(&request))
|
let decoded_bytes = hex::decode(request.strip_prefix("0x").unwrap_or(&request))
|
||||||
.map_err(|e| format!("Invalid hex {:?}", e))?;
|
.map_err(RequestsError::InvalidHex)?;
|
||||||
match RequestPrefix::from_prefix(i as u8) {
|
|
||||||
Some(RequestPrefix::Deposit) => {
|
// The first byte of each element is the `request_type` and the remaining bytes are the `request_data`.
|
||||||
requests.deposits = DepositRequests::<E>::from_ssz_bytes(&decoded_bytes)
|
// Elements with empty `request_data` **MUST** be excluded from the list.
|
||||||
.map_err(|e| format!("Failed to decode DepositRequest from EL: {:?}", e))?;
|
let Some((prefix_byte, request_bytes)) = decoded_bytes.split_first() else {
|
||||||
|
return Err(RequestsError::EmptyRequest(i));
|
||||||
|
};
|
||||||
|
if request_bytes.is_empty() {
|
||||||
|
return Err(RequestsError::EmptyRequest(i));
|
||||||
}
|
}
|
||||||
Some(RequestPrefix::Withdrawal) => {
|
// Elements of the list **MUST** be ordered by `request_type` in ascending order
|
||||||
requests.withdrawals = WithdrawalRequests::<E>::from_ssz_bytes(&decoded_bytes)
|
let current_prefix = RequestType::from_prefix(*prefix_byte)
|
||||||
|
.ok_or(RequestsError::InvalidPrefix(*prefix_byte))?;
|
||||||
|
if let Some(prev) = prev_prefix {
|
||||||
|
if prev.to_prefix() >= current_prefix.to_prefix() {
|
||||||
|
return Err(RequestsError::InvalidOrdering);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_prefix = Some(current_prefix);
|
||||||
|
|
||||||
|
match current_prefix {
|
||||||
|
RequestType::Deposit => {
|
||||||
|
requests.deposits = DepositRequests::<E>::from_ssz_bytes(request_bytes)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
format!("Failed to decode WithdrawalRequest from EL: {:?}", e)
|
RequestsError::DecodeError(format!(
|
||||||
|
"Failed to decode DepositRequest from EL: {:?}",
|
||||||
|
e
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Some(RequestPrefix::Consolidation) => {
|
RequestType::Withdrawal => {
|
||||||
requests.consolidations =
|
requests.withdrawals = WithdrawalRequests::<E>::from_ssz_bytes(request_bytes)
|
||||||
ConsolidationRequests::<E>::from_ssz_bytes(&decoded_bytes).map_err(
|
.map_err(|e| {
|
||||||
|e| format!("Failed to decode ConsolidationRequest from EL: {:?}", e),
|
RequestsError::DecodeError(format!(
|
||||||
)?;
|
"Failed to decode WithdrawalRequest from EL: {:?}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
RequestType::Consolidation => {
|
||||||
|
requests.consolidations =
|
||||||
|
ConsolidationRequests::<E>::from_ssz_bytes(request_bytes).map_err(|e| {
|
||||||
|
RequestsError::DecodeError(format!(
|
||||||
|
"Failed to decode ConsolidationRequest from EL: {:?}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
None => return Err("Empty requests string".to_string()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(requests)
|
Ok(requests)
|
||||||
@@ -448,7 +486,9 @@ impl<E: EthSpec> TryFrom<JsonGetPayloadResponse<E>> for GetPayloadResponse<E> {
|
|||||||
block_value: response.block_value,
|
block_value: response.block_value,
|
||||||
blobs_bundle: response.blobs_bundle.into(),
|
blobs_bundle: response.blobs_bundle.into(),
|
||||||
should_override_builder: response.should_override_builder,
|
should_override_builder: response.should_override_builder,
|
||||||
requests: response.execution_requests.try_into()?,
|
requests: response.execution_requests.try_into().map_err(|e| {
|
||||||
|
format!("Failed to convert json to execution requests : {:?}", e)
|
||||||
|
})?,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,10 +43,29 @@ impl<E: EthSpec> ExecutionRequests<E> {
|
|||||||
/// Returns the encoding according to EIP-7685 to send
|
/// Returns the encoding according to EIP-7685 to send
|
||||||
/// to the execution layer over the engine api.
|
/// to the execution layer over the engine api.
|
||||||
pub fn get_execution_requests_list(&self) -> Vec<Bytes> {
|
pub fn get_execution_requests_list(&self) -> Vec<Bytes> {
|
||||||
let deposit_bytes = Bytes::from(self.deposits.as_ssz_bytes());
|
let mut requests_list = Vec::new();
|
||||||
let withdrawal_bytes = Bytes::from(self.withdrawals.as_ssz_bytes());
|
if !self.deposits.is_empty() {
|
||||||
let consolidation_bytes = Bytes::from(self.consolidations.as_ssz_bytes());
|
requests_list.push(Bytes::from_iter(
|
||||||
vec![deposit_bytes, withdrawal_bytes, consolidation_bytes]
|
[RequestType::Deposit.to_prefix()]
|
||||||
|
.into_iter()
|
||||||
|
.chain(self.deposits.as_ssz_bytes()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if !self.withdrawals.is_empty() {
|
||||||
|
requests_list.push(Bytes::from_iter(
|
||||||
|
[RequestType::Withdrawal.to_prefix()]
|
||||||
|
.into_iter()
|
||||||
|
.chain(self.withdrawals.as_ssz_bytes()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if !self.consolidations.is_empty() {
|
||||||
|
requests_list.push(Bytes::from_iter(
|
||||||
|
[RequestType::Consolidation.to_prefix()]
|
||||||
|
.into_iter()
|
||||||
|
.chain(self.consolidations.as_ssz_bytes()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
requests_list
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate the execution layer `requests_hash` based on EIP-7685.
|
/// Generate the execution layer `requests_hash` based on EIP-7685.
|
||||||
@@ -55,9 +74,8 @@ impl<E: EthSpec> ExecutionRequests<E> {
|
|||||||
pub fn requests_hash(&self) -> Hash256 {
|
pub fn requests_hash(&self) -> Hash256 {
|
||||||
let mut hasher = DynamicContext::new();
|
let mut hasher = DynamicContext::new();
|
||||||
|
|
||||||
for (i, request) in self.get_execution_requests_list().iter().enumerate() {
|
for request in self.get_execution_requests_list().iter() {
|
||||||
let mut request_hasher = DynamicContext::new();
|
let mut request_hasher = DynamicContext::new();
|
||||||
request_hasher.update(&[i as u8]);
|
|
||||||
request_hasher.update(request);
|
request_hasher.update(request);
|
||||||
let request_hash = request_hasher.finalize();
|
let request_hash = request_hasher.finalize();
|
||||||
|
|
||||||
@@ -70,13 +88,13 @@ impl<E: EthSpec> ExecutionRequests<E> {
|
|||||||
|
|
||||||
/// This is used to index into the `execution_requests` array.
|
/// This is used to index into the `execution_requests` array.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum RequestPrefix {
|
pub enum RequestType {
|
||||||
Deposit,
|
Deposit,
|
||||||
Withdrawal,
|
Withdrawal,
|
||||||
Consolidation,
|
Consolidation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestPrefix {
|
impl RequestType {
|
||||||
pub fn from_prefix(prefix: u8) -> Option<Self> {
|
pub fn from_prefix(prefix: u8) -> Option<Self> {
|
||||||
match prefix {
|
match prefix {
|
||||||
0 => Some(Self::Deposit),
|
0 => Some(Self::Deposit),
|
||||||
@@ -85,6 +103,13 @@ impl RequestPrefix {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn to_prefix(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Self::Deposit => 0,
|
||||||
|
Self::Withdrawal => 1,
|
||||||
|
Self::Consolidation => 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ pub use crate::execution_payload_header::{
|
|||||||
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderRef,
|
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderRef,
|
||||||
ExecutionPayloadHeaderRefMut,
|
ExecutionPayloadHeaderRefMut,
|
||||||
};
|
};
|
||||||
pub use crate::execution_requests::{ExecutionRequests, RequestPrefix};
|
pub use crate::execution_requests::{ExecutionRequests, RequestType};
|
||||||
pub use crate::fork::Fork;
|
pub use crate::fork::Fork;
|
||||||
pub use crate::fork_context::ForkContext;
|
pub use crate::fork_context::ForkContext;
|
||||||
pub use crate::fork_data::ForkData;
|
pub use crate::fork_data::ForkData;
|
||||||
|
|||||||
Reference in New Issue
Block a user