1
1
use std:: thread;
2
2
3
- use anyhow:: anyhow;
3
+ use anyhow:: { anyhow, Context as AnyhowContext } ;
4
4
use futures:: StreamExt ;
5
5
use reqwest_eventsource:: Event ;
6
6
use tokio:: { sync:: mpsc, task:: JoinHandle } ;
@@ -9,7 +9,7 @@ use tracing::{debug, error, info};
9
9
use crate :: {
10
10
args:: Args ,
11
11
clients:: {
12
- beacon:: types:: { BlockId , HeadBlockEventData , Topic } ,
12
+ beacon:: types:: { BlockId , FinalizedCheckpointEventData , HeadBlockEventData , Topic } ,
13
13
blobscan:: types:: BlockchainSyncState ,
14
14
} ,
15
15
context:: { Config as ContextConfig , Context } ,
@@ -150,38 +150,77 @@ impl Indexer {
150
150
151
151
tokio:: spawn ( async move {
152
152
let result: Result < ( ) , IndexerError > = async {
153
+ let beacon_client = task_context. beacon_client ( ) ;
153
154
let blobscan_client = task_context. blobscan_client ( ) ;
154
155
let mut event_source = task_context
155
156
. beacon_client ( )
156
- . subscribe_to_events ( vec ! [ Topic :: Head ] ) ?;
157
+ . subscribe_to_events ( vec ! [ Topic :: Head , Topic :: FinalizedCheckpoint ] ) ?;
157
158
let mut is_initial_sync_to_head = true ;
158
159
159
160
while let Some ( event) = event_source. next ( ) . await {
160
161
match event {
161
162
Ok ( Event :: Open ) => {
162
- debug ! ( target = "indexer" , "Listening for head block events…" )
163
+ debug ! ( target = "indexer" , "Listening for head and finalized block events…" )
163
164
}
164
165
Ok ( Event :: Message ( event) ) => {
165
- let head_block_data =
166
- serde_json:: from_str :: < HeadBlockEventData > ( & event. data ) ?;
167
-
168
- let head_block_id = & BlockId :: Slot ( head_block_data. slot ) ;
169
- let initial_block_id = if is_initial_sync_to_head {
170
- is_initial_sync_to_head = false ;
171
- & start_block_id
172
- } else {
173
- head_block_id
174
- } ;
175
-
176
- synchronizer. run ( initial_block_id, head_block_id) . await ?;
177
-
178
- blobscan_client
179
- . update_sync_state ( BlockchainSyncState {
180
- last_lower_synced_slot : None ,
181
- last_upper_synced_slot : Some ( head_block_data. slot ) ,
182
- } )
183
- . await ?;
184
- }
166
+ match event. event . as_str ( ) {
167
+ "head" => {
168
+ let head_block_data =
169
+ serde_json:: from_str :: < HeadBlockEventData > ( & event. data ) ?;
170
+
171
+ let head_block_id = & BlockId :: Slot ( head_block_data. slot ) ;
172
+ let initial_block_id = if is_initial_sync_to_head {
173
+ is_initial_sync_to_head = false ;
174
+ & start_block_id
175
+ } else {
176
+ head_block_id
177
+ } ;
178
+
179
+ synchronizer. run ( initial_block_id, head_block_id) . await ?;
180
+
181
+ blobscan_client
182
+ . update_sync_state ( BlockchainSyncState {
183
+ last_finalized_block : None ,
184
+ last_lower_synced_slot : None ,
185
+ last_upper_synced_slot : Some ( head_block_data. slot ) ,
186
+ } )
187
+ . await ?;
188
+ }
189
+ "finalized_checkpoint" => {
190
+ let finalized_checkpoint_data =
191
+ serde_json:: from_str :: < FinalizedCheckpointEventData > (
192
+ & event. data ,
193
+ ) ?;
194
+ let block_hash = finalized_checkpoint_data. block ;
195
+ let full_block_hash = format ! ( "0x{:x}" , block_hash) ;
196
+ let last_finalized_block_number = beacon_client
197
+ . get_block ( & BlockId :: Hash ( block_hash) )
198
+ . await ?
199
+ . with_context ( || {
200
+ anyhow ! ( "Finalized block with hash {full_block_hash} not found" )
201
+ } ) ?
202
+ . message . body . execution_payload
203
+ . with_context ( || {
204
+ anyhow ! ( "Finalized block with hash {full_block_hash} has no execution payload" )
205
+ } ) ?. block_number ;
206
+
207
+ blobscan_client
208
+ . update_sync_state ( BlockchainSyncState {
209
+ last_lower_synced_slot : None ,
210
+ last_upper_synced_slot : None ,
211
+ last_finalized_block : Some (
212
+ last_finalized_block_number
213
+ ) ,
214
+ } )
215
+ . await ?;
216
+
217
+ info ! ( target = "indexer" , "Finalized block {full_block_hash} detected and stored" ) ;
218
+ } ,
219
+ unexpected_event_id => {
220
+ return Err ( IndexerError :: UnexpectedEvent { event : unexpected_event_id. to_string ( ) } )
221
+ }
222
+ }
223
+ } ,
185
224
Err ( error) => {
186
225
event_source. close ( ) ;
187
226
0 commit comments