// check if payout script works properly for all nodes (check mining address balance) const { config, getNetworkName, getWeb3, BN, testHelper, } = require('./test-helper.js'); let web3 = getWeb3(); const {SqlDao} = require('../common/dao.js'); const sqlDao = new SqlDao(getNetworkName()); sqlDao.createRewardTable(); /* * Gets blocks from the latest round and checks reward */ async function checkMiningReward() { console.log("checkMiningReward"); const validatorsArr = await testHelper.getValidators(web3); let blocksToTest = await getBlocksFromLatestRound(validatorsArr.length); for (let i = 0; i < blocksToTest.length; i++) { let result = await checkBlocksRewards(blocksToTest[i]); console.log("passed: " + result.passed + ", rewardDetails: " + JSON.stringify(result.rewardDetails) + ", transactions: " + JSON.stringify(result.transactions)); sqlDao.addToRewardTable([new Date(Date.now()).toISOString(), (result.passed) ? 1 : 0, result.error, JSON.stringify(result.rewardDetails), JSON.stringify(result.transactions)]); } sqlDao.closeDb(); } //todo check error for all tests checkMiningReward(); /** * Checks if miner got right reward for block creation and adding txs to the block * * @param block (or objects with fields number and miner) * @returns {Promise.<{passed: boolean, error: string, rewardDetails: Array}>} */ async function checkBlocksRewards(block) { // todo: save each validator's rewards let result = {passed: true, error: "", rewardDetails: {}, transactions: []}; console.log("number: " + block.number + ", miner: " + block.miner); let actualBalanceIncrease = new BN(await web3.eth.getBalance(block.miner, block.number)).sub(new BN(await web3.eth.getBalance(block.miner, block.number - 1))); let expectedBalanceIncrease = new BN(config.miningReward); console.log("got reward: " + actualBalanceIncrease); console.log("config.miningReward: " + config.miningReward); //reward will be different if there are txs for (let j = 0; j < block.transactions.length; j++) { let details = {hash: "", price: "", value: "", to: "", from: "", blockNumber: ""}; let tx = await web3.eth.getTransaction(block.transactions[j]); let gasPrice = new BN(tx.gasPrice); let receipt = await web3.eth.getTransactionReceipt(block.transactions[j]); let transactionPrice = new BN(receipt.gasUsed).mul(gasPrice); details.hash = receipt.transactionHash; details.from = tx.from; details.to = tx.to; details.gasPrice = gasPrice.toString(); details.gasUsed = receipt.gasUsed; console.log("receipt.from: " + tx.from); console.log("receipt.to: " + tx.to); details.price = transactionPrice.toString(); details.value = tx.value; details.blockNumber = block.number; if (!(tx.from === block.miner)) { expectedBalanceIncrease = expectedBalanceIncrease.add(transactionPrice); } else if (tx.from === block.miner) { expectedBalanceIncrease = expectedBalanceIncrease.sub(new BN(tx.value)); } else if (tx.to === block.miner) { expectedBalanceIncrease = expectedBalanceIncrease.add(new BN(tx.value)); } console.log("transaction details: " + JSON.stringify(details)); result.transactions.push(details); console.log("expectedBalanceIncrease: " + expectedBalanceIncrease); } result.rewardDetails = { validator: block.miner, block: block.number, gasUsed: block.gasUsed, basicReward: config.miningReward, expectedReward: expectedBalanceIncrease.toString(), actualReward: actualBalanceIncrease.toString(), txsNumber: block.transactions.length, }; let isRewardRight = actualBalanceIncrease.eq(expectedBalanceIncrease); if (!isRewardRight) { result.passed = false; result.error = "Wrong reward, \n" + "validator: " + block.miner + "\nexpected: " + expectedBalanceIncrease + "\nactual: " + actualBalanceIncrease + "\nblock: " + block.number + "; \n\n"; } return result; } /** * Returns the array of latest blocks. Array length will be equal to the number of validators to fit the round. * * @param numberOfValidators * @returns {Array} */ async function getBlocksFromLatestRound(numberOfValidators) { const lastBlock = await web3.eth.getBlock('latest'); const firstNum = lastBlock.number - numberOfValidators + 1; let blocks = []; for (let i = 0; i < numberOfValidators; i++) { blocks[i] = await web3.eth.getBlock(firstNum + i); } console.log("getBlocksFromLatestRound blocks.length: " + blocks.length); return blocks; }