@@ -11,20 +11,18 @@ use reth_trie::{
11
11
prefix_set:: TriePrefixSetsMut , updates:: TrieUpdates , AccountProof , HashedPostState ,
12
12
HashedStorage ,
13
13
} ;
14
- use std:: collections:: HashMap ;
14
+ use std:: { collections:: HashMap , sync :: OnceLock } ;
15
15
16
16
/// A state provider that stores references to in-memory blocks along with their state as well as
17
17
/// the historical state provider for fallback lookups.
18
18
#[ allow( missing_debug_implementations) ]
19
19
pub struct MemoryOverlayStateProvider {
20
- /// The collection of executed parent blocks. Expected order is newest to oldest.
21
- pub ( crate ) in_memory : Vec < ExecutedBlock > ,
22
- /// The collection of hashed state from in-memory blocks.
23
- pub ( crate ) hashed_post_state : HashedPostState ,
24
- /// The collection of aggregated in-memory trie updates.
25
- pub ( crate ) trie_updates : TrieUpdates ,
26
20
/// Historical state provider for state lookups that are not found in in-memory blocks.
27
21
pub ( crate ) historical : Box < dyn StateProvider > ,
22
+ /// The collection of executed parent blocks. Expected order is newest to oldest.
23
+ pub ( crate ) in_memory : Vec < ExecutedBlock > ,
24
+ /// Lazy-loaded in-memory trie data.
25
+ pub ( crate ) trie_state : OnceLock < MemoryOverlayTrieState > ,
28
26
}
29
27
30
28
impl MemoryOverlayStateProvider {
@@ -35,20 +33,29 @@ impl MemoryOverlayStateProvider {
35
33
/// - `in_memory` - the collection of executed ancestor blocks in reverse.
36
34
/// - `historical` - a historical state provider for the latest ancestor block stored in the
37
35
/// database.
38
- pub fn new ( in_memory : Vec < ExecutedBlock > , historical : Box < dyn StateProvider > ) -> Self {
39
- let mut hashed_post_state = HashedPostState :: default ( ) ;
40
- let mut trie_updates = TrieUpdates :: default ( ) ;
41
- for block in in_memory. iter ( ) . rev ( ) {
42
- hashed_post_state. extend_ref ( block. hashed_state . as_ref ( ) ) ;
43
- trie_updates. extend_ref ( block. trie . as_ref ( ) ) ;
44
- }
45
- Self { in_memory, hashed_post_state, trie_updates, historical }
36
+ pub fn new ( historical : Box < dyn StateProvider > , in_memory : Vec < ExecutedBlock > ) -> Self {
37
+ Self { historical, in_memory, trie_state : OnceLock :: new ( ) }
46
38
}
47
39
48
40
/// Turn this state provider into a [`StateProviderBox`]
49
41
pub fn boxed ( self ) -> StateProviderBox {
50
42
Box :: new ( self )
51
43
}
44
+
45
+ /// Return lazy-loaded trie state aggregated from in-memory blocks.
46
+ fn trie_state ( & self ) -> MemoryOverlayTrieState {
47
+ self . trie_state
48
+ . get_or_init ( || {
49
+ let mut hashed_state = HashedPostState :: default ( ) ;
50
+ let mut trie_nodes = TrieUpdates :: default ( ) ;
51
+ for block in self . in_memory . iter ( ) . rev ( ) {
52
+ hashed_state. extend_ref ( block. hashed_state . as_ref ( ) ) ;
53
+ trie_nodes. extend_ref ( block. trie . as_ref ( ) ) ;
54
+ }
55
+ MemoryOverlayTrieState { trie_nodes, hashed_state }
56
+ } )
57
+ . clone ( )
58
+ }
52
59
}
53
60
54
61
impl BlockHashReader for MemoryOverlayStateProvider {
@@ -105,14 +112,13 @@ impl StateRootProvider for MemoryOverlayStateProvider {
105
112
fn hashed_state_root_from_nodes (
106
113
& self ,
107
114
nodes : TrieUpdates ,
108
- hashed_state : HashedPostState ,
115
+ state : HashedPostState ,
109
116
prefix_sets : TriePrefixSetsMut ,
110
117
) -> ProviderResult < B256 > {
111
- let mut trie_nodes = self . trie_updates . clone ( ) ;
118
+ let MemoryOverlayTrieState { mut trie_nodes, mut hashed_state } = self . trie_state ( ) ;
112
119
trie_nodes. extend ( nodes) ;
113
- let mut state = self . hashed_post_state . clone ( ) ;
114
- state. extend ( hashed_state) ;
115
- self . historical . hashed_state_root_from_nodes ( trie_nodes, state, prefix_sets)
120
+ hashed_state. extend ( state) ;
121
+ self . historical . hashed_state_root_from_nodes ( trie_nodes, hashed_state, prefix_sets)
116
122
}
117
123
118
124
fn hashed_state_root_with_updates (
@@ -130,14 +136,17 @@ impl StateRootProvider for MemoryOverlayStateProvider {
130
136
fn hashed_state_root_from_nodes_with_updates (
131
137
& self ,
132
138
nodes : TrieUpdates ,
133
- hashed_state : HashedPostState ,
139
+ state : HashedPostState ,
134
140
prefix_sets : TriePrefixSetsMut ,
135
141
) -> ProviderResult < ( B256 , TrieUpdates ) > {
136
- let mut trie_nodes = self . trie_updates . clone ( ) ;
142
+ let MemoryOverlayTrieState { mut trie_nodes, mut hashed_state } = self . trie_state ( ) ;
137
143
trie_nodes. extend ( nodes) ;
138
- let mut state = self . hashed_post_state . clone ( ) ;
139
- state. extend ( hashed_state) ;
140
- self . historical . hashed_state_root_from_nodes_with_updates ( trie_nodes, state, prefix_sets)
144
+ hashed_state. extend ( state) ;
145
+ self . historical . hashed_state_root_from_nodes_with_updates (
146
+ trie_nodes,
147
+ hashed_state,
148
+ prefix_sets,
149
+ )
141
150
}
142
151
143
152
// TODO: Currently this does not reuse available in-memory trie nodes.
@@ -153,13 +162,13 @@ impl StateRootProvider for MemoryOverlayStateProvider {
153
162
impl StateProofProvider for MemoryOverlayStateProvider {
154
163
fn hashed_proof (
155
164
& self ,
156
- hashed_state : HashedPostState ,
165
+ state : HashedPostState ,
157
166
address : Address ,
158
167
slots : & [ B256 ] ,
159
168
) -> ProviderResult < AccountProof > {
160
- let mut state = self . hashed_post_state . clone ( ) ;
161
- state . extend ( hashed_state ) ;
162
- self . historical . hashed_proof ( state , address, slots)
169
+ let MemoryOverlayTrieState { mut hashed_state , .. } = self . trie_state ( ) ;
170
+ hashed_state . extend ( state ) ;
171
+ self . historical . hashed_proof ( hashed_state , address, slots)
163
172
}
164
173
165
174
// TODO: Currently this does not reuse available in-memory trie nodes.
@@ -168,9 +177,9 @@ impl StateProofProvider for MemoryOverlayStateProvider {
168
177
overlay : HashedPostState ,
169
178
target : HashedPostState ,
170
179
) -> ProviderResult < HashMap < B256 , Bytes > > {
171
- let mut state = self . hashed_post_state . clone ( ) ;
172
- state . extend ( overlay) ;
173
- self . historical . witness ( state , target)
180
+ let MemoryOverlayTrieState { mut hashed_state , .. } = self . trie_state ( ) ;
181
+ hashed_state . extend ( overlay) ;
182
+ self . historical . witness ( hashed_state , target)
174
183
}
175
184
}
176
185
@@ -199,3 +208,12 @@ impl StateProvider for MemoryOverlayStateProvider {
199
208
self . historical . bytecode_by_hash ( code_hash)
200
209
}
201
210
}
211
+
212
+ /// The collection of data necessary for trie-related operations for [`MemoryOverlayStateProvider`].
213
+ #[ derive( Clone , Debug ) ]
214
+ pub ( crate ) struct MemoryOverlayTrieState {
215
+ /// The collection of aggregated in-memory trie updates.
216
+ pub ( crate ) trie_nodes : TrieUpdates ,
217
+ /// The collection of hashed state from in-memory blocks.
218
+ pub ( crate ) hashed_state : HashedPostState ,
219
+ }
0 commit comments