1- import { Logger , LogLevel } from "@lodestar/utils" ;
2- import { CheckpointWithHex , IForkChoice } from "@lodestar/fork-choice" ;
3- import { ValidatorIndex , Slot } from "@lodestar/types" ;
4- import { SLOTS_PER_EPOCH } from "@lodestar/params" ;
5-
1+ import { Logger } from "@lodestar/utils" ;
2+ import { CheckpointWithHex } from "@lodestar/fork-choice" ;
63import { IBeaconDb } from "../../db/index.js" ;
74import { JobItemQueue } from "../../util/queue/index.js" ;
85import { IBeaconChain } from "../interface.js" ;
96import { ChainEvent } from "../emitter.js" ;
10- import { Metrics } from "../../metrics/metrics.js" ;
11- import { IStateRegenerator } from "../regen/interface.js" ;
127import { StatesArchiver , StatesArchiverOpts } from "./archiveStates.js" ;
13- import { archiveBlocks , FinalizedData } from "./archiveBlocks.js" ;
8+ import { archiveBlocks } from "./archiveBlocks.js" ;
149
1510const PROCESS_FINALIZED_CHECKPOINT_QUEUE_LEN = 256 ;
1611
@@ -48,8 +43,7 @@ export class Archiver {
4843 private readonly chain : IBeaconChain ,
4944 private readonly logger : Logger ,
5045 signal : AbortSignal ,
51- opts : ArchiverOpts ,
52- private readonly metrics : Metrics | null
46+ opts : ArchiverOpts
5347 ) {
5448 this . statesArchiver = new StatesArchiver ( chain . regen , db , logger , opts ) ;
5549 this . prevFinalized = chain . forkChoice . getFinalizedCheckpoint ( ) ;
@@ -95,7 +89,7 @@ export class Archiver {
9589 try {
9690 const finalizedEpoch = finalized . epoch ;
9791 this . logger . verbose ( "Start processing finalized checkpoint" , { epoch : finalizedEpoch , rootHex : finalized . rootHex } ) ;
98- const finalizedData = await archiveBlocks (
92+ await archiveBlocks (
9993 this . chain . config ,
10094 this . db ,
10195 this . chain . forkChoice ,
@@ -104,14 +98,6 @@ export class Archiver {
10498 finalized ,
10599 this . chain . clock . currentEpoch
106100 ) ;
107- this . collectFinalizedProposalStats (
108- this . chain . regen ,
109- this . chain . forkChoice ,
110- this . chain . beaconProposerCache ,
111- finalizedData ,
112- finalized ,
113- this . prevFinalized
114- ) ;
115101 this . prevFinalized = finalized ;
116102
117103 // should be after ArchiveBlocksTask to handle restart cleanly
@@ -174,170 +160,4 @@ export class Archiver {
174160 this . logger . error ( "Error updating backfilledRanges on finalization" , { epoch : finalized . epoch } , e as Error ) ;
175161 }
176162 } ;
177-
178- private collectFinalizedProposalStats (
179- regen : IStateRegenerator ,
180- forkChoice : IForkChoice ,
181- beaconProposerCache : IBeaconChain [ "beaconProposerCache" ] ,
182- finalizedData : FinalizedData ,
183- finalized : CheckpointWithHex ,
184- lastFinalized : CheckpointWithHex
185- ) : FinalizedStats {
186- const { finalizedCanonicalCheckpoints, finalizedCanonicalBlocks, finalizedNonCanonicalBlocks} = finalizedData ;
187-
188- // Range to consider is:
189- // lastFinalized.epoch * SLOTS_PER_EPOCH + 1, .... finalized.epoch * SLOTS_PER_EPOCH
190- // So we need to check proposer of lastFinalized (index 1 onwards) as well as 0th index proposer
191- // of current finalized
192- const finalizedProposersCheckpoints : FinalizedData [ "finalizedCanonicalCheckpoints" ] =
193- finalizedCanonicalCheckpoints . filter (
194- ( hexCheck ) => hexCheck . epoch < finalized . epoch && hexCheck . epoch > lastFinalized . epoch
195- ) ;
196- finalizedProposersCheckpoints . push ( lastFinalized ) ;
197- finalizedProposersCheckpoints . push ( finalized ) ;
198-
199- // Sort the data to in following structure to make inferences
200- const slotProposers = new Map < Slot , { canonicalVals : ValidatorIndex [ ] ; nonCanonicalVals : ValidatorIndex [ ] } > ( ) ;
201-
202- // 1. Process canonical blocks
203- for ( const block of finalizedCanonicalBlocks ) {
204- // simply set to the single entry as no double proposal can be there for same slot in canonical
205- slotProposers . set ( block . slot , { canonicalVals : [ block . proposerIndex ] , nonCanonicalVals : [ ] } ) ;
206- }
207-
208- // 2. Process non canonical blocks
209- for ( const block of finalizedNonCanonicalBlocks ) {
210- const slotVals = slotProposers . get ( block . slot ) ?? { canonicalVals : [ ] , nonCanonicalVals : [ ] } ;
211- slotVals . nonCanonicalVals . push ( block . proposerIndex ) ;
212- slotProposers . set ( block . slot , slotVals ) ;
213- }
214-
215- // Some simple calculatable stats for all validators
216- const finalizedCanonicalCheckpointsCount = finalizedCanonicalCheckpoints . length ;
217- const expectedTotalProposalsCount = ( finalized . epoch - lastFinalized . epoch ) * SLOTS_PER_EPOCH ;
218- const finalizedCanonicalBlocksCount = finalizedCanonicalBlocks . length ;
219- const finalizedOrphanedProposalsCount = finalizedNonCanonicalBlocks . length ;
220- const finalizedMissedProposalsCount = expectedTotalProposalsCount - slotProposers . size ;
221-
222- const allValidators : ProposalStats = {
223- total : expectedTotalProposalsCount ,
224- finalized : finalizedCanonicalBlocksCount ,
225- orphaned : finalizedOrphanedProposalsCount ,
226- missed : finalizedMissedProposalsCount ,
227- } ;
228-
229- // Stats about the attached validators
230- const attachedProposers = beaconProposerCache
231- . getProposersSinceEpoch ( finalized . epoch )
232- . map ( ( indexString ) => Number ( indexString ) ) ;
233- const finalizedAttachedValidatorsCount = attachedProposers . length ;
234-
235- // Calculate stats for attached validators, based on states in checkpointState cache
236- let finalizedFoundCheckpointsInStateCache = 0 ;
237-
238- let expectedAttachedValidatorsProposalsCount = 0 ;
239- let finalizedAttachedValidatorsProposalsCount = 0 ;
240- let finalizedAttachedValidatorsOrphanCount = 0 ;
241- let finalizedAttachedValidatorsMissedCount = 0 ;
242-
243- for ( const checkpointHex of finalizedProposersCheckpoints ) {
244- const checkpointState = regen . getCheckpointStateSync ( checkpointHex ) ;
245-
246- // Generate stats for attached validators if we have state info
247- if ( checkpointState !== null ) {
248- finalizedFoundCheckpointsInStateCache ++ ;
249-
250- const epochProposers = checkpointState . epochCtx . proposers ;
251- const startSlot = checkpointState . epochCtx . epoch * SLOTS_PER_EPOCH ;
252-
253- for ( let index = 0 ; index < epochProposers . length ; index ++ ) {
254- const slot = startSlot + index ;
255-
256- // Let skip processing the slots which are out of range
257- // Range to consider is:
258- // lastFinalized.epoch * SLOTS_PER_EPOCH + 1, .... finalized.epoch * SLOTS_PER_EPOCH
259- if ( slot <= lastFinalized . epoch * SLOTS_PER_EPOCH || slot > finalized . epoch * SLOTS_PER_EPOCH ) {
260- continue ;
261- }
262-
263- const proposer = epochProposers [ index ] ;
264-
265- // If this proposer was attached to this BN for this epoch
266- if ( attachedProposers . includes ( proposer ) ) {
267- expectedAttachedValidatorsProposalsCount ++ ;
268-
269- // Get what validators made canonical/non canonical proposals for this slot
270- const { canonicalVals, nonCanonicalVals} = slotProposers . get ( slot ) ?? {
271- canonicalVals : [ ] ,
272- nonCanonicalVals : [ ] ,
273- } ;
274- let wasFinalized = false ;
275-
276- if ( canonicalVals . includes ( proposer ) ) {
277- finalizedAttachedValidatorsProposalsCount ++ ;
278- wasFinalized = true ;
279- }
280- const attachedProposerNonCanSlotProposals = nonCanonicalVals . filter ( ( nonCanVal ) => nonCanVal === proposer ) ;
281- finalizedAttachedValidatorsOrphanCount += attachedProposerNonCanSlotProposals . length ;
282-
283- // Check is this slot proposal was missed by this attached validator
284- if ( ! wasFinalized && attachedProposerNonCanSlotProposals . length === 0 ) {
285- finalizedAttachedValidatorsMissedCount ++ ;
286- }
287- }
288- }
289- }
290- }
291-
292- const attachedValidators : ProposalStats = {
293- total : expectedAttachedValidatorsProposalsCount ,
294- finalized : finalizedAttachedValidatorsProposalsCount ,
295- orphaned : finalizedAttachedValidatorsOrphanCount ,
296- missed : finalizedAttachedValidatorsMissedCount ,
297- } ;
298-
299- this . logger . debug ( "All validators finalized proposal stats" , {
300- ...allValidators ,
301- finalizedCanonicalCheckpointsCount,
302- finalizedFoundCheckpointsInStateCache,
303- } ) ;
304-
305- // Only log to info if there is some relevant data to show
306- // - No need to explicitly track SYNCED state since no validators attached would be there to show
307- // - debug log if validators attached but no proposals were scheduled
308- // - info log if proposals were scheduled (canonical) or there were orphans (non canonical)
309- if ( finalizedAttachedValidatorsCount !== 0 ) {
310- const logLevel =
311- attachedValidators . total !== 0 || attachedValidators . orphaned !== 0 ? LogLevel . info : LogLevel . debug ;
312- this . logger [ logLevel ] ( "Attached validators finalized proposal stats" , {
313- ...attachedValidators ,
314- validators : finalizedAttachedValidatorsCount ,
315- } ) ;
316- } else {
317- this . logger . debug ( "No proposers attached to beacon node" , { finalizedEpoch : finalized . epoch } ) ;
318- }
319-
320- this . metrics ?. allValidators . total . set ( allValidators . total ) ;
321- this . metrics ?. allValidators . finalized . set ( allValidators . finalized ) ;
322- this . metrics ?. allValidators . orphaned . set ( allValidators . orphaned ) ;
323- this . metrics ?. allValidators . missed . set ( allValidators . missed ) ;
324-
325- this . metrics ?. attachedValidators . total . set ( attachedValidators . total ) ;
326- this . metrics ?. attachedValidators . finalized . set ( attachedValidators . finalized ) ;
327- this . metrics ?. attachedValidators . orphaned . set ( attachedValidators . orphaned ) ;
328- this . metrics ?. attachedValidators . missed . set ( attachedValidators . missed ) ;
329-
330- this . metrics ?. finalizedCanonicalCheckpointsCount . set ( finalizedCanonicalCheckpointsCount ) ;
331- this . metrics ?. finalizedFoundCheckpointsInStateCache . set ( finalizedFoundCheckpointsInStateCache ) ;
332- this . metrics ?. finalizedAttachedValidatorsCount . set ( finalizedAttachedValidatorsCount ) ;
333-
334- // Return stats data for the ease of unit testing
335- return {
336- allValidators,
337- attachedValidators,
338- finalizedCanonicalCheckpointsCount,
339- finalizedFoundCheckpointsInStateCache,
340- finalizedAttachedValidatorsCount,
341- } ;
342- }
343163}
0 commit comments