187 lines
7.1 KiB
JavaScript
187 lines
7.1 KiB
JavaScript
require('dotenv').config()
|
|
const Web3Utils = require('web3').utils
|
|
const logger = require('./logger')('validators')
|
|
const { getBridgeABIs, BRIDGE_VALIDATORS_ABI, gasPriceFromSupplier } = require('../commons')
|
|
const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./utils/web3')
|
|
const { getValidatorList } = require('./utils/getValidatorsList')
|
|
|
|
const {
|
|
COMMON_HOME_BRIDGE_ADDRESS,
|
|
COMMON_FOREIGN_BRIDGE_ADDRESS,
|
|
COMMON_HOME_GAS_PRICE_SUPPLIER_URL,
|
|
COMMON_HOME_GAS_PRICE_SPEED_TYPE,
|
|
COMMON_HOME_GAS_PRICE_FALLBACK,
|
|
COMMON_HOME_GAS_PRICE_FACTOR,
|
|
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL,
|
|
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE,
|
|
COMMON_FOREIGN_GAS_PRICE_FALLBACK,
|
|
COMMON_FOREIGN_GAS_PRICE_FACTOR,
|
|
MONITOR_FOREIGN_VALIDATORS_BALANCE_ENABLE,
|
|
MONITOR_HOME_VALIDATORS_BALANCE_ENABLE
|
|
} = process.env
|
|
const MONITOR_VALIDATOR_HOME_TX_LIMIT = Number(process.env.MONITOR_VALIDATOR_HOME_TX_LIMIT) || 0
|
|
const MONITOR_VALIDATOR_FOREIGN_TX_LIMIT = Number(process.env.MONITOR_VALIDATOR_FOREIGN_TX_LIMIT) || 0
|
|
const MONITOR_TX_NUMBER_THRESHOLD = Number(process.env.MONITOR_TX_NUMBER_THRESHOLD) || 100
|
|
|
|
const homeGasPriceSupplierOpts = {
|
|
speedType: COMMON_HOME_GAS_PRICE_SPEED_TYPE,
|
|
factor: COMMON_HOME_GAS_PRICE_FACTOR,
|
|
logger
|
|
}
|
|
|
|
const foreignGasPriceSupplierOpts = {
|
|
speedType: COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE,
|
|
factor: COMMON_FOREIGN_GAS_PRICE_FACTOR,
|
|
logger
|
|
}
|
|
|
|
async function main(bridgeMode) {
|
|
const { HOME_ABI, FOREIGN_ABI } = getBridgeABIs(bridgeMode)
|
|
const homeBridge = new web3Home.eth.Contract(HOME_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
|
const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
|
const homeValidatorsAddress = await homeBridge.methods.validatorContract().call()
|
|
const homeBridgeValidators = new web3Home.eth.Contract(BRIDGE_VALIDATORS_ABI, homeValidatorsAddress)
|
|
|
|
logger.debug('getting last block numbers')
|
|
const homeBlockNumber = await getHomeBlockNumber()
|
|
const foreignBlockNumber = await getForeignBlockNumber()
|
|
const homeConfirmations = await homeBridge.methods.requiredBlockConfirmations().call()
|
|
const foreignConfirmations = await foreignBridge.methods.requiredBlockConfirmations().call()
|
|
const homeDelayedBlockNumber = homeBlockNumber - homeConfirmations
|
|
const foreignDelayedBlockNumber = foreignBlockNumber - foreignConfirmations
|
|
|
|
logger.debug('calling foreignBridge.methods.validatorContract().call()')
|
|
const foreignValidatorsAddress = await foreignBridge.methods.validatorContract().call()
|
|
const foreignBridgeValidators = new web3Foreign.eth.Contract(BRIDGE_VALIDATORS_ABI, foreignValidatorsAddress)
|
|
|
|
logger.debug('calling foreignBridgeValidators getValidatorList()')
|
|
const foreignValidators = (await getValidatorList(foreignValidatorsAddress, web3Foreign.eth, {
|
|
toBlock: foreignBlockNumber,
|
|
logger,
|
|
chain: 'foreign',
|
|
safeToBlock: foreignDelayedBlockNumber
|
|
})).map(web3Foreign.utils.toChecksumAddress)
|
|
|
|
logger.debug('calling homeBridgeValidators getValidatorList()')
|
|
const homeValidators = (await getValidatorList(homeValidatorsAddress, web3Home.eth, {
|
|
toBlock: homeBlockNumber,
|
|
logger,
|
|
chain: 'home',
|
|
safeToBlock: homeDelayedBlockNumber
|
|
})).map(web3Home.utils.toChecksumAddress)
|
|
|
|
const foreignVBalances = {}
|
|
const homeVBalances = {}
|
|
|
|
let homeGasPrice
|
|
let homeGasPriceGwei
|
|
let homeTxCost
|
|
|
|
if (MONITOR_VALIDATOR_HOME_TX_LIMIT) {
|
|
logger.debug('calling home getGasPrices')
|
|
homeGasPrice =
|
|
(await gasPriceFromSupplier(COMMON_HOME_GAS_PRICE_SUPPLIER_URL, homeGasPriceSupplierOpts)) ||
|
|
Web3Utils.toBN(COMMON_HOME_GAS_PRICE_FALLBACK)
|
|
homeGasPriceGwei = Web3Utils.fromWei(homeGasPrice.toString(), 'gwei')
|
|
homeTxCost = homeGasPrice.mul(Web3Utils.toBN(MONITOR_VALIDATOR_HOME_TX_LIMIT))
|
|
}
|
|
|
|
let foreignGasPrice
|
|
let foreignGasPriceGwei
|
|
let foreignTxCost
|
|
|
|
if (MONITOR_VALIDATOR_FOREIGN_TX_LIMIT) {
|
|
logger.debug('calling foreign getGasPrices')
|
|
|
|
foreignGasPrice =
|
|
(await gasPriceFromSupplier(COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL, foreignGasPriceSupplierOpts)) ||
|
|
Web3Utils.toBN(COMMON_FOREIGN_GAS_PRICE_FALLBACK)
|
|
foreignGasPriceGwei = Web3Utils.fromWei(foreignGasPrice.toString(), 'gwei')
|
|
foreignTxCost = foreignGasPrice.mul(Web3Utils.toBN(MONITOR_VALIDATOR_FOREIGN_TX_LIMIT))
|
|
}
|
|
|
|
let validatorsMatch = true
|
|
const foreignValidatorsWithBalanceCheck =
|
|
typeof MONITOR_FOREIGN_VALIDATORS_BALANCE_ENABLE === 'string'
|
|
? MONITOR_FOREIGN_VALIDATORS_BALANCE_ENABLE.split(' ')
|
|
: foreignValidators
|
|
logger.debug('getting foreignValidators balances')
|
|
await Promise.all(
|
|
foreignValidators.map(async v => {
|
|
foreignVBalances[v] = {}
|
|
if (foreignValidatorsWithBalanceCheck.includes(v)) {
|
|
const balance = await web3Foreign.eth.getBalance(v)
|
|
foreignVBalances[v].balance = Web3Utils.fromWei(balance)
|
|
if (MONITOR_VALIDATOR_FOREIGN_TX_LIMIT) {
|
|
foreignVBalances[v].leftTx = Number(
|
|
Web3Utils.toBN(balance)
|
|
.div(foreignTxCost)
|
|
.toString(10)
|
|
)
|
|
foreignVBalances[v].gasPrice = parseFloat(foreignGasPriceGwei)
|
|
}
|
|
}
|
|
|
|
if (!homeValidators.includes(v)) {
|
|
validatorsMatch = false
|
|
foreignVBalances[v].onlyOnForeign = true
|
|
}
|
|
})
|
|
)
|
|
|
|
const homeValidatorsWithBalanceCheck =
|
|
typeof MONITOR_HOME_VALIDATORS_BALANCE_ENABLE === 'string'
|
|
? MONITOR_HOME_VALIDATORS_BALANCE_ENABLE.split(' ')
|
|
: homeValidators
|
|
logger.debug('calling homeValidators balances')
|
|
await Promise.all(
|
|
homeValidators.map(async v => {
|
|
homeVBalances[v] = {}
|
|
if (homeValidatorsWithBalanceCheck.includes(v)) {
|
|
const balance = await web3Home.eth.getBalance(v)
|
|
homeVBalances[v].balance = Web3Utils.fromWei(balance)
|
|
if (MONITOR_VALIDATOR_HOME_TX_LIMIT) {
|
|
homeVBalances[v].leftTx = Number(
|
|
Web3Utils.toBN(balance)
|
|
.div(homeTxCost)
|
|
.toString(10)
|
|
)
|
|
homeVBalances[v].gasPrice = parseFloat(homeGasPriceGwei)
|
|
}
|
|
}
|
|
|
|
if (!foreignValidators.includes(v)) {
|
|
validatorsMatch = false
|
|
homeVBalances[v].onlyOnHome = true
|
|
}
|
|
})
|
|
)
|
|
|
|
logger.debug('calling homeBridgeValidators.methods.requiredSignatures().call()')
|
|
const reqSigHome = await homeBridgeValidators.methods.requiredSignatures().call()
|
|
logger.debug('calling foreignBridgeValidators.methods.requiredSignatures().call()')
|
|
const reqSigForeign = await foreignBridgeValidators.methods.requiredSignatures().call()
|
|
logger.debug('Done')
|
|
return {
|
|
home: {
|
|
validators: homeVBalances,
|
|
requiredSignatures: Number(reqSigHome)
|
|
},
|
|
foreign: {
|
|
validators: foreignVBalances,
|
|
requiredSignatures: Number(reqSigForeign)
|
|
},
|
|
requiredSignaturesMatch: reqSigHome === reqSigForeign,
|
|
validatorsMatch,
|
|
lastChecked: Math.floor(Date.now() / 1000),
|
|
homeOk: Object.values(homeVBalances)
|
|
.filter(vb => typeof vb.leftTx === 'number')
|
|
.every(vb => vb.leftTx >= MONITOR_TX_NUMBER_THRESHOLD),
|
|
foreignOk: Object.values(foreignVBalances)
|
|
.filter(vb => typeof vb.leftTx === 'number')
|
|
.every(vb => vb.leftTx >= MONITOR_TX_NUMBER_THRESHOLD)
|
|
}
|
|
}
|
|
|
|
module.exports = main
|