poa-network-monitor/network-test/missing-rounds.js

120 lines
5.0 KiB
JavaScript

const {
getWeb3,
testHelper,
getNetworkName
} = require('./test-helper.js');
// need to use WebsocketProvider
let web3 = getWeb3(true);
const {SqlDao} = require('../common/dao.js');
const sqlDao = new SqlDao(getNetworkName());
sqlDao.createMissingRoundsTable();
let blocksChecked = 0;
let previousValidatorIndex = -1;
let previousValidator = "";
let previousBlockNumber = -1;
let lastBlock = -1;
let startValidatorIndex = -1;
let validatorsLength = 0;
let isFirstBlock = false;
let currentValidatorIndex;
let missingRoundsCheck = {
/**
*Checks validator of the block
* @param blockHeader
* @param validatorsArr
* @returns {Promise.<Array>} - validators who missed their turn
*/
checkBlock: async function (blockHeader, validatorsArr) {
console.log("--- checkBlock() Got new block: " + blockHeader.number + ", validator: " + blockHeader.miner +
", previousValidatorIndex: " + previousValidatorIndex + ", lastBlock: " + lastBlock);
validatorsLength = validatorsArr.length;
console.log("validatorsLength: " + validatorsLength);
lastBlock = blockHeader.number;
let blocksPassed = lastBlock - previousBlockNumber;
console.log("blocksPassed: " + blocksPassed + ", lastBlock: " + lastBlock + ", previousBlockNumber: " + previousBlockNumber);
currentValidatorIndex = validatorsArr.indexOf(blockHeader.miner);
let missedValidators = [];
if (previousBlockNumber === -1 // in the begin of the test
|| blocksPassed <= 0 // reorg
|| blocksPassed >= validatorsLength // parity or VM could be paused
) {
startValidatorIndex = currentValidatorIndex;
isFirstBlock = true;
console.log("begin, previousValidatorIndex: " + previousValidatorIndex);
} else {
isFirstBlock = false;
let expectedValidatorIndex = (previousValidatorIndex + blocksPassed) % validatorsLength;
let expectedValidator = validatorsArr[expectedValidatorIndex];
let isPassed = expectedValidator === blockHeader.miner;
console.log("expectedValidatorIndex: " + expectedValidatorIndex + "expectedValidator: " + expectedValidator + ", actual: " + blockHeader.miner + ", passed: " + isPassed);
if (!isPassed) {
let ind = expectedValidatorIndex;
// more then one validator could miss round in one time
// all validators in array from expected one till actual will be missed
let added = 0;
while (ind !== currentValidatorIndex && added < validatorsLength) {
console.log("ind: " + ind + ", added : " + validatorsArr[ind]);
missedValidators.push(validatorsArr[ind]);
ind = (ind + 1) % validatorsLength;
added++;
}
}
console.log("blocksChecked: " + blocksChecked);
}
blocksChecked++;
previousValidator = blockHeader.miner;
previousBlockNumber = lastBlock;
previousValidatorIndex = currentValidatorIndex;
return missedValidators;
},
/**
* Checks coming blocks for validators missed their turn.
*
* @returns {Promise.<void>} {{passed: boolean, missedValidators: Array}}
* Returns object that contains boolean result (true if no validators missed the round) and array of validators that missed the round
*/
checkComingBlocks: async function () {
let result = {passed: true, missedValidators: []};
let self = this;
let subscription = web3.eth.subscribe('newBlockHeaders', function (error, result) {
if (error)
console.log("subscription error: " + error);
}).on("data", async function (blockHeader) {
let validatorsArray = await testHelper.getValidators(web3);
let missedFromBlock = await self.checkBlock(blockHeader, validatorsArray);
if (missedFromBlock) {
for (let v of missedFromBlock) {
if (result.missedValidators.indexOf(v) === -1) {
result.missedValidators.push(v);
result.passed = false;
}
}
}
console.log("-- blocksChecked: " + blocksChecked + ", currentValidatorIndex: " + currentValidatorIndex + ", startValidatorIndex: " + startValidatorIndex);
// round is checked, save result and exit
// skip check for first block
if (!isFirstBlock && (currentValidatorIndex === startValidatorIndex)) {
console.log("result: " + JSON.stringify(result));
subscription.unsubscribe();
await sqlDao.addToMissingRounds([new Date(Date.now()).toISOString(), (result.passed) ? 1 : 0, lastBlock, JSON.stringify(result.missedValidators)]);
sqlDao.closeDb();
process.exit(0);
}
});
}
};
missingRoundsCheck.checkComingBlocks();
module.exports = {
missingRoundsCheck
};