11#[ cfg( test) ]
22mod tests;
33
4- use std:: iter:: Skip ;
5- use std:: vec:: IntoIter ;
6-
74use jsonrpsee:: core:: RpcResult ;
85use log:: error;
96use mc_rpc_core:: utils:: get_block_by_block_hash;
@@ -49,62 +46,49 @@ where
4946 StarknetRpcApiError :: BlockNotFound
5047 } ) ?;
5148
52- let block_extrinsics = self
53- . client
54- . block_body ( substrate_block_hash)
55- . map_err ( |e| {
56- error ! ( "Failed to retrieve block body. Substrate block hash: {substrate_block_hash}, error: {e}" ) ;
57- StarknetRpcApiError :: InternalServerError
58- } ) ?
59- . ok_or ( StarknetRpcApiError :: BlockNotFound ) ?;
60-
61- let chain_id = self . client . runtime_api ( ) . chain_id ( substrate_block_hash) . map_err ( |_| {
62- error ! ( "Failed to retrieve chain id" ) ;
63- StarknetRpcApiError :: InternalServerError
49+ let starknet_block = get_block_by_block_hash ( self . client . as_ref ( ) , substrate_block_hash) . map_err ( |e| {
50+ error ! ( "'{e}'" ) ;
51+ StarknetRpcApiError :: BlockNotFound
6452 } ) ?;
6553
66- let index_and_events =
67- self . client . runtime_api ( ) . get_starknet_events_and_their_associated_tx_index ( substrate_block_hash) . map_err (
68- |e| {
69- error ! (
70- "Failed to retrieve starknet events and their associated transaction index. Substrate block \
71- hash: {substrate_block_hash}, chain ID: {chain_id:?}, error: {e}"
72- ) ;
73- StarknetRpcApiError :: InternalServerError
74- } ,
75- ) ?;
54+ let block_hash = starknet_block. header ( ) . hash :: < H > ( ) ;
7655
77- let starknet_block = get_block_by_block_hash ( self . client . as_ref ( ) , substrate_block_hash) . map_err ( |e | {
78- error ! ( "Failed to retrieve starknet block from substrate block hash: error: {e} " ) ;
56+ let chain_id = self . client . runtime_api ( ) . chain_id ( substrate_block_hash) . map_err ( |_ | {
57+ error ! ( "Failed to retrieve chain id " ) ;
7958 StarknetRpcApiError :: InternalServerError
8059 } ) ?;
81- let txn_hashes = self . get_cached_transaction_hashes ( starknet_block. header ( ) . hash :: < H > ( ) . into ( ) ) ;
82- let block_extrinsics_len = block_extrinsics. len ( ) ;
83- let starknet_txs =
84- self . client . runtime_api ( ) . extrinsic_filter ( substrate_block_hash, block_extrinsics) . map_err ( |e| {
85- error ! ( "Failed to filter extrinsics. Substrate block hash: {substrate_block_hash}, error: {e}" ) ;
86- StarknetRpcApiError :: InternalServerError
87- } ) ?;
88- let inherent_count = block_extrinsics_len - starknet_txs. len ( ) ;
89- let mut tx_hash_and_events: Vec < ( Felt252Wrapper , starknet_api:: transaction:: Event ) > = vec ! [ ] ;
90- for ( index, event) in index_and_events {
91- let tx_index = index as usize - inherent_count;
92- let tx_hash = self . try_txn_hash_from_cache (
93- tx_index,
94- & txn_hashes,
95- & starknet_txs,
96- chain_id,
97- Some ( starknet_block. header ( ) . block_number ) ,
98- ) ?;
99- tx_hash_and_events. push ( ( tx_hash, event) ) ;
100- }
10160
102- let starknet_block = match get_block_by_block_hash ( self . client . as_ref ( ) , substrate_block_hash) {
103- Ok ( block) => block,
104- Err ( _) => return Err ( StarknetRpcApiError :: BlockNotFound ) ,
61+ // get txs hashes from cache or compute them
62+ let block_txs_hashes: Vec < _ > = if let Some ( tx_hashes) = self . get_cached_transaction_hashes ( block_hash. into ( ) ) {
63+ tx_hashes
64+ . into_iter ( )
65+ . map ( |h| {
66+ Felt252Wrapper :: try_from ( h)
67+ . map ( |f| f. 0 )
68+ . map_err ( |e| {
69+ error ! ( "'{e}'" ) ;
70+ StarknetRpcApiError :: InternalServerError
71+ } )
72+ . unwrap ( )
73+ } )
74+ . collect ( )
75+ } else {
76+ starknet_block
77+ . transactions_hashes :: < H > ( chain_id. into ( ) , Some ( starknet_block. header ( ) . block_number ) )
78+ . map ( FieldElement :: from)
79+ . collect ( )
10580 } ;
10681
107- let block_hash = starknet_block. header ( ) . hash :: < H > ( ) ;
82+ // get txs hashes and events from block
83+ // the txs hashes are found by the index of the ordered event
84+ let tx_hash_and_events: Vec < ( Felt252Wrapper , _ ) > = starknet_block
85+ . events ( )
86+ . into_iter ( )
87+ . flat_map ( |ordered_event| {
88+ let tx_hash = block_txs_hashes[ ordered_event. index ( ) as usize ] ;
89+ ordered_event. events ( ) . into_iter ( ) . map ( move |events| ( tx_hash. into ( ) , events. clone ( ) ) )
90+ } )
91+ . collect ( ) ;
10892
10993 let emitted_events = tx_hash_and_events
11094 . into_iter ( )
@@ -134,52 +118,43 @@ where
134118 // get filter values
135119 let continuation_token = filter. continuation_token ;
136120 // skip blocks with continuation token block number
137- let from_block = filter . from_block + continuation_token. block_n ;
121+ let from_block = continuation_token. block_n ;
138122 let mut current_block = from_block;
139123 let to_block = filter. to_block ;
140124 let from_address = filter. from_address ;
141125 let keys = filter. keys ;
142126 let chunk_size = filter. chunk_size ;
143127
144- let mut filtered_events = Vec :: new ( ) ;
128+ let mut filtered_events: Vec < EmittedEvent > = Vec :: new ( ) ;
145129
146130 // Iterate on block range
147131 while current_block <= to_block {
148132 let emitted_events = self . get_block_events ( current_block) ?;
149- let mut unchecked_events = emitted_events. len ( ) ;
150- let events = if current_block == from_block {
151- // check if continuation_token.event_n is not too big
152- if ( unchecked_events as u64 ) < continuation_token. event_n {
153- return Err ( StarknetRpcApiError :: InvalidContinuationToken . into ( ) ) ;
154- }
155- unchecked_events -= continuation_token. event_n as usize ;
156- emitted_events. into_iter ( ) . skip ( continuation_token. event_n as usize )
157- } else {
158- #[ allow( clippy:: iter_skip_zero) ]
159- emitted_events. into_iter ( ) . skip ( 0 )
160- } ;
161-
162- let mut n_visited = 0 ;
163- let block_filtered_events = filter_events_by_params (
164- events,
165- from_address,
166- & keys,
167- chunk_size as usize - filtered_events. len ( ) ,
168- & mut n_visited,
169- ) ;
170-
171- filtered_events. extend ( block_filtered_events) ;
133+
134+ let block_filtered_events: Vec < EmittedEvent > = filter_events_by_params ( emitted_events, from_address, & keys) ;
135+
136+ if current_block == from_block && ( block_filtered_events. len ( ) as u64 ) < continuation_token. event_n {
137+ return Err ( StarknetRpcApiError :: InvalidContinuationToken . into ( ) ) ;
138+ }
139+
140+ #[ allow( clippy:: iter_skip_zero) ]
141+ let block_filtered_reduced_events: Vec < EmittedEvent > = block_filtered_events
142+ . into_iter ( )
143+ . skip ( if current_block == from_block { continuation_token. event_n as usize } else { 0 } )
144+ . take ( chunk_size as usize - filtered_events. len ( ) )
145+ . collect ( ) ;
146+
147+ let num_events = block_filtered_reduced_events. len ( ) ;
148+
149+ filtered_events. extend ( block_filtered_reduced_events) ;
172150
173151 if filtered_events. len ( ) == chunk_size as usize {
174- let token = if current_block < to_block || n_visited < unchecked_events {
175- let mut event_n = n_visited as u64 ;
176- if continuation_token. block_n == current_block {
177- event_n += continuation_token. event_n ;
178- }
179- Some ( ContinuationToken { block_n : current_block - from_block, event_n } . to_string ( ) )
152+ let event_n = if current_block == from_block {
153+ continuation_token. event_n + chunk_size
180154 } else {
181- None
155+ num_events as u64
182156 } ;
157+ let token = Some ( ContinuationToken { block_n : current_block, event_n } . to_string ( ) ) ;
183158
184159 return Ok ( EventsPage { events : filtered_events, continuation_token : token } ) ;
185160 }
@@ -205,17 +180,14 @@ where
205180/// * `(block_events: Vec<EventWrapper>, continuation_token: usize)` - A tuple of the filtered
206181/// events and the first index which still hasn't been processed block_id and an instance of Block
207182pub fn filter_events_by_params < ' a , ' b : ' a > (
208- events : Skip < IntoIter < EmittedEvent > > ,
183+ events : Vec < EmittedEvent > ,
209184 address : Option < Felt252Wrapper > ,
210185 keys : & ' a [ Vec < FieldElement > ] ,
211- max_results : usize ,
212- n_visited : & ' b mut usize ,
213186) -> Vec < EmittedEvent > {
214187 let mut filtered_events = vec ! [ ] ;
215188
216189 // Iterate on block events.
217190 for event in events {
218- * n_visited += 1 ;
219191 let match_from_address = address. map_or ( true , |addr| addr. 0 == event. from_address ) ;
220192 // Based on https://github.com/starkware-libs/papyrus
221193 let match_keys = keys
@@ -225,9 +197,6 @@ pub fn filter_events_by_params<'a, 'b: 'a>(
225197
226198 if match_from_address && match_keys {
227199 filtered_events. push ( event) ;
228- if filtered_events. len ( ) >= max_results {
229- break ;
230- }
231200 }
232201 }
233202 filtered_events
0 commit comments