Skip to content

Commit

Permalink
chore: reduce number of Evm monomorphizations (paradigmxyz#8030)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes authored May 1, 2024
1 parent 399afd8 commit 0938504
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 106 deletions.
12 changes: 8 additions & 4 deletions crates/payload/builder/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,13 @@ impl CachedReads {
}
}

/// A [Database] that caches reads inside [CachedReads].
#[derive(Debug)]
struct CachedReadsDbMut<'a, DB> {
cached: &'a mut CachedReads,
db: DB,
pub struct CachedReadsDbMut<'a, DB> {
/// The cache of reads.
pub cached: &'a mut CachedReads,
/// The underlying database.
pub db: DB,
}

impl<'a, DB: DatabaseRef> Database for CachedReadsDbMut<'a, DB> {
Expand Down Expand Up @@ -126,7 +129,8 @@ impl<'a, DB: DatabaseRef> Database for CachedReadsDbMut<'a, DB> {
/// `revm::db::State` for repeated payload build jobs.
#[derive(Debug)]
pub struct CachedReadsDBRef<'a, DB> {
inner: RefCell<CachedReadsDbMut<'a, DB>>,
/// The inner cache reads db mut.
pub inner: RefCell<CachedReadsDbMut<'a, DB>>,
}

impl<'a, DB: DatabaseRef> DatabaseRef for CachedReadsDBRef<'a, DB> {
Expand Down
81 changes: 53 additions & 28 deletions crates/payload/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,47 +73,69 @@ where
debug!(target: "payload_builder", parent_hash = ?parent_block.hash(), parent_number = parent_block.number, "building empty payload");

let state = client.state_by_block_hash(parent_block.hash()).map_err(|err| {
warn!(target: "payload_builder", parent_hash=%parent_block.hash(), %err, "failed to get state for empty payload");
err
})?;
warn!(target: "payload_builder",
parent_hash=%parent_block.hash(),
%err,
"failed to get state for empty payload"
);
err
})?;
let mut db = State::builder()
.with_database_boxed(Box::new(StateProviderDatabase::new(&state)))
.with_database(StateProviderDatabase::new(state))
.with_bundle_update()
.build();

let base_fee = initialized_block_env.basefee.to::<u64>();
let block_number = initialized_block_env.number.to::<u64>();
let block_gas_limit: u64 = initialized_block_env.gas_limit.try_into().unwrap_or(u64::MAX);
let block_gas_limit = initialized_block_env.gas_limit.try_into().unwrap_or(u64::MAX);

// apply eip-4788 pre block contract call
pre_block_beacon_root_contract_call(
&mut db,
&chain_spec,
block_number,
&initialized_cfg,
&initialized_block_env,
&attributes,
).map_err(|err| {
warn!(target: "payload_builder", parent_hash=%parent_block.hash(), %err, "failed to apply beacon root contract call for empty payload");
err
})?;

let WithdrawalsOutcome { withdrawals_root, withdrawals } =
commit_withdrawals(&mut db, &chain_spec, attributes.timestamp, attributes.withdrawals.clone()).map_err(|err| {
warn!(target: "payload_builder", parent_hash=%parent_block.hash(), %err, "failed to commit withdrawals for empty payload");
err
})?;
&mut db,
&chain_spec,
block_number,
&initialized_cfg,
&initialized_block_env,
&attributes,
)
.map_err(|err| {
warn!(target: "payload_builder",
parent_hash=%parent_block.hash(),
%err,
"failed to apply beacon root contract call for empty payload"
);
err
})?;

let WithdrawalsOutcome { withdrawals_root, withdrawals } = commit_withdrawals(
&mut db,
&chain_spec,
attributes.timestamp,
attributes.withdrawals.clone(),
)
.map_err(|err| {
warn!(target: "payload_builder",
parent_hash=%parent_block.hash(),
%err,
"failed to commit withdrawals for empty payload"
);
err
})?;

// merge all transitions into bundle state, this would apply the withdrawal balance
// changes and 4788 contract call
db.merge_transitions(BundleRetention::PlainState);

// calculate the state root
let bundle_state = db.take_bundle();
let state_root = state.state_root(&bundle_state).map_err(|err| {
warn!(target: "payload_builder", parent_hash=%parent_block.hash(), %err, "failed to calculate state root for empty payload");
err
})?;
let state_root = db.database.state_root(&bundle_state).map_err(|err| {
warn!(target: "payload_builder",
parent_hash=%parent_block.hash(),
%err,
"failed to calculate state root for empty payload"
);
err
})?;

let mut excess_blob_gas = None;
let mut blob_gas_used = None;
Expand Down Expand Up @@ -178,9 +200,9 @@ where
let BuildArguments { client, pool, mut cached_reads, config, cancel, best_payload } = args;

let state_provider = client.state_by_block_hash(config.parent_block.hash())?;
let state = StateProviderDatabase::new(&state_provider);
let state = StateProviderDatabase::new(state_provider);
let mut db =
State::builder().with_database_ref(cached_reads.as_db(&state)).with_bundle_update().build();
State::builder().with_database_ref(cached_reads.as_db(state)).with_bundle_update().build();
let extra_data = config.extra_data();
let PayloadConfig {
initialized_block_env,
Expand Down Expand Up @@ -349,7 +371,10 @@ where
let logs_bloom = bundle.block_logs_bloom(block_number).expect("Number is in range");

// calculate the state root
let state_root = state_provider.state_root(bundle.state())?;
let state_root = {
let state_provider = db.database.0.inner.borrow_mut();
state_provider.db.state_root(bundle.state())?
};

// create the block header
let transactions_root = proofs::calculate_transaction_root(&executed_txs);
Expand Down
67 changes: 44 additions & 23 deletions crates/payload/optimism/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ where
err
})?;
let mut db = State::builder()
.with_database_boxed(Box::new(StateProviderDatabase::new(&state)))
.with_database(StateProviderDatabase::new(state))
.with_bundle_update()
.build();

Expand All @@ -133,33 +133,51 @@ where

// apply eip-4788 pre block contract call
pre_block_beacon_root_contract_call(
&mut db,
&chain_spec,
block_number,
&initialized_cfg,
&initialized_block_env,
&attributes,
).map_err(|err| {
warn!(target: "payload_builder", parent_hash=%parent_block.hash(), %err, "failed to apply beacon root contract call for empty payload");
err
})?;
&mut db,
&chain_spec,
block_number,
&initialized_cfg,
&initialized_block_env,
&attributes,
)
.map_err(|err| {
warn!(target: "payload_builder",
parent_hash=%parent_block.hash(),
%err,
"failed to apply beacon root contract call for empty payload"
);
err
})?;

let WithdrawalsOutcome { withdrawals_root, withdrawals } =
commit_withdrawals(&mut db, &chain_spec, attributes.payload_attributes.timestamp, attributes.payload_attributes.withdrawals.clone()).map_err(|err| {
warn!(target: "payload_builder", parent_hash=%parent_block.hash(), %err, "failed to commit withdrawals for empty payload");
err
})?;
let WithdrawalsOutcome { withdrawals_root, withdrawals } = commit_withdrawals(
&mut db,
&chain_spec,
attributes.payload_attributes.timestamp,
attributes.payload_attributes.withdrawals.clone(),
)
.map_err(|err| {
warn!(target: "payload_builder",
parent_hash=%parent_block.hash(),
%err,
"failed to commit withdrawals for empty payload"
);
err
})?;

// merge all transitions into bundle state, this would apply the withdrawal balance
// changes and 4788 contract call
db.merge_transitions(BundleRetention::PlainState);

// calculate the state root
let bundle_state = db.take_bundle();
let state_root = state.state_root(&bundle_state).map_err(|err| {
warn!(target: "payload_builder", parent_hash=%parent_block.hash(), %err, "failed to calculate state root for empty payload");
err
})?;
let state_root = db.database.state_root(&bundle_state).map_err(|err| {
warn!(target: "payload_builder",
parent_hash=%parent_block.hash(),
%err,
"failed to calculate state root for empty payload"
);
err
})?;

let mut excess_blob_gas = None;
let mut blob_gas_used = None;
Expand Down Expand Up @@ -236,9 +254,9 @@ where
let BuildArguments { client, pool, mut cached_reads, config, cancel, best_payload } = args;

let state_provider = client.state_by_block_hash(config.parent_block.hash())?;
let state = StateProviderDatabase::new(&state_provider);
let state = StateProviderDatabase::new(state_provider);
let mut db =
State::builder().with_database_ref(cached_reads.as_db(&state)).with_bundle_update().build();
State::builder().with_database_ref(cached_reads.as_db(state)).with_bundle_update().build();
let extra_data = config.extra_data();
let PayloadConfig {
initialized_block_env,
Expand Down Expand Up @@ -510,7 +528,10 @@ where
let logs_bloom = bundle.block_logs_bloom(block_number).expect("Number is in range");

// calculate the state root
let state_root = state_provider.state_root(bundle.state())?;
let state_root = {
let state_provider = db.database.0.inner.borrow_mut();
state_provider.db.state_root(bundle.state())?
};

// create the block header
let transactions_root = proofs::calculate_transaction_root(&executed_txs);
Expand Down
36 changes: 12 additions & 24 deletions crates/rpc/rpc/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,14 +323,11 @@ where
self.inner
.eth_api
.spawn_with_call_at(call, at, overrides, move |db, env| {
let (res, _, db) = this.eth_api().inspect_and_return_db(
db,
env,
&mut inspector,
)?;
let (res, _) =
this.eth_api().inspect(&mut *db, env, &mut inspector)?;
let frame = inspector
.into_geth_builder()
.geth_prestate_traces(&res, prestate_config, &db)?;
.geth_prestate_traces(&res, prestate_config, db)?;
Ok(frame)
})
.await?;
Expand All @@ -348,12 +345,9 @@ where
.inner
.eth_api
.spawn_with_call_at(call, at, overrides, move |db, env| {
let (res, _, db) = this.eth_api().inspect_and_return_db(
db,
env,
&mut inspector,
)?;
let frame = inspector.try_into_mux_frame(&res, &db)?;
let (res, _) =
this.eth_api().inspect(&mut *db, env, &mut inspector)?;
let frame = inspector.try_into_mux_frame(&res, db)?;
Ok(frame.into())
})
.await?;
Expand All @@ -370,12 +364,9 @@ where
.eth_api
.spawn_with_call_at(call, at, overrides, move |db, env| {
let mut inspector = JsInspector::new(code, config)?;
let (res, _, db) = this.eth_api().inspect_and_return_db(
db,
env.clone(),
&mut inspector,
)?;
Ok(inspector.json_result(res, &env, &db)?)
let (res, _) =
this.eth_api().inspect(&mut *db, env.clone(), &mut inspector)?;
Ok(inspector.json_result(res, &env, db)?)
})
.await?;

Expand Down Expand Up @@ -564,8 +555,7 @@ where
let mut inspector = TracingInspector::new(
TracingInspectorConfig::from_geth_prestate_config(&prestate_config),
);
let (res, _, db) =
self.eth_api().inspect_and_return_db(db, env, &mut inspector)?;
let (res, _) = self.eth_api().inspect(&mut *db, env, &mut inspector)?;

let frame = inspector.into_geth_builder().geth_prestate_traces(
&res,
Expand All @@ -585,8 +575,7 @@ where

let mut inspector = MuxInspector::try_from_config(mux_config)?;

let (res, _, db) =
self.eth_api().inspect_and_return_db(db, env, &mut inspector)?;
let (res, _) = self.eth_api().inspect(&mut *db, env, &mut inspector)?;
let frame = inspector.try_into_mux_frame(&res, db)?;
return Ok((frame.into(), res.state))
}
Expand All @@ -598,8 +587,7 @@ where
config,
transaction_context.unwrap_or_default(),
)?;
let (res, env, db) =
self.eth_api().inspect_and_return_db(db, env, &mut inspector)?;
let (res, env) = self.eth_api().inspect(&mut *db, env, &mut inspector)?;

let state = res.state.clone();
let result = inspector.json_result(res, &env, db)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/rpc/rpc/src/eth/api/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,14 +451,14 @@ where
&self,
env_gas_limit: U256,
mut env: EnvWithHandlerCfg,
mut db: &mut CacheDB<StateProviderDatabase<S>>,
db: &mut CacheDB<StateProviderDatabase<S>>,
) -> EthApiError
where
S: StateProvider,
{
let req_gas_limit = env.tx.gas_limit;
env.tx.gas_limit = env_gas_limit.try_into().unwrap_or(u64::MAX);
let (res, _) = match self.transact(&mut db, env) {
let (res, _) = match self.transact(db, env) {
Ok(res) => res,
Err(err) => return err,
};
Expand Down
5 changes: 3 additions & 2 deletions crates/rpc/rpc/src/eth/api/pending_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl PendingBlockEnv {

let parent_hash = origin.build_target_hash();
let state_provider = client.history_by_block_hash(parent_hash)?;
let state = StateProviderDatabase::new(&state_provider);
let mut db = State::builder().with_database(Box::new(state)).with_bundle_update().build();
let state = StateProviderDatabase::new(state_provider);
let mut db = State::builder().with_database(state).with_bundle_update().build();

let mut cumulative_gas_used = 0;
let mut sum_blob_gas_used = 0;
Expand Down Expand Up @@ -230,6 +230,7 @@ impl PendingBlockEnv {
let logs_bloom = bundle.block_logs_bloom(block_number).expect("Block is present");

// calculate the state root
let state_provider = &db.database;
let state_root = state_provider.state_root(bundle.state())?;

// create the block header
Expand Down
Loading

0 comments on commit 0938504

Please sign in to comment.