@@ -70,6 +70,11 @@ impl<T: SlotClock + 'static, E: EthSpec, D: KeyValueStore<E>> ValidatorService<T
7070 // Ensure the public key JSON is well-formed even if we do not store it explicitly.
7171 let _ = validator_key_pair. hashsig_public_key ( ) ?;
7272
73+ // Ensure all validator metrics are registered in the global Prometheus
74+ // registry so that the /metrics endpoint exposes the full Zeam metric
75+ // set even before any events have occurred.
76+ metrics:: init ( ) ;
77+
7378 Ok ( Self {
7479 network_recv,
7580 network_send,
@@ -298,6 +303,28 @@ impl<T: SlotClock + 'static, E: EthSpec, D: KeyValueStore<E>> ValidatorService<T
298303 let justified = & state. latest_justified ;
299304 let finalized = & state. latest_finalized ;
300305
306+ // Update chain status metrics
307+ if let Ok ( gauge) = & * metrics:: LEAN_HEAD_SLOT {
308+ gauge. set ( head_block. slot . 0 as i64 ) ;
309+ }
310+ if let Ok ( gauge) = & * metrics:: LEAN_LATEST_JUSTIFIED_SLOT {
311+ gauge. set ( justified. slot . 0 as i64 ) ;
312+ }
313+ if let Ok ( gauge) = & * metrics:: LEAN_LATEST_FINALIZED_SLOT {
314+ gauge. set ( finalized. slot . 0 as i64 ) ;
315+ }
316+ if let Ok ( safe_root) = self . chain . fetch_safe_target ( )
317+ && let Some ( root) = safe_root
318+ && let Ok ( Some ( block) ) = self . chain . fetch_block ( root)
319+ && let Ok ( gauge) = & * metrics:: LEAN_LATEST_SAFE_SLOT
320+ {
321+ gauge. set ( block. slot . 0 as i64 ) ;
322+ }
323+ if let Ok ( gauge) = & * metrics:: LEAN_VALIDATORS_COUNT {
324+ gauge. set ( state. validators . len ( ) as i64 ) ;
325+ }
326+
327+
301328 let sep = "=" . repeat ( 63 ) ;
302329 info ! (
303330 separator = %sep,
@@ -533,7 +560,15 @@ impl<T: SlotClock + 'static, E: EthSpec, D: KeyValueStore<E>> ValidatorService<T
533560 // NOTE: Signature verification will be implemented when signature verification functions
534561 // become available from the leansig library. For now, we accept all attestations.
535562 let _timer = metrics:: start_timer ( & metrics:: LEAN_PQ_SIGNATURE_ATTESTATION_VERIFICATION_TIME ) ;
563+ let _validation_timer = metrics:: start_timer ( & metrics:: LEAN_ATTESTATION_VALIDATION_TIME ) ;
564+
536565 // [PLACEHOLDER] verification logic
566+ // For now considering all valid
567+ if let Ok ( counter) = & * metrics:: LEAN_ATTESTATIONS_VALID_TOTAL {
568+ counter. inc ( ) ;
569+ }
570+
571+ drop ( _validation_timer) ;
537572 drop ( _timer) ;
538573
539574 debug ! ( validator_id, epoch, "Attestation received and accepted" ) ;
@@ -687,6 +722,10 @@ impl<T: SlotClock + 'static, E: EthSpec, D: KeyValueStore<E>> ValidatorService<T
687722 let proposer_attestation = & signed_block. message . proposer_attestation ;
688723 let block_root = block. tree_hash_root ( ) ;
689724
725+ // Track total time spent in the on_block-style handler, matching the
726+ // Zeam / beacon-node `chain_onblock_duration_seconds` metric name.
727+ let _onblock_timer = metrics:: start_timer ( & metrics:: CHAIN_ONBLOCK_DURATION_SECONDS ) ;
728+
690729 info ! (
691730 slot = block. slot. 0 ,
692731 proposer_index = block. proposer_index,
@@ -745,13 +784,51 @@ impl<T: SlotClock + 'static, E: EthSpec, D: KeyValueStore<E>> ValidatorService<T
745784
746785 debug ! ( "Cloned parent state for state transition" ) ;
747786
748- // Validate cryptographic signatures
749- //
750- // XMSS signature verification is now implemented using leansig.
787+ // Execute state transition function with metrics
788+ let _block_processing_timer =
789+ metrics:: start_timer ( & metrics:: BLOCK_PROCESSING_DURATION_SECONDS ) ;
790+ let _state_timer = metrics:: start_timer ( & metrics:: LEAN_STATE_TRANSITION_TIME ) ;
791+
751792 let valid_signatures = true ;
793+
794+ // Verify signatures if enabled
795+ if valid_signatures {
796+ signed_block. verify_signatures ( & post_state) ?;
797+ }
798+
799+ let block = & signed_block. message . block ;
752800
753- // Execute state transition function to compute post-block state
754- post_state. state_transition ( & signed_block, valid_signatures) ?;
801+ // Process slots (catch up)
802+ if post_state. slot < block. slot {
803+ let slots_processed = block. slot . 0 . saturating_sub ( post_state. slot . 0 ) ;
804+ if let Ok ( counter) = & * metrics:: LEAN_STATE_TRANSITION_SLOTS_PROCESSED_TOTAL {
805+ counter. inc_by ( slots_processed) ;
806+ }
807+
808+ let _slots_timer = metrics:: start_timer ( & metrics:: LEAN_STATE_TRANSITION_SLOTS_PROCESSING_TIME ) ;
809+ post_state. process_slots ( block. slot ) ?;
810+ drop ( _slots_timer) ;
811+ }
812+
813+ // Process block
814+ if let Ok ( counter) = & * metrics:: LEAN_STATE_TRANSITION_ATTESTATIONS_PROCESSED_TOTAL {
815+ counter. inc_by ( block. body . attestations . len ( ) as u64 ) ;
816+ }
817+ let _block_timer = metrics:: start_timer ( & metrics:: LEAN_STATE_TRANSITION_BLOCK_PROCESSING_TIME ) ;
818+ post_state. process_block ( block) ?;
819+ drop ( _block_timer) ;
820+
821+ // Verify state root
822+ let computed_state_root = post_state. tree_hash_root ( ) ;
823+ if block. state_root != computed_state_root {
824+ return Err ( format ! (
825+ "Invalid block state root. Expected: {:?}, got: {:?}" ,
826+ computed_state_root, block. state_root
827+ ) ) ;
828+ }
829+
830+ drop ( _block_processing_timer) ;
831+ drop ( _state_timer) ;
755832
756833 debug ! (
757834 post_slot = post_state. slot. 0 ,
@@ -772,8 +849,10 @@ impl<T: SlotClock + 'static, E: EthSpec, D: KeyValueStore<E>> ValidatorService<T
772849 debug ! ( ?block_root, "Block and state saved to cache and database" ) ;
773850
774851 // Ensure parent chain exists in proto array and register the new block.
852+ let _fc_timer = metrics:: start_timer ( & metrics:: LEAN_FORK_CHOICE_BLOCK_PROCESSING_TIME ) ;
775853 self . chain
776854 . register_block ( block_root, block. slot , block. parent_root ) ?;
855+ drop ( _fc_timer) ;
777856
778857 // Process block body attestations
779858 //
0 commit comments