/
epoch.js
124 lines (105 loc) · 3.9 KB
/
epoch.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
'use strict'
const web3Rpc = require('../models/web3rpc')
const config = require('config')
const logger = require('../helpers/logger')
const ethUtils = require('ethereumjs-util')
const BlockHeader = require('ethereumjs-block/header')
async function scan (blockNumber) {
try {
let block = await web3Rpc.eth.getBlock(blockNumber)
let { m1, m2 } = getM1M2(block)
logger.info(`block number ${block.number} hash ${block.hash} m1 ${m1} m2 ${m2}`)
return {
number: block.number,
hash: block.hash,
m1: m1,
m2: m2
}
} catch (e) {
logger.error('scan error %s %s', blockNumber, e)
return scan(blockNumber)
}
}
function getM1M2 (block) {
const dataBuff = ethUtils.toBuffer(block.extraData)
const sig = ethUtils.fromRpcSig(dataBuff.slice(dataBuff.length - 65, dataBuff.length))
block.extraData = '0x' + ethUtils.toBuffer(block.extraData).slice(0, dataBuff.length - 65).toString('hex')
const headerHash = new BlockHeader({
parentHash: ethUtils.toBuffer(block.parentHash),
uncleHash: ethUtils.toBuffer(block.sha3Uncles),
coinbase: ethUtils.toBuffer(block.miner),
stateRoot: ethUtils.toBuffer(block.stateRoot),
transactionsTrie: ethUtils.toBuffer(block.transactionsRoot),
receiptTrie: ethUtils.toBuffer(block.receiptsRoot),
bloom: ethUtils.toBuffer(block.logsBloom),
difficulty: ethUtils.toBuffer(parseInt(block.difficulty)),
number: ethUtils.toBuffer(block.number),
gasLimit: ethUtils.toBuffer(block.gasLimit),
gasUsed: ethUtils.toBuffer(block.gasUsed),
timestamp: ethUtils.toBuffer(block.timestamp),
extraData: ethUtils.toBuffer(block.extraData),
mixHash: ethUtils.toBuffer(block.mixHash),
nonce: ethUtils.toBuffer(block.nonce)
})
const pub = ethUtils.ecrecover(headerHash.hash(), sig.v, sig.r, sig.s)
const m1 = ethUtils.addHexPrefix(ethUtils.pubToAddress(pub).toString('hex'))
const dataBuffM2 = ethUtils.toBuffer(block.validator)
const sigM2 = ethUtils.fromRpcSig(dataBuffM2.slice(dataBuffM2.length - 65, dataBuffM2.length))
const pubM2 = ethUtils.ecrecover(headerHash.hash(), sigM2.v, sigM2.r, sigM2.s)
const m2 = ethUtils.addHexPrefix(ethUtils.pubToAddress(pubM2).toString('hex'))
return { m1, m2 }
}
async function report (data) {
let m1 = {}
let m2 = {}
data.forEach(it => {
m1[it.m1] = (m1[it.m1] || 0) + 1
m2[it.m2] = (m2[it.m2] || 0) + 1
})
let map = {}
for (let k in m1) {
map[k] = {}
map[k].m1 = m1[k]
}
for (let j in m2) {
map[j] = map[j] || {}
map[j].m2 = m2[j]
}
for (let addr in map) {
logger.info(`addr ${addr} m1 ${map[addr].m1} m2 ${map[addr].m2}`)
}
}
async function getSigners (epochNumber) {
let checkpoint = (epochNumber - 1) * 900
let block = await web3Rpc.eth.getBlock(checkpoint)
let buff = Buffer.from(block.extraData.substring(2), 'hex')
let sbuff = buff.slice(32, buff.length - 65)
let signers = []
if (sbuff.length > 0) {
for (let i = 1; i <= sbuff.length / 20; i++) {
let address = sbuff.slice((i - 1) * 20, i * 20)
signers.push('0x' + address.toString('hex'))
}
}
buff = Buffer.from(block.validators.substring(2), 'hex')
let randoms = []
for (let i = 1; i <= buff.length / 4; i++) {
let k = buff.slice((i - 1) * 4, i * 4)
randoms.push(web3Rpc.utils.hexToUtf8('0x' + k.toString('hex')))
}
return { signers, randoms }
}
async function run (epochNumber) {
let start = (epochNumber - 1) * 900 + 1
let end = epochNumber * 900
let { signers, randoms } = await getSigners(epochNumber)
logger.info(`signers ${signers} randoms ${randoms}`)
let data = []
for (let i=start; i<=end; i++) {
let it = await scan(i)
data.push(it)
}
await report(data)
return process.exit(0)
}
module.exports = { run }