Skip to content

Commit b85bede

Browse files
fix: restore bucket capacity overrides
1 parent b4b9e0b commit b85bede

File tree

6 files changed

+126
-30
lines changed

6 files changed

+126
-30
lines changed

bin/mega-evme/src/common/env.rs

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ use std::str::FromStr;
55
use alloy_primitives::{Address, B256, U256};
66
use clap::{Args, Parser};
77
use mega_evm::{
8-
alloy_evm::Database,
98
revm::{
109
context::{block::BlockEnv, cfg::CfgEnv},
10+
database::{DatabaseRef, WrapDatabaseRef},
1111
primitives::eip4844,
1212
},
13-
BucketId, MegaContext, MegaSpecId, TestExternalEnvs,
13+
BucketId, MegaContext, MegaSpecId, TestDatabaseWrapper, TestExternalEnvs,
1414
};
1515
use tracing::{debug, trace};
1616

1717
use super::{EvmeError, Result};
1818

19+
type ConfiguredRefDatabase<DB> = TestDatabaseWrapper<WrapDatabaseRef<DB>>;
20+
1921
/// Chain configuration arguments (spec and chain ID)
2022
#[derive(Args, Debug, Clone)]
2123
#[command(next_help_heading = "Chain Options")]
@@ -127,19 +129,20 @@ pub struct ExtEnvArgs {
127129
}
128130

129131
impl ExtEnvArgs {
130-
/// Creates [`TestExternalEnvs`] and returns bucket capacity configuration.
131-
pub fn create_external_envs(&self) -> Result<(TestExternalEnvs, Vec<(BucketId, u64)>)> {
132-
let external_envs = TestExternalEnvs::new();
132+
/// Parses CLI-provided bucket capacity overrides.
133+
pub fn bucket_capacities(&self) -> Result<Vec<(BucketId, u64)>> {
134+
self.bucket_capacity
135+
.iter()
136+
.map(|bucket_capacity| parse_bucket_capacity(bucket_capacity))
137+
.collect()
138+
}
133139

134-
// Parse bucket capacities
135-
let mut bucket_capacities = Vec::new();
136-
for bucket_capacity_str in &self.bucket_capacity {
137-
let (bucket_id, capacity) = parse_bucket_capacity(bucket_capacity_str)?;
138-
bucket_capacities.push((bucket_id, capacity));
139-
}
140-
debug!(external_envs = ?external_envs, bucket_capacities = ?bucket_capacities, "Evm TestExternalEnvs created");
140+
/// Creates [`TestExternalEnvs`].
141+
pub fn create_external_envs(&self) -> Result<TestExternalEnvs> {
142+
let external_envs = TestExternalEnvs::new();
143+
debug!(external_envs = ?external_envs, "Evm TestExternalEnvs created");
141144

142-
Ok((external_envs, bucket_capacities))
145+
Ok(external_envs)
143146
}
144147
}
145148

@@ -175,19 +178,26 @@ impl EnvArgs {
175178
self.block.create_block_env()
176179
}
177180

178-
/// Creates [`TestExternalEnvs`] and returns bucket capacity configuration.
179-
pub fn create_external_envs(&self) -> Result<(TestExternalEnvs, Vec<(BucketId, u64)>)> {
181+
/// Creates [`TestExternalEnvs`].
182+
pub fn create_external_envs(&self) -> Result<TestExternalEnvs> {
180183
self.ext.create_external_envs()
181184
}
182185

183186
/// Creates a [`MegaContext`] with all environment configurations.
184-
pub fn create_evm_context<DB: Database>(
187+
pub fn create_evm_context<DB>(
185188
&self,
186189
db: DB,
187-
) -> Result<MegaContext<DB, TestExternalEnvs>> {
190+
) -> Result<MegaContext<ConfiguredRefDatabase<DB>, TestExternalEnvs>>
191+
where
192+
DB: DatabaseRef,
193+
<DB as DatabaseRef>::Error: Send + Sync + 'static,
194+
{
188195
let cfg = self.create_cfg_env()?;
189196
let block = self.create_block_env()?;
190-
let (external_envs, _bucket_capacities) = self.create_external_envs()?;
197+
let external_envs = self.create_external_envs()?;
198+
let bucket_capacities = self.ext.bucket_capacities()?;
199+
let db = TestDatabaseWrapper::new(WrapDatabaseRef::from(db))
200+
.with_bucket_capacities(bucket_capacities);
191201

192202
Ok(MegaContext::new(db, cfg.spec)
193203
.with_cfg(cfg)
@@ -218,3 +228,25 @@ pub fn parse_bucket_capacity(s: &str) -> Result<(u32, u64)> {
218228
trace!(string = %s, bucket_id = %bucket_id, capacity = %capacity, "Parsed bucket capacity");
219229
Ok((bucket_id, capacity))
220230
}
231+
232+
#[cfg(test)]
233+
mod tests {
234+
use super::*;
235+
use mega_evm::{revm::Database as _, test_utils::MemoryDatabase, MIN_BUCKET_SIZE};
236+
237+
#[test]
238+
fn bucket_capacities_apply_to_wrapped_database() {
239+
let address = Address::repeat_byte(0x11);
240+
let bucket_id = TestDatabaseWrapper::<MemoryDatabase>::bucket_id_for_account(address);
241+
let capacity = MIN_BUCKET_SIZE as u64 * 4;
242+
let args = ExtEnvArgs { bucket_capacity: vec![format!("{bucket_id}:{capacity}")] };
243+
244+
let wrapped = TestDatabaseWrapper::new(MemoryDatabase::default())
245+
.with_bucket_capacities(args.bucket_capacities().unwrap());
246+
247+
assert_eq!(
248+
wrapped.salt_bucket_capacity(address, None).unwrap(),
249+
(bucket_id as usize, capacity)
250+
);
251+
}
252+
}

bin/mega-evme/src/common/trace.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use alloy_rpc_types_trace::geth::{
88
};
99
use clap::{Parser, ValueEnum};
1010
use mega_evm::{
11+
alloy_evm::Database as AlloyDatabase,
1112
revm::{
1213
context::{
1314
result::{ExecutionResult, ResultAndState},
@@ -22,7 +23,7 @@ use mega_evm::{
2223
use revm_inspectors::tracing::{TracingInspector, TracingInspectorConfig};
2324
use tracing::{debug, info, trace};
2425

25-
use super::{EvmeError, EvmeState};
26+
use super::EvmeError;
2627

2728
/// Tracer type for execution analysis
2829
#[derive(Debug, Clone, Copy, ValueEnum, Default)]
@@ -213,14 +214,13 @@ impl TraceArgs {
213214
}
214215

215216
/// Execute transaction with optional tracing
216-
pub fn execute_transaction<N, P>(
217+
pub fn execute_transaction<DB>(
217218
&self,
218-
evm_context: MegaContext<&mut EvmeState<N, P>, TestExternalEnvs>,
219+
evm_context: MegaContext<DB, TestExternalEnvs>,
219220
tx: MegaTransaction,
220221
) -> Result<(ExecutionResult<MegaHaltReason>, EvmState, Option<String>), EvmeError>
221222
where
222-
N: alloy_network::Network,
223-
P: alloy_provider::Provider<N> + std::fmt::Debug,
223+
DB: AlloyDatabase + DatabaseRef,
224224
{
225225
if self.is_tracing_enabled() {
226226
info!(tracer = ?self.tracer, "Evm executing with tracing");

bin/mega-evme/src/replay/cmd.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ use mega_evm::{
1111
revm::{
1212
context::{result::ExecutionResult, BlockEnv, ContextTr},
1313
context_interface::block::BlobExcessGasAndPrice,
14-
database::{states::bundle_state::BundleRetention, StateBuilder},
14+
database::{states::bundle_state::BundleRetention, StateBuilder, WrapDatabaseRef},
1515
DatabaseRef,
1616
},
1717
BlockLimits, EvmTxRuntimeLimits, MegaBlockExecutionCtx, MegaBlockExecutorFactory,
18-
MegaEvmFactory, MegaHardforks, MegaSpecId,
18+
MegaEvmFactory, MegaHardforks, MegaSpecId, TestDatabaseWrapper,
1919
};
2020
use tracing::{debug, info, trace, warn};
2121

@@ -226,7 +226,7 @@ impl Cmd {
226226
let transaction_index = preceding_transactions.len() as u64;
227227
debug!(transaction_index, "Setting up block executor");
228228

229-
let (external_env_factory, _bucket_capacities) = self.ext_args.create_external_envs()?;
229+
let external_env_factory = self.ext_args.create_external_envs()?;
230230
let evm_factory = MegaEvmFactory::new().with_external_env_factory(external_env_factory);
231231
let block_executor_factory = MegaBlockExecutorFactory::new(
232232
&hardforks,
@@ -263,6 +263,9 @@ impl Cmd {
263263
let mut inspector = self.trace_args.create_inspector();
264264

265265
// Create state and block executor with inspector
266+
let bucket_capacities = self.ext_args.bucket_capacities()?;
267+
let database = TestDatabaseWrapper::new(WrapDatabaseRef::from(&*database))
268+
.with_bucket_capacities(bucket_capacities);
266269
let mut state = StateBuilder::new().with_database(database).with_bundle_update().build();
267270
let mut block_executor = block_executor_factory.create_executor_with_inspector(
268271
&mut state,

bin/mega-evme/src/run/cmd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl Cmd {
9595
}
9696

9797
// Create EVM context and execute transaction
98-
let evm_context = self.env_args.create_evm_context(&mut state)?;
98+
let evm_context = self.env_args.create_evm_context(&state)?;
9999
let start = Instant::now();
100100
let (exec_result, evm_state, trace_data) =
101101
self.trace_args.execute_transaction(evm_context, tx)?;

bin/mega-evme/src/tx/cmd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl Cmd {
9292

9393
// Step 3: Execute transaction
9494
info!("Executing transaction");
95-
let evm_context = self.env_args.create_evm_context(&mut state)?;
95+
let evm_context = self.env_args.create_evm_context(&state)?;
9696
let start = Instant::now();
9797
let (exec_result, evm_state, trace_data) =
9898
self.trace_args.execute_transaction(evm_context, tx.clone())?;

crates/mega-evm/src/external/test_utils.rs

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,14 @@ const PLAIN_STORAGE_KEY_LEN: usize = PLAIN_ACCOUNT_KEY_LEN + SLOT_KEY_LEN;
141141
///
142142
/// This wrapper delegates all database operations to the inner database,
143143
/// but adds configurable bucket capacity tracking for testing dynamic gas costs.
144-
#[derive(Debug, Clone)]
144+
#[derive(derive_more::Debug, Clone)]
145145
pub struct TestDatabaseWrapper<DB> {
146146
/// The inner database implementation.
147+
#[debug(skip)]
147148
pub inner: DB,
148149
/// Bucket capacities. Maps bucket IDs to their capacity values.
149150
/// Buckets not in this map default to [`MIN_BUCKET_SIZE`](crate::MIN_BUCKET_SIZE).
151+
#[debug(skip)]
150152
bucket_capacity: Rc<RefCell<HashMap<BucketId, u64>>>,
151153
}
152154

@@ -170,7 +172,19 @@ impl<DB> TestDatabaseWrapper<DB> {
170172
///
171173
/// `self` for method chaining
172174
pub fn with_bucket_capacity(self, bucket_id: BucketId, capacity: u64) -> Self {
173-
self.bucket_capacity.borrow_mut().insert(bucket_id, capacity);
175+
self.with_bucket_capacities([(bucket_id, capacity)])
176+
}
177+
178+
/// Configures multiple bucket capacities at once.
179+
///
180+
/// # Returns
181+
///
182+
/// `self` for method chaining
183+
pub fn with_bucket_capacities(
184+
self,
185+
bucket_capacities: impl IntoIterator<Item = (BucketId, u64)>,
186+
) -> Self {
187+
self.bucket_capacity.borrow_mut().extend(bucket_capacities);
174188
self
175189
}
176190

@@ -234,3 +248,50 @@ impl<DB: revm::Database> revm::Database for TestDatabaseWrapper<DB> {
234248
Ok((bucket_id as usize, capacity))
235249
}
236250
}
251+
252+
impl<DB: revm::DatabaseRef> revm::DatabaseRef for TestDatabaseWrapper<DB> {
253+
type Error = DB::Error;
254+
255+
fn basic_ref(&self, address: Address) -> Result<Option<revm::state::AccountInfo>, Self::Error> {
256+
self.inner.basic_ref(address)
257+
}
258+
259+
fn code_by_hash_ref(&self, code_hash: B256) -> Result<revm::state::Bytecode, Self::Error> {
260+
self.inner.code_by_hash_ref(code_hash)
261+
}
262+
263+
fn storage_ref(&self, address: Address, index: U256) -> Result<U256, Self::Error> {
264+
self.inner.storage_ref(address, index)
265+
}
266+
267+
fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
268+
self.inner.block_hash_ref(number)
269+
}
270+
271+
fn salt_bucket_capacity_ref(
272+
&self,
273+
address: Address,
274+
index: Option<U256>,
275+
) -> Result<(usize, u64), Self::Error> {
276+
let bucket_id = if let Some(key) = index {
277+
Self::bucket_id_for_slot(address, key)
278+
} else {
279+
Self::bucket_id_for_account(address)
280+
};
281+
282+
let capacity = self
283+
.bucket_capacity
284+
.borrow()
285+
.get(&bucket_id)
286+
.copied()
287+
.unwrap_or(salt::constant::MIN_BUCKET_SIZE as u64);
288+
289+
Ok((bucket_id as usize, capacity))
290+
}
291+
}
292+
293+
impl<DB: revm::DatabaseCommit> revm::DatabaseCommit for TestDatabaseWrapper<DB> {
294+
fn commit(&mut self, changes: revm::primitives::HashMap<Address, revm::state::Account>) {
295+
self.inner.commit(changes);
296+
}
297+
}

0 commit comments

Comments
 (0)