mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-02 04:14:33 +00:00
Delete legacy payload reconstruction (#6213)
* Delete legacy payload reconstruction * Delete unneeded failing test * Merge remote-tracking branch 'origin/unstable' into remove-more-ethers * Merge remote-tracking branch 'origin/unstable' into remove-more-ethers * Cleanups
This commit is contained in:
@@ -710,10 +710,8 @@ impl From<Error> for BeaconChainError {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::beacon_block_streamer::{BeaconBlockStreamer, CheckCaches};
|
use crate::beacon_block_streamer::{BeaconBlockStreamer, CheckCaches};
|
||||||
use crate::test_utils::{test_spec, BeaconChainHarness, EphemeralHarnessType};
|
use crate::test_utils::{test_spec, BeaconChainHarness, EphemeralHarnessType};
|
||||||
use execution_layer::test_utils::{Block, DEFAULT_ENGINE_CAPABILITIES};
|
use execution_layer::test_utils::Block;
|
||||||
use execution_layer::EngineCapabilities;
|
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
use std::time::Duration;
|
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use types::{
|
use types::{
|
||||||
ChainSpec, Epoch, EthSpec, FixedBytesExtended, Hash256, Keypair, MinimalEthSpec, Slot,
|
ChainSpec, Epoch, EthSpec, FixedBytesExtended, Hash256, Keypair, MinimalEthSpec, Slot,
|
||||||
@@ -864,147 +862,4 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn check_fallback_altair_to_electra() {
|
|
||||||
let slots_per_epoch = MinimalEthSpec::slots_per_epoch() as usize;
|
|
||||||
let num_epochs = 10;
|
|
||||||
let bellatrix_fork_epoch = 2usize;
|
|
||||||
let capella_fork_epoch = 4usize;
|
|
||||||
let deneb_fork_epoch = 6usize;
|
|
||||||
let electra_fork_epoch = 8usize;
|
|
||||||
let num_blocks_produced = num_epochs * slots_per_epoch;
|
|
||||||
|
|
||||||
let mut spec = test_spec::<MinimalEthSpec>();
|
|
||||||
spec.altair_fork_epoch = Some(Epoch::new(0));
|
|
||||||
spec.bellatrix_fork_epoch = Some(Epoch::new(bellatrix_fork_epoch as u64));
|
|
||||||
spec.capella_fork_epoch = Some(Epoch::new(capella_fork_epoch as u64));
|
|
||||||
spec.deneb_fork_epoch = Some(Epoch::new(deneb_fork_epoch as u64));
|
|
||||||
spec.electra_fork_epoch = Some(Epoch::new(electra_fork_epoch as u64));
|
|
||||||
|
|
||||||
let harness = get_harness(VALIDATOR_COUNT, spec);
|
|
||||||
|
|
||||||
// modify execution engine so it doesn't support engine_payloadBodiesBy* methods
|
|
||||||
let mock_execution_layer = harness.mock_execution_layer.as_ref().unwrap();
|
|
||||||
mock_execution_layer
|
|
||||||
.server
|
|
||||||
.set_engine_capabilities(EngineCapabilities {
|
|
||||||
get_payload_bodies_by_hash_v1: false,
|
|
||||||
get_payload_bodies_by_range_v1: false,
|
|
||||||
..DEFAULT_ENGINE_CAPABILITIES
|
|
||||||
});
|
|
||||||
// refresh capabilities cache
|
|
||||||
harness
|
|
||||||
.chain
|
|
||||||
.execution_layer
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.get_engine_capabilities(Some(Duration::ZERO))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// go to bellatrix fork
|
|
||||||
harness
|
|
||||||
.extend_slots(bellatrix_fork_epoch * slots_per_epoch)
|
|
||||||
.await;
|
|
||||||
// extend half an epoch
|
|
||||||
harness.extend_slots(slots_per_epoch / 2).await;
|
|
||||||
// trigger merge
|
|
||||||
harness
|
|
||||||
.execution_block_generator()
|
|
||||||
.move_to_terminal_block()
|
|
||||||
.expect("should move to terminal block");
|
|
||||||
let timestamp = harness.get_timestamp_at_slot() + harness.spec.seconds_per_slot;
|
|
||||||
harness
|
|
||||||
.execution_block_generator()
|
|
||||||
.modify_last_block(|block| {
|
|
||||||
if let Block::PoW(terminal_block) = block {
|
|
||||||
terminal_block.timestamp = timestamp;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// finish out merge epoch
|
|
||||||
harness.extend_slots(slots_per_epoch / 2).await;
|
|
||||||
// finish rest of epochs
|
|
||||||
harness
|
|
||||||
.extend_slots((num_epochs - 1 - bellatrix_fork_epoch) * slots_per_epoch)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let head = harness.chain.head_snapshot();
|
|
||||||
let state = &head.beacon_state;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
state.slot(),
|
|
||||||
Slot::new(num_blocks_produced as u64),
|
|
||||||
"head should be at the current slot"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
state.current_epoch(),
|
|
||||||
num_blocks_produced as u64 / MinimalEthSpec::slots_per_epoch(),
|
|
||||||
"head should be at the expected epoch"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
state.current_justified_checkpoint().epoch,
|
|
||||||
state.current_epoch() - 1,
|
|
||||||
"the head should be justified one behind the current epoch"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
state.finalized_checkpoint().epoch,
|
|
||||||
state.current_epoch() - 2,
|
|
||||||
"the head should be finalized two behind the current epoch"
|
|
||||||
);
|
|
||||||
|
|
||||||
let block_roots: Vec<Hash256> = harness
|
|
||||||
.chain
|
|
||||||
.forwards_iter_block_roots(Slot::new(0))
|
|
||||||
.expect("should get iter")
|
|
||||||
.map(Result::unwrap)
|
|
||||||
.map(|(root, _)| root)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut expected_blocks = vec![];
|
|
||||||
// get all blocks the old fashioned way
|
|
||||||
for root in &block_roots {
|
|
||||||
let block = harness
|
|
||||||
.chain
|
|
||||||
.get_block(root)
|
|
||||||
.await
|
|
||||||
.expect("should get block")
|
|
||||||
.expect("block should exist");
|
|
||||||
expected_blocks.push(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
for epoch in 0..num_epochs {
|
|
||||||
let start = epoch * slots_per_epoch;
|
|
||||||
let mut epoch_roots = vec![Hash256::zero(); slots_per_epoch];
|
|
||||||
epoch_roots[..].clone_from_slice(&block_roots[start..(start + slots_per_epoch)]);
|
|
||||||
let streamer = BeaconBlockStreamer::new(&harness.chain, CheckCaches::No)
|
|
||||||
.expect("should create streamer");
|
|
||||||
let (block_tx, mut block_rx) = mpsc::unbounded_channel();
|
|
||||||
streamer.stream(epoch_roots.clone(), block_tx).await;
|
|
||||||
|
|
||||||
for (i, expected_root) in epoch_roots.into_iter().enumerate() {
|
|
||||||
let (found_root, found_block_result) =
|
|
||||||
block_rx.recv().await.expect("should get block");
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
found_root, expected_root,
|
|
||||||
"expected block root should match"
|
|
||||||
);
|
|
||||||
match found_block_result.as_ref() {
|
|
||||||
Ok(maybe_block) => {
|
|
||||||
let found_block = maybe_block.clone().expect("should have a block");
|
|
||||||
let expected_block = expected_blocks
|
|
||||||
.get(start + i)
|
|
||||||
.expect("should get expected block");
|
|
||||||
assert_eq!(
|
|
||||||
found_block.as_ref(),
|
|
||||||
expected_block,
|
|
||||||
"expected block should match found block"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Err(e) => panic!("Error retrieving block {}: {:?}", expected_root, e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
use crate::{BeaconChain, BeaconChainError as Error, BeaconChainTypes};
|
use crate::{BeaconChain, BeaconChainError as Error, BeaconChainTypes};
|
||||||
use execution_layer::BlockByNumberQuery;
|
use execution_layer::BlockByNumberQuery;
|
||||||
use serde::{Deserialize, Serialize, Serializer};
|
use serde::{Deserialize, Serialize, Serializer};
|
||||||
use slog::debug;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use types::*;
|
use types::*;
|
||||||
@@ -199,7 +198,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
else {
|
else {
|
||||||
return Ok(GenesisExecutionPayloadStatus::Irrelevant);
|
return Ok(GenesisExecutionPayloadStatus::Irrelevant);
|
||||||
};
|
};
|
||||||
let fork = self.spec.fork_name_at_epoch(Epoch::new(0));
|
|
||||||
|
|
||||||
let execution_layer = self
|
let execution_layer = self
|
||||||
.execution_layer
|
.execution_layer
|
||||||
@@ -222,49 +220,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double-check the block by reconstructing it.
|
|
||||||
let execution_payload = execution_layer
|
|
||||||
.get_payload_by_hash_legacy(exec_block_hash, fork)
|
|
||||||
.await
|
|
||||||
.map_err(|e| Error::ExecutionLayerGetBlockByHashFailed(Box::new(e)))?
|
|
||||||
.ok_or(Error::BlockHashMissingFromExecutionLayer(exec_block_hash))?;
|
|
||||||
|
|
||||||
// Verify payload integrity.
|
|
||||||
let header_from_payload = ExecutionPayloadHeader::from(execution_payload.to_ref());
|
|
||||||
|
|
||||||
let got_transactions_root = header_from_payload.transactions_root();
|
|
||||||
let expected_transactions_root = latest_execution_payload_header.transactions_root();
|
|
||||||
let got_withdrawals_root = header_from_payload.withdrawals_root().ok();
|
|
||||||
let expected_withdrawals_root = latest_execution_payload_header.withdrawals_root().ok();
|
|
||||||
|
|
||||||
if got_transactions_root != expected_transactions_root {
|
|
||||||
return Ok(GenesisExecutionPayloadStatus::TransactionsRootMismatch {
|
|
||||||
got: got_transactions_root,
|
|
||||||
expected: expected_transactions_root,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(expected) = expected_withdrawals_root {
|
|
||||||
if let Some(got) = got_withdrawals_root {
|
|
||||||
if got != expected {
|
|
||||||
return Ok(GenesisExecutionPayloadStatus::WithdrawalsRootMismatch {
|
|
||||||
got,
|
|
||||||
expected,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if header_from_payload.to_ref() != latest_execution_payload_header {
|
|
||||||
debug!(
|
|
||||||
self.log,
|
|
||||||
"Genesis execution payload reconstruction failure";
|
|
||||||
"consensus_node_header" => ?latest_execution_payload_header,
|
|
||||||
"execution_node_header" => ?header_from_payload
|
|
||||||
);
|
|
||||||
return Ok(GenesisExecutionPayloadStatus::OtherMismatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(GenesisExecutionPayloadStatus::Correct(exec_block_hash))
|
Ok(GenesisExecutionPayloadStatus::Correct(exec_block_hash))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ use eth2::types::{
|
|||||||
BlobsBundle, SsePayloadAttributes, SsePayloadAttributesV1, SsePayloadAttributesV2,
|
BlobsBundle, SsePayloadAttributes, SsePayloadAttributesV1, SsePayloadAttributesV2,
|
||||||
SsePayloadAttributesV3,
|
SsePayloadAttributesV3,
|
||||||
};
|
};
|
||||||
use ethers_core::types::Transaction;
|
|
||||||
use ethers_core::utils::rlp;
|
|
||||||
use ethers_core::utils::rlp::{Decodable, Rlp};
|
|
||||||
use http::deposit_methods::RpcError;
|
use http::deposit_methods::RpcError;
|
||||||
pub use json_structures::{JsonWithdrawal, TransitionConfigurationV1};
|
pub use json_structures::{JsonWithdrawal, TransitionConfigurationV1};
|
||||||
use pretty_reqwest_error::PrettyReqwestError;
|
use pretty_reqwest_error::PrettyReqwestError;
|
||||||
@@ -43,8 +40,6 @@ pub use new_payload_request::{
|
|||||||
NewPayloadRequestDeneb, NewPayloadRequestElectra,
|
NewPayloadRequestDeneb, NewPayloadRequestElectra,
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::json_structures::{JsonConsolidationRequest, JsonDepositRequest, JsonWithdrawalRequest};
|
|
||||||
|
|
||||||
pub const LATEST_TAG: &str = "latest";
|
pub const LATEST_TAG: &str = "latest";
|
||||||
|
|
||||||
pub type PayloadId = [u8; 8];
|
pub type PayloadId = [u8; 8];
|
||||||
@@ -74,7 +69,6 @@ pub enum Error {
|
|||||||
RequiredMethodUnsupported(&'static str),
|
RequiredMethodUnsupported(&'static str),
|
||||||
UnsupportedForkVariant(String),
|
UnsupportedForkVariant(String),
|
||||||
InvalidClientVersion(String),
|
InvalidClientVersion(String),
|
||||||
RlpDecoderError(rlp::DecoderError),
|
|
||||||
TooManyConsolidationRequests(usize),
|
TooManyConsolidationRequests(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,12 +103,6 @@ impl From<builder_client::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<rlp::DecoderError> for Error {
|
|
||||||
fn from(e: rlp::DecoderError) -> Self {
|
|
||||||
Error::RlpDecoderError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ssz_types::Error> for Error {
|
impl From<ssz_types::Error> for Error {
|
||||||
fn from(e: ssz_types::Error) -> Self {
|
fn from(e: ssz_types::Error) -> Self {
|
||||||
Error::SszError(e)
|
Error::SszError(e)
|
||||||
@@ -161,186 +149,6 @@ pub struct ExecutionBlock {
|
|||||||
pub timestamp: u64,
|
pub timestamp: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Representation of an execution block with enough detail to reconstruct a payload.
|
|
||||||
#[superstruct(
|
|
||||||
variants(Bellatrix, Capella, Deneb, Electra),
|
|
||||||
variant_attributes(
|
|
||||||
derive(Clone, Debug, PartialEq, Serialize, Deserialize,),
|
|
||||||
serde(bound = "E: EthSpec", rename_all = "camelCase"),
|
|
||||||
),
|
|
||||||
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
|
|
||||||
partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant")
|
|
||||||
)]
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(bound = "E: EthSpec", rename_all = "camelCase", untagged)]
|
|
||||||
pub struct ExecutionBlockWithTransactions<E: EthSpec> {
|
|
||||||
pub parent_hash: ExecutionBlockHash,
|
|
||||||
#[serde(alias = "miner")]
|
|
||||||
#[serde(with = "serde_utils::address_hex")]
|
|
||||||
pub fee_recipient: Address,
|
|
||||||
pub state_root: Hash256,
|
|
||||||
pub receipts_root: Hash256,
|
|
||||||
#[serde(with = "ssz_types::serde_utils::hex_fixed_vec")]
|
|
||||||
pub logs_bloom: FixedVector<u8, E::BytesPerLogsBloom>,
|
|
||||||
#[serde(alias = "mixHash")]
|
|
||||||
pub prev_randao: Hash256,
|
|
||||||
#[serde(rename = "number", with = "serde_utils::u64_hex_be")]
|
|
||||||
pub block_number: u64,
|
|
||||||
#[serde(with = "serde_utils::u64_hex_be")]
|
|
||||||
pub gas_limit: u64,
|
|
||||||
#[serde(with = "serde_utils::u64_hex_be")]
|
|
||||||
pub gas_used: u64,
|
|
||||||
#[serde(with = "serde_utils::u64_hex_be")]
|
|
||||||
pub timestamp: u64,
|
|
||||||
#[serde(with = "ssz_types::serde_utils::hex_var_list")]
|
|
||||||
pub extra_data: VariableList<u8, E::MaxExtraDataBytes>,
|
|
||||||
pub base_fee_per_gas: Uint256,
|
|
||||||
#[serde(rename = "hash")]
|
|
||||||
pub block_hash: ExecutionBlockHash,
|
|
||||||
pub transactions: Vec<Transaction>,
|
|
||||||
#[superstruct(only(Capella, Deneb, Electra))]
|
|
||||||
pub withdrawals: Vec<JsonWithdrawal>,
|
|
||||||
#[superstruct(only(Deneb, Electra))]
|
|
||||||
#[serde(with = "serde_utils::u64_hex_be")]
|
|
||||||
pub blob_gas_used: u64,
|
|
||||||
#[superstruct(only(Deneb, Electra))]
|
|
||||||
#[serde(with = "serde_utils::u64_hex_be")]
|
|
||||||
pub excess_blob_gas: u64,
|
|
||||||
#[superstruct(only(Electra))]
|
|
||||||
pub deposit_requests: Vec<JsonDepositRequest>,
|
|
||||||
#[superstruct(only(Electra))]
|
|
||||||
pub withdrawal_requests: Vec<JsonWithdrawalRequest>,
|
|
||||||
#[superstruct(only(Electra))]
|
|
||||||
pub consolidation_requests: Vec<JsonConsolidationRequest>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: EthSpec> TryFrom<ExecutionPayload<E>> for ExecutionBlockWithTransactions<E> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn try_from(payload: ExecutionPayload<E>) -> Result<Self, Error> {
|
|
||||||
let json_payload = match payload {
|
|
||||||
ExecutionPayload::Bellatrix(block) => {
|
|
||||||
Self::Bellatrix(ExecutionBlockWithTransactionsBellatrix {
|
|
||||||
parent_hash: block.parent_hash,
|
|
||||||
fee_recipient: block.fee_recipient,
|
|
||||||
state_root: block.state_root,
|
|
||||||
receipts_root: block.receipts_root,
|
|
||||||
logs_bloom: block.logs_bloom,
|
|
||||||
prev_randao: block.prev_randao,
|
|
||||||
block_number: block.block_number,
|
|
||||||
gas_limit: block.gas_limit,
|
|
||||||
gas_used: block.gas_used,
|
|
||||||
timestamp: block.timestamp,
|
|
||||||
extra_data: block.extra_data,
|
|
||||||
base_fee_per_gas: block.base_fee_per_gas,
|
|
||||||
block_hash: block.block_hash,
|
|
||||||
transactions: block
|
|
||||||
.transactions
|
|
||||||
.iter()
|
|
||||||
.map(|tx| Transaction::decode(&Rlp::new(tx)))
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ExecutionPayload::Capella(block) => {
|
|
||||||
Self::Capella(ExecutionBlockWithTransactionsCapella {
|
|
||||||
parent_hash: block.parent_hash,
|
|
||||||
fee_recipient: block.fee_recipient,
|
|
||||||
state_root: block.state_root,
|
|
||||||
receipts_root: block.receipts_root,
|
|
||||||
logs_bloom: block.logs_bloom,
|
|
||||||
prev_randao: block.prev_randao,
|
|
||||||
block_number: block.block_number,
|
|
||||||
gas_limit: block.gas_limit,
|
|
||||||
gas_used: block.gas_used,
|
|
||||||
timestamp: block.timestamp,
|
|
||||||
extra_data: block.extra_data,
|
|
||||||
base_fee_per_gas: block.base_fee_per_gas,
|
|
||||||
block_hash: block.block_hash,
|
|
||||||
transactions: block
|
|
||||||
.transactions
|
|
||||||
.iter()
|
|
||||||
.map(|tx| Transaction::decode(&Rlp::new(tx)))
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
withdrawals: Vec::from(block.withdrawals)
|
|
||||||
.into_iter()
|
|
||||||
.map(|withdrawal| withdrawal.into())
|
|
||||||
.collect(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ExecutionPayload::Deneb(block) => Self::Deneb(ExecutionBlockWithTransactionsDeneb {
|
|
||||||
parent_hash: block.parent_hash,
|
|
||||||
fee_recipient: block.fee_recipient,
|
|
||||||
state_root: block.state_root,
|
|
||||||
receipts_root: block.receipts_root,
|
|
||||||
logs_bloom: block.logs_bloom,
|
|
||||||
prev_randao: block.prev_randao,
|
|
||||||
block_number: block.block_number,
|
|
||||||
gas_limit: block.gas_limit,
|
|
||||||
gas_used: block.gas_used,
|
|
||||||
timestamp: block.timestamp,
|
|
||||||
extra_data: block.extra_data,
|
|
||||||
base_fee_per_gas: block.base_fee_per_gas,
|
|
||||||
block_hash: block.block_hash,
|
|
||||||
transactions: block
|
|
||||||
.transactions
|
|
||||||
.iter()
|
|
||||||
.map(|tx| Transaction::decode(&Rlp::new(tx)))
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
withdrawals: Vec::from(block.withdrawals)
|
|
||||||
.into_iter()
|
|
||||||
.map(|withdrawal| withdrawal.into())
|
|
||||||
.collect(),
|
|
||||||
blob_gas_used: block.blob_gas_used,
|
|
||||||
excess_blob_gas: block.excess_blob_gas,
|
|
||||||
}),
|
|
||||||
ExecutionPayload::Electra(block) => {
|
|
||||||
Self::Electra(ExecutionBlockWithTransactionsElectra {
|
|
||||||
parent_hash: block.parent_hash,
|
|
||||||
fee_recipient: block.fee_recipient,
|
|
||||||
state_root: block.state_root,
|
|
||||||
receipts_root: block.receipts_root,
|
|
||||||
logs_bloom: block.logs_bloom,
|
|
||||||
prev_randao: block.prev_randao,
|
|
||||||
block_number: block.block_number,
|
|
||||||
gas_limit: block.gas_limit,
|
|
||||||
gas_used: block.gas_used,
|
|
||||||
timestamp: block.timestamp,
|
|
||||||
extra_data: block.extra_data,
|
|
||||||
base_fee_per_gas: block.base_fee_per_gas,
|
|
||||||
block_hash: block.block_hash,
|
|
||||||
transactions: block
|
|
||||||
.transactions
|
|
||||||
.iter()
|
|
||||||
.map(|tx| Transaction::decode(&Rlp::new(tx)))
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
withdrawals: Vec::from(block.withdrawals)
|
|
||||||
.into_iter()
|
|
||||||
.map(|withdrawal| withdrawal.into())
|
|
||||||
.collect(),
|
|
||||||
blob_gas_used: block.blob_gas_used,
|
|
||||||
excess_blob_gas: block.excess_blob_gas,
|
|
||||||
deposit_requests: block
|
|
||||||
.deposit_requests
|
|
||||||
.into_iter()
|
|
||||||
.map(|deposit| deposit.into())
|
|
||||||
.collect(),
|
|
||||||
withdrawal_requests: block
|
|
||||||
.withdrawal_requests
|
|
||||||
.into_iter()
|
|
||||||
.map(|withdrawal| withdrawal.into())
|
|
||||||
.collect(),
|
|
||||||
consolidation_requests: block
|
|
||||||
.consolidation_requests
|
|
||||||
.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(json_payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[superstruct(
|
#[superstruct(
|
||||||
variants(V1, V2, V3),
|
variants(V1, V2, V3),
|
||||||
variant_attributes(derive(Clone, Debug, Eq, Hash, PartialEq),),
|
variant_attributes(derive(Clone, Debug, Eq, Hash, PartialEq),),
|
||||||
|
|||||||
@@ -734,54 +734,6 @@ impl HttpJsonRpc {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_block_by_hash_with_txns<E: EthSpec>(
|
|
||||||
&self,
|
|
||||||
block_hash: ExecutionBlockHash,
|
|
||||||
fork: ForkName,
|
|
||||||
) -> Result<Option<ExecutionBlockWithTransactions<E>>, Error> {
|
|
||||||
let params = json!([block_hash, true]);
|
|
||||||
Ok(Some(match fork {
|
|
||||||
ForkName::Bellatrix => ExecutionBlockWithTransactions::Bellatrix(
|
|
||||||
self.rpc_request(
|
|
||||||
ETH_GET_BLOCK_BY_HASH,
|
|
||||||
params,
|
|
||||||
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
|
|
||||||
)
|
|
||||||
.await?,
|
|
||||||
),
|
|
||||||
ForkName::Capella => ExecutionBlockWithTransactions::Capella(
|
|
||||||
self.rpc_request(
|
|
||||||
ETH_GET_BLOCK_BY_HASH,
|
|
||||||
params,
|
|
||||||
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
|
|
||||||
)
|
|
||||||
.await?,
|
|
||||||
),
|
|
||||||
ForkName::Deneb => ExecutionBlockWithTransactions::Deneb(
|
|
||||||
self.rpc_request(
|
|
||||||
ETH_GET_BLOCK_BY_HASH,
|
|
||||||
params,
|
|
||||||
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
|
|
||||||
)
|
|
||||||
.await?,
|
|
||||||
),
|
|
||||||
ForkName::Electra => ExecutionBlockWithTransactions::Electra(
|
|
||||||
self.rpc_request(
|
|
||||||
ETH_GET_BLOCK_BY_HASH,
|
|
||||||
params,
|
|
||||||
ETH_GET_BLOCK_BY_HASH_TIMEOUT * self.execution_timeout_multiplier,
|
|
||||||
)
|
|
||||||
.await?,
|
|
||||||
),
|
|
||||||
ForkName::Base | ForkName::Altair => {
|
|
||||||
return Err(Error::UnsupportedForkVariant(format!(
|
|
||||||
"called get_block_by_hash_with_txns with fork {:?}",
|
|
||||||
fork
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn new_payload_v1<E: EthSpec>(
|
pub async fn new_payload_v1<E: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
execution_payload: ExecutionPayload<E>,
|
execution_payload: ExecutionPayload<E>,
|
||||||
|
|||||||
@@ -778,6 +778,57 @@ pub struct JsonExecutionPayloadBody<E: EthSpec> {
|
|||||||
Option<VariableList<ConsolidationRequest, E::MaxConsolidationRequestsPerPayload>>,
|
Option<VariableList<ConsolidationRequest, E::MaxConsolidationRequestsPerPayload>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: EthSpec> From<ExecutionPayloadBodyV1<E>> for JsonExecutionPayloadBodyV1<E> {
|
||||||
|
fn from(value: ExecutionPayloadBodyV1<E>) -> Self {
|
||||||
|
Self {
|
||||||
|
transactions: value.transactions,
|
||||||
|
withdrawals: value.withdrawals.map(|json_withdrawals| {
|
||||||
|
VariableList::from(
|
||||||
|
json_withdrawals
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: EthSpec> From<ExecutionPayloadBodyV2<E>> for JsonExecutionPayloadBodyV2<E> {
|
||||||
|
fn from(value: ExecutionPayloadBodyV2<E>) -> Self {
|
||||||
|
Self {
|
||||||
|
transactions: value.transactions,
|
||||||
|
withdrawals: value.withdrawals.map(|json_withdrawals| {
|
||||||
|
VariableList::from(
|
||||||
|
json_withdrawals
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
deposit_requests: value.deposit_requests.map(|receipts| {
|
||||||
|
VariableList::from(receipts.into_iter().map(Into::into).collect::<Vec<_>>())
|
||||||
|
}),
|
||||||
|
withdrawal_requests: value.withdrawal_requests.map(|withdrawal_requests| {
|
||||||
|
VariableList::from(
|
||||||
|
withdrawal_requests
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
consolidation_requests: value.consolidation_requests.map(|consolidation_requests| {
|
||||||
|
VariableList::from(
|
||||||
|
consolidation_requests
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> From<JsonExecutionPayloadBody<E>> for ExecutionPayloadBody<E> {
|
impl<E: EthSpec> From<JsonExecutionPayloadBody<E>> for ExecutionPayloadBody<E> {
|
||||||
fn from(value: JsonExecutionPayloadBody<E>) -> Self {
|
fn from(value: JsonExecutionPayloadBody<E>) -> Self {
|
||||||
match value {
|
match value {
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ pub enum Error {
|
|||||||
payload: ExecutionBlockHash,
|
payload: ExecutionBlockHash,
|
||||||
transactions_root: Hash256,
|
transactions_root: Hash256,
|
||||||
},
|
},
|
||||||
|
PayloadBodiesByRangeNotSupported,
|
||||||
InvalidJWTSecret(String),
|
InvalidJWTSecret(String),
|
||||||
InvalidForkForPayload,
|
InvalidForkForPayload,
|
||||||
InvalidPayloadBody(String),
|
InvalidPayloadBody(String),
|
||||||
@@ -1804,7 +1805,6 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
|||||||
header: &ExecutionPayloadHeader<E>,
|
header: &ExecutionPayloadHeader<E>,
|
||||||
fork: ForkName,
|
fork: ForkName,
|
||||||
) -> Result<Option<ExecutionPayload<E>>, Error> {
|
) -> Result<Option<ExecutionPayload<E>>, Error> {
|
||||||
let hash = header.block_hash();
|
|
||||||
let block_number = header.block_number();
|
let block_number = header.block_number();
|
||||||
|
|
||||||
// Handle default payload body.
|
// Handle default payload body.
|
||||||
@@ -1823,7 +1823,9 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
|||||||
|
|
||||||
// Use efficient payload bodies by range method if supported.
|
// Use efficient payload bodies by range method if supported.
|
||||||
let capabilities = self.get_engine_capabilities(None).await?;
|
let capabilities = self.get_engine_capabilities(None).await?;
|
||||||
if capabilities.get_payload_bodies_by_range_v1 {
|
if capabilities.get_payload_bodies_by_range_v1
|
||||||
|
|| capabilities.get_payload_bodies_by_range_v2
|
||||||
|
{
|
||||||
let mut payload_bodies = self.get_payload_bodies_by_range(block_number, 1).await?;
|
let mut payload_bodies = self.get_payload_bodies_by_range(block_number, 1).await?;
|
||||||
|
|
||||||
if payload_bodies.len() != 1 {
|
if payload_bodies.len() != 1 {
|
||||||
@@ -1838,8 +1840,7 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
|||||||
})
|
})
|
||||||
.transpose()
|
.transpose()
|
||||||
} else {
|
} else {
|
||||||
// Fall back to eth_blockByHash.
|
Err(Error::PayloadBodiesByRangeNotSupported)
|
||||||
self.get_payload_by_hash_legacy(hash, fork).await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1854,196 +1855,6 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
|||||||
.map_err(Error::EngineError)
|
.map_err(Error::EngineError)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_payload_by_hash_legacy(
|
|
||||||
&self,
|
|
||||||
hash: ExecutionBlockHash,
|
|
||||||
fork: ForkName,
|
|
||||||
) -> Result<Option<ExecutionPayload<E>>, Error> {
|
|
||||||
self.engine()
|
|
||||||
.request(|engine| async move {
|
|
||||||
self.get_payload_by_hash_from_engine(engine, hash, fork)
|
|
||||||
.await
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.map_err(Box::new)
|
|
||||||
.map_err(Error::EngineError)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_payload_by_hash_from_engine(
|
|
||||||
&self,
|
|
||||||
engine: &Engine,
|
|
||||||
hash: ExecutionBlockHash,
|
|
||||||
fork: ForkName,
|
|
||||||
) -> Result<Option<ExecutionPayload<E>>, ApiError> {
|
|
||||||
let _timer = metrics::start_timer(&metrics::EXECUTION_LAYER_GET_PAYLOAD_BY_BLOCK_HASH);
|
|
||||||
|
|
||||||
if hash == ExecutionBlockHash::zero() {
|
|
||||||
return match fork {
|
|
||||||
ForkName::Bellatrix => Ok(Some(ExecutionPayloadBellatrix::default().into())),
|
|
||||||
ForkName::Capella => Ok(Some(ExecutionPayloadCapella::default().into())),
|
|
||||||
ForkName::Deneb => Ok(Some(ExecutionPayloadDeneb::default().into())),
|
|
||||||
ForkName::Electra => Ok(Some(ExecutionPayloadElectra::default().into())),
|
|
||||||
ForkName::Base | ForkName::Altair => Err(ApiError::UnsupportedForkVariant(
|
|
||||||
format!("called get_payload_by_hash_from_engine with {}", fork),
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(block) = engine
|
|
||||||
.api
|
|
||||||
.get_block_by_hash_with_txns::<E>(hash, fork)
|
|
||||||
.await?
|
|
||||||
else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
|
|
||||||
let convert_transactions = |transactions: Vec<EthersTransaction>| {
|
|
||||||
VariableList::new(
|
|
||||||
transactions
|
|
||||||
.into_iter()
|
|
||||||
.map(|tx| VariableList::new(tx.rlp().to_vec()))
|
|
||||||
.collect::<Result<Vec<_>, ssz_types::Error>>()?,
|
|
||||||
)
|
|
||||||
.map_err(ApiError::SszError)
|
|
||||||
};
|
|
||||||
|
|
||||||
let payload = match block {
|
|
||||||
ExecutionBlockWithTransactions::Bellatrix(bellatrix_block) => {
|
|
||||||
ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
|
||||||
parent_hash: bellatrix_block.parent_hash,
|
|
||||||
fee_recipient: bellatrix_block.fee_recipient,
|
|
||||||
state_root: bellatrix_block.state_root,
|
|
||||||
receipts_root: bellatrix_block.receipts_root,
|
|
||||||
logs_bloom: bellatrix_block.logs_bloom,
|
|
||||||
prev_randao: bellatrix_block.prev_randao,
|
|
||||||
block_number: bellatrix_block.block_number,
|
|
||||||
gas_limit: bellatrix_block.gas_limit,
|
|
||||||
gas_used: bellatrix_block.gas_used,
|
|
||||||
timestamp: bellatrix_block.timestamp,
|
|
||||||
extra_data: bellatrix_block.extra_data,
|
|
||||||
base_fee_per_gas: bellatrix_block.base_fee_per_gas,
|
|
||||||
block_hash: bellatrix_block.block_hash,
|
|
||||||
transactions: convert_transactions(bellatrix_block.transactions)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ExecutionBlockWithTransactions::Capella(capella_block) => {
|
|
||||||
let withdrawals = VariableList::new(
|
|
||||||
capella_block
|
|
||||||
.withdrawals
|
|
||||||
.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.map_err(ApiError::DeserializeWithdrawals)?;
|
|
||||||
ExecutionPayload::Capella(ExecutionPayloadCapella {
|
|
||||||
parent_hash: capella_block.parent_hash,
|
|
||||||
fee_recipient: capella_block.fee_recipient,
|
|
||||||
state_root: capella_block.state_root,
|
|
||||||
receipts_root: capella_block.receipts_root,
|
|
||||||
logs_bloom: capella_block.logs_bloom,
|
|
||||||
prev_randao: capella_block.prev_randao,
|
|
||||||
block_number: capella_block.block_number,
|
|
||||||
gas_limit: capella_block.gas_limit,
|
|
||||||
gas_used: capella_block.gas_used,
|
|
||||||
timestamp: capella_block.timestamp,
|
|
||||||
extra_data: capella_block.extra_data,
|
|
||||||
base_fee_per_gas: capella_block.base_fee_per_gas,
|
|
||||||
block_hash: capella_block.block_hash,
|
|
||||||
transactions: convert_transactions(capella_block.transactions)?,
|
|
||||||
withdrawals,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ExecutionBlockWithTransactions::Deneb(deneb_block) => {
|
|
||||||
let withdrawals = VariableList::new(
|
|
||||||
deneb_block
|
|
||||||
.withdrawals
|
|
||||||
.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.map_err(ApiError::DeserializeWithdrawals)?;
|
|
||||||
ExecutionPayload::Deneb(ExecutionPayloadDeneb {
|
|
||||||
parent_hash: deneb_block.parent_hash,
|
|
||||||
fee_recipient: deneb_block.fee_recipient,
|
|
||||||
state_root: deneb_block.state_root,
|
|
||||||
receipts_root: deneb_block.receipts_root,
|
|
||||||
logs_bloom: deneb_block.logs_bloom,
|
|
||||||
prev_randao: deneb_block.prev_randao,
|
|
||||||
block_number: deneb_block.block_number,
|
|
||||||
gas_limit: deneb_block.gas_limit,
|
|
||||||
gas_used: deneb_block.gas_used,
|
|
||||||
timestamp: deneb_block.timestamp,
|
|
||||||
extra_data: deneb_block.extra_data,
|
|
||||||
base_fee_per_gas: deneb_block.base_fee_per_gas,
|
|
||||||
block_hash: deneb_block.block_hash,
|
|
||||||
transactions: convert_transactions(deneb_block.transactions)?,
|
|
||||||
withdrawals,
|
|
||||||
blob_gas_used: deneb_block.blob_gas_used,
|
|
||||||
excess_blob_gas: deneb_block.excess_blob_gas,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ExecutionBlockWithTransactions::Electra(electra_block) => {
|
|
||||||
let withdrawals = VariableList::new(
|
|
||||||
electra_block
|
|
||||||
.withdrawals
|
|
||||||
.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.map_err(ApiError::DeserializeWithdrawals)?;
|
|
||||||
let deposit_requests = VariableList::new(
|
|
||||||
electra_block
|
|
||||||
.deposit_requests
|
|
||||||
.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.map_err(ApiError::DeserializeDepositRequests)?;
|
|
||||||
let withdrawal_requests = VariableList::new(
|
|
||||||
electra_block
|
|
||||||
.withdrawal_requests
|
|
||||||
.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.map_err(ApiError::DeserializeWithdrawalRequests)?;
|
|
||||||
let n_consolidations = electra_block.consolidation_requests.len();
|
|
||||||
let consolidation_requests = VariableList::new(
|
|
||||||
electra_block
|
|
||||||
.consolidation_requests
|
|
||||||
.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
)
|
|
||||||
.map_err(|_| ApiError::TooManyConsolidationRequests(n_consolidations))?;
|
|
||||||
ExecutionPayload::Electra(ExecutionPayloadElectra {
|
|
||||||
parent_hash: electra_block.parent_hash,
|
|
||||||
fee_recipient: electra_block.fee_recipient,
|
|
||||||
state_root: electra_block.state_root,
|
|
||||||
receipts_root: electra_block.receipts_root,
|
|
||||||
logs_bloom: electra_block.logs_bloom,
|
|
||||||
prev_randao: electra_block.prev_randao,
|
|
||||||
block_number: electra_block.block_number,
|
|
||||||
gas_limit: electra_block.gas_limit,
|
|
||||||
gas_used: electra_block.gas_used,
|
|
||||||
timestamp: electra_block.timestamp,
|
|
||||||
extra_data: electra_block.extra_data,
|
|
||||||
base_fee_per_gas: electra_block.base_fee_per_gas,
|
|
||||||
block_hash: electra_block.block_hash,
|
|
||||||
transactions: convert_transactions(electra_block.transactions)?,
|
|
||||||
withdrawals,
|
|
||||||
blob_gas_used: electra_block.blob_gas_used,
|
|
||||||
excess_blob_gas: electra_block.excess_blob_gas,
|
|
||||||
deposit_requests,
|
|
||||||
withdrawal_requests,
|
|
||||||
consolidation_requests,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Some(payload))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn propose_blinded_beacon_block(
|
pub async fn propose_blinded_beacon_block(
|
||||||
&self,
|
&self,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
|
|||||||
@@ -54,13 +54,6 @@ pub static EXECUTION_LAYER_PRE_PREPARED_PAYLOAD_ID: LazyLock<Result<IntCounterVe
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
pub static EXECUTION_LAYER_GET_PAYLOAD_BY_BLOCK_HASH: LazyLock<Result<Histogram>> =
|
|
||||||
LazyLock::new(|| {
|
|
||||||
try_create_histogram(
|
|
||||||
"execution_layer_get_payload_by_block_hash_time",
|
|
||||||
"Time to reconstruct a payload from the EE using eth_getBlockByHash",
|
|
||||||
)
|
|
||||||
});
|
|
||||||
pub static EXECUTION_LAYER_GET_PAYLOAD_BODIES_BY_RANGE: LazyLock<Result<Histogram>> =
|
pub static EXECUTION_LAYER_GET_PAYLOAD_BODIES_BY_RANGE: LazyLock<Result<Histogram>> =
|
||||||
LazyLock::new(|| {
|
LazyLock::new(|| {
|
||||||
try_create_histogram(
|
try_create_histogram(
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
|
use crate::engine_api::{
|
||||||
|
json_structures::{
|
||||||
|
JsonForkchoiceUpdatedV1Response, JsonPayloadStatusV1, JsonPayloadStatusV1Status,
|
||||||
|
},
|
||||||
|
ExecutionBlock, PayloadAttributes, PayloadId, PayloadStatusV1, PayloadStatusV1Status,
|
||||||
|
};
|
||||||
use crate::engines::ForkchoiceState;
|
use crate::engines::ForkchoiceState;
|
||||||
use crate::EthersTransaction;
|
use crate::EthersTransaction;
|
||||||
use crate::{
|
|
||||||
engine_api::{
|
|
||||||
json_structures::{
|
|
||||||
JsonForkchoiceUpdatedV1Response, JsonPayloadStatusV1, JsonPayloadStatusV1Status,
|
|
||||||
},
|
|
||||||
ExecutionBlock, PayloadAttributes, PayloadId, PayloadStatusV1, PayloadStatusV1Status,
|
|
||||||
},
|
|
||||||
ExecutionBlockWithTransactions,
|
|
||||||
};
|
|
||||||
use eth2::types::BlobsBundle;
|
use eth2::types::BlobsBundle;
|
||||||
use kzg::{Kzg, KzgCommitment, KzgProof};
|
use kzg::{Kzg, KzgCommitment, KzgProof};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -89,17 +86,13 @@ impl<E: EthSpec> Block<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_execution_block_with_tx(&self) -> Option<ExecutionBlockWithTransactions<E>> {
|
pub fn as_execution_payload(&self) -> Option<ExecutionPayload<E>> {
|
||||||
match self {
|
match self {
|
||||||
Block::PoS(payload) => Some(payload.clone().try_into().unwrap()),
|
Block::PoS(payload) => Some(payload.clone()),
|
||||||
Block::PoW(block) => Some(
|
Block::PoW(block) => Some(ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
||||||
ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
block_hash: block.block_hash,
|
||||||
block_hash: block.block_hash,
|
..Default::default()
|
||||||
..Default::default()
|
})),
|
||||||
})
|
|
||||||
.try_into()
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,20 +248,17 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
|
|||||||
.map(|block| block.as_execution_block(self.terminal_total_difficulty))
|
.map(|block| block.as_execution_block(self.terminal_total_difficulty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execution_block_with_txs_by_hash(
|
pub fn execution_payload_by_hash(
|
||||||
&self,
|
&self,
|
||||||
hash: ExecutionBlockHash,
|
hash: ExecutionBlockHash,
|
||||||
) -> Option<ExecutionBlockWithTransactions<E>> {
|
) -> Option<ExecutionPayload<E>> {
|
||||||
self.block_by_hash(hash)
|
self.block_by_hash(hash)
|
||||||
.and_then(|block| block.as_execution_block_with_tx())
|
.and_then(|block| block.as_execution_payload())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execution_block_with_txs_by_number(
|
pub fn execution_payload_by_number(&self, number: u64) -> Option<ExecutionPayload<E>> {
|
||||||
&self,
|
|
||||||
number: u64,
|
|
||||||
) -> Option<ExecutionBlockWithTransactions<E>> {
|
|
||||||
self.block_by_number(number)
|
self.block_by_number(number)
|
||||||
.and_then(|block| block.as_execution_block_with_tx())
|
.and_then(|block| block.as_execution_payload())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_to_block_prior_to_terminal_block(&mut self) -> Result<(), String> {
|
pub fn move_to_block_prior_to_terminal_block(&mut self) -> Result<(), String> {
|
||||||
|
|||||||
@@ -83,12 +83,10 @@ pub async fn handle_rpc<E: EthSpec>(
|
|||||||
.ok_or_else(|| "missing/invalid params[1] value".to_string())
|
.ok_or_else(|| "missing/invalid params[1] value".to_string())
|
||||||
.map_err(|s| (s, BAD_PARAMS_ERROR_CODE))?;
|
.map_err(|s| (s, BAD_PARAMS_ERROR_CODE))?;
|
||||||
if full_tx {
|
if full_tx {
|
||||||
Ok(serde_json::to_value(
|
Err((
|
||||||
ctx.execution_block_generator
|
"full_tx support has been removed".to_string(),
|
||||||
.read()
|
BAD_PARAMS_ERROR_CODE,
|
||||||
.execution_block_with_txs_by_hash(hash),
|
))
|
||||||
)
|
|
||||||
.unwrap())
|
|
||||||
} else {
|
} else {
|
||||||
Ok(serde_json::to_value(
|
Ok(serde_json::to_value(
|
||||||
ctx.execution_block_generator
|
ctx.execution_block_generator
|
||||||
@@ -556,40 +554,25 @@ pub async fn handle_rpc<E: EthSpec>(
|
|||||||
|
|
||||||
let mut response = vec![];
|
let mut response = vec![];
|
||||||
for block_num in start..(start + count) {
|
for block_num in start..(start + count) {
|
||||||
let maybe_block = ctx
|
let maybe_payload = ctx
|
||||||
.execution_block_generator
|
.execution_block_generator
|
||||||
.read()
|
.read()
|
||||||
.execution_block_with_txs_by_number(block_num);
|
.execution_payload_by_number(block_num);
|
||||||
|
|
||||||
match maybe_block {
|
match maybe_payload {
|
||||||
Some(block) => {
|
Some(payload) => {
|
||||||
let transactions = Transactions::<E>::new(
|
assert!(
|
||||||
block
|
!payload.fork_name().electra_enabled(),
|
||||||
.transactions()
|
"payload bodies V1 is not supported for Electra blocks"
|
||||||
.iter()
|
);
|
||||||
.map(|transaction| VariableList::new(transaction.rlp().to_vec()))
|
let payload_body = ExecutionPayloadBodyV1 {
|
||||||
.collect::<Result<_, _>>()
|
transactions: payload.transactions().clone(),
|
||||||
.map_err(|e| {
|
withdrawals: payload.withdrawals().ok().cloned(),
|
||||||
(
|
};
|
||||||
format!("failed to deserialize transaction: {:?}", e),
|
let json_payload_body = JsonExecutionPayloadBody::V1(
|
||||||
GENERIC_ERROR_CODE,
|
JsonExecutionPayloadBodyV1::<E>::from(payload_body),
|
||||||
)
|
);
|
||||||
})?,
|
response.push(Some(json_payload_body));
|
||||||
)
|
|
||||||
.map_err(|e| {
|
|
||||||
(
|
|
||||||
format!("failed to deserialize transactions: {:?}", e),
|
|
||||||
GENERIC_ERROR_CODE,
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
response.push(Some(JsonExecutionPayloadBodyV1::<E> {
|
|
||||||
transactions,
|
|
||||||
withdrawals: block
|
|
||||||
.withdrawals()
|
|
||||||
.ok()
|
|
||||||
.map(|withdrawals| VariableList::from(withdrawals.clone())),
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
None => response.push(None),
|
None => response.push(None),
|
||||||
}
|
}
|
||||||
@@ -611,63 +594,28 @@ pub async fn handle_rpc<E: EthSpec>(
|
|||||||
|
|
||||||
let mut response = vec![];
|
let mut response = vec![];
|
||||||
for block_num in start..(start + count) {
|
for block_num in start..(start + count) {
|
||||||
let maybe_block = ctx
|
let maybe_payload = ctx
|
||||||
.execution_block_generator
|
.execution_block_generator
|
||||||
.read()
|
.read()
|
||||||
.execution_block_with_txs_by_number(block_num);
|
.execution_payload_by_number(block_num);
|
||||||
|
|
||||||
match maybe_block {
|
|
||||||
Some(block) => {
|
|
||||||
let transactions = Transactions::<E>::new(
|
|
||||||
block
|
|
||||||
.transactions()
|
|
||||||
.iter()
|
|
||||||
.map(|transaction| VariableList::new(transaction.rlp().to_vec()))
|
|
||||||
.collect::<Result<_, _>>()
|
|
||||||
.map_err(|e| {
|
|
||||||
(
|
|
||||||
format!("failed to deserialize transaction: {:?}", e),
|
|
||||||
GENERIC_ERROR_CODE,
|
|
||||||
)
|
|
||||||
})?,
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
|
||||||
(
|
|
||||||
format!("failed to deserialize transactions: {:?}", e),
|
|
||||||
GENERIC_ERROR_CODE,
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
|
match maybe_payload {
|
||||||
|
Some(payload) => {
|
||||||
// TODO(electra): add testing for:
|
// TODO(electra): add testing for:
|
||||||
// deposit_requests
|
// deposit_requests
|
||||||
// withdrawal_requests
|
// withdrawal_requests
|
||||||
// consolidation_requests
|
// consolidation_requests
|
||||||
response.push(Some(JsonExecutionPayloadBodyV2::<E> {
|
let payload_body = ExecutionPayloadBodyV2 {
|
||||||
transactions,
|
transactions: payload.transactions().clone(),
|
||||||
withdrawals: block
|
withdrawals: payload.withdrawals().ok().cloned(),
|
||||||
.withdrawals()
|
deposit_requests: payload.deposit_requests().ok().cloned(),
|
||||||
.ok()
|
withdrawal_requests: payload.withdrawal_requests().ok().cloned(),
|
||||||
.map(|withdrawals| VariableList::from(withdrawals.clone())),
|
consolidation_requests: payload.consolidation_requests().ok().cloned(),
|
||||||
deposit_requests: block.deposit_requests().ok().map(
|
};
|
||||||
|deposit_requests| VariableList::from(deposit_requests.clone()),
|
let json_payload_body = JsonExecutionPayloadBody::V2(
|
||||||
),
|
JsonExecutionPayloadBodyV2::<E>::from(payload_body),
|
||||||
withdrawal_requests: block.withdrawal_requests().ok().map(
|
);
|
||||||
|withdrawal_requests| {
|
response.push(Some(json_payload_body));
|
||||||
VariableList::from(withdrawal_requests.clone())
|
|
||||||
},
|
|
||||||
),
|
|
||||||
consolidation_requests: block.consolidation_requests().ok().map(
|
|
||||||
|consolidation_requests| {
|
|
||||||
VariableList::from(
|
|
||||||
consolidation_requests
|
|
||||||
.clone()
|
|
||||||
.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
None => response.push(None),
|
None => response.push(None),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -649,15 +649,7 @@ async fn check_payload_reconstruction<E: GenericExecutionEngine>(
|
|||||||
ee: &ExecutionPair<E, MainnetEthSpec>,
|
ee: &ExecutionPair<E, MainnetEthSpec>,
|
||||||
payload: &ExecutionPayload<MainnetEthSpec>,
|
payload: &ExecutionPayload<MainnetEthSpec>,
|
||||||
) {
|
) {
|
||||||
// check via legacy eth_getBlockByHash
|
// check via payload bodies method
|
||||||
let reconstructed = ee
|
|
||||||
.execution_layer
|
|
||||||
.get_payload_by_hash_legacy(payload.block_hash(), payload.fork_name())
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(reconstructed, *payload);
|
|
||||||
// also check via payload bodies method
|
|
||||||
let capabilities = ee
|
let capabilities = ee
|
||||||
.execution_layer
|
.execution_layer
|
||||||
.get_engine_capabilities(None)
|
.get_engine_capabilities(None)
|
||||||
|
|||||||
Reference in New Issue
Block a user