import { Address , BlockHeader } from '@celo/connect' ; import { eqAddress } from '@celo/utils/lib/address' ; import { bitIsSet , parseBlockExtraData } from '@celo/utils/lib/istanbul' ; /**
 * Cache to efficiently retreive the elected validators for many blocks within an epoch.
 */ export class ElectionResultsCache { private readonly cache = new Map ( ) ; constructor ( private readonly election , private readonly epochSize ) { } param blockNumber async electedSigners ( blockNumber ) { const epoch = this . epochNumber ( blockNumber ) ; const cached = this . cache . get ( epoch ) ; if ( cached ) { return cached ; } const electedSigners = await this . election . getValidatorSigners ( epoch === 1 ? blockNumber : this . firstBlockOfEpoch ( epoch ) ) ; this . cache . set ( epoch , electedSigners ) ; return electedSigners ; } param signer param blockNumber async elected ( signer , blockNumber ) { const electedSigners = await this . electedSigners ( blockNumber ) ; return electedSigners . some ( eqAddress . bind ( null , signer ) ) ; } param signer param block async signedParent ( signer , block ) { const electedSigners = await this . electedSigners ( block . number ) ; const signerIndex = electedSigners . map ( eqAddress . bind ( null , signer ) ) . indexOf ( true ) ; if ( signerIndex < 0 ) { return false ; } const bitmap = parseBlockExtraData ( block . extraData ) . parentAggregatedSeal . bitmap ; return bitIsSet ( bitmap , signerIndex ) ; } private epochNumber ( blockNumber ) { return Math . ceil ( blockNumber / this . epochSize ) ; } private firstBlockOfEpoch ( epochNumber ) { return ( epochNumber - 1 ) * this . epochSize + 1 ; } }