tokenbridge/monitor/alerts.js

163 lines
5.5 KiB
JavaScript
Raw Normal View History

2019-05-08 16:12:02 +03:00
require('dotenv').config()
const Web3 = require('web3')
const logger = require('./logger')('alerts')
const eventsInfo = require('./utils/events')
const { getBlockNumber } = require('./utils/contract')
const { processedMsgNotDelivered, eventWithoutReference } = require('./utils/message')
2019-09-18 22:45:13 +03:00
const { BRIDGE_MODES } = require('../commons')
2019-05-08 16:12:02 +03:00
Consistent variable naming (#198) * Add console.table * First steps in validate script * env rename * Added parameter names * Descriptions * Print and configuration * Added more parameters * Rename gas oracle to gas supplier * More changes * Removed env examples for now * RPC rename * Bridge address rename * More changes * jobs * Renames * Typo * jobs * Changes * jobs * Changes * Monitor changes * jovs * Typo * Changes * REACT_APP_ env prefix * Typo * Rollback changes * Oracle deployment * Defaults * Monitor * Naming * Typo * Typo * Envs * ui deployment * ALl jobs * Vars in ultimate * Lint * Lint * Lint * Another way to add REACT_APP prefixing * Unnecessary mapping * No output timeout * No output timeout * Got rid of ERC20_TOKEN_ADDRESS * Configuration readme * Configuration * Prefixes * timeout * Docs * Docs * docs * docs * docs * Roll back ERC20_TOKEN_ADDRESS for erc-to-erc * Typo * lint * Rollback * ROllback validator * Rollback yarn.lock * dai and wetc update * Rollback ERC20_TOKEN_ADDRESS * erc to native * examples * all jobs * roll back * roll back ERC20_TOKEN_ADDRESS: "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B" * ui env example * typo * Allow rpc for ultimate * Test * ERC20_TOKEN_ADDRESS rollback * Specify port * React port * All jobs * cosmetics * Values * Restore erc20 token * Rearrange example for easier comparision * Rearrange ultimate for easier comparision * Rearrange for easier comparision * Refactor * Conditional app styles * Loading environment variables in react app * Add missing vars for UI in wetc and dai * Bring back test parameters readme * Readme for monitor vars * Reading environment variables in e2e-commons (#207)
2019-09-13 10:11:38 +03:00
const { COMMON_HOME_RPC_URL, COMMON_FOREIGN_RPC_URL } = process.env
2019-05-08 16:12:02 +03:00
Consistent variable naming (#198) * Add console.table * First steps in validate script * env rename * Added parameter names * Descriptions * Print and configuration * Added more parameters * Rename gas oracle to gas supplier * More changes * Removed env examples for now * RPC rename * Bridge address rename * More changes * jobs * Renames * Typo * jobs * Changes * jobs * Changes * Monitor changes * jovs * Typo * Changes * REACT_APP_ env prefix * Typo * Rollback changes * Oracle deployment * Defaults * Monitor * Naming * Typo * Typo * Envs * ui deployment * ALl jobs * Vars in ultimate * Lint * Lint * Lint * Another way to add REACT_APP prefixing * Unnecessary mapping * No output timeout * No output timeout * Got rid of ERC20_TOKEN_ADDRESS * Configuration readme * Configuration * Prefixes * timeout * Docs * Docs * docs * docs * docs * Roll back ERC20_TOKEN_ADDRESS for erc-to-erc * Typo * lint * Rollback * ROllback validator * Rollback yarn.lock * dai and wetc update * Rollback ERC20_TOKEN_ADDRESS * erc to native * examples * all jobs * roll back * roll back ERC20_TOKEN_ADDRESS: "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B" * ui env example * typo * Allow rpc for ultimate * Test * ERC20_TOKEN_ADDRESS rollback * Specify port * React port * All jobs * cosmetics * Values * Restore erc20 token * Rearrange example for easier comparision * Rearrange ultimate for easier comparision * Rearrange for easier comparision * Refactor * Conditional app styles * Loading environment variables in react app * Add missing vars for UI in wetc and dai * Bring back test parameters readme * Readme for monitor vars * Reading environment variables in e2e-commons (#207)
2019-09-13 10:11:38 +03:00
const homeProvider = new Web3.providers.HttpProvider(COMMON_HOME_RPC_URL)
2019-05-08 16:12:02 +03:00
const web3Home = new Web3(homeProvider)
Consistent variable naming (#198) * Add console.table * First steps in validate script * env rename * Added parameter names * Descriptions * Print and configuration * Added more parameters * Rename gas oracle to gas supplier * More changes * Removed env examples for now * RPC rename * Bridge address rename * More changes * jobs * Renames * Typo * jobs * Changes * jobs * Changes * Monitor changes * jovs * Typo * Changes * REACT_APP_ env prefix * Typo * Rollback changes * Oracle deployment * Defaults * Monitor * Naming * Typo * Typo * Envs * ui deployment * ALl jobs * Vars in ultimate * Lint * Lint * Lint * Another way to add REACT_APP prefixing * Unnecessary mapping * No output timeout * No output timeout * Got rid of ERC20_TOKEN_ADDRESS * Configuration readme * Configuration * Prefixes * timeout * Docs * Docs * docs * docs * docs * Roll back ERC20_TOKEN_ADDRESS for erc-to-erc * Typo * lint * Rollback * ROllback validator * Rollback yarn.lock * dai and wetc update * Rollback ERC20_TOKEN_ADDRESS * erc to native * examples * all jobs * roll back * roll back ERC20_TOKEN_ADDRESS: "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B" * ui env example * typo * Allow rpc for ultimate * Test * ERC20_TOKEN_ADDRESS rollback * Specify port * React port * All jobs * cosmetics * Values * Restore erc20 token * Rearrange example for easier comparision * Rearrange ultimate for easier comparision * Rearrange for easier comparision * Refactor * Conditional app styles * Loading environment variables in react app * Add missing vars for UI in wetc and dai * Bring back test parameters readme * Readme for monitor vars * Reading environment variables in e2e-commons (#207)
2019-09-13 10:11:38 +03:00
const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
2019-05-08 16:12:02 +03:00
const web3Foreign = new Web3(foreignProvider)
async function main() {
2019-09-18 22:45:13 +03:00
const {
homeToForeignRequests,
homeToForeignConfirmations,
foreignToHomeConfirmations,
foreignToHomeRequests,
bridgeMode
} = await eventsInfo()
2019-05-08 16:12:02 +03:00
2019-09-18 22:45:13 +03:00
let xSignatures
let xAffirmations
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
xSignatures = homeToForeignConfirmations.filter(processedMsgNotDelivered(homeToForeignRequests))
xAffirmations = foreignToHomeConfirmations.filter(processedMsgNotDelivered(foreignToHomeRequests))
} else {
xSignatures = homeToForeignConfirmations.filter(eventWithoutReference(homeToForeignRequests))
xAffirmations = foreignToHomeConfirmations.filter(eventWithoutReference(foreignToHomeRequests))
2019-09-18 22:45:13 +03:00
}
2019-05-30 21:05:36 +03:00
logger.debug('building misbehavior blocks')
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
2019-05-08 16:12:02 +03:00
2019-05-30 21:05:36 +03:00
const baseRange = [false, false, false, false, false]
const xSignaturesMisbehavior = buildRangesObject(
xSignatures.map(findMisbehaviorRange(foreignBlockNumber)).reduce(mergeRanges, baseRange)
)
const xAffirmationsMisbehavior = buildRangesObject(
xAffirmations.map(findMisbehaviorRange(homeBlockNumber)).reduce(mergeRanges, baseRange)
)
2019-05-08 16:12:02 +03:00
2019-05-30 21:05:36 +03:00
logger.debug('extracting most recent transactionHash')
const { transactionHash: xSignaturesMostRecentTxHash = '' } = xSignatures.sort(sortEvents).reverse()[0] || {}
const { transactionHash: xAffirmationsMostRecentTxHash = '' } = xAffirmations.sort(sortEvents).reverse()[0] || {}
2019-05-08 16:12:02 +03:00
2019-05-30 21:05:36 +03:00
logger.debug('building transaction objects')
const foreignValidators = await Promise.all(xSignatures.map(event => findTxSender(web3Foreign)(event)))
const homeValidators = await Promise.all(xAffirmations.map(event => findTxSender(web3Home)(event)))
2019-05-08 16:12:02 +03:00
const xSignaturesTxs = xSignatures.reduce(buildTxList(foreignValidators), {})
const xAffirmationsTxs = xAffirmations.reduce(buildTxList(homeValidators), {})
2019-05-08 16:12:02 +03:00
2019-05-30 21:05:36 +03:00
logger.debug('Done')
2019-05-08 16:12:02 +03:00
2019-05-30 21:05:36 +03:00
return {
executeSignatures: {
misbehavior: xSignaturesMisbehavior,
mostRecentTxHash: xSignaturesMostRecentTxHash,
transactions: xSignaturesTxs
},
executeAffirmations: {
misbehavior: xAffirmationsMisbehavior,
mostRecentTxHash: xAffirmationsMostRecentTxHash,
transactions: xAffirmationsTxs
},
lastChecked: Math.floor(Date.now() / 1000)
2019-05-08 16:12:02 +03:00
}
}
/**
* Finds the location for the blockNumber in a specific range starting from currentBlockNumber
* @param {BN} currentBlockNumber
* @returns {function({blockNumber?: *}): boolean[]}
*/
const findMisbehaviorRange = currentBlockNumber => ({ blockNumber }) => {
const minus60 = currentBlockNumber.sub(Web3.utils.toBN(60))
const minus180 = currentBlockNumber.sub(Web3.utils.toBN(180))
const minus720 = currentBlockNumber.sub(Web3.utils.toBN(720))
const minus17280 = currentBlockNumber.sub(Web3.utils.toBN(17280))
return [
minus60.lte(blockNumber),
minus180.lte(blockNumber) && minus60.gt(blockNumber),
minus720.lte(blockNumber) && minus180.gt(blockNumber),
minus17280.lte(blockNumber) && minus720.gt(blockNumber),
minus17280.gt(blockNumber)
]
}
/**
* Merges range arrays into one single array
* @param {Array} acc
* @param {Array} range
* @returns {Array}
*/
const mergeRanges = (acc, range) => acc.map((item, index) => item || range[index])
/**
* Converts an array of boolean into the object representation of the ranges
* @param {Array} range
* @returns {{
* last60blocks: *,
* last60to180blocks: *,
* last180to720blocks: *,
* last720to17280blocks: *,
* last17280blocks: *
* }}
*/
const buildRangesObject = range => ({
last60blocks: range[0],
last60to180blocks: range[1],
last180to720blocks: range[2],
last720to17280blocks: range[3],
before17280blocks: range[4]
})
/**
* Sorts events by blockNumber from oldest to newest
* @param {Object} prev
* @param {Object} next
* @returns {number}
*/
const sortEvents = ({ blockNumber: prev }, { blockNumber: next }) => prev - next
/**
* Retrieves the transaction object and returns the 'from' key from it using the provided web3 instance
* @param {Object} web3
* @returns {function({transactionHash?: *}): Transaction.from}
*/
const findTxSender = web3 => async ({ transactionHash }) => {
const { from } = await web3.eth.getTransaction(transactionHash)
return from
}
/**
* Builds a list of transactions information using the txHash as key
* _validatorsList_ is a correlative list of validators addresses for each event processed
* @param {Array} validatorsList
* @returns {{acc[event.txHash]: {
* value: string,
* block: number,
* referenceTx: string,
* recipient: string,
* validator: string
* }}}
*/
const buildTxList = validatorsList => (acc, event, index) => {
acc[event.transactionHash] = {
2019-05-08 16:12:02 +03:00
value: event.value,
block: event.blockNumber,
referenceTx: event.referenceTx,
recipient: event.recipient,
validator: validatorsList[index]
}
return acc
}
module.exports = main