@@ -174,6 +174,31 @@ fn process_payload(payload: FlashblocksPayloadV1, cache: Arc<Cache>) {
174
174
return ;
175
175
}
176
176
177
+ // When index is 0, we're starting a new block - emit metric for previous block
178
+ let index = payload. index ;
179
+ if index == 0 {
180
+ // Get highest index from previous block
181
+ if let Some ( prev_highest_index) = cache. get :: < u64 > ( "highest_payload_index" ) {
182
+ // Record metric: total flash blocks = highest_index + 1 (since it's 0-indexed)
183
+ metrics. flashblocks_in_block . record ( ( prev_highest_index + 1 ) as f64 ) ;
184
+ println ! ( "Previous block had {} flash blocks" , prev_highest_index + 1 ) ;
185
+ }
186
+
187
+ // Reset highest index to 0 for new block
188
+ if let Err ( e) = cache. set ( "highest_payload_index" , & 0u64 , Some ( 10 ) ) {
189
+ error ! ( "Failed to reset highest flash index: {}" , e) ;
190
+ }
191
+ } else {
192
+ // Update highest index if current index is higher
193
+ let current_highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap_or ( 0 ) ;
194
+ if index > current_highest {
195
+ if let Err ( e) = cache. set ( "highest_payload_index" , & index, Some ( 10 ) ) {
196
+ error ! ( "Failed to update highest flash index: {}" , e) ;
197
+ }
198
+ }
199
+ }
200
+
201
+
177
202
// Prevent updating to older blocks
178
203
let current_block = cache. get :: < OpBlock > ( "pending" ) ;
179
204
if current_block. is_some ( ) && current_block. unwrap ( ) . number > block_number {
@@ -505,6 +530,49 @@ mod tests {
505
530
metadata : serde_json:: to_value ( metadata) . unwrap ( ) ,
506
531
}
507
532
}
533
+
534
+ // Create payload with specific index and block number
535
+ fn create_payload_with_index ( index : u64 , block_number : u64 ) -> FlashblocksPayloadV1 {
536
+ let base = if index == 0 {
537
+ Some ( ExecutionPayloadBaseV1 {
538
+ parent_hash : Default :: default ( ) ,
539
+ parent_beacon_block_root : Default :: default ( ) ,
540
+ fee_recipient : Address :: from_str ( "0x1234567890123456789012345678901234567890" ) . unwrap ( ) ,
541
+ block_number,
542
+ gas_limit : 1000000 ,
543
+ timestamp : 1234567890 ,
544
+ prev_randao : Default :: default ( ) ,
545
+ extra_data : Default :: default ( ) ,
546
+ base_fee_per_gas : U256 :: from ( 1000 ) ,
547
+ } )
548
+ } else {
549
+ None
550
+ } ;
551
+
552
+ let delta = ExecutionPayloadFlashblockDeltaV1 {
553
+ transactions : vec ! [ ] ,
554
+ withdrawals : vec ! [ ] ,
555
+ state_root : B256 :: repeat_byte ( index as u8 ) ,
556
+ receipts_root : B256 :: repeat_byte ( ( index + 1 ) as u8 ) ,
557
+ logs_bloom : Default :: default ( ) ,
558
+ gas_used : 21000 * index,
559
+ block_hash : B256 :: repeat_byte ( ( index + 2 ) as u8 ) ,
560
+ } ;
561
+
562
+ let metadata = Metadata {
563
+ block_number,
564
+ receipts : HashMap :: default ( ) ,
565
+ new_account_balances : HashMap :: default ( ) ,
566
+ } ;
567
+
568
+ FlashblocksPayloadV1 {
569
+ index,
570
+ payload_id : PayloadId :: new ( [ 0 ; 8 ] ) ,
571
+ base,
572
+ diff : delta,
573
+ metadata : serde_json:: to_value ( metadata) . unwrap ( ) ,
574
+ }
575
+ }
508
576
509
577
fn create_second_payload ( ) -> FlashblocksPayloadV1 {
510
578
// Create second payload (index 1) with transactions
@@ -688,4 +756,76 @@ mod tests {
688
756
// Verify no block was stored, since it skips the first payload
689
757
assert ! ( cache. get:: <OpBlock >( "pending" ) . is_none( ) ) ;
690
758
}
759
+
760
+ #[ test]
761
+ fn test_flash_block_tracking ( ) {
762
+ // Create cache
763
+ let cache = Arc :: new ( Cache :: default ( ) ) ;
764
+
765
+ // Process first block with 3 flash blocks
766
+ // Block 1, payload 0 (starts a new block)
767
+ let payload1_0 = create_payload_with_index ( 0 , 1 ) ;
768
+ process_payload ( payload1_0, cache. clone ( ) ) ;
769
+
770
+ // Check that highest_payload_index was set to 0
771
+ let highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap ( ) ;
772
+ assert_eq ! ( highest, 0 ) ;
773
+
774
+ // Block 1, payload 1
775
+ let payload1_1 = create_payload_with_index ( 1 , 1 ) ;
776
+ process_payload ( payload1_1, cache. clone ( ) ) ;
777
+
778
+ // Check that highest_payload_index was updated
779
+ let highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap ( ) ;
780
+ assert_eq ! ( highest, 1 ) ;
781
+
782
+ // Block 1, payload 2
783
+ let payload1_2 = create_payload_with_index ( 2 , 1 ) ;
784
+ process_payload ( payload1_2, cache. clone ( ) ) ;
785
+
786
+ // Check that highest_payload_index was updated
787
+ let highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap ( ) ;
788
+ assert_eq ! ( highest, 2 ) ;
789
+
790
+ // Now start a new block (block 2, payload 0)
791
+ let payload2_0 = create_payload_with_index ( 0 , 2 ) ;
792
+ process_payload ( payload2_0, cache. clone ( ) ) ;
793
+
794
+ // Check that highest_payload_index was reset to 0
795
+ let highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap ( ) ;
796
+ assert_eq ! ( highest, 0 ) ;
797
+
798
+ // Block 2, payload 1 (out of order with payload 3)
799
+ let payload2_1 = create_payload_with_index ( 1 , 2 ) ;
800
+ process_payload ( payload2_1, cache. clone ( ) ) ;
801
+
802
+ // Check that highest_payload_index was updated
803
+ let highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap ( ) ;
804
+ assert_eq ! ( highest, 1 ) ;
805
+
806
+ // Block 2, payload 3 (skipping 2)
807
+ let payload2_3 = create_payload_with_index ( 3 , 2 ) ;
808
+ process_payload ( payload2_3, cache. clone ( ) ) ;
809
+
810
+ // Check that highest_payload_index was updated
811
+ let highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap ( ) ;
812
+ assert_eq ! ( highest, 3 ) ;
813
+
814
+ // Block 2, payload 2 (out of order, should not change highest)
815
+ let payload2_2 = create_payload_with_index ( 2 , 2 ) ;
816
+ process_payload ( payload2_2, cache. clone ( ) ) ;
817
+
818
+ // Check that highest_payload_index is still 3
819
+ let highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap ( ) ;
820
+ assert_eq ! ( highest, 3 ) ;
821
+
822
+ // Start block 3, payload 0
823
+ let payload3_0 = create_payload_with_index ( 0 , 3 ) ;
824
+ process_payload ( payload3_0, cache. clone ( ) ) ;
825
+
826
+ // Check that highest_payload_index was reset to 0
827
+ // Also verify metric would have been recorded (though we can't directly check the metric's value)
828
+ let highest = cache. get :: < u64 > ( "highest_payload_index" ) . unwrap ( ) ;
829
+ assert_eq ! ( highest, 0 ) ;
830
+ }
691
831
}
0 commit comments