Skip to content

Commit 5a7d446

Browse files
greged93mattsseshekhirin
authored
feat: withdraw trie root slot (#312)
* feat: update execute_with_state_closure closure Signed-off-by: Gregory Edison <[email protected]> * feat: LoadWithdrawRoot Signed-off-by: Gregory Edison <[email protected]> * chore: fix clippy docs (paradigmxyz#17726) Co-authored-by: Alexey Shekhirin <[email protected]> * fix: clippy Signed-off-by: Gregory Edison <[email protected]> --------- Signed-off-by: Gregory Edison <[email protected]> Co-authored-by: Matthias Seitz <[email protected]> Co-authored-by: Alexey Shekhirin <[email protected]>
1 parent e204180 commit 5a7d446

File tree

11 files changed

+122
-8
lines changed

11 files changed

+122
-8
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/evm/evm/src/either.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ where
5858
state: F,
5959
) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
6060
where
61-
F: FnMut(&revm::database::State<DB>),
61+
F: FnMut(&mut revm::database::State<DB>),
6262
{
6363
match self {
6464
Self::Left(a) => a.execute_with_state_closure(block, state),

crates/evm/evm/src/execute.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,11 @@ pub trait Executor<DB: Database>: Sized {
100100
mut f: F,
101101
) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
102102
where
103-
F: FnMut(&State<DB>),
103+
F: FnMut(&mut State<DB>),
104104
{
105105
let result = self.execute_one(block)?;
106106
let mut state = self.into_state();
107-
f(&state);
107+
f(&mut state);
108108
Ok(BlockExecutionOutput { state: state.take_bundle(), result })
109109
}
110110

crates/ress/provider/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ where
154154
// invalid blocks.
155155
if let Err(error) = self.evm_config.batch_executor(&mut db).execute_with_state_closure(
156156
&block,
157-
|state: &State<_>| {
157+
|state: &mut State<_>| {
158158
record.record_executed_state(state);
159159
},
160160
) {

crates/rpc/rpc/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ alloy-serde.workspace = true
6464
revm = { workspace = true, features = ["optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee"] }
6565
revm-primitives = { workspace = true, features = ["serde"] }
6666

67+
# scroll
68+
reth-scroll-evm = { workspace = true, optional = true }
69+
6770
# rpc
6871
jsonrpsee.workspace = true
6972
http.workspace = true
@@ -104,3 +107,4 @@ jsonrpsee = { workspace = true, features = ["client"] }
104107

105108
[features]
106109
js-tracer = ["revm-inspectors/js-tracer", "reth-rpc-eth-types/js-tracer"]
110+
scroll = ["reth-scroll-evm"]

crates/rpc/rpc/src/debug.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,11 +640,18 @@ where
640640

641641
let mut witness_record = ExecutionWitnessRecord::default();
642642

643+
let mut withdraw_root_res: Result<_, reth_errors::ProviderError> = Ok(());
643644
let _ = block_executor
644-
.execute_with_state_closure(&(*block).clone(), |statedb: &State<_>| {
645+
.execute_with_state_closure(&(*block).clone(), |statedb: &mut State<_>| {
646+
#[cfg(feature = "scroll")]
647+
{
648+
use reth_scroll_evm::LoadWithdrawRoot;
649+
withdraw_root_res = statedb.load_withdraw_root();
650+
}
645651
witness_record.record_executed_state(statedb);
646652
})
647653
.map_err(|err| EthApiError::Internal(err.into()))?;
654+
withdraw_root_res?;
648655

649656
let ExecutionWitnessRecord { hashed_state, codes, keys, lowest_block_number } =
650657
witness_record;

crates/scroll/evm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ thiserror.workspace = true
4747
tracing.workspace = true
4848

4949
[dev-dependencies]
50-
alloy-primitives = { workspace = true, features = ["getrandom"] }
50+
alloy-primitives = { workspace = true, features = ["getrandom", "rand"] }
5151
eyre.workspace = true
5252

5353
[features]

crates/scroll/evm/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub use base_fee::{
2323
mod receipt;
2424
pub use receipt::ScrollRethReceiptBuilder;
2525

26+
mod withdraw_root;
27+
pub use withdraw_root::LoadWithdrawRoot;
28+
2629
use crate::build::ScrollBlockAssembler;
2730
use alloc::sync::Arc;
2831

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
use alloy_primitives::{address, Address, U256};
2+
use revm::{database::State, Database};
3+
4+
const L2_MESSAGE_QUEUE_ADDRESS: Address = address!("0x5300000000000000000000000000000000000000");
5+
const WITHDRAW_TRIE_ROOT_SLOT: U256 = U256::ZERO;
6+
7+
/// Instance that implements the trait can load the `L2MessageQueue` withdraw root in state.
8+
pub trait LoadWithdrawRoot<DB: Database> {
9+
/// Load the withdrawal root.
10+
fn load_withdraw_root(&mut self) -> Result<(), DB::Error>;
11+
}
12+
13+
impl<DB: Database> LoadWithdrawRoot<DB> for State<DB> {
14+
fn load_withdraw_root(&mut self) -> Result<(), DB::Error> {
15+
// we load the account in cache and query the storage slot. The storage slot will only be
16+
// loaded from database if it is not already know.
17+
self.load_cache_account(L2_MESSAGE_QUEUE_ADDRESS)?;
18+
let _ = revm::Database::storage(self, L2_MESSAGE_QUEUE_ADDRESS, WITHDRAW_TRIE_ROOT_SLOT);
19+
20+
Ok(())
21+
}
22+
}
23+
24+
#[cfg(test)]
25+
mod tests {
26+
use super::*;
27+
use std::{collections::HashMap, convert::Infallible};
28+
29+
use alloy_primitives::B256;
30+
use revm::{bytecode::Bytecode, state::AccountInfo};
31+
use revm_primitives::{StorageKey, StorageValue};
32+
33+
#[derive(Default)]
34+
struct InMemoryDb {
35+
pub accounts: HashMap<Address, AccountInfo>,
36+
pub storage: HashMap<(Address, U256), U256>,
37+
}
38+
39+
impl Database for InMemoryDb {
40+
type Error = Infallible;
41+
42+
fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
43+
Ok(self.accounts.get(&address).cloned())
44+
}
45+
46+
fn code_by_hash(&mut self, _code_hash: B256) -> Result<Bytecode, Self::Error> {
47+
Ok(Default::default())
48+
}
49+
50+
fn storage(
51+
&mut self,
52+
address: Address,
53+
index: StorageKey,
54+
) -> Result<StorageValue, Self::Error> {
55+
Ok(self.storage.get(&(address, index)).copied().unwrap_or_default())
56+
}
57+
58+
fn block_hash(&mut self, _number: u64) -> Result<B256, Self::Error> {
59+
Ok(Default::default())
60+
}
61+
}
62+
63+
#[test]
64+
fn test_should_load_withdraw_root() -> eyre::Result<()> {
65+
// init db
66+
let mut db = InMemoryDb::default();
67+
68+
// load L2 message queue contract
69+
let withdraw_root = U256::random();
70+
db.accounts.insert(L2_MESSAGE_QUEUE_ADDRESS, Default::default());
71+
db.storage.insert((L2_MESSAGE_QUEUE_ADDRESS, U256::ZERO), withdraw_root);
72+
73+
let mut state =
74+
State::builder().with_database(db).with_bundle_update().without_state_clear().build();
75+
76+
assert!(state
77+
.cache
78+
.accounts
79+
.get(&L2_MESSAGE_QUEUE_ADDRESS)
80+
.map(|acc| acc.storage_slot(WITHDRAW_TRIE_ROOT_SLOT))
81+
.is_none());
82+
83+
// load root
84+
state.load_withdraw_root()?;
85+
86+
assert_eq!(
87+
state
88+
.cache
89+
.accounts
90+
.get(&L2_MESSAGE_QUEUE_ADDRESS)
91+
.unwrap()
92+
.storage_slot(WITHDRAW_TRIE_ROOT_SLOT)
93+
.unwrap(),
94+
withdraw_root
95+
);
96+
97+
Ok(())
98+
}
99+
}

crates/scroll/rpc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ reth-rpc-eth-api = { workspace = true, features = ["scroll"] }
2121
reth-rpc-eth-types.workspace = true
2222
reth-tasks = { workspace = true, features = ["rayon"] }
2323
reth-transaction-pool.workspace = true
24-
reth-rpc.workspace = true
24+
reth-rpc = { workspace = true, features = ["scroll"] }
2525
reth-rpc-convert = { workspace = true, features = ["scroll"] }
2626
reth-node-api.workspace = true
2727
reth-node-builder.workspace = true

0 commit comments

Comments
 (0)