2019-05-08 16:12:02 +03:00
|
|
|
require('dotenv').config()
|
|
|
|
const logger = require('./logger')('alerts')
|
|
|
|
const eventsInfo = require('./utils/events')
|
2019-10-29 22:22:02 +03:00
|
|
|
const { processedMsgNotDelivered, eventWithoutReference } = require('./utils/message')
|
2019-09-18 22:45:13 +03:00
|
|
|
const { BRIDGE_MODES } = require('../commons')
|
2020-11-04 14:24:42 +03:00
|
|
|
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./utils/web3')
|
2019-05-08 16:12:02 +03:00
|
|
|
|
|
|
|
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 {
|
2019-10-29 22:22:02 +03:00
|
|
|
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')
|
2020-11-04 14:24:42 +03:00
|
|
|
const homeBlockNumber = await getHomeBlockNumber()
|
|
|
|
const foreignBlockNumber = await getForeignBlockNumber()
|
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')
|
2019-08-01 16:10:22 +03:00
|
|
|
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')
|
2019-08-01 16:10:22 +03:00
|
|
|
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
|
|
|
|
2019-10-29 22:22: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
|
2020-11-04 14:24:42 +03:00
|
|
|
* @param {Number} currentBlockNumber
|
2019-05-08 16:12:02 +03:00
|
|
|
* @returns {function({blockNumber?: *}): boolean[]}
|
|
|
|
*/
|
|
|
|
const findMisbehaviorRange = currentBlockNumber => ({ blockNumber }) => {
|
2020-11-04 14:24:42 +03:00
|
|
|
const minus60 = currentBlockNumber - 60
|
|
|
|
const minus180 = currentBlockNumber - 180
|
|
|
|
const minus720 = currentBlockNumber - 720
|
|
|
|
const minus17280 = currentBlockNumber - 17280
|
2019-05-08 16:12:02 +03:00
|
|
|
|
|
|
|
return [
|
2020-11-04 14:24:42 +03:00
|
|
|
minus60 <= blockNumber,
|
|
|
|
minus180 <= blockNumber && minus60 > blockNumber,
|
|
|
|
minus720 <= blockNumber && minus180 > blockNumber,
|
|
|
|
minus17280 <= blockNumber && minus720 > blockNumber,
|
|
|
|
minus17280 > blockNumber
|
2019-05-08 16:12:02 +03:00
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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) => {
|
2019-10-29 22:22:02 +03:00
|
|
|
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
|