@@ -4,7 +4,7 @@ use alloy::{
44 eips:: BlockId ,
55 network:: { primitives:: HeaderResponse , BlockResponse } ,
66 primitives:: { Address , B256 } ,
7- rpc:: types:: { EIP1186AccountProofResponse , Filter , Log } ,
7+ rpc:: types:: { Filter , Log } ,
88} ;
99use async_trait:: async_trait;
1010use eyre:: { eyre, Result } ;
@@ -56,95 +56,64 @@ where
5656 block_id : BlockId ,
5757 ) -> Result < Account > {
5858 let block_hash = match block_id {
59- BlockId :: Hash ( hash) => {
60- let hash: B256 = hash. into ( ) ;
61- hash
62- }
63- block_id => {
64- let block = self
65- . inner
66- . get_block ( block_id, false )
67- . await ?
68- . ok_or ( eyre ! ( "block not found" ) ) ?;
69- block. header ( ) . hash ( )
70- }
59+ BlockId :: Hash ( hash) => hash. into ( ) ,
60+ _ => self
61+ . inner
62+ . get_block ( block_id, false )
63+ . await ?
64+ . ok_or_else ( || eyre ! ( "block not found" ) ) ?
65+ . header ( )
66+ . hash ( ) ,
7167 } ;
7268
73- let slots_left_to_fetch = match self . cache . get_account ( address, slots, block_hash) {
74- Some ( ( cached, missing_slots) ) => {
75- if missing_slots. is_empty ( ) {
76- if with_code && cached. code . is_none ( ) {
77- // All account data is cached, but code is missing - fetch code directly
78- let expected = cached. account . code_hash ;
79- let acc_with_code = self
69+ let cached = self . cache . get_account ( address, slots, block_hash) ;
70+
71+ match cached {
72+ None => {
73+ if with_code {
74+ if let Some ( ( cached_code_hash, cached_code) ) =
75+ self . cache . get_code_optimistically ( address)
76+ {
77+ let fetched = self
8078 . inner
81- . get_account ( address, & [ ] , true , block_hash. into ( ) )
79+ . get_account ( address, slots , false , block_hash. into ( ) )
8280 . await ?;
83- let code = acc_with_code
84- . code
85- . ok_or_else ( || eyre ! ( "provider did not return code" ) ) ? ;
86- if acc_with_code . account . code_hash != expected {
87- return Err ( eyre ! ( "code_hash changed while fetching code" ) ) ;
81+ if fetched . account . code_hash == cached_code_hash {
82+ let mut account = fetched ;
83+ account . code = Some ( cached_code ) ;
84+ self . cache . insert_account ( address , & account , block_hash ) ;
85+ return Ok ( account ) ;
8886 }
89- self . cache . insert_code ( expected, code. clone ( ) ) ;
90- return Ok ( Account {
91- code : Some ( code) ,
92- ..cached
93- } ) ;
9487 }
95- return Ok ( cached) ;
9688 }
97- missing_slots
89+ let fetched = self
90+ . inner
91+ . get_account ( address, slots, with_code, block_hash. into ( ) )
92+ . await ?;
93+ self . cache . insert_account ( address, & fetched, block_hash) ;
94+ Ok ( fetched)
9895 }
99- None => slots. to_vec ( ) ,
100- } ;
101-
102- // Always fetch account proof without full code because it might be already in cache
103- let account = self
104- . inner
105- . get_account ( address, & slots_left_to_fetch, false , block_hash. into ( ) )
106- . await ?;
107-
108- let response = EIP1186AccountProofResponse {
109- address,
110- balance : account. account . balance ,
111- code_hash : account. account . code_hash ,
112- nonce : account. account . nonce ,
113- storage_hash : account. account . storage_root ,
114- account_proof : account. account_proof . clone ( ) ,
115- storage_proof : account. storage_proof . clone ( ) ,
116- } ;
117-
118- self . cache . insert ( response, None , block_hash) ;
119-
120- // Retrieve from cache again to get the full merged result
121- let ( mut full_account, missing_after) = self
122- . cache
123- . get_account ( address, slots, block_hash)
124- . ok_or ( eyre ! ( "Cache inconsistency after write" ) ) ?;
125-
126- if !missing_after. is_empty ( ) {
127- return Err ( eyre ! ( "Failed to fetch all slots" ) ) ;
128- }
96+ Some ( ( mut account, missing_slots) ) => {
97+ let need_code = with_code && account. code . is_none ( ) ;
98+
99+ if !missing_slots. is_empty ( ) || need_code {
100+ let fetched = self
101+ . inner
102+ . get_account ( address, & missing_slots, need_code, block_hash. into ( ) )
103+ . await ?;
104+ self . cache . insert_account ( address, & fetched, block_hash) ;
105+
106+ account. account = fetched. account ;
107+ account. account_proof = fetched. account_proof ;
108+ account. storage_proof . extend ( fetched. storage_proof ) ;
109+ if let Some ( code) = fetched. code {
110+ account. code = Some ( code) ;
111+ }
112+ }
129113
130- // If code is still missing, fetch via get_account with with_code=true
131- if with_code && full_account. code . is_none ( ) {
132- let expected = full_account. account . code_hash ;
133- let acc_with_code = self
134- . inner
135- . get_account ( address, & [ ] , true , block_hash. into ( ) )
136- . await ?;
137- let code = acc_with_code
138- . code
139- . ok_or_else ( || eyre ! ( "provider did not return code" ) ) ?;
140- if acc_with_code. account . code_hash != expected {
141- return Err ( eyre ! ( "code_hash changed while fetching code" ) ) ;
114+ Ok ( account)
142115 }
143- self . cache . insert_code ( expected, code. clone ( ) ) ;
144- full_account. code = Some ( code) ;
145116 }
146-
147- Ok ( full_account)
148117 }
149118}
150119
0 commit comments