Skip to content

Commit ad9d2be

Browse files
authored
Implement flash block tracking and metrics recording in process_payload function (#23)
1 parent 3f3d846 commit ad9d2be

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

crates/flashblocks-rpc/src/flashblocks.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ fn process_payload(payload: FlashblocksPayloadV1, cache: Arc<Cache>) {
174174
return;
175175
}
176176

177+
// Track flashblock indices and record metrics
178+
update_flashblocks_index(payload.index, &cache, &metrics);
179+
177180
// Prevent updating to older blocks
178181
let current_block = cache.get::<OpBlock>("pending");
179182
if current_block.is_some() && current_block.unwrap().number > block_number {
@@ -302,6 +305,32 @@ fn process_payload(payload: FlashblocksPayloadV1, cache: Arc<Cache>) {
302305
}
303306
}
304307

308+
fn update_flashblocks_index(index: u64, cache: &Arc<Cache>, metrics: &Metrics) {
309+
if index == 0 {
310+
// Get highest index from previous block
311+
if let Some(prev_highest_index) = cache.get::<u64>("highest_payload_index") {
312+
// Record metric: total flash blocks = highest_index + 1 (since it's 0-indexed)
313+
metrics
314+
.flashblocks_in_block
315+
.record((prev_highest_index + 1) as f64);
316+
println!("Previous block had {} flash blocks", prev_highest_index + 1);
317+
}
318+
319+
// Reset highest index to 0 for new block
320+
if let Err(e) = cache.set("highest_payload_index", &0u64, Some(10)) {
321+
error!("Failed to reset highest flash index: {}", e);
322+
}
323+
} else {
324+
// Update highest index if current index is higher
325+
let current_highest = cache.get::<u64>("highest_payload_index").unwrap_or(0);
326+
if index > current_highest {
327+
if let Err(e) = cache.set("highest_payload_index", &index, Some(10)) {
328+
error!("Failed to update highest flash index: {}", e);
329+
}
330+
}
331+
}
332+
}
333+
305334
fn get_and_set_transactions(
306335
transactions: Vec<Bytes>,
307336
payload_index: u64,
@@ -506,6 +535,50 @@ mod tests {
506535
}
507536
}
508537

538+
// Create payload with specific index and block number
539+
fn create_payload_with_index(index: u64, block_number: u64) -> FlashblocksPayloadV1 {
540+
let base = if index == 0 {
541+
Some(ExecutionPayloadBaseV1 {
542+
parent_hash: Default::default(),
543+
parent_beacon_block_root: Default::default(),
544+
fee_recipient: Address::from_str("0x1234567890123456789012345678901234567890")
545+
.unwrap(),
546+
block_number,
547+
gas_limit: 1000000,
548+
timestamp: 1234567890,
549+
prev_randao: Default::default(),
550+
extra_data: Default::default(),
551+
base_fee_per_gas: U256::from(1000),
552+
})
553+
} else {
554+
None
555+
};
556+
557+
let delta = ExecutionPayloadFlashblockDeltaV1 {
558+
transactions: vec![],
559+
withdrawals: vec![],
560+
state_root: B256::repeat_byte(index as u8),
561+
receipts_root: B256::repeat_byte((index + 1) as u8),
562+
logs_bloom: Default::default(),
563+
gas_used: 21000 * index,
564+
block_hash: B256::repeat_byte((index + 2) as u8),
565+
};
566+
567+
let metadata = Metadata {
568+
block_number,
569+
receipts: HashMap::default(),
570+
new_account_balances: HashMap::default(),
571+
};
572+
573+
FlashblocksPayloadV1 {
574+
index,
575+
payload_id: PayloadId::new([0; 8]),
576+
base,
577+
diff: delta,
578+
metadata: serde_json::to_value(metadata).unwrap(),
579+
}
580+
}
581+
509582
fn create_second_payload() -> FlashblocksPayloadV1 {
510583
// Create second payload (index 1) with transactions
511584
// tx1 hash: 0x3cbbc9a6811ac5b2a2e5780bdb67baffc04246a59f39e398be048f1b2d05460c
@@ -688,4 +761,76 @@ mod tests {
688761
// Verify no block was stored, since it skips the first payload
689762
assert!(cache.get::<OpBlock>("pending").is_none());
690763
}
764+
765+
#[test]
766+
fn test_flash_block_tracking() {
767+
// Create cache
768+
let cache = Arc::new(Cache::default());
769+
770+
// Process first block with 3 flash blocks
771+
// Block 1, payload 0 (starts a new block)
772+
let payload1_0 = create_payload_with_index(0, 1);
773+
process_payload(payload1_0, cache.clone());
774+
775+
// Check that highest_payload_index was set to 0
776+
let highest = cache.get::<u64>("highest_payload_index").unwrap();
777+
assert_eq!(highest, 0);
778+
779+
// Block 1, payload 1
780+
let payload1_1 = create_payload_with_index(1, 1);
781+
process_payload(payload1_1, cache.clone());
782+
783+
// Check that highest_payload_index was updated
784+
let highest = cache.get::<u64>("highest_payload_index").unwrap();
785+
assert_eq!(highest, 1);
786+
787+
// Block 1, payload 2
788+
let payload1_2 = create_payload_with_index(2, 1);
789+
process_payload(payload1_2, cache.clone());
790+
791+
// Check that highest_payload_index was updated
792+
let highest = cache.get::<u64>("highest_payload_index").unwrap();
793+
assert_eq!(highest, 2);
794+
795+
// Now start a new block (block 2, payload 0)
796+
let payload2_0 = create_payload_with_index(0, 2);
797+
process_payload(payload2_0, cache.clone());
798+
799+
// Check that highest_payload_index was reset to 0
800+
let highest = cache.get::<u64>("highest_payload_index").unwrap();
801+
assert_eq!(highest, 0);
802+
803+
// Block 2, payload 1 (out of order with payload 3)
804+
let payload2_1 = create_payload_with_index(1, 2);
805+
process_payload(payload2_1, cache.clone());
806+
807+
// Check that highest_payload_index was updated
808+
let highest = cache.get::<u64>("highest_payload_index").unwrap();
809+
assert_eq!(highest, 1);
810+
811+
// Block 2, payload 3 (skipping 2)
812+
let payload2_3 = create_payload_with_index(3, 2);
813+
process_payload(payload2_3, cache.clone());
814+
815+
// Check that highest_payload_index was updated
816+
let highest = cache.get::<u64>("highest_payload_index").unwrap();
817+
assert_eq!(highest, 3);
818+
819+
// Block 2, payload 2 (out of order, should not change highest)
820+
let payload2_2 = create_payload_with_index(2, 2);
821+
process_payload(payload2_2, cache.clone());
822+
823+
// Check that highest_payload_index is still 3
824+
let highest = cache.get::<u64>("highest_payload_index").unwrap();
825+
assert_eq!(highest, 3);
826+
827+
// Start block 3, payload 0
828+
let payload3_0 = create_payload_with_index(0, 3);
829+
process_payload(payload3_0, cache.clone());
830+
831+
// Check that highest_payload_index was reset to 0
832+
// Also verify metric would have been recorded (though we can't directly check the metric's value)
833+
let highest = cache.get::<u64>("highest_payload_index").unwrap();
834+
assert_eq!(highest, 0);
835+
}
691836
}

crates/flashblocks-rpc/src/metrics.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ pub struct Metrics {
2626

2727
#[metric(describe = "Count of times flashblocks get_block_by_number is called")]
2828
pub get_block_by_number: Counter,
29+
30+
#[metric(describe = "Number of flashblocks in a block")]
31+
pub flashblocks_in_block: Histogram,
2932
}

0 commit comments

Comments
 (0)