Skip to content

Instantly share code, notes, and snippets.

@zviadm
Created September 26, 2020 09:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zviadm/d997afa5405e03378710f68fa7089363 to your computer and use it in GitHub Desktop.
Save zviadm/d997afa5405e03378710f68fa7089363 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
import commander from 'commander';
import StatsdClient from 'statsd-client'
import { concurrentMap } from '@celo/utils/lib/async'
import { Validator } from '@celo/contractkit/lib/wrappers/Validators';
import { bitIsSet, parseBlockExtraData } from '@celo/utils/lib/istanbul'
import { cleanupName } from './stats-utils';
import BigNumber from 'bignumber.js';
import { initKit, DefaultIPC } from './kit-utils';
const program = commander.program
.version(require('../package.json').version)
.option("-n --network <url>", "CELO url to connect to.", DefaultIPC)
.parse(process.argv);
process.on('unhandledRejection', (reason, _promise) => {
// @ts-ignore
console.error('Unhandled Rejection at:', reason.stack || reason)
process.exit(1)
})
async function main() {
console.log("START:", new Date(Date.now()))
const opts = program.opts()
const stats = new StatsdClient({host: 'localhost', port: 8125})
const kit = await initKit(opts.network)
const election = await kit.contracts.getElection()
const current = await kit.web3.eth.getBlockNumber()
const currentEpoch = await kit.getEpochNumberOfBlock(current)
let startBlock = await kit.getFirstBlockNumberForEpoch(currentEpoch)
// No need to fetch full history for quick missed blocks stats.
if (startBlock < current - 1000) {
startBlock = current - 1000
}
console.log(`fetching blocks: ${current - startBlock + 1}...`)
const blocks = await concurrentMap(
2,
[...Array(current - startBlock + 1).keys()], (i) => kit.web3.eth.getBlock(startBlock + i))
const validators = await kit.contracts.getValidators()
const electedSigners = await election.getCurrentValidatorSigners(startBlock)
const blockBitmaps = blocks.map((b) => parseBlockExtraData(b.extraData).parentAggregatedSeal.bitmap)
for (let signerIndex = 0; signerIndex < electedSigners.length; signerIndex += 1) {
const signer = electedSigners[signerIndex]
const validator = await validators.getValidatorFromSigner(signer, startBlock)
const name = cleanupName(validator.name)
if (!name.startsWith("wotrust")) {
console.log(`skipping: ${name} - ${validator.address}`)
continue
}
missedUptimeForValidator(stats, validator, signerIndex, blockBitmaps)
}
stats.gauge("stats_reported.missed-uptime", 1)
stats.close()
kit.stop()
console.log("END:", new Date(Date.now()))
}
function missedUptimeForValidator(
stats: StatsdClient,
electedValidator: Validator,
signerIndex: number,
blockBitmaps: BigNumber[]) {
const signer = electedValidator.signer
let missedTotal = 0
let missed = 0
let idx = 0
let missedInLast100 = 0
for (const block of blockBitmaps) {
idx += 1
const signed = bitIsSet(block, signerIndex)
if (signed) {
missed = 0
continue
}
missed += 1
if (missed >= 12) {
missedTotal += 1
}
if (idx > blockBitmaps.length - 100) {
missedInLast100 += 1
}
}
const name = cleanupName(electedValidator.name)
console.log(`${name} signer: ${signer} missed: ${missedTotal}, missed in last 100: ${missedInLast100}`)
stats.gauge(`missed_uptime.${name}.${signer.slice(2, 6)}`, missedTotal)
stats.gauge(`missed_signatures.${name}.${signer.slice(2, 6)}`, missedInLast100)
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment