refactor: remove PostExecutionInput (#14464)

This commit is contained in:
Arsenii Kulikov
2025-02-13 14:24:00 +04:00
committed by GitHub
parent f425a4dbcd
commit 46462ae0a6
18 changed files with 78 additions and 88 deletions

5
Cargo.lock generated
View File

@ -6881,10 +6881,10 @@ name = "reth-consensus"
version = "1.2.0" version = "1.2.0"
dependencies = [ dependencies = [
"alloy-consensus", "alloy-consensus",
"alloy-eips",
"alloy-primitives", "alloy-primitives",
"auto_impl", "auto_impl",
"derive_more", "derive_more",
"reth-execution-types",
"reth-primitives-traits", "reth-primitives-traits",
] ]
@ -7529,6 +7529,7 @@ dependencies = [
"reth-chainspec", "reth-chainspec",
"reth-consensus", "reth-consensus",
"reth-consensus-common", "reth-consensus-common",
"reth-execution-types",
"reth-primitives", "reth-primitives",
"reth-primitives-traits", "reth-primitives-traits",
"tracing", "tracing",
@ -7704,6 +7705,7 @@ dependencies = [
"alloy-primitives", "alloy-primitives",
"arbitrary", "arbitrary",
"bincode", "bincode",
"derive_more",
"rand 0.8.5", "rand 0.8.5",
"reth-ethereum-primitives", "reth-ethereum-primitives",
"reth-execution-errors", "reth-execution-errors",
@ -8433,6 +8435,7 @@ dependencies = [
"reth-chainspec", "reth-chainspec",
"reth-consensus", "reth-consensus",
"reth-consensus-common", "reth-consensus-common",
"reth-execution-types",
"reth-optimism-chainspec", "reth-optimism-chainspec",
"reth-optimism-forks", "reth-optimism-forks",
"reth-optimism-primitives", "reth-optimism-primitives",

View File

@ -12,10 +12,10 @@ workspace = true
[dependencies] [dependencies]
# reth # reth
reth-execution-types.workspace = true
reth-primitives-traits.workspace = true reth-primitives-traits.workspace = true
# ethereum # ethereum
alloy-eips.workspace = true
alloy-primitives.workspace = true alloy-primitives.workspace = true
alloy-consensus.workspace = true alloy-consensus.workspace = true
@ -28,10 +28,10 @@ default = ["std"]
std = [ std = [
"reth-primitives-traits/std", "reth-primitives-traits/std",
"alloy-primitives/std", "alloy-primitives/std",
"alloy-eips/std",
"alloy-consensus/std", "alloy-consensus/std",
"reth-primitives-traits/std", "reth-primitives-traits/std",
"derive_more/std", "derive_more/std",
"reth-execution-types/std",
] ]
test-utils = [ test-utils = [
"reth-primitives-traits/test-utils", "reth-primitives-traits/test-utils",

View File

@ -13,8 +13,8 @@ extern crate alloc;
use alloc::{fmt::Debug, sync::Arc, vec::Vec}; use alloc::{fmt::Debug, sync::Arc, vec::Vec};
use alloy_consensus::Header; use alloy_consensus::Header;
use alloy_eips::eip7685::Requests;
use alloy_primitives::{BlockHash, BlockNumber, Bloom, B256, U256}; use alloy_primitives::{BlockHash, BlockNumber, Bloom, B256, U256};
use reth_execution_types::BlockExecutionResult;
use reth_primitives_traits::{ use reth_primitives_traits::{
constants::MINIMUM_GAS_LIMIT, transaction::error::InvalidTransactionError, Block, GotExpected, constants::MINIMUM_GAS_LIMIT, transaction::error::InvalidTransactionError, Block, GotExpected,
GotExpectedBoxed, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader, GotExpectedBoxed, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader,
@ -27,22 +27,6 @@ pub mod noop;
/// test helpers for mocking consensus /// test helpers for mocking consensus
pub mod test_utils; pub mod test_utils;
/// Post execution input passed to [`FullConsensus::validate_block_post_execution`].
#[derive(Debug)]
pub struct PostExecutionInput<'a, R> {
/// Receipts of the block.
pub receipts: &'a [R],
/// EIP-7685 requests of the block.
pub requests: &'a Requests,
}
impl<'a, R> PostExecutionInput<'a, R> {
/// Creates a new instance of `PostExecutionInput`.
pub const fn new(receipts: &'a [R], requests: &'a Requests) -> Self {
Self { receipts, requests }
}
}
/// [`Consensus`] implementation which knows full node primitives and is able to validation block's /// [`Consensus`] implementation which knows full node primitives and is able to validation block's
/// execution outcome. /// execution outcome.
#[auto_impl::auto_impl(&, Arc)] #[auto_impl::auto_impl(&, Arc)]
@ -56,7 +40,7 @@ pub trait FullConsensus<N: NodePrimitives>: AsConsensus<N::Block> {
fn validate_block_post_execution( fn validate_block_post_execution(
&self, &self,
block: &RecoveredBlock<N::Block>, block: &RecoveredBlock<N::Block>,
input: PostExecutionInput<'_, N::Receipt>, result: &BlockExecutionResult<N::Receipt>,
) -> Result<(), ConsensusError>; ) -> Result<(), ConsensusError>;
} }

View File

@ -1,6 +1,7 @@
use crate::{Consensus, ConsensusError, FullConsensus, HeaderValidator, PostExecutionInput}; use crate::{Consensus, ConsensusError, FullConsensus, HeaderValidator};
use alloc::sync::Arc; use alloc::sync::Arc;
use alloy_primitives::U256; use alloy_primitives::U256;
use reth_execution_types::BlockExecutionResult;
use reth_primitives_traits::{Block, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader}; use reth_primitives_traits::{Block, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader};
/// A Consensus implementation that does nothing. /// A Consensus implementation that does nothing.
@ -57,8 +58,8 @@ impl<N: NodePrimitives> FullConsensus<N> for NoopConsensus {
fn validate_block_post_execution( fn validate_block_post_execution(
&self, &self,
_block: &RecoveredBlock<N::Block>, _block: &RecoveredBlock<N::Block>,
_input: PostExecutionInput<'_, N::Receipt>, _result: &BlockExecutionResult<N::Receipt>,
) -> Result<(), Self::Error> { ) -> Result<(), ConsensusError> {
Ok(()) Ok(())
} }
} }

View File

@ -1,6 +1,7 @@
use crate::{Consensus, ConsensusError, FullConsensus, HeaderValidator, PostExecutionInput}; use crate::{Consensus, ConsensusError, FullConsensus, HeaderValidator};
use alloy_primitives::U256; use alloy_primitives::U256;
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use reth_execution_types::BlockExecutionResult;
use reth_primitives_traits::{Block, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader}; use reth_primitives_traits::{Block, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader};
/// Consensus engine implementation for testing /// Consensus engine implementation for testing
@ -50,7 +51,7 @@ impl<N: NodePrimitives> FullConsensus<N> for TestConsensus {
fn validate_block_post_execution( fn validate_block_post_execution(
&self, &self,
_block: &RecoveredBlock<N::Block>, _block: &RecoveredBlock<N::Block>,
_input: PostExecutionInput<'_, N::Receipt>, _result: &BlockExecutionResult<N::Receipt>,
) -> Result<(), ConsensusError> { ) -> Result<(), ConsensusError> {
if self.fail_validation() { if self.fail_validation() {
Err(ConsensusError::BaseFeeMissing) Err(ConsensusError::BaseFeeMissing)

View File

@ -26,7 +26,7 @@ use reth_chain_state::{
CanonicalInMemoryState, ExecutedBlock, ExecutedBlockWithTrieUpdates, CanonicalInMemoryState, ExecutedBlock, ExecutedBlockWithTrieUpdates,
MemoryOverlayStateProvider, NewCanonicalChain, MemoryOverlayStateProvider, NewCanonicalChain,
}; };
use reth_consensus::{Consensus, FullConsensus, PostExecutionInput}; use reth_consensus::{Consensus, FullConsensus};
pub use reth_engine_primitives::InvalidBlockHook; pub use reth_engine_primitives::InvalidBlockHook;
use reth_engine_primitives::{ use reth_engine_primitives::{
BeaconConsensusEngineEvent, BeaconEngineMessage, BeaconOnNewPayloadError, EngineTypes, BeaconConsensusEngineEvent, BeaconEngineMessage, BeaconOnNewPayloadError, EngineTypes,
@ -2527,10 +2527,7 @@ where
// Ensure that prewarm tasks don't send proof messages after state root sender is dropped // Ensure that prewarm tasks don't send proof messages after state root sender is dropped
cancel_execution.cancel(); cancel_execution.cancel();
if let Err(err) = self.consensus.validate_block_post_execution( if let Err(err) = self.consensus.validate_block_post_execution(&block, &output) {
&block,
PostExecutionInput::new(&output.receipts, &output.requests),
) {
// call post-block hook // call post-block hook
self.invalid_block_hook.on_invalid_block(&parent_block, &block, &output, None); self.invalid_block_hook.on_invalid_block(&parent_block, &block, &output, None);
return Err(err.into()) return Err(err.into())

View File

@ -12,6 +12,7 @@ workspace = true
[dependencies] [dependencies]
# reth # reth
reth-execution-types.workspace = true
reth-chainspec.workspace = true reth-chainspec.workspace = true
reth-consensus-common.workspace = true reth-consensus-common.workspace = true
reth-primitives.workspace = true reth-primitives.workspace = true

View File

@ -12,15 +12,14 @@ use alloy_consensus::EMPTY_OMMER_ROOT_HASH;
use alloy_eips::merge::ALLOWED_FUTURE_BLOCK_TIME_SECONDS; use alloy_eips::merge::ALLOWED_FUTURE_BLOCK_TIME_SECONDS;
use alloy_primitives::U256; use alloy_primitives::U256;
use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_chainspec::{EthChainSpec, EthereumHardforks};
use reth_consensus::{ use reth_consensus::{Consensus, ConsensusError, FullConsensus, HeaderValidator};
Consensus, ConsensusError, FullConsensus, HeaderValidator, PostExecutionInput,
};
use reth_consensus_common::validation::{ use reth_consensus_common::validation::{
validate_4844_header_standalone, validate_against_parent_4844, validate_4844_header_standalone, validate_against_parent_4844,
validate_against_parent_eip1559_base_fee, validate_against_parent_hash_number, validate_against_parent_eip1559_base_fee, validate_against_parent_hash_number,
validate_against_parent_timestamp, validate_block_pre_execution, validate_body_against_header, validate_against_parent_timestamp, validate_block_pre_execution, validate_body_against_header,
validate_header_base_fee, validate_header_extra_data, validate_header_gas, validate_header_base_fee, validate_header_extra_data, validate_header_gas,
}; };
use reth_execution_types::BlockExecutionResult;
use reth_primitives::{NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader}; use reth_primitives::{NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader};
use reth_primitives_traits::{ use reth_primitives_traits::{
constants::{GAS_LIMIT_BOUND_DIVISOR, MINIMUM_GAS_LIMIT}, constants::{GAS_LIMIT_BOUND_DIVISOR, MINIMUM_GAS_LIMIT},
@ -104,9 +103,9 @@ where
fn validate_block_post_execution( fn validate_block_post_execution(
&self, &self,
block: &RecoveredBlock<N::Block>, block: &RecoveredBlock<N::Block>,
input: PostExecutionInput<'_, N::Receipt>, result: &BlockExecutionResult<N::Receipt>,
) -> Result<(), ConsensusError> { ) -> Result<(), ConsensusError> {
validate_block_post_execution(block, &self.chain_spec, input.receipts, input.requests) validate_block_post_execution(block, &self.chain_spec, &result.receipts, &result.requests)
} }
} }

View File

@ -26,6 +26,8 @@ alloy-eips.workspace = true
serde = { workspace = true, optional = true } serde = { workspace = true, optional = true }
serde_with = { workspace = true, optional = true } serde_with = { workspace = true, optional = true }
derive_more.workspace = true
[dev-dependencies] [dev-dependencies]
arbitrary.workspace = true arbitrary.workspace = true
bincode.workspace = true bincode.workspace = true
@ -65,4 +67,5 @@ std = [
"reth-trie-common/std", "reth-trie-common/std",
"reth-ethereum-primitives/std", "reth-ethereum-primitives/std",
"reth-execution-errors/std", "reth-execution-errors/std",
"derive_more/std",
] ]

View File

@ -13,17 +13,24 @@ pub struct BlockExecutionResult<T> {
pub gas_used: u64, pub gas_used: u64,
} }
/// The output of an ethereum block. /// [`BlockExecutionResult`] combined with state.
/// #[derive(
/// Contains the state changes, transaction receipts, and total gas used in the block. Debug,
#[derive(Debug, Clone, PartialEq, Eq)] Clone,
PartialEq,
Eq,
derive_more::AsRef,
derive_more::AsMut,
derive_more::Deref,
derive_more::DerefMut,
)]
pub struct BlockExecutionOutput<T> { pub struct BlockExecutionOutput<T> {
/// All the receipts of the transactions in the block.
#[as_ref]
#[as_mut]
#[deref]
#[deref_mut]
pub result: BlockExecutionResult<T>,
/// The changed state of the block after execution. /// The changed state of the block after execution.
pub state: BundleState, pub state: BundleState,
/// All the receipts of the transactions in the block.
pub receipts: Vec<T>,
/// All the EIP-7685 requests in the block.
pub requests: Requests,
/// The total gas used by the block.
pub gas_used: u64,
} }

View File

@ -129,12 +129,12 @@ impl<T> ExecutionOutcome<T> {
} }
/// Creates a new `ExecutionOutcome` from a single block execution result. /// Creates a new `ExecutionOutcome` from a single block execution result.
pub fn single(block_number: u64, result: BlockExecutionOutput<T>) -> Self { pub fn single(block_number: u64, output: BlockExecutionOutput<T>) -> Self {
Self { Self {
bundle: result.state, bundle: output.state,
receipts: vec![result.receipts], receipts: vec![output.result.receipts],
first_block: block_number, first_block: block_number,
requests: vec![result.requests], requests: vec![output.result.requests],
} }
} }
@ -396,13 +396,8 @@ impl ExecutionOutcome {
} }
impl<T> From<(BlockExecutionOutput<T>, BlockNumber)> for ExecutionOutcome<T> { impl<T> From<(BlockExecutionOutput<T>, BlockNumber)> for ExecutionOutcome<T> {
fn from(value: (BlockExecutionOutput<T>, BlockNumber)) -> Self { fn from((output, block_number): (BlockExecutionOutput<T>, BlockNumber)) -> Self {
Self { Self::single(block_number, output)
bundle: value.0.state,
receipts: vec![value.0.receipts],
first_block: value.1,
requests: vec![value.0.requests],
}
} }
} }

View File

@ -57,9 +57,9 @@ pub trait Executor<DB: Database>: Sized {
block: &RecoveredBlock<<Self::Primitives as NodePrimitives>::Block>, block: &RecoveredBlock<<Self::Primitives as NodePrimitives>::Block>,
) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error> ) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
{ {
let BlockExecutionResult { receipts, requests, gas_used } = self.execute_one(block)?; let result = self.execute_one(block)?;
let mut state = self.into_state(); let mut state = self.into_state();
Ok(BlockExecutionOutput { state: state.take_bundle(), receipts, requests, gas_used }) Ok(BlockExecutionOutput { state: state.take_bundle(), result })
} }
/// Executes multiple inputs in the batch, and returns an aggregated [`ExecutionOutcome`]. /// Executes multiple inputs in the batch, and returns an aggregated [`ExecutionOutcome`].
@ -96,10 +96,10 @@ pub trait Executor<DB: Database>: Sized {
where where
F: FnMut(&State<DB>), F: FnMut(&State<DB>),
{ {
let BlockExecutionResult { receipts, requests, gas_used } = self.execute_one(block)?; let result = self.execute_one(block)?;
let mut state = self.into_state(); let mut state = self.into_state();
f(&state); f(&state);
Ok(BlockExecutionOutput { state: state.take_bundle(), receipts, requests, gas_used }) Ok(BlockExecutionOutput { state: state.take_bundle(), result })
} }
/// Executes the EVM with the given input and accepts a state hook closure that is invoked with /// Executes the EVM with the given input and accepts a state hook closure that is invoked with
@ -112,10 +112,9 @@ pub trait Executor<DB: Database>: Sized {
where where
F: OnStateHook + 'static, F: OnStateHook + 'static,
{ {
let BlockExecutionResult { receipts, requests, gas_used } = let result = self.execute_one_with_state_hook(block, state_hook)?;
self.execute_one_with_state_hook(block, state_hook)?;
let mut state = self.into_state(); let mut state = self.into_state();
Ok(BlockExecutionOutput { state: state.take_bundle(), receipts, requests, gas_used }) Ok(BlockExecutionOutput { state: state.take_bundle(), result })
} }
/// Consumes the executor and returns the [`State`] containing all state changes. /// Consumes the executor and returns the [`State`] containing all state changes.

View File

@ -83,12 +83,14 @@ impl<DB: Database> Executor<DB> for MockExecutorProvider {
self.exec_results.lock().pop().unwrap(); self.exec_results.lock().pop().unwrap();
Ok(BlockExecutionOutput { Ok(BlockExecutionOutput {
state: bundle, state: bundle,
result: BlockExecutionResult {
receipts: receipts.into_iter().flatten().collect(), receipts: receipts.into_iter().flatten().collect(),
requests: requests.into_iter().fold(Requests::default(), |mut reqs, req| { requests: requests.into_iter().fold(Requests::default(), |mut reqs, req| {
reqs.extend(req); reqs.extend(req);
reqs reqs
}), }),
gas_used: 0, gas_used: 0,
},
}) })
} }

View File

@ -13,6 +13,7 @@ workspace = true
[dependencies] [dependencies]
# reth # reth
reth-execution-types.workspace = true
reth-chainspec.workspace = true reth-chainspec.workspace = true
reth-consensus-common.workspace = true reth-consensus-common.workspace = true
reth-consensus.workspace = true reth-consensus.workspace = true
@ -54,5 +55,9 @@ std = [
"alloy-consensus/std", "alloy-consensus/std",
"alloy-trie/std", "alloy-trie/std",
"op-alloy-consensus/std", "op-alloy-consensus/std",
"reth-execution-types/std",
]
optimism = [
"reth-optimism-primitives/optimism",
"reth-execution-types/optimism",
] ]
optimism = ["reth-optimism-primitives/optimism"]

View File

@ -18,15 +18,14 @@ use alloc::sync::Arc;
use alloy_consensus::{BlockHeader as _, EMPTY_OMMER_ROOT_HASH}; use alloy_consensus::{BlockHeader as _, EMPTY_OMMER_ROOT_HASH};
use alloy_primitives::{B64, U256}; use alloy_primitives::{B64, U256};
use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_chainspec::{EthChainSpec, EthereumHardforks};
use reth_consensus::{ use reth_consensus::{Consensus, ConsensusError, FullConsensus, HeaderValidator};
Consensus, ConsensusError, FullConsensus, HeaderValidator, PostExecutionInput,
};
use reth_consensus_common::validation::{ use reth_consensus_common::validation::{
validate_against_parent_4844, validate_against_parent_eip1559_base_fee, validate_against_parent_4844, validate_against_parent_eip1559_base_fee,
validate_against_parent_hash_number, validate_against_parent_timestamp, validate_against_parent_hash_number, validate_against_parent_timestamp,
validate_body_against_header, validate_cancun_gas, validate_header_base_fee, validate_body_against_header, validate_cancun_gas, validate_header_base_fee,
validate_header_extra_data, validate_header_gas, validate_shanghai_withdrawals, validate_header_extra_data, validate_header_gas, validate_shanghai_withdrawals,
}; };
use reth_execution_types::BlockExecutionResult;
use reth_optimism_forks::OpHardforks; use reth_optimism_forks::OpHardforks;
use reth_optimism_primitives::DepositReceipt; use reth_optimism_primitives::DepositReceipt;
use reth_primitives::{GotExpected, NodePrimitives, RecoveredBlock, SealedHeader}; use reth_primitives::{GotExpected, NodePrimitives, RecoveredBlock, SealedHeader};
@ -62,9 +61,9 @@ impl<ChainSpec: EthChainSpec + OpHardforks, N: NodePrimitives<Receipt: DepositRe
fn validate_block_post_execution( fn validate_block_post_execution(
&self, &self,
block: &RecoveredBlock<N::Block>, block: &RecoveredBlock<N::Block>,
input: PostExecutionInput<'_, N::Receipt>, result: &BlockExecutionResult<N::Receipt>,
) -> Result<(), ConsensusError> { ) -> Result<(), ConsensusError> {
validate_block_post_execution(block.header(), &self.chain_spec, input.receipts) validate_block_post_execution(block.header(), &self.chain_spec, &result.receipts)
} }
} }

View File

@ -434,7 +434,7 @@ mod tests {
)) ))
.unwrap(); .unwrap();
let receipts = output.receipts; let receipts = &output.receipts;
let tx_receipt = &receipts[0]; let tx_receipt = &receipts[0];
let deposit_receipt = &receipts[1]; let deposit_receipt = &receipts[1];
@ -510,7 +510,7 @@ mod tests {
)) ))
.expect("Executing a block while canyon is active should not fail"); .expect("Executing a block while canyon is active should not fail");
let receipts = output.receipts; let receipts = &output.receipts;
let tx_receipt = &receipts[0]; let tx_receipt = &receipts[0];
let deposit_receipt = &receipts[1]; let deposit_receipt = &receipts[1];

View File

@ -13,7 +13,7 @@ use alloy_rpc_types_engine::{
use async_trait::async_trait; use async_trait::async_trait;
use jsonrpsee::core::RpcResult; use jsonrpsee::core::RpcResult;
use reth_chainspec::{ChainSpecProvider, EthereumHardforks}; use reth_chainspec::{ChainSpecProvider, EthereumHardforks};
use reth_consensus::{Consensus, FullConsensus, PostExecutionInput}; use reth_consensus::{Consensus, FullConsensus};
use reth_engine_primitives::PayloadValidator; use reth_engine_primitives::PayloadValidator;
use reth_errors::{BlockExecutionError, ConsensusError, ProviderError}; use reth_errors::{BlockExecutionError, ConsensusError, ProviderError};
use reth_evm::execute::{BlockExecutorProvider, Executor}; use reth_evm::execute::{BlockExecutorProvider, Executor};
@ -184,10 +184,7 @@ where
return Err(ValidationApiError::Blacklist(account)) return Err(ValidationApiError::Blacklist(account))
} }
self.consensus.validate_block_post_execution( self.consensus.validate_block_post_execution(&block, &output)?;
&block,
PostExecutionInput::new(&output.receipts, &output.requests),
)?;
self.ensure_payment(&block, &output, &message)?; self.ensure_payment(&block, &output, &message)?;

View File

@ -4,7 +4,7 @@ use alloy_eips::{eip1898::BlockWithParent, NumHash};
use alloy_primitives::BlockNumber; use alloy_primitives::BlockNumber;
use num_traits::Zero; use num_traits::Zero;
use reth_config::config::ExecutionConfig; use reth_config::config::ExecutionConfig;
use reth_consensus::{ConsensusError, FullConsensus, PostExecutionInput}; use reth_consensus::{ConsensusError, FullConsensus};
use reth_db::{static_file::HeaderMask, tables}; use reth_db::{static_file::HeaderMask, tables};
use reth_evm::{ use reth_evm::{
execute::{BlockExecutorProvider, Executor}, execute::{BlockExecutorProvider, Executor},
@ -355,10 +355,7 @@ where
}) })
})?; })?;
if let Err(err) = self.consensus.validate_block_post_execution( if let Err(err) = self.consensus.validate_block_post_execution(&block, &result) {
&block,
PostExecutionInput::new(&result.receipts, &result.requests),
) {
return Err(StageError::Block { return Err(StageError::Block {
block: Box::new(BlockWithParent::new( block: Box::new(BlockWithParent::new(
block.header().parent_hash(), block.header().parent_hash(),