diff --git a/oracle-e2e/test/ercToNative.js b/oracle-e2e/test/ercToNative.js index df2df5e2..ef306b4d 100644 --- a/oracle-e2e/test/ercToNative.js +++ b/oracle-e2e/test/ercToNative.js @@ -1,6 +1,5 @@ const Web3 = require('web3') const assert = require('assert') -const promiseRetry = require('promise-retry') const { user, secondUser, @@ -196,211 +195,4 @@ describe('erc to native', () => { ) }) } - it('should not invest dai when chai token is disabled', async () => { - const bridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call() - - await foreignBridge.methods.setMinDaiTokenBalance(foreignWeb3.utils.toWei('2', 'ether')).send({ - from: validator.address, - gas: '1000000' - }) // set min limit for automatic investment to 2*2 dai - - const valueToTransfer = foreignWeb3.utils.toWei('5', 'ether') - - // this transfer won't trigger a call to convert to chai - await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({ - from: user.address, - gas: '1000000' - }) - - await promiseRetry(async (retry, number) => { - if (number < 4) { - retry() - } else { - const updatedBridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call() - assert( - toBN(bridgeDaiTokenBalance) - .add(toBN(valueToTransfer)) - .eq(toBN(updatedBridgeDaiTokenBalance)), - 'Dai tokens should not be when chai is disabled' - ) - } - }) - }) - it('should invest dai after enough tokens are collected on bridge account', async () => { - await foreignBridge.methods.initializeChaiToken().send({ - from: validator.address, - gas: '1000000' - }) // initialize chai token - await foreignBridge.methods.setMinDaiTokenBalance('0').send({ - from: validator.address, - gas: '1000000' - }) // set investing limit to 0 - await foreignBridge.methods.convertDaiToChai().send({ - from: validator.address, - gas: '1000000' - }) // convert all existing dai tokens on bridge account to chai, in order to start from zero balance - await foreignBridge.methods.setMinDaiTokenBalance(foreignWeb3.utils.toWei('2', 'ether')).send({ - from: validator.address, - gas: '1000000' - }) // set investing limit to 2 dai, automatically invest should happen after 4 dai - - const valueToTransfer = foreignWeb3.utils.toWei('3', 'ether') - - // this transfer won't trigger a call to convert to chai - await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({ - from: user.address, - gas: '1000000' - }) - - await promiseRetry(async (retry, number) => { - if (number < 4) { - retry() - } else { - const bridgeDaiTokenBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call() - assert( - valueToTransfer === bridgeDaiTokenBalance, - 'Dai tokens should not be invested automatically before twice limit is reached' - ) - } - }) - - // this transfer will trigger call to convert to chai - await erc20Token.methods.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, valueToTransfer).send({ - from: user.address, - gas: '1000000' - }) - - await promiseRetry(async retry => { - const updatedBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call() - if (toBN(updatedBalance).gte(toBN(valueToTransfer).add(toBN(valueToTransfer)))) { - retry() - } else { - const updatedBalance = await erc20Token.methods.balanceOf(COMMON_FOREIGN_BRIDGE_ADDRESS).call() - assert( - toBN(updatedBalance).eq(toBN(foreignWeb3.utils.toWei('2', 'ether'))), - 'Dai bridge balance should be equal to limit' - ) - } - }) - }) - - if (process.env.ULTIMATE !== 'true') { - describe('handling of chai swaps', async () => { - before(async () => { - // Next tests check validator nonces, this will force every validator to submit signature/affirmation - // Set 3 required signatures for home bridge - await setRequiredSignatures({ - bridgeContract: homeBridge, - web3: homeWeb3, - requiredSignatures: 3, - options: { - from: validator.address, - gas: '4000000' - } - }) - - // Set 3 required signatures for foreign bridge - await setRequiredSignatures({ - bridgeContract: foreignBridge, - web3: foreignWeb3, - requiredSignatures: 3, - options: { - from: validator.address, - gas: '4000000' - } - }) - }) - - it('should not handle transfer event in paying interest', async () => { - await foreignBridge.methods.setInterestReceiver(user.address).send({ - from: validator.address, - gas: '1000000' - }) - const initialNonce = await homeWeb3.eth.getTransactionCount(validator.address) - await foreignBridge.methods.payInterest().send({ - from: user.address, - gas: '1000000' - }) - - await promiseRetry(async (retry, number) => { - if (number < 6) { - retry() - } else { - const nonce = await homeWeb3.eth.getTransactionCount(validator.address) - assert( - nonce === initialNonce, - 'Validator should not process transfer event originated during converting Chai => Dai' - ) - } - }) - }) - - it('should not handle chai withdrawal transfer event in executeSignatures as a regular transfer', async () => { - await foreignBridge.methods.setMinDaiTokenBalance('0').send({ - from: validator.address, - gas: '1000000' - }) // set investing limit to 0 - await foreignBridge.methods.convertDaiToChai().send({ - from: validator.address, - gas: '1000000' - }) // convert all existing dai tokens on bridge account to chai, in order to start from zero balance - - const initialNonce = await homeWeb3.eth.getTransactionCount(validator.address) - - const originalBalance = await erc20Token.methods.balanceOf(user.address).call() - // send transaction to home bridge - await homeWeb3.eth.sendTransaction({ - from: user.address, - to: COMMON_HOME_BRIDGE_ADDRESS, - gasPrice: '1', - gas: '1000000', - value: homeWeb3.utils.toWei('0.01') - }) - - // check that balance increases - await uniformRetry(async retry => { - const balance = await erc20Token.methods.balanceOf(user.address).call() - if (toBN(balance).lte(toBN(originalBalance))) { - retry() - } - }) - - await promiseRetry(async (retry, number) => { - if (number < 6) { - retry() - } else { - const nonce = await homeWeb3.eth.getTransactionCount(validator.address) - assert( - nonce === initialNonce + 1, - 'Validator should not process transfer event originated during converting Chai => Dai' - ) - } - }) - }) - - after(async () => { - // Set 2 required signatures for home bridge - await setRequiredSignatures({ - bridgeContract: homeBridge, - web3: homeWeb3, - requiredSignatures: 2, - options: { - from: validator.address, - gas: '4000000' - } - }) - - // Set 2 required signatures for foreign bridge - await setRequiredSignatures({ - bridgeContract: foreignBridge, - web3: foreignWeb3, - requiredSignatures: 2, - options: { - from: validator.address, - gas: '4000000' - } - }) - }) - }) - } }) diff --git a/oracle/config/convert-to-chai-worker.config.js b/oracle/config/convert-to-chai-worker.config.js deleted file mode 100644 index 8f30b098..00000000 --- a/oracle/config/convert-to-chai-worker.config.js +++ /dev/null @@ -1,20 +0,0 @@ -const baseConfig = require('./base.config') -const { EXIT_CODES } = require('../src/utils/constants') - -const id = `${baseConfig.id}-convert-to-chai` - -const workerRequired = baseConfig.id === 'erc-native' - -if (!workerRequired) { - console.error(`Convert to chai tokens worker not required for bridge mode ${process.env.ORACLE_BRIDGE_MODE}`) - process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED) -} - -module.exports = { - ...baseConfig.bridgeConfig, - ...baseConfig.foreignConfig, - workerQueue: 'convert-to-chai', - senderQueue: 'foreign-prioritized', - name: `worker-${id}`, - id -} diff --git a/oracle/config/transfer-watcher.config.js b/oracle/config/transfer-watcher.config.js index c7c82282..cee7829c 100644 --- a/oracle/config/transfer-watcher.config.js +++ b/oracle/config/transfer-watcher.config.js @@ -29,11 +29,6 @@ if (!transferWatcherRequired) { process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED) } -const workerQueueConfig = {} -if (baseConfig.id === 'erc-native') { - workerQueueConfig.workerQueue = 'convert-to-chai' -} - module.exports = { ...baseConfig.bridgeConfig, ...baseConfig.foreignConfig, @@ -42,7 +37,6 @@ module.exports = { eventAbi: ERC20_ABI, eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS }, queue: 'home-prioritized', - ...workerQueueConfig, name: `watcher-${id}`, id } diff --git a/oracle/docker-compose-erc-native.yml b/oracle/docker-compose-erc-native.yml index a5abc9e1..5cbf7237 100644 --- a/oracle/docker-compose-erc-native.yml +++ b/oracle/docker-compose-erc-native.yml @@ -7,7 +7,6 @@ services: service: rabbit networks: - net_rabbit_bridge_transfer - - net_rabbit_bridge_convert_to_chai_worker redis: extends: file: docker-compose.yml @@ -51,18 +50,6 @@ services: networks: - net_db_bridge_transfer - net_rabbit_bridge_transfer - bridge_convert_to_chai_worker: - cpus: 0.1 - mem_limit: 500m - image: poanetwork/tokenbridge-oracle:latest - env_file: ./.env - environment: - - NODE_ENV=production - - ORACLE_VALIDATOR_ADDRESS=${ORACLE_VALIDATOR_ADDRESS} - restart: unless-stopped - entrypoint: yarn worker:convert-to-chai - networks: - - net_rabbit_bridge_convert_to_chai_worker bridge_senderhome: extends: file: docker-compose.yml @@ -111,5 +98,3 @@ networks: driver: bridge net_rabbit_bridge_senderforeign: driver: bridge - net_rabbit_bridge_convert_to_chai_worker: - driver: bridge diff --git a/oracle/package.json b/oracle/package.json index 76eb2f18..b519df3b 100644 --- a/oracle/package.json +++ b/oracle/package.json @@ -9,7 +9,6 @@ "watcher:collected-signatures": "./scripts/start-worker.sh watcher collected-signatures-watcher", "watcher:affirmation-request": "./scripts/start-worker.sh watcher affirmation-request-watcher", "watcher:transfer": "./scripts/start-worker.sh watcher transfer-watcher", - "worker:convert-to-chai": "./scripts/start-worker.sh worker convert-to-chai-worker", "sender:home": "./scripts/start-worker.sh sender home-sender", "sender:foreign": "./scripts/start-worker.sh sender foreign-sender", "confirm:transfer": "./scripts/start-worker.sh confirmRelay transfer-watcher", diff --git a/oracle/src/confirmRelay.js b/oracle/src/confirmRelay.js index f4ca59f6..262efe39 100644 --- a/oracle/src/confirmRelay.js +++ b/oracle/src/confirmRelay.js @@ -47,7 +47,6 @@ async function initialize() { connectWatcherToQueue({ queueName: config.queue, - workerQueue: config.workerQueue, cb: runMain }) } catch (e) { diff --git a/oracle/src/services/amqpClient.js b/oracle/src/services/amqpClient.js index 588d95e4..b3cc147f 100644 --- a/oracle/src/services/amqpClient.js +++ b/oracle/src/services/amqpClient.js @@ -26,25 +26,18 @@ async function isAttached() { return new Promise(res => dns.lookup(amqpHost, err => res(err === null))) } -function connectWatcherToQueue({ queueName, workerQueue, cb }) { +function connectWatcherToQueue({ queueName, cb }) { const channelWrapper = connection.createChannel({ json: true, async setup(channel) { await channel.assertQueue(queueName, { durable: true, maxPriority: SENDER_QUEUE_MAX_PRIORITY }) - if (workerQueue) { - await channel.assertQueue(workerQueue, { durable: true }) - } } }) const sendToQueue = data => channelWrapper.sendToQueue(queueName, data, { persistent: true, priority: SENDER_QUEUE_SEND_PRIORITY }) - let sendToWorker - if (workerQueue) { - sendToWorker = data => channelWrapper.sendToQueue(workerQueue, data, { persistent: true }) - } - cb({ sendToQueue, sendToWorker, channel: channelWrapper }) + cb({ sendToQueue, channel: channelWrapper }) } function connectSenderToQueue({ queueName, oldQueueName, cb, resendInterval }) { @@ -105,42 +98,6 @@ function connectSenderToQueue({ queueName, oldQueueName, cb, resendInterval }) { }) } -function connectWorkerToQueue({ queueName, senderQueue, cb }) { - const deadLetterExchange = `${queueName}-retry` - - const channelWrapper = connection.createChannel({ - json: true - }) - - channelWrapper.addSetup(async channel => { - await channel.assertExchange(deadLetterExchange, 'fanout', { durable: true }) - await channel.assertQueue(queueName, { durable: true }) - await channel.assertQueue(senderQueue, { durable: true, maxPriority: SENDER_QUEUE_MAX_PRIORITY }) - await channel.bindQueue(queueName, deadLetterExchange) - await channel.prefetch(1) - await channel.consume(queueName, msg => - cb({ - msg, - channel: channelWrapper, - ackMsg: job => channelWrapper.ack(job), - nackMsg: job => channelWrapper.nack(job, false, true), - sendToSenderQueue: data => - channelWrapper.sendToQueue(senderQueue, data, { persistent: true, priority: SENDER_QUEUE_SEND_PRIORITY }), - scheduleForRetry: async (data, msgRetries = 0) => { - await generateRetry({ - data, - msgRetries, - channelWrapper, - channel, - queueName, - deadLetterExchange - }) - } - }) - ) - }) -} - async function generateRetry({ data, msgRetries, channelWrapper, channel, queueName, deadLetterExchange }) { const retries = msgRetries + 1 const delay = getRetrySequence(retries) * 1000 @@ -183,7 +140,6 @@ module.exports = { isAttached, connectWatcherToQueue, connectSenderToQueue, - connectWorkerToQueue, connection, generateRetry } diff --git a/oracle/src/utils/chaiUtils.js b/oracle/src/utils/chaiUtils.js deleted file mode 100644 index 0d82c16e..00000000 --- a/oracle/src/utils/chaiUtils.js +++ /dev/null @@ -1,13 +0,0 @@ -async function isChaiTokenEnabled(bridgeContract, logger) { - logger.debug('Checking Chai availability') - try { - return await bridgeContract.methods.isChaiTokenEnabled().call() - } catch (e) { - logger.debug('Method isChaiTokenEnabled is not supported') - return false - } -} - -module.exports = { - isChaiTokenEnabled -} diff --git a/oracle/src/watcher.js b/oracle/src/watcher.js index 977c6c69..c99fdc4d 100644 --- a/oracle/src/watcher.js +++ b/oracle/src/watcher.js @@ -9,7 +9,6 @@ const { getShutdownFlag } = require('./services/shutdownState') const { getRequiredBlockConfirmations, getEvents } = require('./tx/web3') const { checkHTTPS, watchdog } = require('./utils/utils') const { EXIT_CODES } = require('./utils/constants') -const { isChaiTokenEnabled } = require('./utils/chaiUtils') if (process.argv.length < 3) { logger.error('Please check the number of arguments, config file was not provided') @@ -47,7 +46,6 @@ async function initialize() { await getLastProcessedBlock() connectWatcherToQueue({ queueName: config.queue, - workerQueue: config.workerQueue, cb: runMain }) } catch (e) { @@ -56,16 +54,16 @@ async function initialize() { } } -async function runMain({ sendToQueue, sendToWorker }) { +async function runMain({ sendToQueue }) { try { if (connection.isConnected() && redis.status === 'ready') { if (config.maxProcessingTime) { - await watchdog(() => main({ sendToQueue, sendToWorker }), config.maxProcessingTime, () => { + await watchdog(() => main({ sendToQueue }), config.maxProcessingTime, () => { logger.fatal('Max processing time reached') process.exit(EXIT_CODES.MAX_TIME_REACHED) }) } else { - await main({ sendToQueue, sendToWorker }) + await main({ sendToQueue }) } } } catch (e) { @@ -73,7 +71,7 @@ async function runMain({ sendToQueue, sendToWorker }) { } setTimeout(() => { - runMain({ sendToQueue, sendToWorker }) + runMain({ sendToQueue }) }, config.pollingInterval) } @@ -147,16 +145,7 @@ async function getLastBlockToProcess() { return lastBlockNumber.sub(requiredBlockConfirmations) } -async function isWorkerNeeded() { - switch (config.id) { - case 'erc-native-transfer': - return isChaiTokenEnabled(bridgeContract, logger) - default: - return true - } -} - -async function main({ sendToQueue, sendToWorker }) { +async function main({ sendToQueue }) { try { const wasShutdown = await getShutdownFlag(logger, config.shutdownKey, false) if (await getShutdownFlag(logger, config.shutdownKey, true)) { @@ -191,10 +180,6 @@ async function main({ sendToQueue, sendToWorker }) { logger.info(`Found ${events.length} ${config.event} events`) if (events.length) { - if (sendToWorker && (await isWorkerNeeded())) { - await sendToWorker({ blockNumber: toBlock.toString() }) - } - const job = await processEvents(events) logger.info('Transactions to send:', job.length) diff --git a/oracle/src/worker.js b/oracle/src/worker.js deleted file mode 100644 index 6fcff505..00000000 --- a/oracle/src/worker.js +++ /dev/null @@ -1,73 +0,0 @@ -const path = require('path') -const logger = require('./services/logger') -const { checkHTTPS, watchdog } = require('./utils/utils') -const { EXIT_CODES } = require('./utils/constants') -const { connectWorkerToQueue } = require('./services/amqpClient') - -const config = require(path.join('../config/', process.argv[2])) - -const convertToChai = require('./workers/convertToChai')(config) - -const web3Instance = config.web3 - -async function initialize() { - try { - const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger) - - web3Instance.currentProvider.urls.forEach(checkHttps(config.chain)) - - connectWorkerToQueue({ - queueName: config.workerQueue, - senderQueue: config.senderQueue, - cb: options => { - if (config.maxProcessingTime) { - return watchdog(() => main(options), config.maxProcessingTime, () => { - logger.fatal('Max processing time reached') - process.exit(EXIT_CODES.MAX_TIME_REACHED) - }) - } - - return main(options) - } - }) - } catch (e) { - logger.error(e.message) - process.exit(EXIT_CODES.GENERAL_ERROR) - } -} - -async function run(blockNumber) { - if (config.id === 'erc-native-convert-to-chai') { - return convertToChai(blockNumber) - } else { - return [] - } -} - -async function main({ msg, ackMsg, nackMsg, sendToSenderQueue, scheduleForRetry }) { - try { - const { blockNumber } = JSON.parse(msg.content) - logger.info(`Msg received with block number ${blockNumber}`) - - try { - const job = await run(blockNumber) - - logger.info('Transactions to send:', job.length) - - if (job.length) { - await sendToSenderQueue(job) - } - } catch (e) { - logger.info(`Sending failed msg to retry`) - await scheduleForRetry({ blockNumber }, msg.properties.headers['x-retries']) - } - - ackMsg(msg) - } catch (e) { - logger.error(e) - nackMsg(msg) - } - logger.debug(`Finished worker operation`) -} - -initialize() diff --git a/oracle/src/workers/convertToChai.js b/oracle/src/workers/convertToChai.js deleted file mode 100644 index 71c48638..00000000 --- a/oracle/src/workers/convertToChai.js +++ /dev/null @@ -1,80 +0,0 @@ -require('../../env') -const { HttpListProviderError } = require('../services/HttpListProvider') -const rootLogger = require('../services/logger') -const { web3Foreign } = require('../services/web3') - -const { BRIDGE_VALIDATORS_ABI } = require('../../../commons') - -let validatorContract = null - -function convertToChaiBuilder(config) { - const foreignBridge = new web3Foreign.eth.Contract(config.foreignBridgeAbi, config.foreignBridgeAddress) - return async function convertToChai(blockNumber) { - const txToSend = [] - - const logger = rootLogger.child({ - blockNumber: blockNumber.toString() - }) - - logger.debug(`Starting convert to chai operation`) - - if (validatorContract === null) { - logger.debug('Getting validator contract address') - const validatorContractAddress = await foreignBridge.methods.validatorContract().call() - logger.debug({ validatorContractAddress }, 'Validator contract address obtained') - - validatorContract = new web3Foreign.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorContractAddress) - } - - logger.debug(`Checking if is validator duty`) - const validatorDuty = await validatorContract.methods.isValidatorDuty(config.validatorAddress).call() - - if (!validatorDuty) { - logger.info(`Convert to chai discarded because is not validator duty`) - return txToSend - } - - logger.debug(`Checking if dai token balance is above the threshold`) - const daiNeedsToBeInvested = await foreignBridge.methods.isDaiNeedsToBeInvested().call() - - if (!daiNeedsToBeInvested) { - logger.info(`Convert to chai discarded because dai balance is below the threshold or chai token is not set`) - return txToSend - } - - let gasEstimate - - try { - logger.debug(`Estimate gas`) - gasEstimate = await foreignBridge.methods.convertDaiToChai().estimateGas({ - from: config.validatorAddress - }) - - logger.debug({ gasEstimate }, 'Gas estimated') - } catch (e) { - if (e instanceof HttpListProviderError) { - const errorMsg = 'RPC Connection Error: convertToChai Gas Estimate cannot be obtained.' - logger.error(e, errorMsg) - throw new Error(errorMsg) - } else { - logger.error(e, 'Unknown error while processing transaction') - throw e - } - } - - // generate data - const data = await foreignBridge.methods.convertDaiToChai().encodeABI() - - // push to job - txToSend.push({ - data, - gasEstimate, - transactionReference: `convert to chai operation for block number ${blockNumber.toString()}`, - to: config.foreignBridgeAddress - }) - - return txToSend - } -} - -module.exports = convertToChaiBuilder