Created
September 26, 2020 09:29
-
-
Save zviadm/d997afa5405e03378710f68fa7089363 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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