Skip to content

Commit 43eb7c2

Browse files
committed
fix: relax &mut bound
1 parent b8e319f commit 43eb7c2

7 files changed

Lines changed: 352 additions & 230 deletions

File tree

crates/storage/src/hot/db/inconsistent.rs

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ use alloy::primitives::{Address, B256, U256};
33
use reth::primitives::{Account, Bytecode, Header, SealedHeader};
44
use reth_db::{BlockNumberList, models::BlockNumberAddress};
55
use reth_db_api::models::ShardedKey;
6+
use trevm::revm::{
7+
database::states::{PlainStateReverts, PlainStorageRevert},
8+
state::AccountInfo,
9+
};
610

711
/// Trait for database write operations on standard hot tables.
812
///
@@ -13,54 +17,45 @@ pub trait UnsafeDbWrite: HotKvWrite + super::sealed::Sealed {
1317
/// Write a block header. This will leave the DB in an inconsistent state
1418
/// until the corresponding header number is also written. Users should
1519
/// prefer [`Self::put_header`] instead.
16-
fn put_header_inconsistent(&mut self, header: &Header) -> Result<(), Self::Error> {
20+
fn put_header_inconsistent(&self, header: &Header) -> Result<(), Self::Error> {
1721
self.queue_put::<tables::Headers>(&header.number, header)
1822
}
1923

2024
/// Write a block number by its hash. This will leave the DB in an
2125
/// inconsistent state until the corresponding header is also written.
2226
/// Users should prefer [`Self::put_header`] instead.
23-
fn put_header_number_inconsistent(
24-
&mut self,
25-
hash: &B256,
26-
number: u64,
27-
) -> Result<(), Self::Error> {
27+
fn put_header_number_inconsistent(&self, hash: &B256, number: u64) -> Result<(), Self::Error> {
2828
self.queue_put::<tables::HeaderNumbers>(hash, &number)
2929
}
3030

3131
/// Write contract Bytecode by its hash.
32-
fn put_bytecode(&mut self, code_hash: &B256, bytecode: &Bytecode) -> Result<(), Self::Error> {
32+
fn put_bytecode(&self, code_hash: &B256, bytecode: &Bytecode) -> Result<(), Self::Error> {
3333
self.queue_put::<tables::Bytecodes>(code_hash, bytecode)
3434
}
3535

3636
/// Write an account by its address.
37-
fn put_account(&mut self, address: &Address, account: &Account) -> Result<(), Self::Error> {
37+
fn put_account(&self, address: &Address, account: &Account) -> Result<(), Self::Error> {
3838
self.queue_put::<tables::PlainAccountState>(address, account)
3939
}
4040

4141
/// Write a storage entry by its address and key.
42-
fn put_storage(
43-
&mut self,
44-
address: &Address,
45-
key: &B256,
46-
entry: &U256,
47-
) -> Result<(), Self::Error> {
42+
fn put_storage(&self, address: &Address, key: &B256, entry: &U256) -> Result<(), Self::Error> {
4843
self.queue_put_dual::<tables::PlainStorageState>(address, key, entry)
4944
}
5045

5146
/// Write a sealed block header (header + number).
52-
fn put_header(&mut self, header: &SealedHeader) -> Result<(), Self::Error> {
47+
fn put_header(&self, header: &SealedHeader) -> Result<(), Self::Error> {
5348
self.put_header_inconsistent(header.header())
5449
.and_then(|_| self.put_header_number_inconsistent(&header.hash(), header.number))
5550
}
5651

5752
/// Delete a header by block number.
58-
fn delete_header(&mut self, number: u64) -> Result<(), Self::Error> {
53+
fn delete_header(&self, number: u64) -> Result<(), Self::Error> {
5954
self.queue_delete::<tables::Headers>(&number)
6055
}
6156

6257
/// Delete a header number mapping by hash.
63-
fn delete_header_number(&mut self, hash: &B256) -> Result<(), Self::Error> {
58+
fn delete_header_number(&self, hash: &B256) -> Result<(), Self::Error> {
6459
self.queue_delete::<tables::HeaderNumbers>(hash)
6560
}
6661

@@ -85,7 +80,7 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HotHistoryRead {
8580
///
8681
/// Accounts are keyed
8782
fn write_account_history(
88-
&mut self,
83+
&self,
8984
address: &Address,
9085
latest_height: u64,
9186
touched: &BlockNumberList,
@@ -96,7 +91,7 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HotHistoryRead {
9691
/// Write an account change (pre-state) for an account at a specific
9792
/// block.
9893
fn write_account_prestate(
99-
&mut self,
94+
&self,
10095
block_number: u64,
10196
address: Address,
10297
pre_state: &Account,
@@ -107,7 +102,7 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HotHistoryRead {
107102
/// Write storage history, by highest block number and touched block
108103
/// numbers.
109104
fn write_storage_history(
110-
&mut self,
105+
&self,
111106
address: &Address,
112107
slot: B256,
113108
highest_block_number: u64,
@@ -120,7 +115,7 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HotHistoryRead {
120115
/// Write a storage change (before state) for an account at a specific
121116
/// block.
122117
fn write_storage_prestate(
123-
&mut self,
118+
&self,
124119
block_number: u64,
125120
address: Address,
126121
slot: &B256,
@@ -129,6 +124,83 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HotHistoryRead {
129124
let block_number_address = BlockNumberAddress((block_number, address));
130125
self.queue_put_dual::<tables::StorageChangeSets>(&block_number_address, slot, prestate)
131126
}
127+
128+
/// Write a pre-state for every storage key that exists for an account at a
129+
/// specific block.
130+
fn write_wipe(&self, block_number: u64, address: &Address) -> Result<(), Self::Error> {
131+
// SAFETY: the cursor is scoped to the transaction lifetime, which is
132+
// valid for the duration of this method.
133+
let mut cursor = self.traverse_dual::<tables::PlainStorageState>()?;
134+
135+
let Some(start) = cursor.next_dual_above(address, &B256::ZERO)? else {
136+
// No storage entries at or above this address
137+
return Ok(());
138+
};
139+
140+
if start.0 != *address {
141+
// No storage entries for this address
142+
return Ok(());
143+
}
144+
145+
self.write_storage_prestate(block_number, *address, &start.1, &start.2)?;
146+
147+
while let Some((k, k2, v)) = cursor.next_k2()? {
148+
if k != *address {
149+
break;
150+
}
151+
152+
self.write_storage_prestate(block_number, *address, &k2, &v)?;
153+
}
154+
155+
Ok(())
156+
}
157+
158+
/// Write a block's plain state revert information.
159+
fn write_plain_revert(
160+
&self,
161+
block_number: u64,
162+
accounts: &[(Address, Option<AccountInfo>)],
163+
storage: &[PlainStorageRevert],
164+
) -> Result<(), Self::Error> {
165+
for (address, info) in accounts {
166+
let account = info.as_ref().map(Account::from).unwrap_or_default();
167+
168+
if let Some(bytecode) = info.as_ref().and_then(|info| info.code.clone()) {
169+
let code_hash = account.bytecode_hash.expect("info has bytecode; hash must exist");
170+
let bytecode = Bytecode(bytecode);
171+
self.put_bytecode(&code_hash, &bytecode)?;
172+
}
173+
174+
self.write_account_prestate(block_number, *address, &account)?;
175+
}
176+
177+
for entry in storage {
178+
if entry.wiped {
179+
return self.write_wipe(block_number, &entry.address);
180+
}
181+
for (key, old_value) in entry.storage_revert.iter() {
182+
self.write_storage_prestate(
183+
block_number,
184+
entry.address,
185+
&B256::from(key.to_be_bytes()),
186+
&old_value.to_previous_value(),
187+
)?;
188+
}
189+
}
190+
191+
Ok(())
192+
}
193+
194+
/// Write multiple blocks' plain state revert information.
195+
fn write_plain_reverts(
196+
&self,
197+
first_block_number: u64,
198+
PlainStateReverts { accounts, storage }: &PlainStateReverts,
199+
) -> Result<(), Self::Error> {
200+
accounts.iter().zip(storage.iter()).enumerate().try_for_each(|(idx, (acc, sto))| {
201+
self.write_plain_revert(first_block_number + idx as u64, acc, sto)
202+
})
203+
}
132204
}
133205

134206
impl<T> UnsafeHistoryWrite for T where T: UnsafeDbWrite + HotKvWrite {}

crates/storage/src/hot/db/mod.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
//! Primary access for hot storage backends.
2-
//!
3-
//!
4-
//!
1+
//! Primary access traits for hot storage backends.
52
63
mod consistent;
74
pub use consistent::HistoryWrite;
@@ -18,7 +15,7 @@ pub use read::{HotDbRead, HotHistoryRead};
1815
pub(crate) mod sealed {
1916
use crate::hot::model::HotKvRead;
2017

21-
/// Sealed trait to prevent external implementations of HotDbReader and HotDbWriter.
18+
/// Sealed trait to prevent external implementations of hot database traits.
2219
#[allow(dead_code, unreachable_pub)]
2320
pub trait Sealed {}
2421
impl<T> Sealed for T where T: HotKvRead {}

0 commit comments

Comments
 (0)