-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathmemory_overlay.rs
134 lines (119 loc) · 4.71 KB
/
memory_overlay.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use super::ExecutedBlock;
use reth_errors::ProviderResult;
use reth_primitives::{Account, Address, BlockNumber, Bytecode, StorageKey, StorageValue, B256};
use reth_storage_api::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider,
};
use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState};
/// A state provider that stores references to in-memory blocks along with their state as well as
/// the historical state provider for fallback lookups.
#[allow(missing_debug_implementations)]
pub struct MemoryOverlayStateProvider {
/// The collection of executed parent blocks.
in_memory: Vec<ExecutedBlock>,
/// The collection of hashed state from in-memory blocks.
hashed_post_state: HashedPostState,
/// Historical state provider for state lookups that are not found in in-memory blocks.
historical: Box<dyn StateProvider>,
}
impl MemoryOverlayStateProvider {
/// Create new memory overlay state provider.
pub fn new(in_memory: Vec<ExecutedBlock>, historical: Box<dyn StateProvider>) -> Self {
let mut hashed_post_state = HashedPostState::default();
for block in &in_memory {
hashed_post_state.extend(block.hashed_state.as_ref().clone());
}
Self { in_memory, hashed_post_state, historical }
}
}
impl BlockHashReader for MemoryOverlayStateProvider {
fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>> {
for block in self.in_memory.iter().rev() {
if block.block.number == number {
return Ok(Some(block.block.hash()))
}
}
self.historical.block_hash(number)
}
fn canonical_hashes_range(
&self,
start: BlockNumber,
end: BlockNumber,
) -> ProviderResult<Vec<B256>> {
let range = start..end;
let mut earliest_block_number = None;
let mut in_memory_hashes = Vec::new();
for block in self.in_memory.iter().rev() {
if range.contains(&block.block.number) {
in_memory_hashes.insert(0, block.block.hash());
earliest_block_number = Some(block.block.number);
}
}
let mut hashes =
self.historical.canonical_hashes_range(start, earliest_block_number.unwrap_or(end))?;
hashes.append(&mut in_memory_hashes);
Ok(hashes)
}
}
impl AccountReader for MemoryOverlayStateProvider {
fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
for block in self.in_memory.iter().rev() {
if let Some(account) = block.execution_output.account(&address) {
return Ok(account)
}
}
self.historical.basic_account(address)
}
}
impl StateRootProvider for MemoryOverlayStateProvider {
// TODO: Currently this does not reuse available in-memory trie nodes.
fn hashed_state_root(&self, hashed_state: &HashedPostState) -> ProviderResult<B256> {
let mut state = self.hashed_post_state.clone();
state.extend(hashed_state.clone());
self.historical.hashed_state_root(&state)
}
// TODO: Currently this does not reuse available in-memory trie nodes.
fn hashed_state_root_with_updates(
&self,
hashed_state: &HashedPostState,
) -> ProviderResult<(B256, TrieUpdates)> {
let mut state = self.hashed_post_state.clone();
state.extend(hashed_state.clone());
self.historical.hashed_state_root_with_updates(&state)
}
}
impl StateProofProvider for MemoryOverlayStateProvider {
// TODO: Currently this does not reuse available in-memory trie nodes.
fn hashed_proof(
&self,
hashed_state: &HashedPostState,
address: Address,
slots: &[B256],
) -> ProviderResult<AccountProof> {
let mut state = self.hashed_post_state.clone();
state.extend(hashed_state.clone());
self.historical.hashed_proof(&state, address, slots)
}
}
impl StateProvider for MemoryOverlayStateProvider {
fn storage(
&self,
address: Address,
storage_key: StorageKey,
) -> ProviderResult<Option<StorageValue>> {
for block in self.in_memory.iter().rev() {
if let Some(value) = block.execution_output.storage(&address, storage_key.into()) {
return Ok(Some(value))
}
}
self.historical.storage(address, storage_key)
}
fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult<Option<Bytecode>> {
for block in self.in_memory.iter().rev() {
if let Some(contract) = block.execution_output.bytecode(&code_hash) {
return Ok(Some(contract))
}
}
self.historical.bytecode_by_hash(code_hash)
}
}