feat: update el requests for devnet 4 (#11865)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Oliver
2024-10-19 14:48:35 +02:00
committed by GitHub
parent 2ae93682b4
commit 3bd695ee63
106 changed files with 799 additions and 1328 deletions

View File

@ -25,7 +25,6 @@ serde = { workspace = true, optional = true }
serde_with = { workspace = true, optional = true }
[dev-dependencies]
alloy-eips.workspace = true
arbitrary.workspace = true
bincode.workspace = true
rand.workspace = true
@ -35,5 +34,9 @@ reth-primitives = { workspace = true, features = ["arbitrary", "test-utils"] }
default = ["std"]
optimism = ["reth-primitives/optimism", "revm/optimism"]
serde = ["dep:serde", "reth-trie/serde", "revm/serde"]
serde-bincode-compat = ["reth-primitives/serde-bincode-compat", "reth-trie/serde-bincode-compat", "serde_with"]
serde-bincode-compat = [
"reth-primitives/serde-bincode-compat",
"reth-trie/serde-bincode-compat",
"serde_with",
]
std = []

View File

@ -1,5 +1,5 @@
use alloy_eips::eip7685::Requests;
use alloy_primitives::U256;
use reth_primitives::Request;
use revm::db::BundleState;
/// A helper type for ethereum block inputs that consists of a block and the total difficulty.
@ -33,8 +33,8 @@ pub struct BlockExecutionOutput<T> {
pub state: BundleState,
/// All the receipts of the transactions in the block.
pub receipts: Vec<T>,
/// All the EIP-7685 requests of the transactions in the block.
pub requests: Vec<Request>,
/// All the EIP-7685 requests in the block.
pub requests: Requests,
/// The total gas used by the block.
pub gas_used: u64,
}

View File

@ -1,6 +1,7 @@
use crate::BlockExecutionOutput;
use alloy_eips::eip7685::Requests;
use alloy_primitives::{Address, BlockNumber, Bloom, Log, B256, U256};
use reth_primitives::{logs_bloom, Account, Bytecode, Receipt, Receipts, Requests, StorageEntry};
use reth_primitives::{logs_bloom, Account, Bytecode, Receipt, Receipts, StorageEntry};
use reth_trie::HashedPostState;
use revm::{
db::{states::BundleState, BundleAccount},
@ -357,7 +358,7 @@ impl From<(BlockExecutionOutput<Receipt>, BlockNumber)> for ExecutionOutcome {
bundle: value.0.state,
receipts: Receipts::from(value.0.receipts),
first_block: value.1,
requests: vec![Requests::from(value.0.requests)],
requests: vec![value.0.requests],
}
}
}
@ -365,9 +366,9 @@ impl From<(BlockExecutionOutput<Receipt>, BlockNumber)> for ExecutionOutcome {
#[cfg(test)]
mod tests {
use super::*;
use alloy_eips::{eip6110::DepositRequest, eip7002::WithdrawalRequest};
use alloy_primitives::{Address, FixedBytes, LogData, B256};
use reth_primitives::{Receipts, Request, Requests, TxType};
use alloy_eips::eip7685::Requests;
use alloy_primitives::{bytes, Address, LogData, B256};
use reth_primitives::{Receipts, TxType};
use std::collections::HashMap;
#[test]
@ -393,29 +394,8 @@ mod tests {
})]],
};
// Create a Requests object with a vector of requests, including DepositRequest and
// WithdrawalRequest
let requests = vec![Requests(vec![
Request::DepositRequest(DepositRequest {
pubkey: FixedBytes::<48>::from([1; 48]),
withdrawal_credentials: B256::from([0; 32]),
amount: 1111,
signature: FixedBytes::<96>::from([2; 96]),
index: 222,
}),
Request::DepositRequest(DepositRequest {
pubkey: FixedBytes::<48>::from([23; 48]),
withdrawal_credentials: B256::from([0; 32]),
amount: 34343,
signature: FixedBytes::<96>::from([43; 96]),
index: 1212,
}),
Request::WithdrawalRequest(WithdrawalRequest {
source_address: Address::from([1; 20]),
validator_pubkey: FixedBytes::<48>::from([10; 48]),
amount: 72,
}),
])];
// Create a Requests object with a vector of requests
let requests = vec![Requests::new(vec![bytes!("dead"), bytes!("beef"), bytes!("beebee")])];
// Define the first block number
let first_block = 123;
@ -657,17 +637,12 @@ mod tests {
// Define the first block number
let first_block = 123;
// Create a DepositRequest object with specific attributes.
let request = Request::DepositRequest(DepositRequest {
pubkey: FixedBytes::<48>::from([1; 48]),
withdrawal_credentials: B256::from([0; 32]),
amount: 1111,
signature: FixedBytes::<96>::from([2; 96]),
index: 222,
});
// Create a request.
let request = bytes!("deadbeef");
// Create a vector of Requests containing the request.
let requests = vec![Requests(vec![request]), Requests(vec![request])];
let requests =
vec![Requests::new(vec![request.clone()]), Requests::new(vec![request.clone()])];
// Create a ExecutionOutcome object with the created bundle, receipts, requests, and
// first_block
@ -681,7 +656,7 @@ mod tests {
assert_eq!(exec_res.receipts, Receipts { receipt_vec: vec![vec![Some(receipt)]] });
// Assert that the requests are properly cut after reverting to the initial block number.
assert_eq!(exec_res.requests, vec![Requests(vec![request])]);
assert_eq!(exec_res.requests, vec![Requests::new(vec![request])]);
// Assert that the revert_to method returns false when attempting to revert to a block
// number greater than the initial block number.
@ -709,17 +684,11 @@ mod tests {
// Create a Receipts object containing the receipt.
let receipts = Receipts { receipt_vec: vec![vec![Some(receipt.clone())]] };
// Create a DepositRequest object with specific attributes.
let request = Request::DepositRequest(DepositRequest {
pubkey: FixedBytes::<48>::from([1; 48]),
withdrawal_credentials: B256::from([0; 32]),
amount: 1111,
signature: FixedBytes::<96>::from([2; 96]),
index: 222,
});
// Create a request.
let request = bytes!("deadbeef");
// Create a vector of Requests containing the request.
let requests = vec![Requests(vec![request])];
let requests = vec![Requests::new(vec![request.clone()])];
// Define the initial block number.
let first_block = 123;
@ -739,7 +708,7 @@ mod tests {
receipts: Receipts {
receipt_vec: vec![vec![Some(receipt.clone())], vec![Some(receipt)]]
},
requests: vec![Requests(vec![request]), Requests(vec![request])],
requests: vec![Requests::new(vec![request.clone()]), Requests::new(vec![request])],
first_block: 123,
}
);
@ -771,18 +740,15 @@ mod tests {
// Define the first block number
let first_block = 123;
// Create a DepositRequest object with specific attributes.
let request = Request::DepositRequest(DepositRequest {
pubkey: FixedBytes::<48>::from([1; 48]),
withdrawal_credentials: B256::from([0; 32]),
amount: 1111,
signature: FixedBytes::<96>::from([2; 96]),
index: 222,
});
// Create a request.
let request = bytes!("deadbeef");
// Create a vector of Requests containing the request.
let requests =
vec![Requests(vec![request]), Requests(vec![request]), Requests(vec![request])];
let requests = vec![
Requests::new(vec![request.clone()]),
Requests::new(vec![request.clone()]),
Requests::new(vec![request.clone()]),
];
// Create a ExecutionOutcome object with the created bundle, receipts, requests, and
// first_block
@ -796,7 +762,7 @@ mod tests {
let lower_execution_outcome = ExecutionOutcome {
bundle: Default::default(),
receipts: Receipts { receipt_vec: vec![vec![Some(receipt.clone())]] },
requests: vec![Requests(vec![request])],
requests: vec![Requests::new(vec![request.clone()])],
first_block,
};
@ -806,7 +772,7 @@ mod tests {
receipts: Receipts {
receipt_vec: vec![vec![Some(receipt.clone())], vec![Some(receipt)]],
},
requests: vec![Requests(vec![request]), Requests(vec![request])],
requests: vec![Requests::new(vec![request.clone()]), Requests::new(vec![request])],
first_block: 124,
};

View File

@ -9,10 +9,11 @@ pub use reth_storage_errors::provider::ProviderError;
use crate::system_calls::OnStateHook;
use alloc::{boxed::Box, vec::Vec};
use alloy_eips::eip7685::Requests;
use alloy_primitives::BlockNumber;
use core::{fmt::Display, marker::PhantomData};
use reth_consensus::ConsensusError;
use reth_primitives::{BlockWithSenders, Receipt, Request};
use reth_primitives::{BlockWithSenders, Receipt};
use reth_prune_types::PruneModes;
use reth_revm::batch::BlockBatchRecord;
use revm::{db::BundleState, State};
@ -190,7 +191,7 @@ pub trait BlockExecutionStrategy<DB> {
block: &BlockWithSenders,
total_difficulty: U256,
receipts: &[Receipt],
) -> Result<Vec<Request>, Self::Error>;
) -> Result<Requests, Self::Error>;
/// Returns a reference to the current state.
fn state_ref(&self) -> &State<DB>;
@ -209,7 +210,7 @@ pub trait BlockExecutionStrategy<DB> {
&self,
block: &BlockWithSenders,
receipts: &[Receipt],
requests: &[Request],
requests: &Requests,
) -> Result<(), ConsensusError>;
}
@ -450,10 +451,10 @@ where
#[cfg(test)]
mod tests {
use super::*;
use alloy_eips::eip6110::DepositRequest;
use alloy_primitives::U256;
use reth_chainspec::{ChainSpec, MAINNET};
use revm::db::{CacheDB, EmptyDBTyped};
use revm_primitives::bytes;
use std::sync::Arc;
#[derive(Clone, Default)]
@ -545,14 +546,14 @@ mod tests {
_evm_config: EvmConfig,
state: State<DB>,
execute_transactions_result: (Vec<Receipt>, u64),
apply_post_execution_changes_result: Vec<Request>,
apply_post_execution_changes_result: Requests,
finish_result: BundleState,
}
#[derive(Clone)]
struct TestExecutorStrategyFactory {
execute_transactions_result: (Vec<Receipt>, u64),
apply_post_execution_changes_result: Vec<Request>,
apply_post_execution_changes_result: Requests,
finish_result: BundleState,
}
@ -607,7 +608,7 @@ mod tests {
_block: &BlockWithSenders,
_total_difficulty: U256,
_receipts: &[Receipt],
) -> Result<Vec<Request>, Self::Error> {
) -> Result<Requests, Self::Error> {
Ok(self.apply_post_execution_changes_result.clone())
}
@ -629,7 +630,7 @@ mod tests {
&self,
_block: &BlockWithSenders,
_receipts: &[Receipt],
_requests: &[Request],
_requests: &Requests,
) -> Result<(), ConsensusError> {
Ok(())
}
@ -651,8 +652,7 @@ mod tests {
let expected_gas_used = 10;
let expected_receipts = vec![Receipt::default()];
let expected_execute_transactions_result = (expected_receipts.clone(), expected_gas_used);
let expected_apply_post_execution_changes_result =
vec![Request::DepositRequest(DepositRequest::default())];
let expected_apply_post_execution_changes_result = Requests::new(vec![bytes!("deadbeef")]);
let expected_finish_result = BundleState::default();
let strategy_factory = TestExecutorStrategyFactory {

View File

@ -1,10 +1,10 @@
//! [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) system call implementation.
use crate::ConfigureEvm;
use alloc::{boxed::Box, format, string::ToString, vec::Vec};
use alloy_eips::eip7002::{WithdrawalRequest, WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS};
use alloy_primitives::{bytes::Buf, Address, Bytes, FixedBytes};
use alloc::{boxed::Box, format};
use alloy_eips::eip7002::WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS;
use alloy_primitives::Bytes;
use reth_execution_errors::{BlockExecutionError, BlockValidationError};
use reth_primitives::{Header, Request};
use reth_primitives::Header;
use revm::{interpreter::Host, Database, Evm};
use revm_primitives::{ExecutionResult, ResultAndState};
@ -62,52 +62,23 @@ where
Ok(res)
}
/// Parses the withdrawal requests from the execution output.
/// Calls the withdrawals requests system contract, and returns the requests from the execution
/// output.
#[inline]
pub(crate) fn post_commit(result: ExecutionResult) -> Result<Vec<Request>, BlockExecutionError> {
let mut data = match result {
pub(crate) fn post_commit(result: ExecutionResult) -> Result<Bytes, BlockExecutionError> {
match result {
ExecutionResult::Success { output, .. } => Ok(output.into_data()),
ExecutionResult::Revert { output, .. } => {
Err(BlockValidationError::WithdrawalRequestsContractCall {
message: format!("execution reverted: {output}"),
})
}
.into())
}
ExecutionResult::Halt { reason, .. } => {
Err(BlockValidationError::WithdrawalRequestsContractCall {
message: format!("execution halted: {reason:?}"),
})
}
}?;
// Withdrawals are encoded as a series of withdrawal requests, each with the following
// format:
//
// +------+--------+--------+
// | addr | pubkey | amount |
// +------+--------+--------+
// 20 48 8
const WITHDRAWAL_REQUEST_SIZE: usize = 20 + 48 + 8;
let mut withdrawal_requests = Vec::with_capacity(data.len() / WITHDRAWAL_REQUEST_SIZE);
while data.has_remaining() {
if data.remaining() < WITHDRAWAL_REQUEST_SIZE {
return Err(BlockValidationError::WithdrawalRequestsContractCall {
message: "invalid withdrawal request length".to_string(),
}
.into())
}
let mut source_address = Address::ZERO;
data.copy_to_slice(source_address.as_mut_slice());
let mut validator_pubkey = FixedBytes::<48>::ZERO;
data.copy_to_slice(validator_pubkey.as_mut_slice());
let amount = data.get_u64();
withdrawal_requests
.push(WithdrawalRequest { source_address, validator_pubkey, amount }.into());
}
Ok(withdrawal_requests)
}

View File

@ -1,10 +1,10 @@
//! [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) system call implementation.
use crate::ConfigureEvm;
use alloc::{boxed::Box, format, string::ToString, vec::Vec};
use alloy_eips::eip7251::{ConsolidationRequest, CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS};
use alloy_primitives::{bytes::Buf, Address, Bytes, FixedBytes};
use alloc::{boxed::Box, format};
use alloy_eips::eip7251::CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS;
use alloy_primitives::Bytes;
use reth_execution_errors::{BlockExecutionError, BlockValidationError};
use reth_primitives::{Header, Request};
use reth_primitives::Header;
use revm::{interpreter::Host, Database, Evm};
use revm_primitives::{ExecutionResult, ResultAndState};
@ -64,56 +64,23 @@ where
Ok(res)
}
/// Parses the consolidation requests from the execution output.
/// Calls the consolidation requests system contract, and returns the requests from the execution
/// output.
#[inline]
pub(crate) fn post_commit(result: ExecutionResult) -> Result<Vec<Request>, BlockExecutionError> {
let mut data = match result {
pub(crate) fn post_commit(result: ExecutionResult) -> Result<Bytes, BlockExecutionError> {
match result {
ExecutionResult::Success { output, .. } => Ok(output.into_data()),
ExecutionResult::Revert { output, .. } => {
Err(BlockValidationError::ConsolidationRequestsContractCall {
message: format!("execution reverted: {output}"),
})
}
.into())
}
ExecutionResult::Halt { reason, .. } => {
Err(BlockValidationError::ConsolidationRequestsContractCall {
message: format!("execution halted: {reason:?}"),
})
}
}?;
// Consolidations are encoded as a series of consolidation requests, each with the following
// format:
//
// +------+--------+---------------+
// | addr | pubkey | target pubkey |
// +------+--------+---------------+
// 20 48 48
const CONSOLIDATION_REQUEST_SIZE: usize = 20 + 48 + 48;
let mut consolidation_requests = Vec::with_capacity(data.len() / CONSOLIDATION_REQUEST_SIZE);
while data.has_remaining() {
if data.remaining() < CONSOLIDATION_REQUEST_SIZE {
return Err(BlockValidationError::ConsolidationRequestsContractCall {
message: "invalid consolidation request length".to_string(),
}
.into())
}
let mut source_address = Address::ZERO;
data.copy_to_slice(source_address.as_mut_slice());
let mut source_pubkey = FixedBytes::<48>::ZERO;
data.copy_to_slice(source_pubkey.as_mut_slice());
let mut target_pubkey = FixedBytes::<48>::ZERO;
data.copy_to_slice(target_pubkey.as_mut_slice());
consolidation_requests.push(Request::ConsolidationRequest(ConsolidationRequest {
source_address,
source_pubkey,
target_pubkey,
}));
}
Ok(consolidation_requests)
}

View File

@ -1,11 +1,13 @@
//! System contract call functions.
use crate::ConfigureEvm;
use alloc::{boxed::Box, vec::Vec};
use alloc::{boxed::Box, vec};
use alloy_eips::eip7685::Requests;
use alloy_primitives::Bytes;
use core::fmt::Display;
use reth_chainspec::EthereumHardforks;
use reth_execution_errors::BlockExecutionError;
use reth_primitives::{Block, Header, Request};
use reth_primitives::{Block, Header};
use revm::{Database, DatabaseCommit, Evm};
use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ResultAndState, B256};
@ -119,17 +121,18 @@ where
pub fn apply_post_execution_changes<DB, Ext>(
&mut self,
evm: &mut Evm<'_, Ext, DB>,
) -> Result<Vec<Request>, BlockExecutionError>
) -> Result<Requests, BlockExecutionError>
where
DB: Database + DatabaseCommit,
DB::Error: Display,
{
// todo
// Collect all EIP-7685 requests
let withdrawal_requests = self.apply_withdrawal_requests_contract_call(evm)?;
// Collect all EIP-7251 requests
let consolidation_requests = self.apply_consolidation_requests_contract_call(evm)?;
Ok([withdrawal_requests, consolidation_requests].concat())
Ok(Requests::new(vec![withdrawal_requests, consolidation_requests]))
}
/// Applies the pre-block call to the EIP-2935 blockhashes contract.
@ -247,7 +250,7 @@ where
db: &mut DB,
initialized_cfg: &CfgEnvWithHandlerCfg,
initialized_block_env: &BlockEnv,
) -> Result<Vec<Request>, BlockExecutionError>
) -> Result<Bytes, BlockExecutionError>
where
DB: Database + DatabaseCommit,
DB::Error: Display,
@ -263,7 +266,7 @@ where
pub fn apply_withdrawal_requests_contract_call<DB, Ext>(
&mut self,
evm: &mut Evm<'_, Ext, DB>,
) -> Result<Vec<Request>, BlockExecutionError>
) -> Result<Bytes, BlockExecutionError>
where
DB: Database + DatabaseCommit,
DB::Error: Display,
@ -285,7 +288,7 @@ where
db: &mut DB,
initialized_cfg: &CfgEnvWithHandlerCfg,
initialized_block_env: &BlockEnv,
) -> Result<Vec<Request>, BlockExecutionError>
) -> Result<Bytes, BlockExecutionError>
where
DB: Database + DatabaseCommit,
DB::Error: Display,
@ -301,7 +304,7 @@ where
pub fn apply_consolidation_requests_contract_call<DB, Ext>(
&mut self,
evm: &mut Evm<'_, Ext, DB>,
) -> Result<Vec<Request>, BlockExecutionError>
) -> Result<Bytes, BlockExecutionError>
where
DB: Database + DatabaseCommit,
DB::Error: Display,

View File

@ -7,6 +7,7 @@ use crate::{
},
system_calls::OnStateHook,
};
use alloy_eips::eip7685::Requests;
use alloy_primitives::BlockNumber;
use parking_lot::Mutex;
use reth_execution_errors::BlockExecutionError;
@ -62,7 +63,10 @@ impl<DB> Executor<DB> for MockExecutorProvider {
Ok(BlockExecutionOutput {
state: bundle,
receipts: receipts.into_iter().flatten().flatten().collect(),
requests: requests.into_iter().flatten().collect(),
requests: requests.into_iter().fold(Requests::default(), |mut reqs, req| {
reqs.extend(req);
reqs
}),
gas_used: 0,
})
}