Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/devnet-0' into onbjerg/eip-7685
Browse files Browse the repository at this point in the history
  • Loading branch information
shekhirin committed May 13, 2024
2 parents 486e475 + faf609b commit be76a64
Show file tree
Hide file tree
Showing 36 changed files with 286 additions and 88 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion bin/reth/src/commands/debug_cmd/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ impl Command {
PruneModes::none(),
);
executor.execute_one((&sealed_block.clone().unseal(), td).into())?;
let BatchBlockExecutionOutput { bundle, receipts, first_block } = executor.finalize();
let BatchBlockExecutionOutput { bundle, receipts, requests: _, first_block } =
executor.finalize();
BundleStateWithReceipts::new(bundle, receipts, first_block).write_to_storage(
provider_rw.tx_ref(),
None,
Expand Down
2 changes: 1 addition & 1 deletion crates/config/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl Config {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("reth config file extension must be '{EXTENSION}'"),
));
))
}
confy::store_path(path, self).map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))
}
Expand Down
4 changes: 2 additions & 2 deletions crates/e2e-test-utils/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ impl<E: EngineTypes + 'static> PayloadTestContext<E> {
let payload = self.payload_builder.best_payload(payload_id).await.unwrap().unwrap();
if payload.block().body.is_empty() {
tokio::time::sleep(std::time::Duration::from_millis(20)).await;
continue;
continue
}
break;
break
}
}

Expand Down
3 changes: 3 additions & 0 deletions crates/ethereum/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ revm-interpreter.workspace = true

revm-precompile = { version = "7.0.0", features = ["std"], default-features = false }

# Alloy
alloy-consensus.workspace = true

# misc
tracing.workspace = true

Expand Down
65 changes: 44 additions & 21 deletions crates/ethereum/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
verify::verify_receipts,
EthEvmConfig,
};
use alloy_consensus::Request;
use reth_evm::{
execute::{
BatchBlockExecutionOutput, BatchExecutor, BlockExecutionInput, BlockExecutionOutput,
Expand All @@ -25,6 +26,7 @@ use reth_revm::{
db::states::bundle_state::BundleRetention,
state_change::{
apply_beacon_root_contract_call, apply_blockhashes_update, post_block_balance_increments,
post_block_withdrawal_requests,
},
Evm, State,
};
Expand Down Expand Up @@ -105,6 +107,14 @@ where
}
}

/// Helper type for the output of executing a block.
#[derive(Debug, Clone)]
struct EthExecuteOutput {
receipts: Vec<Receipt>,
requests: Vec<Request>,
gas_used: u64,
}

/// Helper container type for EVM with chain spec.
#[derive(Debug, Clone)]
struct EthEvmExecutor<EvmConfig> {
Expand All @@ -118,18 +128,21 @@ impl<EvmConfig> EthEvmExecutor<EvmConfig>
where
EvmConfig: ConfigureEvm,
{
/// Executes the transactions in the block and returns the receipts.
/// Executes the transactions in the block and returns the receipts of the transactions in the
/// block, the total gas used and the list of EIP-7685 [requests](Request).
///
/// This applies the pre-execution changes, and executes the transactions.
/// This applies the pre-execution and post-execution changes that require an [EVM](Evm), and
/// executes the transactions.
///
/// # Note
///
/// It does __not__ apply post-execution changes.
fn execute_pre_and_transactions<Ext, DB>(
/// It does __not__ apply post-execution changes that do not require an [EVM](Evm), for that see
/// [EthBlockExecutor::post_execution].
fn execute_state_transitions<Ext, DB>(
&self,
block: &BlockWithSenders,
mut evm: Evm<'_, Ext, &mut State<DB>>,
) -> Result<(Vec<Receipt>, u64), BlockExecutionError>
) -> Result<EthExecuteOutput, BlockExecutionError>
where
DB: Database<Error = ProviderError>,
{
Expand All @@ -155,7 +168,7 @@ where
transaction_gas_limit: transaction.gas_limit(),
block_available_gas,
}
.into());
.into())
}

EvmConfig::fill_tx_env(evm.tx_mut(), transaction, *sender);
Expand Down Expand Up @@ -188,7 +201,6 @@ where
},
);
}
drop(evm);

// Check if gas used matches the value set in header.
if block.gas_used != cumulative_gas_used {
Expand All @@ -197,10 +209,15 @@ where
gas: GotExpected { got: cumulative_gas_used, expected: block.gas_used },
gas_spent_by_tx: receipts.gas_spent_by_tx()?,
}
.into());
.into())
}

Ok((receipts, cumulative_gas_used))
// Collect all EIP-7685 requests
let withdrawal_requests =
post_block_withdrawal_requests(&self.chain_spec, block.timestamp, &mut evm)?;
let requests = withdrawal_requests;

Ok(EthExecuteOutput { receipts, requests, gas_used: cumulative_gas_used })
}
}

Expand Down Expand Up @@ -261,23 +278,23 @@ where

/// Execute a single block and apply the state changes to the internal state.
///
/// Returns the receipts of the transactions in the block and the total gas used.
/// Returns the receipts of the transactions in the block, the total gas used and the list of
/// EIP-7685 [requests](Request).
///
/// Returns an error if execution fails or receipt verification fails.
fn execute_and_verify(
&mut self,
block: &BlockWithSenders,
total_difficulty: U256,
) -> Result<(Vec<Receipt>, u64), BlockExecutionError> {
) -> Result<EthExecuteOutput, BlockExecutionError> {
// 1. prepare state on new block
self.on_new_block(&block.header);

// 2. configure the evm and execute
let env = self.evm_env_for_block(&block.header, total_difficulty);

let (receipts, gas_used) = {
let EthExecuteOutput { receipts, requests, gas_used } = {
let evm = self.executor.evm_config.evm_with_env(&mut self.state, env);
self.executor.execute_pre_and_transactions(block, evm)
self.executor.execute_state_transitions(block, evm)
}?;

// 3. apply post execution changes
Expand All @@ -294,11 +311,11 @@ where
receipts.iter(),
) {
debug!(target: "evm", %error, ?receipts, "receipts verification failed");
return Err(error);
return Err(error)
};
}

Ok((receipts, gas_used))
Ok(EthExecuteOutput { receipts, requests, gas_used })
}

/// Apply settings before a new block is executed.
Expand All @@ -308,8 +325,8 @@ where
self.state.set_state_clear_flag(state_clear_flag);
}

/// Apply post execution state changes, including block rewards, withdrawals, and irregular DAO
/// hardfork state change.
/// Apply post execution state changes that do not require an [EVM](Evm), such as: block
/// rewards, withdrawals, and irregular DAO hardfork state change
pub fn post_execution(
&mut self,
block: &BlockWithSenders,
Expand Down Expand Up @@ -366,12 +383,13 @@ where
/// State changes are committed to the database.
fn execute(mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
let BlockExecutionInput { block, total_difficulty } = input;
let (receipts, gas_used) = self.execute_and_verify(block, total_difficulty)?;
let EthExecuteOutput { receipts, requests, gas_used } =
self.execute_and_verify(block, total_difficulty)?;

// NOTE: we need to merge keep the reverts for the bundle retention
self.state.merge_transitions(BundleRetention::Reverts);

Ok(BlockExecutionOutput { state: self.state.take_bundle(), receipts, gas_used })
Ok(BlockExecutionOutput { state: self.state.take_bundle(), receipts, requests, gas_used })
}
}

Expand Down Expand Up @@ -408,7 +426,8 @@ where

fn execute_one(&mut self, input: Self::Input<'_>) -> Result<(), Self::Error> {
let BlockExecutionInput { block, total_difficulty } = input;
let (receipts, _gas_used) = self.executor.execute_and_verify(block, total_difficulty)?;
let EthExecuteOutput { receipts, requests, gas_used: _ } =
self.executor.execute_and_verify(block, total_difficulty)?;

// prepare the state according to the prune mode
let retention = self.batch_record.bundle_retention(block.number);
Expand All @@ -417,6 +436,9 @@ where
// store receipts in the set
self.batch_record.save_receipts(receipts)?;

// store requests in the set
self.batch_record.save_requests(requests);

if self.batch_record.first_block().is_none() {
self.batch_record.set_first_block(block.number);
}
Expand All @@ -430,6 +452,7 @@ where
BatchBlockExecutionOutput::new(
self.executor.state.take_bundle(),
self.batch_record.take_receipts(),
self.batch_record.take_requests(),
self.batch_record.first_block().unwrap_or_default(),
)
}
Expand Down
10 changes: 5 additions & 5 deletions crates/ethereum/evm/src/instructions/eip3074.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ fn auth_instruction<EXT, DB: Database>(
ctx.remove(AUTHORIZED_VAR_NAME);
push!(interp, B256::ZERO.into());
interp.instruction_result = InstructionResult::Continue;
return;
return
}
acc
}
Err(_) => {
interp.instruction_result = InstructionResult::Revert;
return;
return
}
};
let nonce = authority_account.0.info.nonce;
Expand All @@ -132,7 +132,7 @@ fn auth_instruction<EXT, DB: Database>(
Ok(signer) => signer,
Err(_) => {
interp.instruction_result = InstructionResult::Revert;
return;
return
}
};

Expand Down Expand Up @@ -164,7 +164,7 @@ fn authcall_instruction<EXT, DB: Database>(
Some(address) => Address::from_slice(&address),
None => {
interp.instruction_result = InstructionResult::Revert;
return;
return
}
};

Expand All @@ -181,7 +181,7 @@ fn authcall_instruction<EXT, DB: Database>(
pop!(interp, value);
if interp.is_static && value != U256::ZERO {
interp.instruction_result = InstructionResult::CallNotAllowedInsideStatic;
return;
return
}

let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interp) else {
Expand Down
5 changes: 4 additions & 1 deletion crates/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ revm-primitives.workspace = true
revm.workspace = true
reth-interfaces.workspace = true

# alloy
alloy-consensus.workspace = true

futures-util.workspace = true
parking_lot = { workspace = true, optional = true }

[dev-dependencies]
parking_lot.workspace = true

[features]
test-utils = ["dep:parking_lot"]
test-utils = ["dep:parking_lot"]
23 changes: 20 additions & 3 deletions crates/evm/src/execute.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
//! Traits for execution.

use alloy_consensus::Request;
use reth_interfaces::{executor::BlockExecutionError, provider::ProviderError};
use reth_primitives::{BlockNumber, BlockWithSenders, PruneModes, Receipt, Receipts, U256};
use reth_primitives::{
BlockNumber, BlockWithSenders, PruneModes, Receipt, Receipts, Requests, U256,
};
use revm::db::BundleState;
use revm_primitives::db::Database;

Expand Down Expand Up @@ -80,6 +83,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>,
/// The total gas used by the block.
pub gas_used: u64,
}
Expand All @@ -95,14 +100,26 @@ pub struct BatchBlockExecutionOutput {
///
/// If receipt is None it means it is pruned.
pub receipts: Receipts,
/// The collection of EIP-7685 requests.
/// Outer vector stores requests for each block sequentially.
/// The inner vector stores requests ordered by transaction number.
///
/// A transaction may have zero or more requests, so the length of the inner vector is not
/// guaranteed to be the same as the number of transactions.
pub requests: Vec<Requests>,
/// First block of bundle state.
pub first_block: BlockNumber,
}

impl BatchBlockExecutionOutput {
/// Create Bundle State.
pub fn new(bundle: BundleState, receipts: Receipts, first_block: BlockNumber) -> Self {
Self { bundle, receipts, first_block }
pub fn new(
bundle: BundleState,
receipts: Receipts,
requests: Vec<Requests>,
first_block: BlockNumber,
) -> Self {
Self { bundle, receipts, requests, first_block }
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/evm/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ impl<DB> Executor<DB> for MockExecutorProvider {
state: bundle,
receipts: receipts.into_iter().flatten().flatten().collect(),
gas_used: 0,
requests: vec![],
})
}
}
Expand Down
8 changes: 7 additions & 1 deletion crates/interfaces/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,17 @@ pub enum BlockValidationError {
///
/// [EIP-2935]: https://eips.ethereum.org/EIPS/eip-2935
#[error("failed to apply EIP-2935 pre-block state transition: {message}")]
// todo: better variant name
// TODO: better variant name
Eip2935StateTransition {
/// The error message.
message: String,
},
/// EVM error during withdrawal requests contract call
#[error("failed to apply withdrawal requests contract call: {message}")]
WithdrawalRequestsContractCall {
/// The error message.
message: String,
},
}

/// BlockExecutor Errors
Expand Down

0 comments on commit be76a64

Please sign in to comment.