Skip to content

Commit

Permalink
Activate Dencun/Cancun upgrade (#1436)
Browse files Browse the repository at this point in the history
  • Loading branch information
eyusufatik authored Nov 11, 2024
1 parent 79eb7c6 commit e699aeb
Show file tree
Hide file tree
Showing 28 changed files with 432 additions and 352 deletions.
15 changes: 6 additions & 9 deletions crates/ethereum-rpc/src/gas_price/gas_oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,15 +217,12 @@ impl<C: sov_modules_api::Context> GasPriceOracle<C> {
}
}
let last_entry = fee_entries.last().expect("is not empty");
base_fee_per_gas.push(
calculate_next_block_base_fee(
last_entry.gas_used as u128,
last_entry.gas_limit as u128,
Some(last_entry.base_fee_per_gas),
self.provider.get_chain_config(working_set).base_fee_params,
)
.unwrap() as u128,
);
base_fee_per_gas.push(calculate_next_block_base_fee(
last_entry.gas_used as u128,
last_entry.gas_limit as u128,
last_entry.base_fee_per_gas,
self.provider.get_chain_config(working_set).base_fee_params,
));

Ok(FeeHistory {
base_fee_per_gas,
Expand Down
42 changes: 13 additions & 29 deletions crates/evm/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ use core::panic;

use anyhow::Result;
use reth_primitives::TransactionSignedEcRecovered;
use revm::primitives::{CfgEnv, CfgEnvWithHandlerCfg, EVMError, SpecId};
use revm::primitives::{BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, EVMError, SpecId};
use sov_modules_api::prelude::*;
use sov_modules_api::{native_error, CallResponse, WorkingSet};

use crate::evm::db::EvmDb;
use crate::evm::executor::{self};
use crate::evm::handler::{CitreaExternal, CitreaExternalExt};
use crate::evm::primitive_types::{BlockEnv, Receipt, TransactionSignedAndRecovered};
use crate::evm::primitive_types::{Receipt, TransactionSignedAndRecovered};
use crate::evm::{EvmChainConfig, RlpEvmTransaction};
use crate::system_contracts::{BitcoinLightClient, Bridge};
use crate::system_events::{create_system_transactions, SYSTEM_SIGNER};
use crate::{Evm, PendingTransaction, SystemEvent};
use crate::{citrea_spec_id_to_evm_spec_id, Evm, PendingTransaction, SystemEvent};

#[cfg_attr(
feature = "serde",
Expand All @@ -36,12 +36,13 @@ impl<C: sov_modules_api::Context> Evm<C> {
l1_fee_rate: u128,
cfg: EvmChainConfig,
block_env: BlockEnv,
active_spec: SpecId,
working_set: &mut WorkingSet<C>,
) {
// don't use self.block_env here
// function is expected to use block_env passed as argument

let cfg_env: CfgEnvWithHandlerCfg = get_cfg_env(&block_env, cfg);
let cfg_env: CfgEnvWithHandlerCfg = get_cfg_env(cfg, active_spec);

let l1_block_hash_exists = self
.accounts
Expand Down Expand Up @@ -108,7 +109,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
transaction: TransactionSignedAndRecovered {
signer: tx.signer(),
signed_transaction: tx.into(),
block_number,
block_number: block_number.saturating_to(),
},
receipt,
};
Expand Down Expand Up @@ -140,7 +141,8 @@ impl<C: sov_modules_api::Context> Evm<C> {
.collect();

let cfg = self.cfg.get(working_set).expect("Evm config must be set");
let cfg_env: CfgEnvWithHandlerCfg = get_cfg_env(&self.block_env, cfg);
let active_evm_spec = citrea_spec_id_to_evm_spec_id(context.active_spec());
let cfg_env: CfgEnvWithHandlerCfg = get_cfg_env(cfg, active_evm_spec);

let l1_fee_rate = context.l1_fee_rate();
let mut citrea_handler_ext = CitreaExternal::new(l1_fee_rate);
Expand All @@ -158,11 +160,12 @@ impl<C: sov_modules_api::Context> Evm<C> {

let results = executor::execute_multiple_tx(
evm_db,
self.block_env,
self.block_env.clone(),
&users_txs,
cfg_env,
&mut citrea_handler_ext,
cumulative_gas_used,
&mut self.blob_gas_used,
);

// Iterate each evm_txs_recovered and results pair
Expand Down Expand Up @@ -199,7 +202,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
transaction: TransactionSignedAndRecovered {
signer: evm_tx_recovered.signer(),
signed_transaction: evm_tx_recovered.into(),
block_number,
block_number: block_number.saturating_to(),
},
receipt,
};
Expand Down Expand Up @@ -245,28 +248,9 @@ impl<C: sov_modules_api::Context> Evm<C> {

/// Get cfg env for a given block number
/// Returns correct config depending on spec for given block number
pub(crate) fn get_cfg_env(block_env: &BlockEnv, cfg: EvmChainConfig) -> CfgEnvWithHandlerCfg {
let mut cfg_env = CfgEnvWithHandlerCfg::new_with_spec_id(
CfgEnv::default(),
get_spec_id(cfg.spec, block_env.number),
);
pub(crate) fn get_cfg_env(cfg: EvmChainConfig, spec_id: SpecId) -> CfgEnvWithHandlerCfg {
let mut cfg_env = CfgEnvWithHandlerCfg::new_with_spec_id(CfgEnv::default(), spec_id);
cfg_env.chain_id = cfg.chain_id;
cfg_env.limit_contract_code_size = cfg.limit_contract_code_size;
cfg_env
}

/// Get spec id for a given block number
/// Returns the first spec id defined for block >= block_number
pub(crate) fn get_spec_id(spec: Vec<(u64, SpecId)>, block_number: u64) -> SpecId {
match spec.binary_search_by(|&(k, _)| k.cmp(&block_number)) {
Ok(index) => spec[index].1,
Err(index) => {
if index > 0 {
spec[index - 1].1
} else {
// this should never happen as we cover this in genesis
panic!("EVM spec must start from block 0")
}
}
}
}
3 changes: 1 addition & 2 deletions crates/evm/src/evm/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ use std::cmp::min;
use reth_primitives::{B256, U256};
use reth_rpc_eth_types::error::{EthApiError, EthResult, RpcInvalidTransactionError};
use reth_rpc_types::TransactionRequest;
use revm::primitives::{CfgEnvWithHandlerCfg, TxEnv};
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg, TxEnv};

use crate::caller_gas_allowance;
use crate::primitive_types::BlockEnv;

/// Helper type for representing the fees of a [TransactionRequest]
pub(crate) struct CallFees {
Expand Down
72 changes: 48 additions & 24 deletions crates/evm/src/evm/conversions.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use citrea_primitives::forks::FORKS;
use reth_primitives::{
Bytes as RethBytes, TransactionSigned, TransactionSignedEcRecovered, TransactionSignedNoHash,
KECCAK_EMPTY,
Bytes as RethBytes, SealedHeader, TransactionSigned, TransactionSignedEcRecovered,
TransactionSignedNoHash, KECCAK_EMPTY,
};
use revm::primitives::{
AccountInfo as ReVmAccountInfo, BlockEnv as ReVmBlockEnv, TransactTo, TxEnv, U256,
AccountInfo as ReVmAccountInfo, BlobExcessGasAndPrice, BlockEnv, SpecId, TransactTo, TxEnv,
U256,
};
use sov_modules_api::fork::fork_from_block_number;

use super::primitive_types::{BlockEnv, RlpEvmTransaction, TransactionSignedAndRecovered};
use super::primitive_types::{RlpEvmTransaction, TransactionSignedAndRecovered};
use super::AccountInfo;
use crate::citrea_spec_id_to_evm_spec_id;

impl From<AccountInfo> for ReVmAccountInfo {
fn from(info: AccountInfo) -> Self {
Expand Down Expand Up @@ -45,30 +49,13 @@ impl From<AccountInfo> for reth_primitives::Account {
}
}

impl From<BlockEnv> for ReVmBlockEnv {
fn from(block_env: BlockEnv) -> Self {
Self {
number: U256::from(block_env.number),
coinbase: block_env.coinbase,
timestamp: U256::from(block_env.timestamp),
difficulty: U256::ZERO,
prevrandao: Some(block_env.prevrandao),
basefee: U256::from(block_env.basefee),
gas_limit: U256::from(block_env.gas_limit),
// EIP-4844 related field
// https://github.com/Sovereign-Labs/sovereign-sdk/issues/912
blob_excess_gas_and_price: None,
}
}
}

pub(crate) fn create_tx_env(tx: &TransactionSignedEcRecovered) -> TxEnv {
pub(crate) fn create_tx_env(tx: &TransactionSignedEcRecovered, spec_id: SpecId) -> TxEnv {
let to = match tx.to() {
Some(addr) => TransactTo::Call(addr),
None => TransactTo::Create,
};

TxEnv {
let mut tx_env = TxEnv {
caller: tx.signer(),
gas_limit: tx.gas_limit(),
gas_price: U256::from(tx.effective_gas_price(None)),
Expand All @@ -78,14 +65,26 @@ pub(crate) fn create_tx_env(tx: &TransactionSignedEcRecovered) -> TxEnv {
data: RethBytes::from(tx.input().to_vec()),
chain_id: tx.chain_id(),
nonce: Some(tx.nonce()),
// TODO handle access list
access_list: vec![],
// EIP-4844 related fields
// https://github.com/Sovereign-Labs/sovereign-sdk/issues/912
blob_hashes: vec![],
max_fee_per_blob_gas: None,
authorization_list: None,
};

if spec_id >= SpecId::CANCUN {
// A bug was found before activating cancun
// Access list supplied with txs were ignored
// that's why we can only use the access list if spec >= cancun
tx_env.access_list = tx.access_list().cloned().unwrap_or_default().0;

// EIP-4844 related fields
tx_env.blob_hashes = tx.blob_versioned_hashes().unwrap_or_default();
tx_env.max_fee_per_blob_gas = tx.max_fee_per_blob_gas().map(U256::from);
}

tx_env
}

#[derive(Debug, PartialEq, Clone)]
Expand Down Expand Up @@ -132,3 +131,28 @@ impl From<TransactionSignedAndRecovered> for TransactionSignedEcRecovered {
)
}
}

pub(crate) fn sealed_block_to_block_env(sealed_header: &SealedHeader) -> BlockEnv {
BlockEnv {
number: U256::from(sealed_header.number),
coinbase: sealed_header.beneficiary,
timestamp: U256::from(sealed_header.timestamp),
prevrandao: Some(sealed_header.mix_hash),
basefee: U256::from(sealed_header.base_fee_per_gas.unwrap_or_default()),
gas_limit: U256::from(sealed_header.gas_limit),
difficulty: U256::from(0),
blob_excess_gas_and_price: sealed_header
.excess_blob_gas
.or_else(|| {
if citrea_spec_id_to_evm_spec_id(
fork_from_block_number(FORKS.to_vec(), sealed_header.number).spec_id,
) >= SpecId::CANCUN
{
Some(0)
} else {
None
}
})
.map(BlobExcessGasAndPrice::new),
}
}
31 changes: 25 additions & 6 deletions crates/evm/src/evm/executor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use alloy_eips::eip4844::MAX_DATA_GAS_PER_BLOCK;
use reth_primitives::TransactionSignedEcRecovered;
use revm::primitives::{
CfgEnvWithHandlerCfg, EVMError, Env, EvmState, ExecutionResult, ResultAndState,
BlockEnv, CfgEnvWithHandlerCfg, EVMError, Env, EvmState, ExecutionResult, ResultAndState,
};
use revm::{self, Context, Database, DatabaseCommit, EvmContext};
use sov_modules_api::{native_error, native_trace};
Expand All @@ -9,7 +10,6 @@ use tracing::trace_span;

use super::conversions::create_tx_env;
use super::handler::{citrea_handler, CitreaExternalExt};
use super::primitive_types::BlockEnv;
use crate::db::DBError;
use crate::SYSTEM_SIGNER;

Expand All @@ -24,7 +24,7 @@ where
{
/// Creates a new Citrea EVM with the given parameters.
pub fn new(db: DB, block_env: BlockEnv, config_env: CfgEnvWithHandlerCfg, ext: EXT) -> Self {
let evm_env = Env::boxed(config_env.cfg_env, block_env.into(), Default::default());
let evm_env = Env::boxed(config_env.cfg_env, block_env, Default::default());
let evm_context = EvmContext::new_with_env(db, evm_env);
let context = Context::new(evm_context, ext);
let handler = citrea_handler(config_env.handler_cfg);
Expand All @@ -41,7 +41,7 @@ where
DB: DatabaseCommit,
{
self.evm.context.external.set_current_tx_hash(tx.hash());
*self.evm.tx_mut() = create_tx_env(tx);
*self.evm.tx_mut() = create_tx_env(tx, self.evm.spec_id());
self.evm.transact_commit()
}

Expand All @@ -52,7 +52,7 @@ where
tx: &TransactionSignedEcRecovered,
) -> Result<ResultAndState, EVMError<DB::Error>> {
self.evm.context.external.set_current_tx_hash(tx.hash());
*self.evm.tx_mut() = create_tx_env(tx);
*self.evm.tx_mut() = create_tx_env(tx, self.evm.spec_id());
self.evm.transact()
}

Expand Down Expand Up @@ -87,12 +87,13 @@ pub(crate) fn execute_multiple_tx<
config_env: CfgEnvWithHandlerCfg,
ext: &mut EXT,
prev_gas_used: u64,
blob_gas_used: &mut u64,
) -> Vec<Result<ExecutionResult, EVMError<DBError>>> {
if txs.is_empty() {
return vec![];
}

let block_gas_limit = block_env.gas_limit;
let block_gas_limit: u64 = block_env.gas_limit.saturating_to();

let mut cumulative_gas_used = prev_gas_used;

Expand All @@ -104,6 +105,19 @@ pub(crate) fn execute_multiple_tx<
let _span =
trace_span!("Processing tx", i = _i, signer = %tx.signer(), tx_hash = %tx.hash())
.entered();

if tx.is_eip4844()
// can unwrap because we checked if it's EIP-4844
&& *blob_gas_used + tx.blob_gas_used().unwrap() > MAX_DATA_GAS_PER_BLOCK
{
native_error!("Blob gas used exceeds block gas limit");
tx_results.push(Err(EVMError::Custom(format!(
"Blob gas used exceeds block gas limit {:?}",
block_gas_limit
))));
continue;
}

let result_and_state = match evm.transact(tx) {
Ok(result_and_state) => result_and_state,
Err(e) => {
Expand All @@ -129,6 +143,11 @@ pub(crate) fn execute_multiple_tx<
native_trace!("Commiting tx to DB");
evm.commit(result_and_state.state);
cumulative_gas_used += result_and_state.result.gas_used();

if tx.is_eip4844() {
*blob_gas_used += tx.blob_gas_used().unwrap();
}

Ok(result_and_state.result)
};
tx_results.push(result);
Expand Down
2 changes: 2 additions & 0 deletions crates/evm/src/evm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ pub struct EvmChainConfig {
/// By default it is 0x6000 (~25kb).
pub limit_contract_code_size: Option<usize>,

/// DO NOT USE THIS FIELD ever again
///
/// List of EVM hardforks by block number
pub spec: Vec<(u64, SpecId)>,

Expand Down
Loading

0 comments on commit e699aeb

Please sign in to comment.