From f43e99cd642c1d540d52eb35c1973e549247e3e3 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 25 Sep 2018 11:43:38 -0300 Subject: [PATCH 01/62] Add ERC20-to-Native contract abis --- abis/ForeignBridgeErcToNative.abi.json | 452 ++++++++++++++++ abis/HomeBridgeErcToNative.abi.json | 716 +++++++++++++++++++++++++ 2 files changed, 1168 insertions(+) create mode 100644 abis/ForeignBridgeErcToNative.abi.json create mode 100644 abis/HomeBridgeErcToNative.abi.json diff --git a/abis/ForeignBridgeErcToNative.abi.json b/abis/ForeignBridgeErcToNative.abi.json new file mode 100644 index 0000000..45fc322 --- /dev/null +++ b/abis/ForeignBridgeErcToNative.abi.json @@ -0,0 +1,452 @@ +[ + { + "constant": true, + "inputs": [ + { + "name": "_txHash", + "type": "bytes32" + } + ], + "name": "relayedMessages", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "vs", + "type": "uint8[]" + }, + { + "name": "rs", + "type": "bytes32[]" + }, + { + "name": "ss", + "type": "bytes32[]" + }, + { + "name": "message", + "type": "bytes" + } + ], + "name": "executeSignatures", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_day", + "type": "uint256" + } + ], + "name": "totalSpentPerDay", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentDay", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "requiredBlockConfirmations", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "dailyLimit", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "requiredSignatures", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "validatorContract", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "deployedAtBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBridgeInterfacesVersion", + "outputs": [ + { + "name": "major", + "type": "uint64" + }, + { + "name": "minor", + "type": "uint64" + }, + { + "name": "patch", + "type": "uint64" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_minPerTx", + "type": "uint256" + } + ], + "name": "setMinPerTx", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_blockConfirmations", + "type": "uint256" + } + ], + "name": "setRequiredBlockConfirmations", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_dailyLimit", + "type": "uint256" + } + ], + "name": "setDailyLimit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_gasPrice", + "type": "uint256" + } + ], + "name": "setGasPrice", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_maxPerTx", + "type": "uint256" + } + ], + "name": "setMaxPerTx", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minPerTx", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "withinLimit", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxPerTx", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "gasPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "name": "transactionHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "gasPrice", + "type": "uint256" + } + ], + "name": "GasPriceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "requiredBlockConfirmations", + "type": "uint256" + } + ], + "name": "RequiredBlockConfirmationChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newLimit", + "type": "uint256" + } + ], + "name": "DailyLimitChanged", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "name": "_validatorContract", + "type": "address" + }, + { + "name": "_erc20token", + "type": "address" + }, + { + "name": "_requiredBlockConfirmations", + "type": "uint256" + }, + { + "name": "_gasPrice", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBridgeMode", + "outputs": [ + { + "name": "_data", + "type": "bytes4" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_token", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "name": "claimTokens", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "erc20token", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/abis/HomeBridgeErcToNative.abi.json b/abis/HomeBridgeErcToNative.abi.json new file mode 100644 index 0000000..53eefd4 --- /dev/null +++ b/abis/HomeBridgeErcToNative.abi.json @@ -0,0 +1,716 @@ +[ + { + "constant": true, + "inputs": [ + { + "name": "_message", + "type": "bytes32" + } + ], + "name": "numMessagesSigned", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_hash", + "type": "bytes32" + }, + { + "name": "_index", + "type": "uint256" + } + ], + "name": "signature", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_day", + "type": "uint256" + } + ], + "name": "totalSpentPerDay", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentDay", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "requiredBlockConfirmations", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "requiredMessageLength", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_hash", + "type": "bytes32" + } + ], + "name": "message", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "signature", + "type": "bytes" + }, + { + "name": "message", + "type": "bytes" + } + ], + "name": "submitSignature", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "dailyLimit", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_token", + "type": "address" + }, + { + "name": "_to", + "type": "address" + } + ], + "name": "claimTokens", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_withdrawal", + "type": "bytes32" + } + ], + "name": "numAffirmationsSigned", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_withdrawal", + "type": "bytes32" + } + ], + "name": "affirmationsSigned", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "requiredSignatures", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_message", + "type": "bytes32" + } + ], + "name": "messagesSigned", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "validatorContract", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "recipient", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "transactionHash", + "type": "bytes32" + } + ], + "name": "executeAffirmation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "deployedAtBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBridgeInterfacesVersion", + "outputs": [ + { + "name": "major", + "type": "uint64" + }, + { + "name": "minor", + "type": "uint64" + }, + { + "name": "patch", + "type": "uint64" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_minPerTx", + "type": "uint256" + } + ], + "name": "setMinPerTx", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_blockConfirmations", + "type": "uint256" + } + ], + "name": "setRequiredBlockConfirmations", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_dailyLimit", + "type": "uint256" + } + ], + "name": "setDailyLimit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_gasPrice", + "type": "uint256" + } + ], + "name": "setGasPrice", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_maxPerTx", + "type": "uint256" + } + ], + "name": "setMaxPerTx", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minPerTx", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "withinLimit", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxPerTx", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "gasPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_number", + "type": "uint256" + } + ], + "name": "isAlreadyProcessed", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "UserRequestForSignature", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "name": "transactionHash", + "type": "bytes32" + } + ], + "name": "AffirmationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "signer", + "type": "address" + }, + { + "indexed": false, + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "SignedForUserRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "signer", + "type": "address" + }, + { + "indexed": false, + "name": "transactionHash", + "type": "bytes32" + } + ], + "name": "SignedForAffirmation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "authorityResponsibleForRelay", + "type": "address" + }, + { + "indexed": false, + "name": "messageHash", + "type": "bytes32" + }, + { + "indexed": false, + "name": "NumberOfCollectedSignatures", + "type": "uint256" + } + ], + "name": "CollectedSignatures", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "gasPrice", + "type": "uint256" + } + ], + "name": "GasPriceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "requiredBlockConfirmations", + "type": "uint256" + } + ], + "name": "RequiredBlockConfirmationChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newLimit", + "type": "uint256" + } + ], + "name": "DailyLimitChanged", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "name": "_validatorContract", + "type": "address" + }, + { + "name": "_dailyLimit", + "type": "uint256" + }, + { + "name": "_maxPerTx", + "type": "uint256" + }, + { + "name": "_minPerTx", + "type": "uint256" + }, + { + "name": "_homeGasPrice", + "type": "uint256" + }, + { + "name": "_requiredBlockConfirmations", + "type": "uint256" + }, + { + "name": "_blockReward", + "type": "address" + } + ], + "name": "initialize", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBridgeMode", + "outputs": [ + { + "name": "_data", + "type": "bytes4" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "blockRewardContract", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBurntCoins", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_blockReward", + "type": "address" + } + ], + "name": "setBlockRewardContract", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] From 9487e38e6adda86feced5984ad449508b343eee9 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 25 Sep 2018 11:44:53 -0300 Subject: [PATCH 02/62] Add support ERC20-to-Native --- config/affirmation-request-watcher.config.js | 43 ++++++++++--------- config/base.config.js | 38 ++++++++++++---- config/collected-signatures-watcher.config.js | 2 +- config/signature-request-watcher.config.js | 2 +- src/services/gasPrice.js | 10 ++--- src/watcher.js | 15 ++++--- 6 files changed, 66 insertions(+), 44 deletions(-) diff --git a/config/affirmation-request-watcher.config.js b/config/affirmation-request-watcher.config.js index b1961aa..24e770d 100644 --- a/config/affirmation-request-watcher.config.js +++ b/config/affirmation-request-watcher.config.js @@ -2,25 +2,26 @@ require('dotenv').config() const baseConfig = require('./base.config') const erc20Abi = require('../abis/ERC20.abi') -const id = baseConfig.isErcToErc ? 'erc-affirmation-request' : 'affirmation-request' +const id = `${baseConfig.id}-affirmation-request` -module.exports = baseConfig.isErcToErc - ? { - ...baseConfig.bridgeConfig, - ...baseConfig.foreignConfig, - event: 'Transfer', - eventContractAddress: process.env.ERC20_TOKEN_ADDRESS, - eventAbi: erc20Abi, - eventFilter: { to: process.env.FOREIGN_BRIDGE_ADDRESS }, - queue: 'home', - name: `watcher-${id}`, - id - } - : { - ...baseConfig.bridgeConfig, - ...baseConfig.foreignConfig, - event: 'UserRequestForAffirmation', - queue: 'home', - name: `watcher-${id}`, - id - } +module.exports = + baseConfig.id === 'erc-erc' || baseConfig.id === 'erc-native' + ? { + ...baseConfig.bridgeConfig, + ...baseConfig.foreignConfig, + event: 'Transfer', + eventContractAddress: process.env.ERC20_TOKEN_ADDRESS, + eventAbi: erc20Abi, + eventFilter: { to: process.env.FOREIGN_BRIDGE_ADDRESS }, + queue: 'home', + name: `watcher-${id}`, + id + } + : { + ...baseConfig.bridgeConfig, + ...baseConfig.foreignConfig, + event: 'UserRequestForAffirmation', + queue: 'home', + name: `watcher-${id}`, + id + } diff --git a/config/base.config.js b/config/base.config.js index 171113f..9673be4 100644 --- a/config/base.config.js +++ b/config/base.config.js @@ -2,16 +2,38 @@ require('dotenv').config() const { web3Home, web3Foreign } = require('../src/services/web3') -const homeNativeAbi = require('../abis/HomeBridgeNativeToErc.abi') -const foreignNativeAbi = require('../abis/ForeignBridgeNativeToErc.abi') +const homeNativeErcAbi = require('../abis/HomeBridgeNativeToErc.abi') +const foreignNativeErcAbi = require('../abis/ForeignBridgeNativeToErc.abi') -const homeErcAbi = require('../abis/HomeBridgeErcToErc.abi') -const foreignErcAbi = require('../abis/ForeignBridgeErcToErc.abi') +const homeErcErcAbi = require('../abis/HomeBridgeErcToErc.abi') +const foreignErcErcAbi = require('../abis/ForeignBridgeErcToErc.abi') -const isErcToErc = process.env.BRIDGE_MODE && process.env.BRIDGE_MODE === 'ERC_TO_ERC' +const homeErcNativeAbi = require('../abis/HomeBridgeErcToNative.abi') +const foreignErcNativeAbi = require('../abis/ForeignBridgeErcToNative.abi') -const homeAbi = isErcToErc ? homeErcAbi : homeNativeAbi -const foreignAbi = isErcToErc ? foreignErcAbi : foreignNativeAbi +let homeAbi +let foreignAbi +let id + +switch (process.env.BRIDGE_MODE) { + case 'NATIVE_TO_ERC': + homeAbi = homeNativeErcAbi + foreignAbi = foreignNativeErcAbi + id = 'native-erc' + break + case 'ERC_TO_ERC': + homeAbi = homeErcErcAbi + foreignAbi = foreignErcErcAbi + id = 'erc-erc' + break + case 'ERC_TO_NATIVE': + homeAbi = homeErcNativeAbi + foreignAbi = foreignErcNativeAbi + id = 'erc-native' + break + default: + throw new Error(`Bridge Mode: ${process.env.BRIDGE_MODE} not supported.`) +} const bridgeConfig = { homeBridgeAddress: process.env.HOME_BRIDGE_ADDRESS, @@ -45,5 +67,5 @@ module.exports = { bridgeConfig, homeConfig, foreignConfig, - isErcToErc + id } diff --git a/config/collected-signatures-watcher.config.js b/config/collected-signatures-watcher.config.js index dcca2a7..cdffa34 100644 --- a/config/collected-signatures-watcher.config.js +++ b/config/collected-signatures-watcher.config.js @@ -1,6 +1,6 @@ const baseConfig = require('./base.config') -const id = baseConfig.isErcToErc ? 'erc-collected-signatures' : 'collected-signatures' +const id = `${baseConfig.id}-collected-signatures` module.exports = { ...baseConfig.bridgeConfig, diff --git a/config/signature-request-watcher.config.js b/config/signature-request-watcher.config.js index d80e371..a487c43 100644 --- a/config/signature-request-watcher.config.js +++ b/config/signature-request-watcher.config.js @@ -1,6 +1,6 @@ const baseConfig = require('./base.config') -const id = baseConfig.isErcToErc ? 'erc-signature-request' : 'signature-request' +const id = `${baseConfig.id}-signature-request` module.exports = { ...baseConfig.bridgeConfig, diff --git a/src/services/gasPrice.js b/src/services/gasPrice.js index 4768122..05178aa 100644 --- a/src/services/gasPrice.js +++ b/src/services/gasPrice.js @@ -1,15 +1,11 @@ require('dotenv').config() const fetch = require('node-fetch') const { web3Home, web3Foreign } = require('../services/web3') -const { isErcToErc } = require('../../config/base.config') -const HomeNativeABI = require('../../abis/HomeBridgeNativeToErc.abi') -const ForeignNativeABI = require('../../abis/ForeignBridgeNativeToErc.abi') -const HomeErcABI = require('../../abis/HomeBridgeErcToErc.abi') -const ForeignErcABI = require('../../abis/ForeignBridgeErcToErc.abi') +const { bridgeConfig } = require('../../config/base.config') const logger = require('../services/logger') -const HomeABI = isErcToErc ? HomeErcABI : HomeNativeABI -const ForeignABI = isErcToErc ? ForeignNativeABI : ForeignErcABI +const HomeABI = bridgeConfig.homeBridgeAbi +const ForeignABI = bridgeConfig.foreignBridgeAbi const { FOREIGN_BRIDGE_ADDRESS, diff --git a/src/watcher.js b/src/watcher.js index 3e748c6..9dc01fd 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -70,15 +70,18 @@ function updateLastProcessedBlock(lastBlockNumber) { function processEvents(events) { switch (config.id) { - case 'signature-request': - case 'erc-signature-request': + case 'native-erc-signature-request': + case 'erc-erc-signature-request': + case 'erc-native-signature-request': return processSignatureRequests(events) - case 'collected-signatures': - case 'erc-collected-signatures': + case 'native-erc-collected-signatures': + case 'erc-erc-collected-signatures': + case 'erc-native-collected-signatures': return processCollectedSignatures(events) - case 'affirmation-request': + case 'native-erc-affirmation-request': return processAffirmationRequests(events) - case 'erc-affirmation-request': + case 'erc-erc-affirmation-request': + case 'erc-native-affirmation-request': return processTransfers(events) default: return [] From 54b3e4ba870d363db417cabd51d14640e8d71929 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 25 Sep 2018 11:47:37 -0300 Subject: [PATCH 03/62] Update blocks related scripts --- scripts/getValidatorStartBlocks.js | 10 +++------- scripts/resetLastBlock.js | 5 ++--- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/scripts/getValidatorStartBlocks.js b/scripts/getValidatorStartBlocks.js index c8bf491..39d8a1f 100644 --- a/scripts/getValidatorStartBlocks.js +++ b/scripts/getValidatorStartBlocks.js @@ -3,18 +3,14 @@ require('dotenv').config({ path: path.join(__dirname, '../.env') }) const Web3 = require('web3') -const HomeNativeABI = require('../abis/HomeBridgeNativeToErc.abi') -const ForeignNativeABI = require('../abis/ForeignBridgeNativeToErc.abi') -const HomeErcABI = require('../abis/HomeBridgeErcToErc.abi') -const ForeignErcABI = require('../abis/ForeignBridgeErcToErc.abi') const bridgeValidatorsABI = require('../abis/BridgeValidators.abi') const rpcUrlsManager = require('../src/services/getRpcUrlsManager') -const isErcToErc = process.env.BRIDGE_MODE && process.env.BRIDGE_MODE === 'ERC_TO_ERC' +const { bridgeConfig } = require('../config/base.config') -const homeABI = isErcToErc ? HomeErcABI : HomeNativeABI -const foreignABI = isErcToErc ? ForeignNativeABI : ForeignErcABI +const homeABI = bridgeConfig.homeBridgeAbi +const foreignABI = bridgeConfig.foreignBridgeAbi async function getStartBlock(rpcUrl, bridgeAddress, bridgeAbi) { try { diff --git a/scripts/resetLastBlock.js b/scripts/resetLastBlock.js index 4ed6be5..a985677 100644 --- a/scripts/resetLastBlock.js +++ b/scripts/resetLastBlock.js @@ -3,6 +3,7 @@ const path = require('path') require('dotenv').config({ path: path.join(__dirname, '../.env') }) +const { id } = require('../config/base.config') const redis = new Redis(process.env.REDIS_URL) @@ -25,9 +26,7 @@ function logError(message) { } function getRedisKey(name) { - const isErcToErc = process.env.BRIDGE_MODE && process.env.BRIDGE_MODE === 'ERC_TO_ERC' - const prefix = isErcToErc ? 'erc-' : '' - return `${prefix}${name}:lastProcessedBlock` + return `${id}-${name}:lastProcessedBlock` } async function main() { From 9966070801465dd672745276c126c16a6975d855 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 25 Sep 2018 12:03:39 -0300 Subject: [PATCH 04/62] Update transactions scripts --- .../sendForeign.js} | 6 +- .../sendHome.js} | 6 +- scripts/erc20_to_native/sendForeign.js | 95 +++++++++++++++++++ .../sendHome.js} | 8 +- .../sendForeign.js} | 6 +- scripts/native_to_erc20/sendHome.js | 55 +++++++++++ 6 files changed, 163 insertions(+), 13 deletions(-) rename scripts/{sendUserTxToErcForeign.js => erc20_to_erc20/sendForeign.js} (92%) rename scripts/{sendUserTxToErcHome.js => erc20_to_erc20/sendHome.js} (93%) create mode 100644 scripts/erc20_to_native/sendForeign.js rename scripts/{sendUserTxToHome.js => erc20_to_native/sendHome.js} (86%) rename scripts/{sendUserTxToForeign.js => native_to_erc20/sendForeign.js} (92%) create mode 100644 scripts/native_to_erc20/sendHome.js diff --git a/scripts/sendUserTxToErcForeign.js b/scripts/erc20_to_erc20/sendForeign.js similarity index 92% rename from scripts/sendUserTxToErcForeign.js rename to scripts/erc20_to_erc20/sendForeign.js index b093b7c..f636985 100644 --- a/scripts/sendUserTxToErcForeign.js +++ b/scripts/erc20_to_erc20/sendForeign.js @@ -1,11 +1,11 @@ const path = require('path') require('dotenv').config({ - path: path.join(__dirname, '../.env') + path: path.join(__dirname, '../../.env') }) const Web3 = require('web3') const Web3Utils = require('web3-utils') -const rpcUrlsManager = require('../src/services/getRpcUrlsManager') -const { sendTx, sendRawTx } = require('../src/tx/sendTx') +const rpcUrlsManager = require('../../src/services/getRpcUrlsManager') +const { sendTx, sendRawTx } = require('../../src/tx/sendTx') const { USER_ADDRESS, diff --git a/scripts/sendUserTxToErcHome.js b/scripts/erc20_to_erc20/sendHome.js similarity index 93% rename from scripts/sendUserTxToErcHome.js rename to scripts/erc20_to_erc20/sendHome.js index 1461d99..2d620a3 100644 --- a/scripts/sendUserTxToErcHome.js +++ b/scripts/erc20_to_erc20/sendHome.js @@ -1,11 +1,11 @@ const path = require('path') require('dotenv').config({ - path: path.join(__dirname, '../.env') + path: path.join(__dirname, '../../.env') }) const Web3 = require('web3') const Web3Utils = require('web3-utils') -const rpcUrlsManager = require('../src/services/getRpcUrlsManager') -const { sendTx, sendRawTx } = require('../src/tx/sendTx') +const rpcUrlsManager = require('../../src/services/getRpcUrlsManager') +const { sendTx, sendRawTx } = require('../../src/tx/sendTx') const { USER_ADDRESS, diff --git a/scripts/erc20_to_native/sendForeign.js b/scripts/erc20_to_native/sendForeign.js new file mode 100644 index 0000000..f636985 --- /dev/null +++ b/scripts/erc20_to_native/sendForeign.js @@ -0,0 +1,95 @@ +const path = require('path') +require('dotenv').config({ + path: path.join(__dirname, '../../.env') +}) +const Web3 = require('web3') +const Web3Utils = require('web3-utils') +const rpcUrlsManager = require('../../src/services/getRpcUrlsManager') +const { sendTx, sendRawTx } = require('../../src/tx/sendTx') + +const { + USER_ADDRESS, + USER_ADDRESS_PRIVATE_KEY, + FOREIGN_BRIDGE_ADDRESS, + FOREIGN_MIN_AMOUNT_PER_TX, + ERC20_TOKEN_ADDRESS +} = process.env + +const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPOSITS_TO_SEND || 1 + +const ERC20_ABI = [ + { + constant: false, + inputs: [ + { + name: '_to', + type: 'address' + }, + { + name: '_value', + type: 'uint256' + } + ], + name: 'transfer', + outputs: [ + { + name: '', + type: 'bool' + } + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function' + } +] + +const foreignRpcUrl = rpcUrlsManager.foreignUrls[0] +const foreignProvider = new Web3.providers.HttpProvider(foreignRpcUrl) +const web3Foreign = new Web3(foreignProvider) + +const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) + +async function main() { + try { + const foreignChaindId = await sendRawTx({ + chain: 'foreign', + params: [], + method: 'net_version' + }) + let nonce = await sendRawTx({ + chain: 'foreign', + method: 'eth_getTransactionCount', + params: [USER_ADDRESS, 'latest'] + }) + nonce = Web3Utils.hexToNumber(nonce) + let actualSent = 0 + for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) { + const gasLimit = await poa20.methods + .transfer(FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX)) + .estimateGas({ from: USER_ADDRESS }) + const data = await poa20.methods + .transfer(FOREIGN_BRIDGE_ADDRESS, Web3Utils.toWei(FOREIGN_MIN_AMOUNT_PER_TX)) + .encodeABI({ from: USER_ADDRESS }) + const txHash = await sendTx({ + chain: 'foreign', + privateKey: USER_ADDRESS_PRIVATE_KEY, + data, + nonce, + gasPrice: '1', + amount: '0', + gasLimit, + to: ERC20_TOKEN_ADDRESS, + web3: web3Foreign, + chainId: foreignChaindId + }) + if (txHash !== undefined) { + nonce++ + actualSent++ + console.log(actualSent, ' # ', txHash) + } + } + } catch (e) { + console.log(e) + } +} +main() diff --git a/scripts/sendUserTxToHome.js b/scripts/erc20_to_native/sendHome.js similarity index 86% rename from scripts/sendUserTxToHome.js rename to scripts/erc20_to_native/sendHome.js index cfe5df2..0fc8f6c 100644 --- a/scripts/sendUserTxToHome.js +++ b/scripts/erc20_to_native/sendHome.js @@ -1,10 +1,10 @@ const path = require('path') require('dotenv').config({ - path: path.join(__dirname, '../.env') + path: path.join(__dirname, '../../.env') }) const Web3Utils = require('web3-utils') -const { web3Home } = require('../src/services/web3') -const { sendTx, sendRawTx } = require('../src/tx/sendTx') +const { web3Home } = require('../../src/services/web3') +const { sendTx, sendRawTx } = require('../../src/tx/sendTx') const { USER_ADDRESS, @@ -37,7 +37,7 @@ async function main() { nonce, gasPrice: '1', amount: HOME_MIN_AMOUNT_PER_TX, - gasLimit: 50000, + gasLimit: 100000, to: HOME_BRIDGE_ADDRESS, web3: web3Home, chainId: homeChaindId diff --git a/scripts/sendUserTxToForeign.js b/scripts/native_to_erc20/sendForeign.js similarity index 92% rename from scripts/sendUserTxToForeign.js rename to scripts/native_to_erc20/sendForeign.js index 2266d90..9248be8 100644 --- a/scripts/sendUserTxToForeign.js +++ b/scripts/native_to_erc20/sendForeign.js @@ -1,10 +1,10 @@ const path = require('path') require('dotenv').config({ - path: path.join(__dirname, '../.env') + path: path.join(__dirname, '../../.env') }) const Web3Utils = require('web3-utils') -const { web3Foreign } = require('../src/services/web3') -const { sendTx, sendRawTx } = require('../src/tx/sendTx') +const { web3Foreign } = require('../../src/services/web3') +const { sendTx, sendRawTx } = require('../../src/tx/sendTx') const { USER_ADDRESS, diff --git a/scripts/native_to_erc20/sendHome.js b/scripts/native_to_erc20/sendHome.js new file mode 100644 index 0000000..0fc8f6c --- /dev/null +++ b/scripts/native_to_erc20/sendHome.js @@ -0,0 +1,55 @@ +const path = require('path') +require('dotenv').config({ + path: path.join(__dirname, '../../.env') +}) +const Web3Utils = require('web3-utils') +const { web3Home } = require('../../src/services/web3') +const { sendTx, sendRawTx } = require('../../src/tx/sendTx') + +const { + USER_ADDRESS, + USER_ADDRESS_PRIVATE_KEY, + HOME_BRIDGE_ADDRESS, + HOME_MIN_AMOUNT_PER_TX +} = process.env + +const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || 1 + +async function main() { + try { + const homeChaindId = await sendRawTx({ + chain: 'home', + params: [], + method: 'net_version' + }) + let nonce = await sendRawTx({ + chain: 'home', + method: 'eth_getTransactionCount', + params: [USER_ADDRESS, 'latest'] + }) + nonce = Web3Utils.hexToNumber(nonce) + let actualSent = 0 + for (let i = 0; i < Number(NUMBER_OF_DEPOSITS_TO_SEND); i++) { + const txHash = await sendTx({ + chain: 'home', + privateKey: USER_ADDRESS_PRIVATE_KEY, + data: '0x', + nonce, + gasPrice: '1', + amount: HOME_MIN_AMOUNT_PER_TX, + gasLimit: 100000, + to: HOME_BRIDGE_ADDRESS, + web3: web3Home, + chainId: homeChaindId + }) + if (txHash !== undefined) { + nonce++ + actualSent++ + console.log(actualSent, ' # ', txHash) + } + } + } catch (e) { + console.log(e) + } +} +main() From b268e5eb719b36e445527947976ef5f1d7dae831 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 25 Sep 2018 12:04:10 -0300 Subject: [PATCH 05/62] Update README --- README.md | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 0bdc7de..a30f6c5 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,13 @@ There are two Senders: 1. Deploy bridge contracts 1. Clone repo: `git clone https://github.com/poanetwork/poa-bridge-contracts` 2. `cd poa-bridge-contracts` - 3. Checkout branch `v2` : `git checkout v2` - 4. Compile contracts: `truffle compile` - 5. Go to deploy folder: `cd deploy` - 6. create a `.env` file: `cp .env.example .env` (look at `.env.example` to see the variables that need to be present) - 7. Execute `node deploy.js` + 3. Checkout branch `refactor_v1` : `git checkout refactor_v1` + 4. Install dependencies: `npm install` + 5. Compile contracts: `npm run compile` + 6. Go to deploy folder: `cd deploy` + 7. Install deploy dependencies: `npm install` + 8. create a `.env` file: `cp .env.example .env` (look at `.env.example` to see the variables that need to be present) + 9. Execute `node deploy.js` 2. Install [RabbitMQ](https://www.rabbitmq.com/) and [Redis](https://redis.io/) - RabbitMQ version: `3.7` @@ -37,17 +39,18 @@ There are two Senders: ## Run the processes ### Native to Erc mode + +On `.env` file set `BRIDGE_MODE=NATIVE_TO_ERC` + - `npm run watcher:signature-request` - `npm run watcher:collected-signatures` - `npm run watcher:affirmation-request` - `npm run sender:home` - `npm run sender:foreign` -To send deposits to home contract run `node tests/sendUserTxToHome.js` +To send deposits to home contract run `node scripts/native_to_erc20/sendHome.js 10` where `10` is how many tx you would like to send out -To send withdrawals to foreign contract run `node tests/sendUserTxToForeign.js` - -Make sure your `HOME_MIN_AMOUNT_PER_TX` and `FOREIGN_MIN_AMOUNT_PER_TX` is same as in your .env deployment contract +To send withdrawals to foreign contract run `node scripts/native_to_erc20/sendForeign.js 10 ` where `10` is how many tx you would like to send out ### Erc to Erc mode @@ -60,9 +63,23 @@ On `.env` file set `BRIDGE_MODE=ERC_TO_ERC` - `npm run sender:home` - `npm run sender:foreign` -To deposit from Foreign to Home contract run `node scripts/sendUserTxToErcForeign.js 10` where `10` is how many tx you would like to send out +To deposit from Foreign to Home contract run `node scripts/erc20_to_erc20/sendForeign.js 10` where `10` is how many tx you would like to send out + +To withdrawal to Home to Foreign contract run `node scripts/erc20_to_erc20/sendHome.js 10` where `10` is how many tx you would like to send out + +### Erc to Native mode + +On `.env` file set `BRIDGE_MODE=ERC_TO_NATIVE` + + - `npm run watcher:signature-request` + - `npm run watcher:collected-signatures` + - `npm run watcher:affirmation-request` + - `npm run sender:home` + - `npm run sender:foreign` + +To deposit from Foreign to Home contract run `node scripts/erc20_to_native/sendForeign.js 10` where `10` is how many tx you would like to send out -To withdrawal to Home to Foreign contract run `node scripts/sendUserTxToErcHome.js 10` where `10` is how many tx you would like to send out +To withdrawal to Home to Foreign contract run `node scripts/erc20_to_native/sendHome.js 10` where `10` is how many tx you would like to send out ### Run with Docker From d38bf876a12a6b6367550415919a897c75b9f596 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 26 Sep 2018 10:00:19 -0300 Subject: [PATCH 06/62] Add ERC20-to-Native deploy on e2e tests WiP --- e2e/Dockerfile | 3 +- e2e/deploy.js | 7 +++++ e2e/docker-compose.yml | 30 ++++++++++++++++++++ e2e/envs/contracts-deploy.env | 7 +++-- e2e/envs/erc-contracts-deploy.env | 7 +++-- e2e/envs/erc-native-contracts-deploy.env | 36 ++++++++++++++++++++++++ 6 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 e2e/envs/erc-native-contracts-deploy.env diff --git a/e2e/Dockerfile b/e2e/Dockerfile index 5507ead..cb54445 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -11,7 +11,8 @@ RUN git clone https://github.com/poanetwork/poa-bridge-contracts.git RUN mkdir submodules && \ mv poa-bridge-contracts submodules && \ cd submodules/poa-bridge-contracts && \ - git checkout refactor_v1 + git fetch && \ + git checkout erc20-to-native-#79 RUN npm install --unsafe-perm diff --git a/e2e/deploy.js b/e2e/deploy.js index b41e806..90ff828 100644 --- a/e2e/deploy.js +++ b/e2e/deploy.js @@ -14,3 +14,10 @@ shell.cd(deployContractsDir) shell.rm('.env') shell.cp(path.join(envsDir, 'erc-contracts-deploy.env'), path.join(deployContractsDir, '.env')) shell.exec('node deploy.js') +shell.rm('.env') +shell.cp( + path.join(envsDir, 'erc-native-contracts-deploy.env'), + path.join(deployContractsDir, '.env') +) +shell.exec('node src/utils/deployBlockReward.js') +shell.exec('node deploy.js') diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index 1e7d8ab..d432fbd 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -18,6 +18,7 @@ services: build: .. environment: - NODE_ENV=production + - BRIDGE_MODE=NATIVE_TO_ERC - QUEUE_URL=amqp://rabbit - REDIS_URL=redis://redis - HOME_RPC_URL=http://parity1:8545 @@ -62,6 +63,35 @@ services: - HOME_MIN_AMOUNT_PER_TX=0.01 - FOREIGN_MIN_AMOUNT_PER_TX=0.01 command: "true" + bridge-erc-native: + build: .. + environment: + - NODE_ENV=production + - BRIDGE_MODE=ERC_TO_NATIVE + - QUEUE_URL=amqp://rabbit + - REDIS_URL=redis://redis + - HOME_RPC_URL=http://parity1:8545 + - FOREIGN_RPC_URL=http://parity2:8545 + - HOME_BRIDGE_ADDRESS= + - FOREIGN_BRIDGE_ADDRESS= + - BLOCK_REWARD_ADDRESS=0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD + - ERC20_TOKEN_ADDRESS=0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9 + - BRIDGEABLE_TOKEN_ADDRESS=0x792455a6bCb62Ed4C4362D323E0590654CA4765c + - VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b + - VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 + - REDIS_LOCK_TTL=1000 + - GAS_PRICE_SPEED_TYPE=standard + - GAS_PRICE_FALLBACK=1 + - HOME_POLLING_INTERVAL=500 + - FOREIGN_POLLING_INTERVAL=500 + - ALLOW_HTTP=yes + - NUMBER_OF_WITHDRAWALS_TO_SEND=3 + - NUMBER_OF_DEPOSITS_TO_SEND=3 + - USER_ADDRESS=0xbb140FbA6242a1c3887A7823F7750a73101383e3 + - USER_ADDRESS_PRIVATE_KEY=63e48a8ba0b99e0377c6b483af4a072cbca5ffbcfdac77be72e69f4960125800 + - HOME_MIN_AMOUNT_PER_TX=0.01 + - FOREIGN_MIN_AMOUNT_PER_TX=0.01 + command: "true" e2e: build: . command: "true" diff --git a/e2e/envs/contracts-deploy.env b/e2e/envs/contracts-deploy.env index b5c0370..0a07499 100644 --- a/e2e/envs/contracts-deploy.env +++ b/e2e/envs/contracts-deploy.env @@ -2,7 +2,8 @@ BRIDGE_MODE=NATIVE_TO_ERC DEPLOYMENT_ACCOUNT_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b DEPLOYMENT_ACCOUNT_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 DEPLOYMENT_GAS_LIMIT=4000000 -DEPLOYMENT_GAS_PRICE=10 +HOME_DEPLOYMENT_GAS_PRICE=10000000000 +FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000 GET_RECEIPT_INTERVAL_IN_MILLISECONDS=50 BRIDGEABLE_TOKEN_NAME="Your New Bridged Token" @@ -17,7 +18,7 @@ HOME_DAILY_LIMIT=30000000000000000000000000 HOME_MAX_AMOUNT_PER_TX=1500000000000000000000000 HOME_MIN_AMOUNT_PER_TX=10000000000000000 HOME_REQUIRED_BLOCK_CONFIRMATIONS=1 -HOME_GAS_PRICE=10 +HOME_GAS_PRICE=1000000000 FOREIGN_RPC_URL=http://parity2:8545 FOREIGN_OWNER_MULTISIG=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b @@ -27,7 +28,7 @@ FOREIGN_DAILY_LIMIT=15000000000000000000000000 FOREIGN_MAX_AMOUNT_PER_TX=750000000000000000000000 FOREIGN_MIN_AMOUNT_PER_TX=10000000000000000 FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1 -FOREIGN_GAS_PRICE=10 +FOREIGN_GAS_PRICE=10000000000 REQUIRED_NUMBER_OF_VALIDATORS=1 VALIDATORS="0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" diff --git a/e2e/envs/erc-contracts-deploy.env b/e2e/envs/erc-contracts-deploy.env index 5aa00e2..7a40d8b 100644 --- a/e2e/envs/erc-contracts-deploy.env +++ b/e2e/envs/erc-contracts-deploy.env @@ -2,7 +2,8 @@ BRIDGE_MODE=ERC_TO_ERC DEPLOYMENT_ACCOUNT_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b DEPLOYMENT_ACCOUNT_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 DEPLOYMENT_GAS_LIMIT=4000000 -DEPLOYMENT_GAS_PRICE=10 +HOME_DEPLOYMENT_GAS_PRICE=10000000000 +FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000 GET_RECEIPT_INTERVAL_IN_MILLISECONDS=50 BRIDGEABLE_TOKEN_NAME="Your New Bridged Token" @@ -17,7 +18,7 @@ HOME_DAILY_LIMIT=30000000000000000000000000 HOME_MAX_AMOUNT_PER_TX=1500000000000000000000000 HOME_MIN_AMOUNT_PER_TX=10000000000000000 HOME_REQUIRED_BLOCK_CONFIRMATIONS=1 -HOME_GAS_PRICE=10 +HOME_GAS_PRICE=1000000000 FOREIGN_RPC_URL=http://parity2:8545 FOREIGN_OWNER_MULTISIG=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b @@ -27,7 +28,7 @@ FOREIGN_DAILY_LIMIT=15000000000000000000000000 FOREIGN_MAX_AMOUNT_PER_TX=750000000000000000000000 FOREIGN_MIN_AMOUNT_PER_TX=10000000000000000 FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1 -FOREIGN_GAS_PRICE=10 +FOREIGN_GAS_PRICE=10000000000 ERC20_TOKEN_ADDRESS=0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9 REQUIRED_NUMBER_OF_VALIDATORS=1 diff --git a/e2e/envs/erc-native-contracts-deploy.env b/e2e/envs/erc-native-contracts-deploy.env new file mode 100644 index 0000000..a1717b5 --- /dev/null +++ b/e2e/envs/erc-native-contracts-deploy.env @@ -0,0 +1,36 @@ +BRIDGE_MODE=ERC_TO_NATIVE +DEPLOYMENT_ACCOUNT_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 +DEPLOYMENT_GAS_LIMIT=4000000 +HOME_DEPLOYMENT_GAS_PRICE=10000000000 +FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000 +GET_RECEIPT_INTERVAL_IN_MILLISECONDS=50 + +BRIDGEABLE_TOKEN_NAME="Your New Bridged Token" +BRIDGEABLE_TOKEN_SYMBOL="TEST" +BRIDGEABLE_TOKEN_DECIMALS="18" + +HOME_RPC_URL=http://parity1:8545 +HOME_OWNER_MULTISIG=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b +HOME_UPGRADEABLE_ADMIN_VALIDATORS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b +HOME_UPGRADEABLE_ADMIN_BRIDGE=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b +HOME_DAILY_LIMIT=30000000000000000000000000 +HOME_MAX_AMOUNT_PER_TX=1500000000000000000000000 +HOME_MIN_AMOUNT_PER_TX=10000000000000000 +HOME_REQUIRED_BLOCK_CONFIRMATIONS=1 +HOME_GAS_PRICE=1000000000 + +FOREIGN_RPC_URL=http://parity2:8545 +FOREIGN_OWNER_MULTISIG=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b +FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b +FOREIGN_UPGRADEABLE_ADMIN_BRIDGE=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b +FOREIGN_DAILY_LIMIT=15000000000000000000000000 +FOREIGN_MAX_AMOUNT_PER_TX=750000000000000000000000 +FOREIGN_MIN_AMOUNT_PER_TX=10000000000000000 +FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1 +FOREIGN_GAS_PRICE=10000000000 + +BLOCK_REWARD_ADDRESS=0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD +ERC20_TOKEN_ADDRESS=0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9 + +REQUIRED_NUMBER_OF_VALIDATORS=1 +VALIDATORS="0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" From 5443e3db6c734bc90f649a6c94bb49fbe151d4eb Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 26 Sep 2018 11:21:49 -0300 Subject: [PATCH 07/62] Update docker config for e2e --- e2e/docker-compose.yml | 4 ++-- e2e/run-tests.sh | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index d432fbd..83a8505 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -72,8 +72,8 @@ services: - REDIS_URL=redis://redis - HOME_RPC_URL=http://parity1:8545 - FOREIGN_RPC_URL=http://parity2:8545 - - HOME_BRIDGE_ADDRESS= - - FOREIGN_BRIDGE_ADDRESS= + - HOME_BRIDGE_ADDRESS=0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9 + - FOREIGN_BRIDGE_ADDRESS=0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9 - BLOCK_REWARD_ADDRESS=0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD - ERC20_TOKEN_ADDRESS=0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9 - BRIDGEABLE_TOKEN_ADDRESS=0x792455a6bCb62Ed4C4362D323E0590654CA4765c diff --git a/e2e/run-tests.sh b/e2e/run-tests.sh index 094bce3..7c243ff 100755 --- a/e2e/run-tests.sh +++ b/e2e/run-tests.sh @@ -6,6 +6,9 @@ docker-compose run -d bridge npm run watcher:affirmation-request docker-compose run -d bridge-erc npm run watcher:signature-request docker-compose run -d bridge-erc npm run watcher:collected-signatures docker-compose run -d bridge-erc npm run watcher:affirmation-request +docker-compose run -d bridge-erc-native npm run watcher:signature-request +docker-compose run -d bridge-erc-native npm run watcher:collected-signatures +docker-compose run -d bridge-erc-native npm run watcher:affirmation-request docker-compose run -d bridge npm run sender:home docker-compose run -d bridge npm run sender:foreign docker-compose run e2e npm start From 0f8d7759d9ef73eb3c7b171bdcd51df090318a0c Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 26 Sep 2018 11:22:05 -0300 Subject: [PATCH 08/62] Add ERC20-to-Native e2e tests --- e2e/test/ercToNative.js | 102 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 e2e/test/ercToNative.js diff --git a/e2e/test/ercToNative.js b/e2e/test/ercToNative.js new file mode 100644 index 0000000..50c1ac7 --- /dev/null +++ b/e2e/test/ercToNative.js @@ -0,0 +1,102 @@ +const path = require('path') +const Web3 = require('web3') +const assert = require('assert') +const promiseRetry = require('promise-retry') +const { user } = require('../constants.json') +const { generateNewBlock } = require('../utils/utils') + +const abisDir = path.join(__dirname, '..', 'submodules/poa-bridge-contracts/build/contracts') + +const homeWeb3 = new Web3(new Web3.providers.HttpProvider('http://parity1:8545')) +const foreignWeb3 = new Web3(new Web3.providers.HttpProvider('http://parity2:8545')) + +const HOME_BRIDGE_ADDRESS = '0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9' +const FOREIGN_BRIDGE_ADDRESS = '0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9' + +const { toBN } = foreignWeb3.utils + +homeWeb3.eth.accounts.wallet.add(user.privateKey) +foreignWeb3.eth.accounts.wallet.add(user.privateKey) + +const tokenAbi = require(path.join(abisDir, 'ERC677BridgeToken.json')).abi +const erc20Token = new foreignWeb3.eth.Contract( + tokenAbi, + '0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9' +) + +describe('erc to native', () => { + it('should convert tokens in foreign to coins in home', async () => { + const balance = await erc20Token.methods.balanceOf(user.address).call() + const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address) + assert(!toBN(balance).isZero(), 'Account should have tokens') + + // send tokens to foreign bridge + await erc20Token.methods + .transfer(FOREIGN_BRIDGE_ADDRESS, homeWeb3.utils.toWei('0.01')) + .send({ + from: user.address, + gas: '1000000' + }) + .catch(e => { + console.error(e) + }) + + // Send a trivial transaction to generate a new block since the watcher + // is configured to wait 1 confirmation block + await generateNewBlock(foreignWeb3, user.address) + + // check that balance increases + await promiseRetry(async retry => { + const balance = await homeWeb3.eth.getBalance(user.address) + if (toBN(balance).lte(toBN(originalBalanceOnHome))) { + retry() + } + }) + }) + it('should convert coins in home to tokens in foreign', async () => { + const originalBalance = await erc20Token.methods.balanceOf(user.address).call() + + // check that account has tokens in home chain + const balance = await homeWeb3.eth.getBalance(user.address) + assert(!toBN(balance).isZero(), 'Account should have tokens') + + // send transaction to home bridge + const depositTx = await homeWeb3.eth.sendTransaction({ + from: user.address, + to: HOME_BRIDGE_ADDRESS, + gasPrice: '1', + gas: '1000000', + value: homeWeb3.utils.toWei('0.01') + }) + + // Send a trivial transaction to generate a new block since the watcher + // is configured to wait 1 confirmation block + await generateNewBlock(homeWeb3, user.address) + + // The bridge should create a new transaction with a CollectedSignatures + // event so we generate another trivial transaction + await promiseRetry( + async retry => { + const lastBlockNumber = await homeWeb3.eth.getBlockNumber() + if (lastBlockNumber >= depositTx.blockNumber + 2) { + await generateNewBlock(homeWeb3, user.address) + } else { + retry() + } + }, + { + forever: true, + factor: 1, + minTimeout: 500 + } + ) + + // check that balance increases + await promiseRetry(async retry => { + const balance = await erc20Token.methods.balanceOf(user.address).call() + if (toBN(balance).lte(toBN(originalBalance))) { + retry() + } + }) + }) +}) From 5bd965bc6748f1b0ff057e99a4b9f458c7660d49 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Wed, 26 Sep 2018 14:00:29 -0300 Subject: [PATCH 09/62] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a30f6c5..1f8c5c8 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ There are two Senders: 1. Deploy bridge contracts 1. Clone repo: `git clone https://github.com/poanetwork/poa-bridge-contracts` 2. `cd poa-bridge-contracts` - 3. Checkout branch `refactor_v1` : `git checkout refactor_v1` + 3. Checkout branch `refactor_v1`: `git checkout refactor_v1` 4. Install dependencies: `npm install` 5. Compile contracts: `npm run compile` 6. Go to deploy folder: `cd deploy` From ceabbf3060b8f2e189b04489e220794cba5f8dc3 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 26 Sep 2018 15:37:33 -0300 Subject: [PATCH 10/62] Set default mode on test environment --- config/base.config.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/config/base.config.js b/config/base.config.js index 9673be4..0b8029c 100644 --- a/config/base.config.js +++ b/config/base.config.js @@ -32,7 +32,13 @@ switch (process.env.BRIDGE_MODE) { id = 'erc-native' break default: - throw new Error(`Bridge Mode: ${process.env.BRIDGE_MODE} not supported.`) + if (process.env.NODE_ENV !== 'test') { + throw new Error(`Bridge Mode: ${process.env.BRIDGE_MODE} not supported.`) + } else { + homeAbi = homeErcNativeAbi + foreignAbi = foreignErcNativeAbi + id = 'erc-native' + } } const bridgeConfig = { From 2173d84694270ca032c34fcb1e6dc4e16fe81201 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 26 Sep 2018 16:15:47 -0300 Subject: [PATCH 11/62] Update sendTx to receive gasPrice on wei unit --- .env.example | 4 ++-- scripts/erc20_to_erc20/sendForeign.js | 2 +- scripts/erc20_to_erc20/sendHome.js | 2 +- scripts/erc20_to_native/sendForeign.js | 2 +- scripts/erc20_to_native/sendHome.js | 2 +- scripts/native_to_erc20/sendForeign.js | 2 +- scripts/native_to_erc20/sendHome.js | 2 +- src/services/gasPrice.js | 3 ++- src/tx/sendTx.js | 2 +- 9 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 7a5b006..2766091 100644 --- a/.env.example +++ b/.env.example @@ -13,12 +13,12 @@ VALIDATOR_ADDRESS_PRIVATE_KEY= HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ HOME_GAS_PRICE_SPEED_TYPE=standard -HOME_GAS_PRICE_FALLBACK=1 +HOME_GAS_PRICE_FALLBACK=1000000000 HOME_GAS_PRICE_UPDATE_INTERVAL=600000 FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ FOREIGN_GAS_PRICE_SPEED_TYPE=standard -FOREIGN_GAS_PRICE_FALLBACK=1 +FOREIGN_GAS_PRICE_FALLBACK=1000000000 FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000 QUEUE_URL=amqp://127.0.0.1 diff --git a/scripts/erc20_to_erc20/sendForeign.js b/scripts/erc20_to_erc20/sendForeign.js index f636985..82767f4 100644 --- a/scripts/erc20_to_erc20/sendForeign.js +++ b/scripts/erc20_to_erc20/sendForeign.js @@ -75,7 +75,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data, nonce, - gasPrice: '1', + gasPrice: '1000000000', amount: '0', gasLimit, to: ERC20_TOKEN_ADDRESS, diff --git a/scripts/erc20_to_erc20/sendHome.js b/scripts/erc20_to_erc20/sendHome.js index 2d620a3..80c28d2 100644 --- a/scripts/erc20_to_erc20/sendHome.js +++ b/scripts/erc20_to_erc20/sendHome.js @@ -80,7 +80,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data, nonce, - gasPrice: '1', + gasPrice: '1000000000', amount: '0', gasLimit, to: BRIDGEABLE_TOKEN_ADDRESS, diff --git a/scripts/erc20_to_native/sendForeign.js b/scripts/erc20_to_native/sendForeign.js index f636985..82767f4 100644 --- a/scripts/erc20_to_native/sendForeign.js +++ b/scripts/erc20_to_native/sendForeign.js @@ -75,7 +75,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data, nonce, - gasPrice: '1', + gasPrice: '1000000000', amount: '0', gasLimit, to: ERC20_TOKEN_ADDRESS, diff --git a/scripts/erc20_to_native/sendHome.js b/scripts/erc20_to_native/sendHome.js index 0fc8f6c..86d16b7 100644 --- a/scripts/erc20_to_native/sendHome.js +++ b/scripts/erc20_to_native/sendHome.js @@ -35,7 +35,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data: '0x', nonce, - gasPrice: '1', + gasPrice: '1000000000', amount: HOME_MIN_AMOUNT_PER_TX, gasLimit: 100000, to: HOME_BRIDGE_ADDRESS, diff --git a/scripts/native_to_erc20/sendForeign.js b/scripts/native_to_erc20/sendForeign.js index 9248be8..819ed10 100644 --- a/scripts/native_to_erc20/sendForeign.js +++ b/scripts/native_to_erc20/sendForeign.js @@ -75,7 +75,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data, nonce, - gasPrice: '1', + gasPrice: '1000000000', amount: '0', gasLimit, to: ERC20_TOKEN_ADDRESS, diff --git a/scripts/native_to_erc20/sendHome.js b/scripts/native_to_erc20/sendHome.js index 0fc8f6c..86d16b7 100644 --- a/scripts/native_to_erc20/sendHome.js +++ b/scripts/native_to_erc20/sendHome.js @@ -35,7 +35,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data: '0x', nonce, - gasPrice: '1', + gasPrice: '1000000000', amount: HOME_MIN_AMOUNT_PER_TX, gasLimit: 100000, to: HOME_BRIDGE_ADDRESS, diff --git a/src/services/gasPrice.js b/src/services/gasPrice.js index 05178aa..35750c9 100644 --- a/src/services/gasPrice.js +++ b/src/services/gasPrice.js @@ -1,5 +1,6 @@ require('dotenv').config() const fetch = require('node-fetch') +const Web3Utils = require('web3-utils') const { web3Home, web3Foreign } = require('../services/web3') const { bridgeConfig } = require('../../config/base.config') const logger = require('../services/logger') @@ -33,7 +34,7 @@ async function fetchGasPriceFromOracle(oracleUrl, speedType) { if (!gasPrice) { throw new Error(`Response from Oracle didn't include gas price for ${speedType} type.`) } - return gasPrice + return Web3Utils.toWei(gasPrice, 'gwei') } async function fetchGasPrice({ bridgeContract, oracleFn }) { diff --git a/src/tx/sendTx.js b/src/tx/sendTx.js index a1a27c3..88ebc97 100644 --- a/src/tx/sendTx.js +++ b/src/tx/sendTx.js @@ -22,7 +22,7 @@ async function sendTx({ to, data, value: Web3Utils.toWei(amount), - gasPrice: Web3Utils.toWei(gasPrice, 'gwei'), + gasPrice, gas: gasLimit }, `0x${privateKey}` From 3189368f140edb6ec01e52d063294faca6418b6c Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Thu, 4 Oct 2018 14:02:08 -0300 Subject: [PATCH 12/62] Add default gas price update interval --- src/services/gasPrice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/gasPrice.js b/src/services/gasPrice.js index 2c70aa9..a8af433 100644 --- a/src/services/gasPrice.js +++ b/src/services/gasPrice.js @@ -65,7 +65,7 @@ async function start(chainId) { let bridgeContract = null let oracleUrl = null let speedType = null - let updateInterval = null + let updateInterval = 600000 if (chainId === 'home') { bridgeContract = homeBridge oracleUrl = HOME_GAS_PRICE_ORACLE_URL From 7fe51a3cef5f2d0dad9cb3dae463b01c3ebae8ea Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 10 Oct 2018 08:23:52 -0300 Subject: [PATCH 13/62] Fix oracle gasPrice conversion to wei --- src/services/gasPrice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/gasPrice.js b/src/services/gasPrice.js index 005a3f6..a4dbac4 100644 --- a/src/services/gasPrice.js +++ b/src/services/gasPrice.js @@ -35,7 +35,7 @@ async function fetchGasPriceFromOracle(oracleUrl, speedType) { if (!gasPrice) { throw new Error(`Response from Oracle didn't include gas price for ${speedType} type.`) } - return Web3Utils.toWei(gasPrice, 'gwei') + return Web3Utils.toWei(Web3Utils.toBN(gasPrice), 'gwei') } async function fetchGasPrice({ bridgeContract, oracleFn }) { From 451da025e0cce5c6863b3c5fe7c9bf53f9d3dbba Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 10 Oct 2018 08:27:09 -0300 Subject: [PATCH 14/62] Use string value to convert gas price to wei --- src/services/gasPrice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/gasPrice.js b/src/services/gasPrice.js index a4dbac4..1661264 100644 --- a/src/services/gasPrice.js +++ b/src/services/gasPrice.js @@ -35,7 +35,7 @@ async function fetchGasPriceFromOracle(oracleUrl, speedType) { if (!gasPrice) { throw new Error(`Response from Oracle didn't include gas price for ${speedType} type.`) } - return Web3Utils.toWei(Web3Utils.toBN(gasPrice), 'gwei') + return Web3Utils.toWei(gasPrice.toString(), 'gwei') } async function fetchGasPrice({ bridgeContract, oracleFn }) { From ec3aaf681591431731aacecaba7ab1c6dfa39b6f Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 10 Oct 2018 10:59:42 -0300 Subject: [PATCH 15/62] Update e2e contracts addresses --- e2e/docker-compose.yml | 79 +++++++++++++----------- e2e/envs/erc-contracts-deploy.env | 2 +- e2e/envs/erc-native-contracts-deploy.env | 4 +- e2e/test/ercToErc.js | 4 +- e2e/test/ercToNative.js | 6 +- 5 files changed, 50 insertions(+), 45 deletions(-) diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index 1d6b8fa..62ee91f 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -29,8 +29,14 @@ services: - VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b - VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 - REDIS_LOCK_TTL=1000 - - GAS_PRICE_SPEED_TYPE=standard - - GAS_PRICE_FALLBACK=1 + - HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ + - HOME_GAS_PRICE_SPEED_TYPE=standard + - HOME_GAS_PRICE_FALLBACK=1000000000 + - HOME_GAS_PRICE_UPDATE_INTERVAL=600000 + - FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ + - FOREIGN_GAS_PRICE_SPEED_TYPE=standard + - FOREIGN_GAS_PRICE_FALLBACK=10000000000 + - FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000 - HOME_POLLING_INTERVAL=500 - FOREIGN_POLLING_INTERVAL=500 - ALLOW_HTTP=yes @@ -45,52 +51,51 @@ services: - HOME_RPC_URL=http://parity1:8545 - FOREIGN_RPC_URL=http://parity2:8545 - HOME_BRIDGE_ADDRESS=0x1feB40aD9420b186F019A717c37f5546165d411E - - FOREIGN_BRIDGE_ADDRESS=0xD0B9745831dDA9cbb47D0dEa904972cDcecc52e8 - - ERC20_TOKEN_ADDRESS=0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9 + - FOREIGN_BRIDGE_ADDRESS=0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127 + - ERC20_TOKEN_ADDRESS=0x3C665A31199694Bf723fD08844AD290207B5797f - BRIDGEABLE_TOKEN_ADDRESS=0x792455a6bCb62Ed4C4362D323E0590654CA4765c - VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b - VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 - REDIS_LOCK_TTL=1000 - - GAS_PRICE_SPEED_TYPE=standard - - GAS_PRICE_FALLBACK=1 + - HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ + - HOME_GAS_PRICE_SPEED_TYPE=standard + - HOME_GAS_PRICE_FALLBACK=1000000000 + - HOME_GAS_PRICE_UPDATE_INTERVAL=600000 + - FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ + - FOREIGN_GAS_PRICE_SPEED_TYPE=standard + - FOREIGN_GAS_PRICE_FALLBACK=10000000000 + - FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000 - HOME_POLLING_INTERVAL=500 - FOREIGN_POLLING_INTERVAL=500 - ALLOW_HTTP=yes - - NUMBER_OF_WITHDRAWALS_TO_SEND=3 - - NUMBER_OF_DEPOSITS_TO_SEND=3 - - USER_ADDRESS=0xbb140FbA6242a1c3887A7823F7750a73101383e3 - - USER_ADDRESS_PRIVATE_KEY=63e48a8ba0b99e0377c6b483af4a072cbca5ffbcfdac77be72e69f4960125800 - - HOME_MIN_AMOUNT_PER_TX=0.01 - - FOREIGN_MIN_AMOUNT_PER_TX=0.01 command: "true" bridge-erc-native: build: .. environment: - - NODE_ENV=production - - BRIDGE_MODE=ERC_TO_NATIVE - - QUEUE_URL=amqp://rabbit - - REDIS_URL=redis://redis - - HOME_RPC_URL=http://parity1:8545 - - FOREIGN_RPC_URL=http://parity2:8545 - - HOME_BRIDGE_ADDRESS=0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9 - - FOREIGN_BRIDGE_ADDRESS=0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9 - - BLOCK_REWARD_ADDRESS=0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD - - ERC20_TOKEN_ADDRESS=0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9 - - BRIDGEABLE_TOKEN_ADDRESS=0x792455a6bCb62Ed4C4362D323E0590654CA4765c - - VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b - - VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 - - REDIS_LOCK_TTL=1000 - - GAS_PRICE_SPEED_TYPE=standard - - GAS_PRICE_FALLBACK=1 - - HOME_POLLING_INTERVAL=500 - - FOREIGN_POLLING_INTERVAL=500 - - ALLOW_HTTP=yes - - NUMBER_OF_WITHDRAWALS_TO_SEND=3 - - NUMBER_OF_DEPOSITS_TO_SEND=3 - - USER_ADDRESS=0xbb140FbA6242a1c3887A7823F7750a73101383e3 - - USER_ADDRESS_PRIVATE_KEY=63e48a8ba0b99e0377c6b483af4a072cbca5ffbcfdac77be72e69f4960125800 - - HOME_MIN_AMOUNT_PER_TX=0.01 - - FOREIGN_MIN_AMOUNT_PER_TX=0.01 + - NODE_ENV=production + - BRIDGE_MODE=ERC_TO_NATIVE + - QUEUE_URL=amqp://rabbit + - REDIS_URL=redis://redis + - HOME_RPC_URL=http://parity1:8545 + - FOREIGN_RPC_URL=http://parity2:8545 + - HOME_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda + - FOREIGN_BRIDGE_ADDRESS=0x488Af810997eD1730cB3a3918cD83b3216E6eAda + - ERC20_TOKEN_ADDRESS=0x3C665A31199694Bf723fD08844AD290207B5797f + - BRIDGEABLE_TOKEN_ADDRESS=0x792455a6bCb62Ed4C4362D323E0590654CA4765c + - VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b + - VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9 + - REDIS_LOCK_TTL=1000 + - HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ + - HOME_GAS_PRICE_SPEED_TYPE=standard + - HOME_GAS_PRICE_FALLBACK=1000000000 + - HOME_GAS_PRICE_UPDATE_INTERVAL=600000 + - FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ + - FOREIGN_GAS_PRICE_SPEED_TYPE=standard + - FOREIGN_GAS_PRICE_FALLBACK=10000000000 + - FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000 + - HOME_POLLING_INTERVAL=500 + - FOREIGN_POLLING_INTERVAL=500 + - ALLOW_HTTP=yes command: "true" e2e: build: . diff --git a/e2e/envs/erc-contracts-deploy.env b/e2e/envs/erc-contracts-deploy.env index 7a40d8b..869261e 100644 --- a/e2e/envs/erc-contracts-deploy.env +++ b/e2e/envs/erc-contracts-deploy.env @@ -29,7 +29,7 @@ FOREIGN_MAX_AMOUNT_PER_TX=750000000000000000000000 FOREIGN_MIN_AMOUNT_PER_TX=10000000000000000 FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1 FOREIGN_GAS_PRICE=10000000000 -ERC20_TOKEN_ADDRESS=0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9 +ERC20_TOKEN_ADDRESS=0x3C665A31199694Bf723fD08844AD290207B5797f REQUIRED_NUMBER_OF_VALIDATORS=1 VALIDATORS="0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" diff --git a/e2e/envs/erc-native-contracts-deploy.env b/e2e/envs/erc-native-contracts-deploy.env index a1717b5..fd86652 100644 --- a/e2e/envs/erc-native-contracts-deploy.env +++ b/e2e/envs/erc-native-contracts-deploy.env @@ -29,8 +29,8 @@ FOREIGN_MIN_AMOUNT_PER_TX=10000000000000000 FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1 FOREIGN_GAS_PRICE=10000000000 -BLOCK_REWARD_ADDRESS=0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD -ERC20_TOKEN_ADDRESS=0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9 +BLOCK_REWARD_ADDRESS=0xF9698Eb93702dfdd0e2d802088d4c21822a8A977 +ERC20_TOKEN_ADDRESS=0x3C665A31199694Bf723fD08844AD290207B5797f REQUIRED_NUMBER_OF_VALIDATORS=1 VALIDATORS="0xaaB52d66283F7A1D5978bcFcB55721ACB467384b" diff --git a/e2e/test/ercToErc.js b/e2e/test/ercToErc.js index 4dfc5da..30459cb 100644 --- a/e2e/test/ercToErc.js +++ b/e2e/test/ercToErc.js @@ -11,7 +11,7 @@ const homeWeb3 = new Web3(new Web3.providers.HttpProvider('http://parity1:8545') const foreignWeb3 = new Web3(new Web3.providers.HttpProvider('http://parity2:8545')) const HOME_BRIDGE_ADDRESS = '0x1feB40aD9420b186F019A717c37f5546165d411E' -const FOREIGN_BRIDGE_ADDRESS = '0xD0B9745831dDA9cbb47D0dEa904972cDcecc52e8' +const FOREIGN_BRIDGE_ADDRESS = '0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127' const { toBN } = foreignWeb3.utils @@ -21,7 +21,7 @@ foreignWeb3.eth.accounts.wallet.add(user.privateKey) const tokenAbi = require(path.join(abisDir, 'ERC677BridgeToken.json')).abi const erc20Token = new foreignWeb3.eth.Contract( tokenAbi, - '0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9' + '0x3C665A31199694Bf723fD08844AD290207B5797f' ) const erc677Token = new homeWeb3.eth.Contract( tokenAbi, diff --git a/e2e/test/ercToNative.js b/e2e/test/ercToNative.js index 50c1ac7..1c739b9 100644 --- a/e2e/test/ercToNative.js +++ b/e2e/test/ercToNative.js @@ -10,8 +10,8 @@ const abisDir = path.join(__dirname, '..', 'submodules/poa-bridge-contracts/buil const homeWeb3 = new Web3(new Web3.providers.HttpProvider('http://parity1:8545')) const foreignWeb3 = new Web3(new Web3.providers.HttpProvider('http://parity2:8545')) -const HOME_BRIDGE_ADDRESS = '0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9' -const FOREIGN_BRIDGE_ADDRESS = '0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9' +const HOME_BRIDGE_ADDRESS = '0x488Af810997eD1730cB3a3918cD83b3216E6eAda' +const FOREIGN_BRIDGE_ADDRESS = '0x488Af810997eD1730cB3a3918cD83b3216E6eAda' const { toBN } = foreignWeb3.utils @@ -21,7 +21,7 @@ foreignWeb3.eth.accounts.wallet.add(user.privateKey) const tokenAbi = require(path.join(abisDir, 'ERC677BridgeToken.json')).abi const erc20Token = new foreignWeb3.eth.Contract( tokenAbi, - '0x7777D2BF48993088dC1ceD832863b80427Ff5Ec9' + '0x3C665A31199694Bf723fD08844AD290207B5797f' ) describe('erc to native', () => { From 4693fbee7c61d01973e59c8df98814c3c1818c48 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 10 Oct 2018 16:04:47 -0300 Subject: [PATCH 16/62] Fix default gas price interval --- src/services/gasPrice.js | 7 +++-- src/utils/constants.js | 3 +- test/gasPrice.test.js | 66 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/services/gasPrice.js b/src/services/gasPrice.js index a8af433..9f8bae4 100644 --- a/src/services/gasPrice.js +++ b/src/services/gasPrice.js @@ -8,6 +8,7 @@ const HomeErcABI = require('../../abis/HomeBridgeErcToErc.abi') const ForeignErcABI = require('../../abis/ForeignBridgeErcToErc.abi') const logger = require('../services/logger') const { setIntervalAndRun } = require('../utils/utils') +const { DEFAULT_UPDATE_INTERVAL } = require('../utils/constants') const HomeABI = isErcToErc ? HomeErcABI : HomeNativeABI const ForeignABI = isErcToErc ? ForeignNativeABI : ForeignErcABI @@ -65,19 +66,19 @@ async function start(chainId) { let bridgeContract = null let oracleUrl = null let speedType = null - let updateInterval = 600000 + let updateInterval = null if (chainId === 'home') { bridgeContract = homeBridge oracleUrl = HOME_GAS_PRICE_ORACLE_URL speedType = HOME_GAS_PRICE_SPEED_TYPE - updateInterval = HOME_GAS_PRICE_UPDATE_INTERVAL + updateInterval = HOME_GAS_PRICE_UPDATE_INTERVAL || DEFAULT_UPDATE_INTERVAL cachedGasPrice = HOME_GAS_PRICE_FALLBACK } else if (chainId === 'foreign') { bridgeContract = foreignBridge oracleUrl = FOREIGN_GAS_PRICE_ORACLE_URL speedType = FOREIGN_GAS_PRICE_SPEED_TYPE - updateInterval = FOREIGN_GAS_PRICE_UPDATE_INTERVAL + updateInterval = FOREIGN_GAS_PRICE_UPDATE_INTERVAL || DEFAULT_UPDATE_INTERVAL cachedGasPrice = FOREIGN_GAS_PRICE_FALLBACK } else { diff --git a/src/utils/constants.js b/src/utils/constants.js index cfc389b..0804914 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -6,5 +6,6 @@ module.exports = { factor: 1.4, maxTimeout: 360000, randomize: true - } + }, + DEFAULT_UPDATE_INTERVAL: 600000 } diff --git a/test/gasPrice.test.js b/test/gasPrice.test.js index 3121cef..a8276c0 100644 --- a/test/gasPrice.test.js +++ b/test/gasPrice.test.js @@ -1,6 +1,8 @@ const sinon = require('sinon') const { expect } = require('chai') +const proxyquire = require('proxyquire').noPreserveCache() const { fetchGasPrice } = require('../src/services/gasPrice') +const { DEFAULT_UPDATE_INTERVAL } = require('../src/utils/constants') describe('gasPrice', () => { describe('fetchGasPrice', () => { @@ -72,4 +74,68 @@ describe('gasPrice', () => { expect(gasPrice).to.equal(null) }) }) + describe('start', () => { + const utils = { setIntervalAndRun: sinon.spy() } + beforeEach(() => { + utils.setIntervalAndRun.resetHistory() + }) + it('should call setIntervalAndRun with HOME_GAS_PRICE_UPDATE_INTERVAL interval value on Home', async () => { + // given + process.env.HOME_GAS_PRICE_UPDATE_INTERVAL = 15000 + const gasPrice = proxyquire('../src/services/gasPrice', { '../utils/utils': utils }) + + // when + await gasPrice.start('home') + + // then + expect(process.env.HOME_GAS_PRICE_UPDATE_INTERVAL).to.equal('15000') + expect(process.env.HOME_GAS_PRICE_UPDATE_INTERVAL).to.not.equal( + DEFAULT_UPDATE_INTERVAL.toString() + ) + expect(utils.setIntervalAndRun.args[0][1]).to.equal( + process.env.HOME_GAS_PRICE_UPDATE_INTERVAL.toString() + ) + }) + it('should call setIntervalAndRun with FOREIGN_GAS_PRICE_UPDATE_INTERVAL interval value on Foreign', async () => { + // given + process.env.FOREIGN_GAS_PRICE_UPDATE_INTERVAL = 15000 + const gasPrice = proxyquire('../src/services/gasPrice', { '../utils/utils': utils }) + + // when + await gasPrice.start('foreign') + + // then + expect(process.env.FOREIGN_GAS_PRICE_UPDATE_INTERVAL).to.equal('15000') + expect(process.env.HOME_GAS_PRICE_UPDATE_INTERVAL).to.not.equal( + DEFAULT_UPDATE_INTERVAL.toString() + ) + expect(utils.setIntervalAndRun.args[0][1]).to.equal( + process.env.FOREIGN_GAS_PRICE_UPDATE_INTERVAL.toString() + ) + }) + it('should call setIntervalAndRun with default interval value on Home', async () => { + // given + delete process.env.HOME_GAS_PRICE_UPDATE_INTERVAL + const gasPrice = proxyquire('../src/services/gasPrice', { '../utils/utils': utils }) + + // when + await gasPrice.start('home') + + // then + expect(process.env.HOME_GAS_PRICE_UPDATE_INTERVAL).to.equal(undefined) + expect(utils.setIntervalAndRun.args[0][1]).to.equal(DEFAULT_UPDATE_INTERVAL) + }) + it('should call setIntervalAndRun with default interval value on Foreign', async () => { + // given + delete process.env.FOREIGN_GAS_PRICE_UPDATE_INTERVAL + const gasPrice = proxyquire('../src/services/gasPrice', { '../utils/utils': utils }) + + // when + await gasPrice.start('foreign') + + // then + expect(process.env.FOREIGN_GAS_PRICE_UPDATE_INTERVAL).to.equal(undefined) + expect(utils.setIntervalAndRun.args[0][1]).to.equal(DEFAULT_UPDATE_INTERVAL) + }) + }) }) From 3d90689226677f76128a9b28b0ea07cee80a9d76 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Thu, 11 Oct 2018 11:11:28 -0300 Subject: [PATCH 17/62] Fix docker parity version to v1.11.11 --- e2e/parity/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/parity/Dockerfile b/e2e/parity/Dockerfile index 81113df..9f1f7ad 100644 --- a/e2e/parity/Dockerfile +++ b/e2e/parity/Dockerfile @@ -1,4 +1,4 @@ -FROM parity/parity:stable +FROM parity/parity:v1.11.11 WORKDIR /stuff From e00143c9db5bb3ab96f2eb480d376aca6ff98481 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 12 Oct 2018 10:15:25 -0300 Subject: [PATCH 18/62] Convert block number to BN --- src/watcher.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/watcher.js b/src/watcher.js index 7c5a428..c044545 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -1,5 +1,6 @@ require('dotenv').config() const path = require('path') +const { toBN } = require('web3').utils const { connectWatcherToQueue, connection } = require('./services/amqpClient') const { getBlockNumber } = require('./tx/web3') const { redis } = require('./services/redisClient') @@ -103,11 +104,15 @@ async function main({ sendToQueue }) { logger.info('All blocks already processed') return } + + const fromBlock = toBN(lastProcessedBlock).add(toBN(1)) + const toBlock = toBN(lastBlockToProcess) + const events = await getEvents({ contract: eventContract, event: config.event, - fromBlock: lastProcessedBlock + 1, - toBlock: lastBlockToProcess, + fromBlock, + toBlock, filter: config.eventFilter }) logger.info(`Found ${events.length} ${config.event} events`) From 879f697c5c6af593b6c9f59a155002c7062cec30 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 12 Oct 2018 11:01:58 -0300 Subject: [PATCH 19/62] Initialize lastProcessedBlock using startBlock - 1 --- config/base.config.js | 5 +++-- src/watcher.js | 23 +++++++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/config/base.config.js b/config/base.config.js index 171113f..41ab880 100644 --- a/config/base.config.js +++ b/config/base.config.js @@ -1,5 +1,6 @@ require('dotenv').config() +const { toBN } = require('web3').utils const { web3Home, web3Foreign } = require('../src/services/web3') const homeNativeAbi = require('../abis/HomeBridgeNativeToErc.abi') @@ -27,7 +28,7 @@ const homeConfig = { bridgeContractAddress: process.env.HOME_BRIDGE_ADDRESS, bridgeAbi: homeAbi, pollingInterval: process.env.HOME_POLLING_INTERVAL, - startBlock: process.env.HOME_START_BLOCK, + startBlock: toBN(process.env.HOME_START_BLOCK || 0), web3: web3Home } @@ -37,7 +38,7 @@ const foreignConfig = { bridgeContractAddress: process.env.FOREIGN_BRIDGE_ADDRESS, bridgeAbi: foreignAbi, pollingInterval: process.env.FOREIGN_POLLING_INTERVAL, - startBlock: process.env.FOREIGN_START_BLOCK, + startBlock: toBN(process.env.FOREIGN_START_BLOCK || 0), web3: web3Foreign } diff --git a/src/watcher.js b/src/watcher.js index c044545..99df94a 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -1,6 +1,6 @@ require('dotenv').config() const path = require('path') -const { toBN } = require('web3').utils +const { BN, toBN } = require('web3').utils const { connectWatcherToQueue, connection } = require('./services/amqpClient') const { getBlockNumber } = require('./tx/web3') const { redis } = require('./services/redisClient') @@ -21,11 +21,14 @@ const processCollectedSignatures = require('./events/processCollectedSignatures' const processAffirmationRequests = require('./events/processAffirmationRequests')(config) const processTransfers = require('./events/processTransfers')(config) +const ZERO = toBN(0) +const ONE = toBN(1) + const web3Instance = config.web3 const bridgeContract = new web3Instance.eth.Contract(config.bridgeAbi, config.bridgeContractAddress) const eventContract = new web3Instance.eth.Contract(config.eventAbi, config.eventContractAddress) const lastBlockRedisKey = `${config.id}:lastProcessedBlock` -let lastProcessedBlock = config.startBlock || 0 +let lastProcessedBlock = BN.max(config.startBlock.sub(ONE), ZERO) async function initialize() { try { @@ -61,12 +64,12 @@ async function runMain({ sendToQueue }) { async function getLastProcessedBlock() { const result = await redis.get(lastBlockRedisKey) - lastProcessedBlock = result ? Number(result) : lastProcessedBlock + lastProcessedBlock = result ? toBN(result) : lastProcessedBlock } function updateLastProcessedBlock(lastBlockNumber) { lastProcessedBlock = lastBlockNumber - return redis.set(lastBlockRedisKey, lastProcessedBlock) + return redis.set(lastBlockRedisKey, lastProcessedBlock.toString()) } function processEvents(events) { @@ -87,26 +90,26 @@ function processEvents(events) { } async function getLastBlockToProcess() { - const lastBlockNumberPromise = getBlockNumber(web3Instance) - const requiredBlockConfirmationsPromise = getRequiredBlockConfirmations(bridgeContract) + const lastBlockNumberPromise = getBlockNumber(web3Instance).then(toBN) + const requiredBlockConfirmationsPromise = getRequiredBlockConfirmations(bridgeContract).then(toBN) const [lastBlockNumber, requiredBlockConfirmations] = await Promise.all([ lastBlockNumberPromise, requiredBlockConfirmationsPromise ]) - return lastBlockNumber - requiredBlockConfirmations + return lastBlockNumber.sub(requiredBlockConfirmations) } async function main({ sendToQueue }) { try { const lastBlockToProcess = await getLastBlockToProcess() - if (lastBlockToProcess <= lastProcessedBlock) { + if (lastBlockToProcess.lte(lastProcessedBlock)) { logger.info('All blocks already processed') return } - const fromBlock = toBN(lastProcessedBlock).add(toBN(1)) - const toBlock = toBN(lastBlockToProcess) + const fromBlock = lastProcessedBlock.add(ONE) + const toBlock = lastBlockToProcess const events = await getEvents({ contract: eventContract, From 591b06c306c44a83fe3bbec62727f782e27a647c Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Fri, 12 Oct 2018 11:06:57 -0300 Subject: [PATCH 20/62] Update README gas price fallback description --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 704fc12..e2383c0 100644 --- a/README.md +++ b/README.md @@ -199,11 +199,11 @@ where the _watcher_ could be one of: | `FOREIGN_POLLING_INTERVAL` | The interval in milliseconds used to request the RPC node in the Foreign network for new blocks. The interval should match the average production time for a new block. | integer | | `HOME_GAS_PRICE_ORACLE_URL` | The URL used to get a JSON response from the gas price prediction oracle for the Home network. The gas price provided by the oracle is used to send the validator's transactions to the RPC node. Since it is assumed that the Home network has a predefined gas price (e.g. the gas price in the Core of POA.Network is `1 GWei`), the gas price oracle parameter can be omitted for such networks. | URL | | `HOME_GAS_PRICE_SPEED_TYPE` | Assuming the gas price oracle responds with the following JSON structure: `{"fast": 20.0, "block_time": 12.834, "health": true, "standard": 6.0, "block_number": 6470469, "instant": 71.0, "slow": 1.889}`, this parameter specifies the desirable transaction speed. The speed type can be omitted when `HOME_GAS_PRICE_ORACLE_URL` is not used. | `instant` / `fast` / `standard` / `slow` | -| `HOME_GAS_PRICE_FALLBACK` | The gas price (in GWei) that is used if both the oracle and the fall back gas price specified in the Home Bridge contract are not available. | integer | +| `HOME_GAS_PRICE_FALLBACK` | The gas price (in Wei) that is used if both the oracle and the fall back gas price specified in the Home Bridge contract are not available. | integer | | `HOME_GAS_PRICE_UPDATE_INTERVAL` | An interval in milliseconds used to get the updated gas price value either from the oracle or from the Home Bridge contract. | integer | | `FOREIGN_GAS_PRICE_ORACLE_URL` | The URL used to get a JSON response from the gas price prediction oracle for the Foreign network. The provided gas price is used to send the validator's transactions to the RPC node. If the Foreign network is Ethereum Foundation mainnet, the oracle URL can be: https://gasprice.poa.network. Otherwise this parameter can be omitted. | URL | | `FOREIGN_GAS_PRICE_SPEED_TYPE` | Assuming the gas price oracle responds with the following JSON structure: `{"fast": 20.0, "block_time": 12.834, "health": true, "standard": 6.0, "block_number": 6470469, "instant": 71.0, "slow": 1.889}`, this parameter specifies the desirable transaction speed. The speed type can be omitted when `FOREIGN_GAS_PRICE_ORACLE_URL`is not used. | `instant` / `fast` / `standard` / `slow` | -| `FOREIGN_GAS_PRICE_FALLBACK` | The gas price (in GWei) used if both the oracle and fall back gas price specified in the Foreign Bridge contract are not available. | integer | +| `FOREIGN_GAS_PRICE_FALLBACK` | The gas price (in Wei) used if both the oracle and fall back gas price specified in the Foreign Bridge contract are not available. | integer | | `FOREIGN_GAS_PRICE_UPDATE_INTERVAL` | The interval in milliseconds used to get the updated gas price value either from the oracle or from the Foreign Bridge contract. | integer | | `VALIDATOR_ADDRESS_PRIVATE_KEY` | The private key of the bridge validator used to sign confirmations before sending transactions to the bridge contracts. The validator account is calculated automatically from the private key. Every bridge instance (set of watchers and senders) must have its own unique private key. The specified private key is used to sign transactions on both sides of the bridge. | hexidecimal without "0x" | | `HOME_START_BLOCK` | The block number in the Home network used to start watching for events when the bridge instance is run for the first time. Usually this is the same block where the Home Bridge contract is deployed. If a new validator instance is being deployed for an existing set of validators, the block number could be the latest block in the chain. | integer | From 5e36ca21c93d754d2eccc17cafa8a75c891407c8 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Sat, 13 Oct 2018 18:04:27 -0300 Subject: [PATCH 21/62] Get tokens addresses from bridge contracts in scripts --- scripts/erc20_to_erc20/sendForeign.js | 36 +++++--------------------- scripts/erc20_to_erc20/sendHome.js | 11 +++++--- scripts/erc20_to_native/sendForeign.js | 36 +++++--------------------- scripts/native_to_erc20/sendForeign.js | 18 +++++++------ 4 files changed, 31 insertions(+), 70 deletions(-) diff --git a/scripts/erc20_to_erc20/sendForeign.js b/scripts/erc20_to_erc20/sendForeign.js index 82767f4..5b0f656 100644 --- a/scripts/erc20_to_erc20/sendForeign.js +++ b/scripts/erc20_to_erc20/sendForeign.js @@ -11,45 +11,23 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, FOREIGN_BRIDGE_ADDRESS, - FOREIGN_MIN_AMOUNT_PER_TX, - ERC20_TOKEN_ADDRESS + FOREIGN_MIN_AMOUNT_PER_TX } = process.env const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPOSITS_TO_SEND || 1 -const ERC20_ABI = [ - { - constant: false, - inputs: [ - { - name: '_to', - type: 'address' - }, - { - name: '_value', - type: 'uint256' - } - ], - name: 'transfer', - outputs: [ - { - name: '', - type: 'bool' - } - ], - payable: false, - stateMutability: 'nonpayable', - type: 'function' - } -] +const ERC20_ABI = require('../../abis/ERC20.abi') +const BRIDGE_ABI = require('../../abis/ForeignBridgeErcToErc.abi') const foreignRpcUrl = rpcUrlsManager.foreignUrls[0] const foreignProvider = new Web3.providers.HttpProvider(foreignRpcUrl) const web3Foreign = new Web3(foreignProvider) -const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) - async function main() { + const bridge = new web3Foreign.eth.Contract(BRIDGE_ABI, FOREIGN_BRIDGE_ADDRESS) + const ERC20_TOKEN_ADDRESS = await bridge.methods.erc20token().call() + const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) + try { const foreignChaindId = await sendRawTx({ chain: 'foreign', diff --git a/scripts/erc20_to_erc20/sendHome.js b/scripts/erc20_to_erc20/sendHome.js index 80c28d2..fc39d69 100644 --- a/scripts/erc20_to_erc20/sendHome.js +++ b/scripts/erc20_to_erc20/sendHome.js @@ -11,8 +11,7 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, HOME_BRIDGE_ADDRESS, - HOME_MIN_AMOUNT_PER_TX, - BRIDGEABLE_TOKEN_ADDRESS + HOME_MIN_AMOUNT_PER_TX } = process.env const NUMBER_OF_WITHDRAWALS_TO_SEND = @@ -48,13 +47,17 @@ const BRIDGEABLE_TOKEN_ABI = [ } ] +const BRIDGE_ABI = require('../../abis/HomeBridgeErcToErc.abi') + const homeRpcUrl = rpcUrlsManager.homeUrls[0] const homeProvider = new Web3.providers.HttpProvider(homeRpcUrl) const web3Home = new Web3(homeProvider) -const erc677 = new web3Home.eth.Contract(BRIDGEABLE_TOKEN_ABI, BRIDGEABLE_TOKEN_ADDRESS) - async function main() { + const bridge = new web3Home.eth.Contract(BRIDGE_ABI, HOME_BRIDGE_ADDRESS) + const BRIDGEABLE_TOKEN_ADDRESS = await bridge.methods.erc677token().call() + const erc677 = new web3Home.eth.Contract(BRIDGEABLE_TOKEN_ABI, BRIDGEABLE_TOKEN_ADDRESS) + try { const homeChainId = await sendRawTx({ chain: 'home', diff --git a/scripts/erc20_to_native/sendForeign.js b/scripts/erc20_to_native/sendForeign.js index 82767f4..000f59b 100644 --- a/scripts/erc20_to_native/sendForeign.js +++ b/scripts/erc20_to_native/sendForeign.js @@ -11,45 +11,23 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, FOREIGN_BRIDGE_ADDRESS, - FOREIGN_MIN_AMOUNT_PER_TX, - ERC20_TOKEN_ADDRESS + FOREIGN_MIN_AMOUNT_PER_TX } = process.env const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPOSITS_TO_SEND || 1 -const ERC20_ABI = [ - { - constant: false, - inputs: [ - { - name: '_to', - type: 'address' - }, - { - name: '_value', - type: 'uint256' - } - ], - name: 'transfer', - outputs: [ - { - name: '', - type: 'bool' - } - ], - payable: false, - stateMutability: 'nonpayable', - type: 'function' - } -] +const ERC20_ABI = require('../../abis/ERC20.abi') +const BRIDGE_ABI = require('../../abis/ForeignBridgeErcToNative.abi') const foreignRpcUrl = rpcUrlsManager.foreignUrls[0] const foreignProvider = new Web3.providers.HttpProvider(foreignRpcUrl) const web3Foreign = new Web3(foreignProvider) -const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) - async function main() { + const bridge = new web3Foreign.eth.Contract(BRIDGE_ABI, FOREIGN_BRIDGE_ADDRESS) + const ERC20_TOKEN_ADDRESS = await bridge.methods.erc20token().call() + const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) + try { const foreignChaindId = await sendRawTx({ chain: 'foreign', diff --git a/scripts/native_to_erc20/sendForeign.js b/scripts/native_to_erc20/sendForeign.js index 819ed10..573d638 100644 --- a/scripts/native_to_erc20/sendForeign.js +++ b/scripts/native_to_erc20/sendForeign.js @@ -10,27 +10,26 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, FOREIGN_BRIDGE_ADDRESS, - FOREIGN_MIN_AMOUNT_PER_TX, - ERC20_TOKEN_ADDRESS + FOREIGN_MIN_AMOUNT_PER_TX } = process.env const NUMBER_OF_WITHDRAWALS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_WITHDRAWALS_TO_SEND || 1 -const ERC20_ABI = [ +const ERC677_ABI = [ { constant: false, inputs: [ { - name: '_to', + name: '', type: 'address' }, { - name: '_value', + name: '', type: 'uint256' }, { - name: '_data', + name: '', type: 'bytes' } ], @@ -46,10 +45,13 @@ const ERC20_ABI = [ type: 'function' } ] - -const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) +const BRIDGE_ABI = require('../../abis/ForeignBridgeNativeToErc.abi') async function main() { + const bridge = new web3Foreign.eth.Contract(BRIDGE_ABI, FOREIGN_BRIDGE_ADDRESS) + const ERC20_TOKEN_ADDRESS = await bridge.methods.erc677token().call() + const poa20 = new web3Foreign.eth.Contract(ERC677_ABI, ERC20_TOKEN_ADDRESS) + try { const foreignChaindId = await sendRawTx({ chain: 'foreign', From 5ec159da0a0bbc05e196ef42e03151267fb9d56a Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 16 Oct 2018 14:00:51 -0300 Subject: [PATCH 22/62] Add gas price variable for testing transactions --- .env.example | 3 ++- README.md | 4 ++-- scripts/erc20_to_erc20/sendForeign.js | 5 +++-- scripts/erc20_to_erc20/sendHome.js | 5 +++-- scripts/erc20_to_native/sendForeign.js | 5 +++-- scripts/erc20_to_native/sendHome.js | 5 +++-- scripts/native_to_erc20/sendForeign.js | 5 +++-- scripts/native_to_erc20/sendHome.js | 5 +++-- 8 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index 2766091..6dc342a 100644 --- a/.env.example +++ b/.env.example @@ -33,4 +33,5 @@ USER_ADDRESS=0x59c4474184579b9c31b5e51445b6eef91cebf370 USER_ADDRESS_PRIVATE_KEY= HOME_MIN_AMOUNT_PER_TX=0.001 FOREIGN_MIN_AMOUNT_PER_TX=0.001 -BRIDGEABLE_TOKEN_ADDRESS= +HOME_TEST_TX_GAS_PRICE=1000000000 +FOREIGN_TEST_TX_GAS_PRICE=1000000000 diff --git a/README.md b/README.md index e2383c0..8eea2de 100644 --- a/README.md +++ b/README.md @@ -277,10 +277,10 @@ When running the processes, the following commands can be used to test functiona | `USER_ADDRESS_PRIVATE_KEY` | A private key belonging to the account. | | `HOME_BRIDGE_ADDRESS` | Address of the bridge in the Home network to send transactions. | | `HOME_MIN_AMOUNT_PER_TX` | Value (in _eth_ or tokens) to be sent in one transaction for the Home network. | +| `HOME_TEST_TX_GAS_PRICE` | The gas price (in Wei) that is used to send transactions in the Home network . | | `FOREIGN_BRIDGE_ADDRESS` | Address of the bridge in the Foreign network to send transactions. | | `FOREIGN_MIN_AMOUNT_PER_TX` | Value (in _eth_ or tokens) to be sent in one transaction for the Foreign network. | -| `ERC20_TOKEN_ADDRESS` | An address of the token deployed on the Home side for `ERC20-to-ERC20` mode. | -| `BRIDGEABLE_TOKEN_ADDRESS` | An address of the token deployed on the Home side for `Native-to-ERC20` mode or on the Foreign side for `ERC20-to-ERC20`. | +| `FOREIGN_TEST_TX_GAS_PRICE` | The gas price (in Wei) that is used to send transactions in the Foreign network . | ## Contributing diff --git a/scripts/erc20_to_erc20/sendForeign.js b/scripts/erc20_to_erc20/sendForeign.js index 5b0f656..ecf7efd 100644 --- a/scripts/erc20_to_erc20/sendForeign.js +++ b/scripts/erc20_to_erc20/sendForeign.js @@ -11,7 +11,8 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, FOREIGN_BRIDGE_ADDRESS, - FOREIGN_MIN_AMOUNT_PER_TX + FOREIGN_MIN_AMOUNT_PER_TX, + FOREIGN_TEST_TX_GAS_PRICE } = process.env const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPOSITS_TO_SEND || 1 @@ -53,7 +54,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data, nonce, - gasPrice: '1000000000', + gasPrice: FOREIGN_TEST_TX_GAS_PRICE, amount: '0', gasLimit, to: ERC20_TOKEN_ADDRESS, diff --git a/scripts/erc20_to_erc20/sendHome.js b/scripts/erc20_to_erc20/sendHome.js index fc39d69..2f959db 100644 --- a/scripts/erc20_to_erc20/sendHome.js +++ b/scripts/erc20_to_erc20/sendHome.js @@ -11,7 +11,8 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, HOME_BRIDGE_ADDRESS, - HOME_MIN_AMOUNT_PER_TX + HOME_MIN_AMOUNT_PER_TX, + HOME_TEST_TX_GAS_PRICE } = process.env const NUMBER_OF_WITHDRAWALS_TO_SEND = @@ -83,7 +84,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data, nonce, - gasPrice: '1000000000', + gasPrice: HOME_TEST_TX_GAS_PRICE, amount: '0', gasLimit, to: BRIDGEABLE_TOKEN_ADDRESS, diff --git a/scripts/erc20_to_native/sendForeign.js b/scripts/erc20_to_native/sendForeign.js index 000f59b..a1130a5 100644 --- a/scripts/erc20_to_native/sendForeign.js +++ b/scripts/erc20_to_native/sendForeign.js @@ -11,7 +11,8 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, FOREIGN_BRIDGE_ADDRESS, - FOREIGN_MIN_AMOUNT_PER_TX + FOREIGN_MIN_AMOUNT_PER_TX, + FOREIGN_TEST_TX_GAS_PRICE } = process.env const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || process.env.NUMBER_OF_DEPOSITS_TO_SEND || 1 @@ -53,7 +54,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data, nonce, - gasPrice: '1000000000', + gasPrice: FOREIGN_TEST_TX_GAS_PRICE, amount: '0', gasLimit, to: ERC20_TOKEN_ADDRESS, diff --git a/scripts/erc20_to_native/sendHome.js b/scripts/erc20_to_native/sendHome.js index 86d16b7..453062b 100644 --- a/scripts/erc20_to_native/sendHome.js +++ b/scripts/erc20_to_native/sendHome.js @@ -10,7 +10,8 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, HOME_BRIDGE_ADDRESS, - HOME_MIN_AMOUNT_PER_TX + HOME_MIN_AMOUNT_PER_TX, + HOME_TEST_TX_GAS_PRICE } = process.env const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || 1 @@ -35,7 +36,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data: '0x', nonce, - gasPrice: '1000000000', + gasPrice: HOME_TEST_TX_GAS_PRICE, amount: HOME_MIN_AMOUNT_PER_TX, gasLimit: 100000, to: HOME_BRIDGE_ADDRESS, diff --git a/scripts/native_to_erc20/sendForeign.js b/scripts/native_to_erc20/sendForeign.js index 573d638..0cdf644 100644 --- a/scripts/native_to_erc20/sendForeign.js +++ b/scripts/native_to_erc20/sendForeign.js @@ -10,7 +10,8 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, FOREIGN_BRIDGE_ADDRESS, - FOREIGN_MIN_AMOUNT_PER_TX + FOREIGN_MIN_AMOUNT_PER_TX, + FOREIGN_TEST_TX_GAS_PRICE } = process.env const NUMBER_OF_WITHDRAWALS_TO_SEND = @@ -77,7 +78,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data, nonce, - gasPrice: '1000000000', + gasPrice: FOREIGN_TEST_TX_GAS_PRICE, amount: '0', gasLimit, to: ERC20_TOKEN_ADDRESS, diff --git a/scripts/native_to_erc20/sendHome.js b/scripts/native_to_erc20/sendHome.js index 86d16b7..453062b 100644 --- a/scripts/native_to_erc20/sendHome.js +++ b/scripts/native_to_erc20/sendHome.js @@ -10,7 +10,8 @@ const { USER_ADDRESS, USER_ADDRESS_PRIVATE_KEY, HOME_BRIDGE_ADDRESS, - HOME_MIN_AMOUNT_PER_TX + HOME_MIN_AMOUNT_PER_TX, + HOME_TEST_TX_GAS_PRICE } = process.env const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || 1 @@ -35,7 +36,7 @@ async function main() { privateKey: USER_ADDRESS_PRIVATE_KEY, data: '0x', nonce, - gasPrice: '1000000000', + gasPrice: HOME_TEST_TX_GAS_PRICE, amount: HOME_MIN_AMOUNT_PER_TX, gasLimit: 100000, to: HOME_BRIDGE_ADDRESS, From b265aa6e85d3e97971ca69960e6563c738a54076 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 16 Oct 2018 14:03:41 -0300 Subject: [PATCH 23/62] Fix docker parity version to v1.11.11 --- e2e/parity/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/parity/Dockerfile b/e2e/parity/Dockerfile index 81113df..9f1f7ad 100644 --- a/e2e/parity/Dockerfile +++ b/e2e/parity/Dockerfile @@ -1,4 +1,4 @@ -FROM parity/parity:stable +FROM parity/parity:v1.11.11 WORKDIR /stuff From 5e71d8eccb535c0bc2da1f032d02fae9ba433715 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 16 Oct 2018 15:04:39 -0300 Subject: [PATCH 24/62] Check amount is bigger than min limit per tx on scripts --- scripts/erc20_to_erc20/sendForeign.js | 3 +++ scripts/erc20_to_erc20/sendHome.js | 3 +++ scripts/erc20_to_native/sendForeign.js | 3 +++ scripts/erc20_to_native/sendHome.js | 6 ++++++ scripts/native_to_erc20/sendForeign.js | 3 +++ scripts/native_to_erc20/sendHome.js | 6 ++++++ scripts/utils/utils.js | 18 ++++++++++++++++++ 7 files changed, 42 insertions(+) create mode 100644 scripts/utils/utils.js diff --git a/scripts/erc20_to_erc20/sendForeign.js b/scripts/erc20_to_erc20/sendForeign.js index ecf7efd..acfa6ce 100644 --- a/scripts/erc20_to_erc20/sendForeign.js +++ b/scripts/erc20_to_erc20/sendForeign.js @@ -6,6 +6,7 @@ const Web3 = require('web3') const Web3Utils = require('web3-utils') const rpcUrlsManager = require('../../src/services/getRpcUrlsManager') const { sendTx, sendRawTx } = require('../../src/tx/sendTx') +const { isValidAmount } = require('../utils/utils') const { USER_ADDRESS, @@ -30,6 +31,8 @@ async function main() { const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) try { + await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge) + const foreignChaindId = await sendRawTx({ chain: 'foreign', params: [], diff --git a/scripts/erc20_to_erc20/sendHome.js b/scripts/erc20_to_erc20/sendHome.js index 2f959db..0023481 100644 --- a/scripts/erc20_to_erc20/sendHome.js +++ b/scripts/erc20_to_erc20/sendHome.js @@ -6,6 +6,7 @@ const Web3 = require('web3') const Web3Utils = require('web3-utils') const rpcUrlsManager = require('../../src/services/getRpcUrlsManager') const { sendTx, sendRawTx } = require('../../src/tx/sendTx') +const { isValidAmount } = require('../utils/utils') const { USER_ADDRESS, @@ -60,6 +61,8 @@ async function main() { const erc677 = new web3Home.eth.Contract(BRIDGEABLE_TOKEN_ABI, BRIDGEABLE_TOKEN_ADDRESS) try { + await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge) + const homeChainId = await sendRawTx({ chain: 'home', params: [], diff --git a/scripts/erc20_to_native/sendForeign.js b/scripts/erc20_to_native/sendForeign.js index a1130a5..457f60a 100644 --- a/scripts/erc20_to_native/sendForeign.js +++ b/scripts/erc20_to_native/sendForeign.js @@ -6,6 +6,7 @@ const Web3 = require('web3') const Web3Utils = require('web3-utils') const rpcUrlsManager = require('../../src/services/getRpcUrlsManager') const { sendTx, sendRawTx } = require('../../src/tx/sendTx') +const { isValidAmount } = require('../utils/utils') const { USER_ADDRESS, @@ -30,6 +31,8 @@ async function main() { const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) try { + await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge) + const foreignChaindId = await sendRawTx({ chain: 'foreign', params: [], diff --git a/scripts/erc20_to_native/sendHome.js b/scripts/erc20_to_native/sendHome.js index 453062b..137c356 100644 --- a/scripts/erc20_to_native/sendHome.js +++ b/scripts/erc20_to_native/sendHome.js @@ -5,6 +5,8 @@ require('dotenv').config({ const Web3Utils = require('web3-utils') const { web3Home } = require('../../src/services/web3') const { sendTx, sendRawTx } = require('../../src/tx/sendTx') +const { isValidAmount } = require('../utils/utils') +const BRIDGE_ABI = require('../../abis/HomeBridgeErcToNative.abi') const { USER_ADDRESS, @@ -17,7 +19,11 @@ const { const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || 1 async function main() { + const bridge = new web3Home.eth.Contract(BRIDGE_ABI, HOME_BRIDGE_ADDRESS) + try { + await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge) + const homeChaindId = await sendRawTx({ chain: 'home', params: [], diff --git a/scripts/native_to_erc20/sendForeign.js b/scripts/native_to_erc20/sendForeign.js index 0cdf644..db1184d 100644 --- a/scripts/native_to_erc20/sendForeign.js +++ b/scripts/native_to_erc20/sendForeign.js @@ -5,6 +5,7 @@ require('dotenv').config({ const Web3Utils = require('web3-utils') const { web3Foreign } = require('../../src/services/web3') const { sendTx, sendRawTx } = require('../../src/tx/sendTx') +const { isValidAmount } = require('../utils/utils') const { USER_ADDRESS, @@ -54,6 +55,8 @@ async function main() { const poa20 = new web3Foreign.eth.Contract(ERC677_ABI, ERC20_TOKEN_ADDRESS) try { + await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge) + const foreignChaindId = await sendRawTx({ chain: 'foreign', params: [], diff --git a/scripts/native_to_erc20/sendHome.js b/scripts/native_to_erc20/sendHome.js index 453062b..de35608 100644 --- a/scripts/native_to_erc20/sendHome.js +++ b/scripts/native_to_erc20/sendHome.js @@ -5,6 +5,8 @@ require('dotenv').config({ const Web3Utils = require('web3-utils') const { web3Home } = require('../../src/services/web3') const { sendTx, sendRawTx } = require('../../src/tx/sendTx') +const { isValidAmount } = require('../utils/utils') +const BRIDGE_ABI = require('../../abis/HomeBridgeNativeToErc.abi') const { USER_ADDRESS, @@ -17,7 +19,11 @@ const { const NUMBER_OF_DEPOSITS_TO_SEND = process.argv[2] || 1 async function main() { + const bridge = new web3Home.eth.Contract(BRIDGE_ABI, HOME_BRIDGE_ADDRESS) + try { + await isValidAmount(HOME_MIN_AMOUNT_PER_TX, bridge) + const homeChaindId = await sendRawTx({ chain: 'home', params: [], diff --git a/scripts/utils/utils.js b/scripts/utils/utils.js new file mode 100644 index 0000000..458746d --- /dev/null +++ b/scripts/utils/utils.js @@ -0,0 +1,18 @@ +const Web3Utils = require('web3-utils') + +async function getMinPerTxLimit(bridge) { + const minPerTx = await bridge.methods.minPerTx().call() + return Web3Utils.fromWei(minPerTx) +} + +async function isValidAmount(amount, bridge) { + const minLimit = await getMinPerTxLimit(bridge) + if (amount < minLimit) { + throw new Error(`The amount per Tx ${amount} should be at least ${minLimit}`) + } +} + +module.exports = { + getMinPerTxLimit, + isValidAmount +} From e8b309ed8ca1fdb5409814492a49ebe33b3da33b Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Tue, 16 Oct 2018 18:43:25 -0300 Subject: [PATCH 25/62] Improve logging --- .../processAffirmationRequests/index.js | 15 ++++++------ .../processCollectedSignatures/index.js | 23 ++++++++----------- src/events/processSignatureRequests/index.js | 15 ++++++------ src/events/processTransfers/index.js | 13 ++++++----- src/sender.js | 13 +++++++++++ src/services/logger.js | 1 + src/watcher.js | 9 +++++++- 7 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/events/processAffirmationRequests/index.js b/src/events/processAffirmationRequests/index.js index 6092cc8..d0b584e 100644 --- a/src/events/processAffirmationRequests/index.js +++ b/src/events/processAffirmationRequests/index.js @@ -1,5 +1,5 @@ require('dotenv').config() -const logger = require('../../services/logger') +const rootLogger = require('../../services/logger') const { web3Home } = require('../../services/web3') const promiseLimit = require('promise-limit') const bridgeValidatorsABI = require('../../../abis/BridgeValidators.abi') @@ -29,12 +29,17 @@ function processAffirmationRequestsBuilder(config) { validatorContract = new web3Home.eth.Contract(bridgeValidatorsABI, validatorContractAddress) } + rootLogger.debug(`Processing ${affirmationRequests.length} AffirmationRequest events`) const callbacks = affirmationRequests.map(affirmationRequest => limit(async () => { const { recipient, value } = affirmationRequest.returnValues + const logger = rootLogger.child({ + eventTransactionHash: affirmationRequest.transactionHash + }) + logger.info( - { eventTransactionHash: affirmationRequest.transactionHash, sender: recipient, value }, + { sender: recipient, value }, `Processing affirmationRequest ${affirmationRequest.transactionHash}` ) @@ -58,14 +63,10 @@ function processAffirmationRequestsBuilder(config) { logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') process.exit(10) } else if (e instanceof AlreadySignedError) { - logger.info( - { eventTransactionHash: affirmationRequest.transactionHash }, - `Already signed affirmationRequest ${affirmationRequest.transactionHash}` - ) + logger.info(`Already signed affirmationRequest ${affirmationRequest.transactionHash}`) return } else if (e instanceof AlreadyProcessedError) { logger.info( - { eventTransactionHash: affirmationRequest.transactionHash }, `affirmationRequest ${ affirmationRequest.transactionHash } was already processed by other validators` diff --git a/src/events/processCollectedSignatures/index.js b/src/events/processCollectedSignatures/index.js index 9d3e318..90db4f9 100644 --- a/src/events/processCollectedSignatures/index.js +++ b/src/events/processCollectedSignatures/index.js @@ -2,7 +2,7 @@ require('dotenv').config() const promiseLimit = require('promise-limit') const { HttpListProviderError } = require('http-list-provider') const bridgeValidatorsABI = require('../../../abis/BridgeValidators.abi') -const logger = require('../../services/logger') +const rootLogger = require('../../services/logger') const { web3Home, web3Foreign } = require('../../services/web3') const { signatureToVRS } = require('../../utils/message') const estimateGas = require('./estimateGas') @@ -38,6 +38,7 @@ function processCollectedSignaturesBuilder(config) { ) } + rootLogger.debug(`Processing ${signatures.length} CollectedSignatures events`) const callbacks = signatures.map(colSignature => limit(async () => { const { @@ -46,11 +47,12 @@ function processCollectedSignaturesBuilder(config) { NumberOfCollectedSignatures } = colSignature.returnValues + const logger = rootLogger.child({ + eventTransactionHash: colSignature.transactionHash + }) + if (authorityResponsibleForRelay === web3Home.utils.toChecksumAddress(VALIDATOR_ADDRESS)) { - logger.info( - { eventTransactionHash: colSignature.transactionHash }, - `Processing CollectedSignatures ${colSignature.transactionHash}` - ) + logger.info(`Processing CollectedSignatures ${colSignature.transactionHash}`) const message = await homeBridge.methods.message(messageHash).call() const requiredSignatures = [] @@ -85,19 +87,13 @@ function processCollectedSignaturesBuilder(config) { 'RPC Connection Error: submitSignature Gas Estimate cannot be obtained.' ) } else if (e instanceof AlreadyProcessedError) { - logger.info( - { eventTransactionHash: colSignature.transactionHash }, - `Already processed CollectedSignatures ${colSignature.transactionHash}` - ) + logger.info(`Already processed CollectedSignatures ${colSignature.transactionHash}`) return } else if ( e instanceof IncompatibleContractError || e instanceof InvalidValidatorError ) { - logger.error( - { eventTransactionHash: colSignature.transactionHash }, - `The message couldn't be processed; skipping: ${e.message}` - ) + logger.error(`The message couldn't be processed; skipping: ${e.message}`) return } else { logger.error(e, 'Unknown error while processing transaction') @@ -113,7 +109,6 @@ function processCollectedSignaturesBuilder(config) { }) } else { logger.info( - { eventTransactionHash: colSignature.transactionHash }, `Validator not responsible for relaying CollectedSignatures ${ colSignature.transactionHash }` diff --git a/src/events/processSignatureRequests/index.js b/src/events/processSignatureRequests/index.js index 93354ca..921707c 100644 --- a/src/events/processSignatureRequests/index.js +++ b/src/events/processSignatureRequests/index.js @@ -2,7 +2,7 @@ require('dotenv').config() const promiseLimit = require('promise-limit') const { HttpListProviderError } = require('http-list-provider') const bridgeValidatorsABI = require('../../../abis/BridgeValidators.abi') -const logger = require('../../services/logger') +const rootLogger = require('../../services/logger') const { web3Home } = require('../../services/web3') const { createMessage } = require('../../utils/message') const estimateGas = require('./estimateGas') @@ -35,12 +35,17 @@ function processSignatureRequestsBuilder(config) { validatorContract = new web3Home.eth.Contract(bridgeValidatorsABI, validatorContractAddress) } + rootLogger.debug(`Processing ${signatureRequests.length} SignatureRequest events`) const callbacks = signatureRequests.map(signatureRequest => limit(async () => { const { recipient, value } = signatureRequest.returnValues + const logger = rootLogger.child({ + eventTransactionHash: signatureRequest.transactionHash + }) + logger.info( - { eventTransactionHash: signatureRequest.transactionHash, sender: recipient, value }, + { sender: recipient, value }, `Processing signatureRequest ${signatureRequest.transactionHash}` ) @@ -73,14 +78,10 @@ function processSignatureRequestsBuilder(config) { logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') process.exit(10) } else if (e instanceof AlreadySignedError) { - logger.info( - { eventTransactionHash: signatureRequest.transactionHash }, - `Already signed signatureRequest ${signatureRequest.transactionHash}` - ) + logger.info(`Already signed signatureRequest ${signatureRequest.transactionHash}`) return } else if (e instanceof AlreadyProcessedError) { logger.info( - { eventTransactionHash: signatureRequest.transactionHash }, `signatureRequest ${ signatureRequest.transactionHash } was already processed by other validators` diff --git a/src/events/processTransfers/index.js b/src/events/processTransfers/index.js index 9d935b2..c110dad 100644 --- a/src/events/processTransfers/index.js +++ b/src/events/processTransfers/index.js @@ -2,7 +2,7 @@ require('dotenv').config() const promiseLimit = require('promise-limit') const { HttpListProviderError } = require('http-list-provider') const bridgeValidatorsABI = require('../../../abis/BridgeValidators.abi') -const logger = require('../../services/logger') +const rootLogger = require('../../services/logger') const { web3Home } = require('../../services/web3') const { AlreadyProcessedError, @@ -29,10 +29,15 @@ function processTransfersBuilder(config) { validatorContract = new web3Home.eth.Contract(bridgeValidatorsABI, validatorContractAddress) } + rootLogger.debug(`Processing ${transfers.length} Transfer events`) const callbacks = transfers.map(transfer => limit(async () => { const { from, value } = transfer.returnValues + const logger = rootLogger.child({ + eventTransactionHash: transfer.transactionHash + }) + let gasEstimate try { gasEstimate = await estimateGas({ @@ -53,14 +58,10 @@ function processTransfersBuilder(config) { logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') process.exit(10) } else if (e instanceof AlreadySignedError) { - logger.info( - { eventTransactionHash: transfer.transactionHash }, - `Already signed transfer ${transfer.transactionHash}` - ) + logger.info(`Already signed transfer ${transfer.transactionHash}`) return } else if (e instanceof AlreadyProcessedError) { logger.info( - { eventTransactionHash: transfer.transactionHash }, `transfer ${transfer.transactionHash} was already processed by other validators` ) return diff --git a/src/sender.js b/src/sender.js index 55d15ed..48e5f15 100644 --- a/src/sender.js +++ b/src/sender.js @@ -76,17 +76,22 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { const gasPrice = await GasPrice.getPrice() const ttl = REDIS_LOCK_TTL * txArray.length + + logger.debug('Acquiring lock') const lock = await redlock.lock(nonceLock, ttl) + logger.debug('Reading nonce') let nonce = await readNonce() let insufficientFunds = false let minimumBalance = null const failedTx = [] + logger.debug(`Sending ${txArray.length} transactions`) await syncForEach(txArray, async job => { const gasLimit = addExtraGas(job.gasEstimate, EXTRA_GAS_PERCENTAGE) try { + logger.debug(`Sendint transaction with nonce ${nonce}`) const txHash = await sendTx({ chain: config.id, data: job.data, @@ -131,7 +136,10 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { } }) + logger.debug('Updating nonce') await updateNonce(nonce) + + logger.debug('Releasing lock') await lock.unlock() if (failedTx.length) { @@ -142,6 +150,9 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { logger.info(`Finished processing msg`) if (insufficientFunds) { + logger.warn( + 'Insufficient funds. Stop sendint transactions until the account has the minimum balance' + ) channel.close() waitForFunds(web3Instance, VALIDATOR_ADDRESS, minimumBalance, resume) } @@ -149,6 +160,8 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { logger.error(e) nackMsg(msg) } + + logger.debug('Finished') } initialize() diff --git a/src/services/logger.js b/src/services/logger.js index 7a81172..e9843d1 100644 --- a/src/services/logger.js +++ b/src/services/logger.js @@ -7,6 +7,7 @@ const config = const logger = pino({ enabled: process.env.NODE_ENV !== 'test', name: config.name, + level: 'debug', base: process.env.NODE_ENV === 'production' ? { diff --git a/src/watcher.js b/src/watcher.js index e7fda30..d1b7cde 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -101,11 +101,15 @@ async function getLastBlockToProcess() { async function main({ sendToQueue }) { try { + logger.debug('Getting last block') const lastBlockToProcess = await getLastBlockToProcess() + if (lastBlockToProcess <= lastProcessedBlock) { - logger.info('All blocks already processed') + logger.debug('All blocks already processed') return } + + logger.debug(`Getting events between block ${lastProcessedBlock + 1} and ${lastBlockToProcess}`) const events = await getEvents({ contract: eventContract, event: config.event, @@ -124,10 +128,13 @@ async function main({ sendToQueue }) { } } + logger.debug('Updating last processed block') await updateLastProcessedBlock(lastBlockToProcess) } catch (e) { logger.error(e) } + + logger.debug('Finished') } initialize() From 6575f0fd2cc8883f042bf2cd94d63840ad8031f0 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Tue, 16 Oct 2018 19:29:07 -0300 Subject: [PATCH 26/62] Compute validator address from private key --- config/base.config.js | 6 +++++- src/events/processAffirmationRequests/index.js | 8 +++----- src/events/processCollectedSignatures/index.js | 6 +++--- src/events/processSignatureRequests/index.js | 8 ++++---- src/events/processTransfers/index.js | 8 +++----- src/sender.js | 12 ++++++++++-- src/utils/utils.js | 15 ++++++++++++++- 7 files changed, 42 insertions(+), 21 deletions(-) diff --git a/config/base.config.js b/config/base.config.js index 0b8029c..77251c3 100644 --- a/config/base.config.js +++ b/config/base.config.js @@ -1,6 +1,7 @@ require('dotenv').config() const { web3Home, web3Foreign } = require('../src/services/web3') +const { privateKeyToAddress } = require('../src/utils/utils') const homeNativeErcAbi = require('../abis/HomeBridgeNativeToErc.abi') const foreignNativeErcAbi = require('../abis/ForeignBridgeNativeToErc.abi') @@ -11,6 +12,8 @@ const foreignErcErcAbi = require('../abis/ForeignBridgeErcToErc.abi') const homeErcNativeAbi = require('../abis/HomeBridgeErcToNative.abi') const foreignErcNativeAbi = require('../abis/ForeignBridgeErcToNative.abi') +const { VALIDATOR_ADDRESS, VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env + let homeAbi let foreignAbi let id @@ -46,7 +49,8 @@ const bridgeConfig = { homeBridgeAbi: homeAbi, foreignBridgeAddress: process.env.FOREIGN_BRIDGE_ADDRESS, foreignBridgeAbi: foreignAbi, - eventFilter: {} + eventFilter: {}, + validatorAddress: VALIDATOR_ADDRESS || privateKeyToAddress(VALIDATOR_ADDRESS_PRIVATE_KEY) } const homeConfig = { diff --git a/src/events/processAffirmationRequests/index.js b/src/events/processAffirmationRequests/index.js index d0b584e..f1af27e 100644 --- a/src/events/processAffirmationRequests/index.js +++ b/src/events/processAffirmationRequests/index.js @@ -12,8 +12,6 @@ const { } = require('../../utils/errors') const { HttpListProviderError } = require('http-list-provider') -const { VALIDATOR_ADDRESS } = process.env - const limit = promiseLimit(MAX_CONCURRENT_EVENTS) let validatorContract = null @@ -52,7 +50,7 @@ function processAffirmationRequestsBuilder(config) { recipient, value, txHash: affirmationRequest.transactionHash, - address: VALIDATOR_ADDRESS + address: config.validatorAddress }) } catch (e) { if (e instanceof HttpListProviderError) { @@ -60,7 +58,7 @@ function processAffirmationRequestsBuilder(config) { 'RPC Connection Error: submitSignature Gas Estimate cannot be obtained.' ) } else if (e instanceof InvalidValidatorError) { - logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') + logger.fatal({ address: config.validatorAddress }, 'Invalid validator') process.exit(10) } else if (e instanceof AlreadySignedError) { logger.info(`Already signed affirmationRequest ${affirmationRequest.transactionHash}`) @@ -80,7 +78,7 @@ function processAffirmationRequestsBuilder(config) { const data = await homeBridge.methods .executeAffirmation(recipient, value, affirmationRequest.transactionHash) - .encodeABI({ from: VALIDATOR_ADDRESS }) + .encodeABI({ from: config.validatorAddress }) txToSend.push({ data, diff --git a/src/events/processCollectedSignatures/index.js b/src/events/processCollectedSignatures/index.js index 90db4f9..d0635a9 100644 --- a/src/events/processCollectedSignatures/index.js +++ b/src/events/processCollectedSignatures/index.js @@ -13,8 +13,6 @@ const { } = require('../../utils/errors') const { MAX_CONCURRENT_EVENTS } = require('../../utils/constants') -const { VALIDATOR_ADDRESS } = process.env - const limit = promiseLimit(MAX_CONCURRENT_EVENTS) let validatorContract = null @@ -51,7 +49,9 @@ function processCollectedSignaturesBuilder(config) { eventTransactionHash: colSignature.transactionHash }) - if (authorityResponsibleForRelay === web3Home.utils.toChecksumAddress(VALIDATOR_ADDRESS)) { + if ( + authorityResponsibleForRelay === web3Home.utils.toChecksumAddress(config.validatorAddress) + ) { logger.info(`Processing CollectedSignatures ${colSignature.transactionHash}`) const message = await homeBridge.methods.message(messageHash).call() diff --git a/src/events/processSignatureRequests/index.js b/src/events/processSignatureRequests/index.js index 921707c..4a6300a 100644 --- a/src/events/processSignatureRequests/index.js +++ b/src/events/processSignatureRequests/index.js @@ -13,7 +13,7 @@ const { } = require('../../utils/errors') const { MAX_CONCURRENT_EVENTS } = require('../../utils/constants') -const { VALIDATOR_ADDRESS, VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env +const { VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env const limit = promiseLimit(MAX_CONCURRENT_EVENTS) @@ -67,7 +67,7 @@ function processSignatureRequestsBuilder(config) { validatorContract, signature: signature.signature, message, - address: VALIDATOR_ADDRESS + address: config.validatorAddress }) } catch (e) { if (e instanceof HttpListProviderError) { @@ -75,7 +75,7 @@ function processSignatureRequestsBuilder(config) { 'RPC Connection Error: submitSignature Gas Estimate cannot be obtained.' ) } else if (e instanceof InvalidValidatorError) { - logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') + logger.fatal({ address: config.validatorAddress }, 'Invalid validator') process.exit(10) } else if (e instanceof AlreadySignedError) { logger.info(`Already signed signatureRequest ${signatureRequest.transactionHash}`) @@ -95,7 +95,7 @@ function processSignatureRequestsBuilder(config) { const data = await homeBridge.methods .submitSignature(signature.signature, message) - .encodeABI({ from: VALIDATOR_ADDRESS }) + .encodeABI({ from: config.validatorAddress }) txToSend.push({ data, diff --git a/src/events/processTransfers/index.js b/src/events/processTransfers/index.js index c110dad..c33db8c 100644 --- a/src/events/processTransfers/index.js +++ b/src/events/processTransfers/index.js @@ -12,8 +12,6 @@ const { const { MAX_CONCURRENT_EVENTS } = require('../../utils/constants') const estimateGas = require('../processAffirmationRequests/estimateGas') -const { VALIDATOR_ADDRESS } = process.env - const limit = promiseLimit(MAX_CONCURRENT_EVENTS) let validatorContract = null @@ -47,7 +45,7 @@ function processTransfersBuilder(config) { recipient: from, value, txHash: transfer.transactionHash, - address: VALIDATOR_ADDRESS + address: config.validatorAddress }) } catch (e) { if (e instanceof HttpListProviderError) { @@ -55,7 +53,7 @@ function processTransfersBuilder(config) { 'RPC Connection Error: submitSignature Gas Estimate cannot be obtained.' ) } else if (e instanceof InvalidValidatorError) { - logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') + logger.fatal({ address: config.validatorAddress }, 'Invalid validator') process.exit(10) } else if (e instanceof AlreadySignedError) { logger.info(`Already signed transfer ${transfer.transactionHash}`) @@ -73,7 +71,7 @@ function processTransfersBuilder(config) { const data = await homeBridge.methods .executeAffirmation(from, value, transfer.transactionHash) - .encodeABI({ from: VALIDATOR_ADDRESS }) + .encodeABI({ from: config.validatorAddress }) txToSend.push({ data, diff --git a/src/sender.js b/src/sender.js index 48e5f15..4b0d2a1 100644 --- a/src/sender.js +++ b/src/sender.js @@ -7,10 +7,18 @@ const logger = require('./services/logger') const rpcUrlsManager = require('./services/getRpcUrlsManager') const { sendTx } = require('./tx/sendTx') const { getNonce, getChainId } = require('./tx/web3') -const { addExtraGas, checkHTTPS, syncForEach, waitForFunds } = require('./utils/utils') +const { + addExtraGas, + checkHTTPS, + syncForEach, + waitForFunds, + privateKeyToAddress +} = require('./utils/utils') const { EXTRA_GAS_PERCENTAGE } = require('./utils/constants') -const { VALIDATOR_ADDRESS, VALIDATOR_ADDRESS_PRIVATE_KEY, REDIS_LOCK_TTL } = process.env +const { VALIDATOR_ADDRESS_PRIVATE_KEY, REDIS_LOCK_TTL } = process.env + +const VALIDATOR_ADDRESS = privateKeyToAddress(VALIDATOR_ADDRESS_PRIVATE_KEY) if (process.argv.length < 3) { logger.error('Please check the number of arguments, config file was not provided') diff --git a/src/utils/utils.js b/src/utils/utils.js index 6834f75..f92f6b1 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -56,10 +56,23 @@ function setIntervalAndRun(f, interval) { return handler } +function add0xPrefix(s) { + if (s.indexOf('0x') === 0) { + return s + } + + return `0x${s}` +} + +function privateKeyToAddress(privateKey) { + return new Web3().eth.accounts.privateKeyToAccount(add0xPrefix(privateKey)).address +} + module.exports = { syncForEach, checkHTTPS, waitForFunds, addExtraGas, - setIntervalAndRun + setIntervalAndRun, + privateKeyToAddress } From 2fad9b9cca14b3eedbcecc8c931c845906c70bc4 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Tue, 16 Oct 2018 19:29:12 -0300 Subject: [PATCH 27/62] Inject logger in checkHTTPS to avoid circular dependency --- src/sender.js | 2 +- src/utils/utils.js | 4 ++-- src/watcher.js | 2 +- test/utils.test.js | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sender.js b/src/sender.js index 4b0d2a1..fbfe212 100644 --- a/src/sender.js +++ b/src/sender.js @@ -34,7 +34,7 @@ let chainId = 0 async function initialize() { try { - const checkHttps = checkHTTPS(process.env.ALLOW_HTTP) + const checkHttps = checkHTTPS(process.env.ALLOW_HTTP, logger) rpcUrlsManager.homeUrls.forEach(checkHttps('home')) rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign')) diff --git a/src/utils/utils.js b/src/utils/utils.js index f92f6b1..ab7f81e 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1,6 +1,6 @@ const BigNumber = require('bignumber.js') const promiseRetry = require('promise-retry') -const logger = require('../services/logger') +const Web3 = require('web3') async function syncForEach(array, callback) { for (let index = 0; index < array.length; index++) { @@ -8,7 +8,7 @@ async function syncForEach(array, callback) { } } -function checkHTTPS(ALLOW_HTTP) { +function checkHTTPS(ALLOW_HTTP, logger) { return function(network) { return function(url) { if (!/^https.*/.test(url)) { diff --git a/src/watcher.js b/src/watcher.js index d1b7cde..dc9314a 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -28,7 +28,7 @@ let lastProcessedBlock = config.startBlock || 0 async function initialize() { try { - const checkHttps = checkHTTPS(process.env.ALLOW_HTTP) + const checkHttps = checkHTTPS(process.env.ALLOW_HTTP, logger) rpcUrlsManager.homeUrls.forEach(checkHttps('home')) rpcUrlsManager.foreignUrls.forEach(checkHttps('foreign')) diff --git a/test/utils.test.js b/test/utils.test.js index 0c1f5ac..2742690 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -44,22 +44,22 @@ describe('utils', () => { }) it('should do nothing if HTTP is allowed and the URL is https', () => { - utils.checkHTTPS('yes')('home')('https://www.google.com') + utils.checkHTTPS('yes', logger)('home')('https://www.google.com') expect(logger.warn.called).to.equal(false) }) it('should emit a warning if HTTP is allowed and the URL is http', () => { - utils.checkHTTPS('yes')('home')('http://www.google.com') + utils.checkHTTPS('yes', logger)('home')('http://www.google.com') expect(logger.warn.called).to.equal(true) }) it('should do nothing if HTTP is not allowed and the URL is https', () => { - utils.checkHTTPS('no')('home')('https://www.google.com') + utils.checkHTTPS('no', logger)('home')('https://www.google.com') expect(logger.warn.called).to.equal(false) }) it('should throw an error if HTTP is not allowed and the URL is http', () => { - expect(() => utils.checkHTTPS('no')('home')('http://www.google.com')).to.throw() + expect(() => utils.checkHTTPS('no', logger)('home')('http://www.google.com')).to.throw() }) }) From ab39d5a8fe77a1ca7d2ae07c1f4644436d4f4a37 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Tue, 16 Oct 2018 19:34:49 -0300 Subject: [PATCH 28/62] Fix typos in log messages --- src/sender.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sender.js b/src/sender.js index fbfe212..e1fc531 100644 --- a/src/sender.js +++ b/src/sender.js @@ -99,7 +99,7 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { const gasLimit = addExtraGas(job.gasEstimate, EXTRA_GAS_PERCENTAGE) try { - logger.debug(`Sendint transaction with nonce ${nonce}`) + logger.debug(`Sending transaction with nonce ${nonce}`) const txHash = await sendTx({ chain: config.id, data: job.data, @@ -159,7 +159,7 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { if (insufficientFunds) { logger.warn( - 'Insufficient funds. Stop sendint transactions until the account has the minimum balance' + 'Insufficient funds. Stop sending transactions until the account has the minimum balance' ) channel.close() waitForFunds(web3Instance, VALIDATOR_ADDRESS, minimumBalance, resume) From 8a806825a9b60de4fcee2c551264a9fd4ace392f Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 17 Oct 2018 10:34:31 -0300 Subject: [PATCH 29/62] Remove min limit check on foreign erc20-to-native script --- scripts/erc20_to_native/sendForeign.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/erc20_to_native/sendForeign.js b/scripts/erc20_to_native/sendForeign.js index 457f60a..a1130a5 100644 --- a/scripts/erc20_to_native/sendForeign.js +++ b/scripts/erc20_to_native/sendForeign.js @@ -6,7 +6,6 @@ const Web3 = require('web3') const Web3Utils = require('web3-utils') const rpcUrlsManager = require('../../src/services/getRpcUrlsManager') const { sendTx, sendRawTx } = require('../../src/tx/sendTx') -const { isValidAmount } = require('../utils/utils') const { USER_ADDRESS, @@ -31,8 +30,6 @@ async function main() { const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) try { - await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge) - const foreignChaindId = await sendRawTx({ chain: 'foreign', params: [], From cc7d72cc5bdf072e3c11bd7940a4c016adbfa57d Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 17 Oct 2018 10:35:24 -0300 Subject: [PATCH 30/62] Remove min limit check on foreign erc20-to-erc20 script --- scripts/erc20_to_erc20/sendForeign.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/erc20_to_erc20/sendForeign.js b/scripts/erc20_to_erc20/sendForeign.js index acfa6ce..ecf7efd 100644 --- a/scripts/erc20_to_erc20/sendForeign.js +++ b/scripts/erc20_to_erc20/sendForeign.js @@ -6,7 +6,6 @@ const Web3 = require('web3') const Web3Utils = require('web3-utils') const rpcUrlsManager = require('../../src/services/getRpcUrlsManager') const { sendTx, sendRawTx } = require('../../src/tx/sendTx') -const { isValidAmount } = require('../utils/utils') const { USER_ADDRESS, @@ -31,8 +30,6 @@ async function main() { const poa20 = new web3Foreign.eth.Contract(ERC20_ABI, ERC20_TOKEN_ADDRESS) try { - await isValidAmount(FOREIGN_MIN_AMOUNT_PER_TX, bridge) - const foreignChaindId = await sendRawTx({ chain: 'foreign', params: [], From 4cd227f9df74388669a3798f89bf14c6a16b276b Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 17 Oct 2018 10:54:02 -0300 Subject: [PATCH 31/62] Fix privateKeyToAddress method if no private key provided --- src/utils/utils.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/utils.js b/src/utils/utils.js index ab7f81e..af2725b 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -65,7 +65,9 @@ function add0xPrefix(s) { } function privateKeyToAddress(privateKey) { - return new Web3().eth.accounts.privateKeyToAccount(add0xPrefix(privateKey)).address + return privateKey + ? new Web3().eth.accounts.privateKeyToAccount(add0xPrefix(privateKey)).address + : null } module.exports = { From 63ee1ff1f870a44ff2229ee2c020163dd51e5688 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Thu, 18 Oct 2018 18:55:30 -0300 Subject: [PATCH 32/62] Add watchdog in watcher --- .env.example | 2 ++ src/utils/utils.js | 20 +++++++++++++++++++- src/watcher.js | 10 ++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index 7a5b006..3efe1bd 100644 --- a/.env.example +++ b/.env.example @@ -28,6 +28,8 @@ REDIS_LOCK_TTL=1000 HOME_START_BLOCK= FOREIGN_START_BLOCK= +MAX_PROCESSING_TIME=600000 + #testing accs USER_ADDRESS=0x59c4474184579b9c31b5e51445b6eef91cebf370 USER_ADDRESS_PRIVATE_KEY= diff --git a/src/utils/utils.js b/src/utils/utils.js index 6834f75..7f4d242 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -56,10 +56,28 @@ function setIntervalAndRun(f, interval) { return handler } +/** + * Run function `f` and return its result, unless `timeout` milliseconds pass before `f` ends. If that happens, run + * `kill` instead. + * + * @param {Function} f The function to run. It is assumed that it's an async function. + * @param {Number} timeout Max time in milliseconds to wait for `f` to finish. + * @param {Function} kill Function that will be called if `f` takes more than `timeout` milliseconds. + */ +async function watchdog(f, timeout, kill) { + const timeoutHandler = setTimeout(kill, timeout) + + const result = await f() + clearTimeout(timeoutHandler) + + return result +} + module.exports = { syncForEach, checkHTTPS, waitForFunds, addExtraGas, - setIntervalAndRun + setIntervalAndRun, + watchdog } diff --git a/src/watcher.js b/src/watcher.js index 99df94a..d7487ab 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -7,7 +7,7 @@ const { redis } = require('./services/redisClient') const logger = require('./services/logger') const rpcUrlsManager = require('./services/getRpcUrlsManager') const { getRequiredBlockConfirmations, getEvents } = require('./tx/web3') -const { checkHTTPS } = require('./utils/utils') +const { checkHTTPS, watchdog } = require('./utils/utils') if (process.argv.length < 3) { logger.error('Please check the number of arguments, config file was not provided') @@ -30,6 +30,8 @@ const eventContract = new web3Instance.eth.Contract(config.eventAbi, config.even const lastBlockRedisKey = `${config.id}:lastProcessedBlock` let lastProcessedBlock = BN.max(config.startBlock.sub(ONE), ZERO) +const maxProcessingTime = process.env.MAX_PROCESSING_TIME + async function initialize() { try { const checkHttps = checkHTTPS(process.env.ALLOW_HTTP) @@ -51,7 +53,11 @@ async function initialize() { async function runMain({ sendToQueue }) { try { if (connection.isConnected() && redis.status === 'ready') { - await main({ sendToQueue }) + if (maxProcessingTime) { + await watchdog(() => main({ sendToQueue }), maxProcessingTime, () => process.exit(11)) + } else { + await main({ sendToQueue }) + } } } catch (e) { logger.error(e) From 3273b23f90df4e7a89ba0c5c09e5d33716b7a6c1 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Thu, 18 Oct 2018 19:08:32 -0300 Subject: [PATCH 33/62] Move exit codes to constants --- src/events/processAffirmationRequests/index.js | 4 ++-- src/events/processSignatureRequests/index.js | 4 ++-- src/events/processTransfers/index.js | 4 ++-- src/utils/constants.js | 6 +++++- src/watcher.js | 5 ++++- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/events/processAffirmationRequests/index.js b/src/events/processAffirmationRequests/index.js index 6092cc8..b6e96d5 100644 --- a/src/events/processAffirmationRequests/index.js +++ b/src/events/processAffirmationRequests/index.js @@ -3,7 +3,7 @@ const logger = require('../../services/logger') const { web3Home } = require('../../services/web3') const promiseLimit = require('promise-limit') const bridgeValidatorsABI = require('../../../abis/BridgeValidators.abi') -const { MAX_CONCURRENT_EVENTS } = require('../../utils/constants') +const { EXIT_CODES, MAX_CONCURRENT_EVENTS } = require('../../utils/constants') const estimateGas = require('./estimateGas') const { AlreadyProcessedError, @@ -56,7 +56,7 @@ function processAffirmationRequestsBuilder(config) { ) } else if (e instanceof InvalidValidatorError) { logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') - process.exit(10) + process.exit(EXIT_CODES.INCOMPATIBILITY) } else if (e instanceof AlreadySignedError) { logger.info( { eventTransactionHash: affirmationRequest.transactionHash }, diff --git a/src/events/processSignatureRequests/index.js b/src/events/processSignatureRequests/index.js index 93354ca..f36ebe3 100644 --- a/src/events/processSignatureRequests/index.js +++ b/src/events/processSignatureRequests/index.js @@ -11,7 +11,7 @@ const { AlreadySignedError, InvalidValidatorError } = require('../../utils/errors') -const { MAX_CONCURRENT_EVENTS } = require('../../utils/constants') +const { EXIT_CODES, MAX_CONCURRENT_EVENTS } = require('../../utils/constants') const { VALIDATOR_ADDRESS, VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env @@ -71,7 +71,7 @@ function processSignatureRequestsBuilder(config) { ) } else if (e instanceof InvalidValidatorError) { logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') - process.exit(10) + process.exit(EXIT_CODES.INCOMPATIBILITY) } else if (e instanceof AlreadySignedError) { logger.info( { eventTransactionHash: signatureRequest.transactionHash }, diff --git a/src/events/processTransfers/index.js b/src/events/processTransfers/index.js index 9d935b2..5b156ab 100644 --- a/src/events/processTransfers/index.js +++ b/src/events/processTransfers/index.js @@ -9,7 +9,7 @@ const { AlreadySignedError, InvalidValidatorError } = require('../../utils/errors') -const { MAX_CONCURRENT_EVENTS } = require('../../utils/constants') +const { EXIT_CODES, MAX_CONCURRENT_EVENTS } = require('../../utils/constants') const estimateGas = require('../processAffirmationRequests/estimateGas') const { VALIDATOR_ADDRESS } = process.env @@ -51,7 +51,7 @@ function processTransfersBuilder(config) { ) } else if (e instanceof InvalidValidatorError) { logger.fatal({ address: VALIDATOR_ADDRESS }, 'Invalid validator') - process.exit(10) + process.exit(EXIT_CODES.INCOMPATIBILITY) } else if (e instanceof AlreadySignedError) { logger.info( { eventTransactionHash: transfer.transactionHash }, diff --git a/src/utils/constants.js b/src/utils/constants.js index 0804914..221fa2c 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -7,5 +7,9 @@ module.exports = { maxTimeout: 360000, randomize: true }, - DEFAULT_UPDATE_INTERVAL: 600000 + DEFAULT_UPDATE_INTERVAL: 600000, + EXIT_CODES: { + INCOMPATIBILITY: 10, + MAX_TIME_REACHED: 11 + } } diff --git a/src/watcher.js b/src/watcher.js index d7487ab..0ce9bf1 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -8,6 +8,7 @@ const logger = require('./services/logger') const rpcUrlsManager = require('./services/getRpcUrlsManager') const { getRequiredBlockConfirmations, getEvents } = require('./tx/web3') const { checkHTTPS, watchdog } = require('./utils/utils') +const { EXIT_CODES } = require('./utils/constants') if (process.argv.length < 3) { logger.error('Please check the number of arguments, config file was not provided') @@ -54,7 +55,9 @@ async function runMain({ sendToQueue }) { try { if (connection.isConnected() && redis.status === 'ready') { if (maxProcessingTime) { - await watchdog(() => main({ sendToQueue }), maxProcessingTime, () => process.exit(11)) + await watchdog(() => main({ sendToQueue }), maxProcessingTime, () => + process.exit(EXIT_CODES.MAX_TIME_REACHED) + ) } else { await main({ sendToQueue }) } From dd3c72770489627b6b846f656dc256fcb00a8439 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Thu, 18 Oct 2018 19:13:26 -0300 Subject: [PATCH 34/62] Add log when process exits --- src/watcher.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/watcher.js b/src/watcher.js index 0ce9bf1..f45ed94 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -55,9 +55,10 @@ async function runMain({ sendToQueue }) { try { if (connection.isConnected() && redis.status === 'ready') { if (maxProcessingTime) { - await watchdog(() => main({ sendToQueue }), maxProcessingTime, () => + await watchdog(() => main({ sendToQueue }), maxProcessingTime, () => { + logger.fatal('Max processing time reached') process.exit(EXIT_CODES.MAX_TIME_REACHED) - ) + }) } else { await main({ sendToQueue }) } From a8c795d7742fc048828e09dc328e4392f688fe3a Mon Sep 17 00:00:00 2001 From: fvictorio Date: Fri, 19 Oct 2018 10:43:44 -0300 Subject: [PATCH 35/62] Add privateKeyToAddress script --- scripts/privateKeyToAddress.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 scripts/privateKeyToAddress.js diff --git a/scripts/privateKeyToAddress.js b/scripts/privateKeyToAddress.js new file mode 100644 index 0000000..79a3c0c --- /dev/null +++ b/scripts/privateKeyToAddress.js @@ -0,0 +1,12 @@ +const { privateKeyToAddress } = require('../src/utils/utils') + +const privateKey = process.argv[2] + +if (!privateKey) { + console.error('Usage: node privateKeyToAddress.js ') + process.exit(1) +} + +const address = privateKeyToAddress(privateKey) + +console.log(address) From 91f378ae6b346958344121ea1ca3864c927ce9cf Mon Sep 17 00:00:00 2001 From: fvictorio Date: Fri, 19 Oct 2018 11:42:29 -0300 Subject: [PATCH 36/62] Take private key from environment variable --- scripts/privateKeyToAddress.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/privateKeyToAddress.js b/scripts/privateKeyToAddress.js index 79a3c0c..be63059 100644 --- a/scripts/privateKeyToAddress.js +++ b/scripts/privateKeyToAddress.js @@ -1,9 +1,13 @@ +const path = require('path') +require('dotenv').config({ + path: path.join(__dirname, '..', '.env') +}) const { privateKeyToAddress } = require('../src/utils/utils') -const privateKey = process.argv[2] +const privateKey = process.env.VALIDATOR_ADDRESS_PRIVATE_KEY if (!privateKey) { - console.error('Usage: node privateKeyToAddress.js ') + console.error('Environment variable VALIDATOR_ADDRESS_PRIVATE_KEY is not set') process.exit(1) } From 1015ab061646aeec35dbfce5859c96f323404d7b Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 11:03:29 -0300 Subject: [PATCH 37/62] Add logs in web3 module --- src/tx/web3.js | 34 +++++++++++++++++++++++++++++----- src/watcher.js | 2 -- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/tx/web3.js b/src/tx/web3.js index d9fb140..6196b02 100644 --- a/src/tx/web3.js +++ b/src/tx/web3.js @@ -1,6 +1,13 @@ +const logger = require('../services/logger').child({ + module: 'web3' +}) + async function getNonce(web3, address) { try { - return await web3.eth.getTransactionCount(address) + logger.debug({ address }, 'Getting transaction count') + const transactionCount = await web3.eth.getTransactionCount(address) + logger.debug({ address, transactionCount }, 'Transaction count obtained') + return transactionCount } catch (e) { throw new Error(`Nonce cannot be obtained`) } @@ -8,7 +15,10 @@ async function getNonce(web3, address) { async function getBlockNumber(web3) { try { - return await web3.eth.getBlockNumber() + logger.debug('Getting block number') + const blockNumber = await web3.eth.getBlockNumber() + logger.debug({ blockNumber }, 'Block number obtained') + return blockNumber } catch (e) { throw new Error(`Block Number cannot be obtained`) } @@ -16,7 +26,10 @@ async function getBlockNumber(web3) { async function getChainId(web3) { try { - return await web3.eth.net.getId() + logger.debug('Getting chain id') + const chainId = await web3.eth.net.getId() + logger.debug({ chainId }, 'Chain id obtained') + return chainId } catch (e) { throw new Error(`Chain Id cannot be obtained`) } @@ -24,7 +37,14 @@ async function getChainId(web3) { async function getRequiredBlockConfirmations(contract) { try { - return await contract.methods.requiredBlockConfirmations().call() + const contractAddress = contract.options.address + logger.debug({ contractAddress }, 'Getting required block confirmations') + const requiredBlockConfirmations = await contract.methods.requiredBlockConfirmations().call() + logger.debug( + { contractAddress, requiredBlockConfirmations }, + 'Required block confirmations obtained' + ) + return requiredBlockConfirmations } catch (e) { throw new Error(`Required block confirmations cannot be obtained`) } @@ -32,7 +52,11 @@ async function getRequiredBlockConfirmations(contract) { async function getEvents({ contract, event, fromBlock, toBlock, filter }) { try { - return await contract.getPastEvents(event, { fromBlock, toBlock, filter }) + const contractAddress = contract.options.address + logger.debug({ contractAddress, event }, 'Getting past events') + const pastEvents = await contract.getPastEvents(event, { fromBlock, toBlock, filter }) + logger.debug({ contractAddress, event, count: pastEvents.length }, 'Past events obtained') + return pastEvents } catch (e) { throw new Error(`${event} events cannot be obtained`) } diff --git a/src/watcher.js b/src/watcher.js index 6914a37..ece7ef1 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -105,7 +105,6 @@ async function getLastBlockToProcess() { async function main({ sendToQueue }) { try { - logger.debug('Getting last block') const lastBlockToProcess = await getLastBlockToProcess() if (lastBlockToProcess.lte(lastProcessedBlock)) { @@ -116,7 +115,6 @@ async function main({ sendToQueue }) { const fromBlock = lastProcessedBlock.add(ONE) const toBlock = lastBlockToProcess - logger.debug(`Getting events between block ${fromBlock} and ${toBlock}`) const events = await getEvents({ contract: eventContract, event: config.event, From c09b7ebe6f1466735dd413881d596931cb3b9705 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 11:09:16 -0300 Subject: [PATCH 38/62] Allow setting log level with env variable --- .env.example | 2 ++ README.md | 1 + src/services/logger.js | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 6dc342a..d132d55 100644 --- a/.env.example +++ b/.env.example @@ -28,6 +28,8 @@ REDIS_LOCK_TTL=1000 HOME_START_BLOCK= FOREIGN_START_BLOCK= +LOG_LEVEL=debug + #testing accs USER_ADDRESS=0x59c4474184579b9c31b5e51445b6eef91cebf370 USER_ADDRESS_PRIVATE_KEY= diff --git a/README.md b/README.md index e70359e..942afbf 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,7 @@ where the _watcher_ could be one of: | `REDIS_URL` | Redis DB URL used by watchers and senders to communicate to the database. Typically set to: `redis://127.0.0.1:6379`. | local URL | | `REDIS_LOCK_TTL` | Threshold in milliseconds for locking a resource in the Redis DB. Until the threshold is exceeded, the resource is unlocked. Usually it is `1000`. | integer | | `ALLOW_HTTP` | **Only use in test environments - must be omitted in production environments.**. If this parameter is specified and set to `yes`, RPC URLs can be specified in form of HTTP links. A warning that the connection is insecure will be written to the logs. | `yes` / `no` | +| `LOG_LEVEL` | Set the level of details in the logs. | `trace` / `debug` / `info` / `warn` / `error` / `fatal` | ### Useful Commands for Development diff --git a/src/services/logger.js b/src/services/logger.js index e9843d1..e7122b7 100644 --- a/src/services/logger.js +++ b/src/services/logger.js @@ -7,7 +7,7 @@ const config = const logger = pino({ enabled: process.env.NODE_ENV !== 'test', name: config.name, - level: 'debug', + level: process.env.LOG_LEVEL || 'debug', base: process.env.NODE_ENV === 'production' ? { From 30a4d100738d8da8a1f1b5e14c015ffb330998d3 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 11:12:02 -0300 Subject: [PATCH 39/62] Show new last processed block in logs --- src/watcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/watcher.js b/src/watcher.js index ece7ef1..d45848d 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -133,7 +133,7 @@ async function main({ sendToQueue }) { } } - logger.debug('Updating last processed block') + logger.debug({ lastProcessedBlock: lastBlockToProcess }, 'Updating last processed block') await updateLastProcessedBlock(lastBlockToProcess) } catch (e) { logger.error(e) From 3402de1073e3c02aaddca769055a5a23269bd09c Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 11:18:58 -0300 Subject: [PATCH 40/62] Improve logs for nonce fetching --- .eslintrc | 1 + src/sender.js | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.eslintrc b/.eslintrc index 3614120..5d33751 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,6 +10,7 @@ "func-names": "off", "no-await-in-loop": "off", "no-console": "off", + "no-else-return": "off", "no-param-reassign": "off", "no-plusplus": "off", "no-restricted-syntax": "off", diff --git a/src/sender.js b/src/sender.js index e1fc531..0d9a02e 100644 --- a/src/sender.js +++ b/src/sender.js @@ -60,12 +60,20 @@ function resume(newBalance) { } async function readNonce(forceUpdate) { + logger.debug('Reading nonce') if (forceUpdate) { + logger.debug('Forcing update of nonce') return getNonce(web3Instance, VALIDATOR_ADDRESS) } - const result = await redis.get(nonceKey) - return result ? Number(result) : getNonce(web3Instance, VALIDATOR_ADDRESS) + const nonce = await redis.get(nonceKey) + if (nonce) { + logger.debug({ nonce }, 'Nonce found in the DB') + return Number(nonce) + } else { + logger.debug("Nonce wasn't found in the DB") + return getNonce(web3Instance, VALIDATOR_ADDRESS) + } } function updateNonce(nonce) { @@ -88,7 +96,6 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { logger.debug('Acquiring lock') const lock = await redlock.lock(nonceLock, ttl) - logger.debug('Reading nonce') let nonce = await readNonce() let insufficientFunds = false let minimumBalance = null From cfc872ada184457ff395cbd92815fe351bc82248 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 11:24:38 -0300 Subject: [PATCH 41/62] Remove unnecessary async/await --- src/sender.js | 2 +- src/services/gasPrice.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sender.js b/src/sender.js index 0d9a02e..9f8344a 100644 --- a/src/sender.js +++ b/src/sender.js @@ -89,7 +89,7 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { const txArray = JSON.parse(msg.content) logger.info(`Msg received with ${txArray.length} Tx to send`) - const gasPrice = await GasPrice.getPrice() + const gasPrice = GasPrice.getPrice() const ttl = REDIS_LOCK_TTL * txArray.length diff --git a/src/services/gasPrice.js b/src/services/gasPrice.js index 2c177a4..8492a9f 100644 --- a/src/services/gasPrice.js +++ b/src/services/gasPrice.js @@ -91,7 +91,7 @@ async function start(chainId) { }, updateInterval) } -async function getPrice() { +function getPrice() { return cachedGasPrice } From a9e4c564276c6dfab9ba738ac9b483bf458b04e2 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 11:26:42 -0300 Subject: [PATCH 42/62] Improve logging in gas price module --- src/services/gasPrice.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/services/gasPrice.js b/src/services/gasPrice.js index 8492a9f..4a37352 100644 --- a/src/services/gasPrice.js +++ b/src/services/gasPrice.js @@ -3,7 +3,9 @@ const fetch = require('node-fetch') const Web3Utils = require('web3-utils') const { web3Home, web3Foreign } = require('../services/web3') const { bridgeConfig } = require('../../config/base.config') -const logger = require('../services/logger') +const logger = require('../services/logger').child({ + module: 'gasPrice' +}) const { setIntervalAndRun } = require('../utils/utils') const { DEFAULT_UPDATE_INTERVAL } = require('../utils/constants') @@ -43,11 +45,13 @@ async function fetchGasPrice({ bridgeContract, oracleFn }) { let gasPrice = null try { gasPrice = await oracleFn() + logger.debug({ gasPrice }, 'Gas price updated using the oracle') } catch (e) { logger.error(`Gas Price API is not available. ${e.message}`) try { gasPrice = await bridgeContract.methods.gasPrice().call() + logger.debug({ gasPrice }, 'Gas price updated using the contracts') } catch (e) { logger.error(`There was a problem getting the gas price from the contract. ${e.message}`) } From 7ca7e58e372fea95bbf56eda1e5bcca4e56f442f Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 11:31:07 -0300 Subject: [PATCH 43/62] Reduce log level when finished processing message --- src/sender.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sender.js b/src/sender.js index 9f8344a..fcd49d5 100644 --- a/src/sender.js +++ b/src/sender.js @@ -162,7 +162,7 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { await sendToQueue(failedTx) } ackMsg(msg) - logger.info(`Finished processing msg`) + logger.debug(`Finished processing msg`) if (insufficientFunds) { logger.warn( From 453cc4bd1f01c9f2f7eccd2bd7bb84963de03444 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 11:52:13 -0300 Subject: [PATCH 44/62] Add logs to waitForFunds function --- src/sender.js | 2 +- src/utils/utils.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/sender.js b/src/sender.js index fcd49d5..5cd8a68 100644 --- a/src/sender.js +++ b/src/sender.js @@ -169,7 +169,7 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { 'Insufficient funds. Stop sending transactions until the account has the minimum balance' ) channel.close() - waitForFunds(web3Instance, VALIDATOR_ADDRESS, minimumBalance, resume) + waitForFunds(web3Instance, VALIDATOR_ADDRESS, minimumBalance, resume, logger) } } catch (e) { logger.error(e) diff --git a/src/utils/utils.js b/src/utils/utils.js index af2725b..d858a34 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -24,13 +24,22 @@ function checkHTTPS(ALLOW_HTTP, logger) { } } -async function waitForFunds(web3, address, minimumBalance, cb) { +async function waitForFunds(web3, address, minimumBalance, cb, logger) { promiseRetry( async retry => { + logger.debug('Getting balance of validator account') const newBalance = web3.utils.toBN(await web3.eth.getBalance(address)) if (newBalance.gte(minimumBalance)) { + logger.debug( + { balance: newBalance, minimumBalance }, + 'Validator has minimum necessary balance' + ) cb(newBalance) } else { + logger.debug( + { balance: newBalance, minimumBalance }, + 'Balance of validator is still less than the minimum' + ) retry() } }, From fbfcd76a613071a26c1d722bac226ffeda8853a2 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 13:29:05 -0300 Subject: [PATCH 45/62] Log validator contract address --- src/events/processAffirmationRequests/index.js | 3 +++ src/events/processCollectedSignatures/index.js | 3 +++ src/events/processSignatureRequests/index.js | 3 +++ src/events/processTransfers/index.js | 3 +++ 4 files changed, 12 insertions(+) diff --git a/src/events/processAffirmationRequests/index.js b/src/events/processAffirmationRequests/index.js index f1af27e..3dba3d6 100644 --- a/src/events/processAffirmationRequests/index.js +++ b/src/events/processAffirmationRequests/index.js @@ -23,7 +23,10 @@ function processAffirmationRequestsBuilder(config) { const txToSend = [] if (validatorContract === null) { + rootLogger.debug('Getting validator contract address') const validatorContractAddress = await homeBridge.methods.validatorContract().call() + rootLogger.debug({ validatorContractAddress }, 'Validator contract address obtained') + validatorContract = new web3Home.eth.Contract(bridgeValidatorsABI, validatorContractAddress) } diff --git a/src/events/processCollectedSignatures/index.js b/src/events/processCollectedSignatures/index.js index d0635a9..43c521e 100644 --- a/src/events/processCollectedSignatures/index.js +++ b/src/events/processCollectedSignatures/index.js @@ -29,7 +29,10 @@ function processCollectedSignaturesBuilder(config) { const txToSend = [] if (validatorContract === null) { + rootLogger.debug('Getting validator contract address') const validatorContractAddress = await foreignBridge.methods.validatorContract().call() + rootLogger.debug({ validatorContractAddress }, 'Validator contract address obtained') + validatorContract = new web3Foreign.eth.Contract( bridgeValidatorsABI, validatorContractAddress diff --git a/src/events/processSignatureRequests/index.js b/src/events/processSignatureRequests/index.js index 4a6300a..cb8266e 100644 --- a/src/events/processSignatureRequests/index.js +++ b/src/events/processSignatureRequests/index.js @@ -31,7 +31,10 @@ function processSignatureRequestsBuilder(config) { } if (validatorContract === null) { + rootLogger.debug('Getting validator contract address') const validatorContractAddress = await homeBridge.methods.validatorContract().call() + rootLogger.debug({ validatorContractAddress }, 'Validator contract address obtained') + validatorContract = new web3Home.eth.Contract(bridgeValidatorsABI, validatorContractAddress) } diff --git a/src/events/processTransfers/index.js b/src/events/processTransfers/index.js index c33db8c..3ba8de4 100644 --- a/src/events/processTransfers/index.js +++ b/src/events/processTransfers/index.js @@ -23,7 +23,10 @@ function processTransfersBuilder(config) { const txToSend = [] if (validatorContract === null) { + rootLogger.debug('Getting validator contract address') const validatorContractAddress = await homeBridge.methods.validatorContract().call() + rootLogger.debug({ validatorContractAddress }, 'Validator contract address obtained') + validatorContract = new web3Home.eth.Contract(bridgeValidatorsABI, validatorContractAddress) } From 10870a4a44ad6211f7b6c3a5c22392f9855a9416 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 13:34:31 -0300 Subject: [PATCH 46/62] Log transaction that generated the transfer event --- src/events/processTransfers/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/events/processTransfers/index.js b/src/events/processTransfers/index.js index 3ba8de4..837ed4f 100644 --- a/src/events/processTransfers/index.js +++ b/src/events/processTransfers/index.js @@ -39,6 +39,8 @@ function processTransfersBuilder(config) { eventTransactionHash: transfer.transactionHash }) + logger.info({ from, value }, `Processing transfer ${transfer.transactionHash}`) + let gasEstimate try { gasEstimate = await estimateGas({ From b2b75daa0c9acc27a43145461e64963ebad290ae Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 13:50:27 -0300 Subject: [PATCH 47/62] Add better logging when estimating gas --- src/events/processAffirmationRequests/estimateGas.js | 6 ++++++ src/events/processAffirmationRequests/index.js | 2 ++ src/events/processCollectedSignatures/estimateGas.js | 6 ++++++ src/events/processCollectedSignatures/index.js | 2 ++ src/events/processSignatureRequests/estimateGas.js | 7 +++++++ src/events/processSignatureRequests/index.js | 2 ++ src/events/processTransfers/index.js | 2 ++ 7 files changed, 27 insertions(+) diff --git a/src/events/processAffirmationRequests/estimateGas.js b/src/events/processAffirmationRequests/estimateGas.js index 1749ad5..5146e59 100644 --- a/src/events/processAffirmationRequests/estimateGas.js +++ b/src/events/processAffirmationRequests/estimateGas.js @@ -4,6 +4,9 @@ const { AlreadySignedError, InvalidValidatorError } = require('../../utils/errors') +const logger = require('../../services/logger').child({ + module: 'processAffirmationRequests:estimateGas' +}) async function estimateGas({ web3, @@ -31,6 +34,7 @@ async function estimateGas({ const senderHash = web3.utils.soliditySha3(address, messageHash) // Check if minimum number of validations was already reached + logger.debug('Check if minimum number of validations was already reached') const numAffirmationsSigned = await homeBridge.methods.numAffirmationsSigned(messageHash).call() const alreadyProcessed = await homeBridge.methods .isAlreadyProcessed(numAffirmationsSigned) @@ -41,6 +45,7 @@ async function estimateGas({ } // Check if the message was already signed by this validator + logger.debug('Check if the message was already signed') const alreadySigned = await homeBridge.methods.affirmationsSigned(senderHash).call() if (alreadySigned) { @@ -48,6 +53,7 @@ async function estimateGas({ } // Check if address is validator + logger.debug('Check if address is a validator') const isValidator = await validatorContract.methods.isValidator(address).call() if (!isValidator) { diff --git a/src/events/processAffirmationRequests/index.js b/src/events/processAffirmationRequests/index.js index 3dba3d6..3ee8f68 100644 --- a/src/events/processAffirmationRequests/index.js +++ b/src/events/processAffirmationRequests/index.js @@ -46,6 +46,7 @@ function processAffirmationRequestsBuilder(config) { let gasEstimate try { + logger.debug('Estimate gas') gasEstimate = await estimateGas({ web3: web3Home, homeBridge, @@ -55,6 +56,7 @@ function processAffirmationRequestsBuilder(config) { txHash: affirmationRequest.transactionHash, address: config.validatorAddress }) + logger.debug({ gasEstimate }, 'Gas estimated') } catch (e) { if (e instanceof HttpListProviderError) { throw new Error( diff --git a/src/events/processCollectedSignatures/estimateGas.js b/src/events/processCollectedSignatures/estimateGas.js index cd49783..7788a99 100644 --- a/src/events/processCollectedSignatures/estimateGas.js +++ b/src/events/processCollectedSignatures/estimateGas.js @@ -6,6 +6,9 @@ const { InvalidValidatorError } = require('../../utils/errors') const { parseMessage } = require('../../utils/message') +const logger = require('../../services/logger').child({ + module: 'processCollectedSignatures:estimateGas' +}) const web3 = new Web3() const { toBN } = Web3.utils @@ -30,6 +33,7 @@ async function estimateGas({ } // check if the message was already processed + logger.debug('Check if the message was already processed') const { txHash } = parseMessage(message) const alreadyProcessed = await foreignBridge.methods.relayedMessages(txHash).call() if (alreadyProcessed) { @@ -37,6 +41,7 @@ async function estimateGas({ } // check if the number of signatures is enough + logger.debug('Check if number of signatures is enough') const requiredSignatures = await validatorContract.methods.requiredSignatures().call() if (toBN(requiredSignatures).gt(toBN(numberOfCollectedSignatures))) { throw new IncompatibleContractError('The number of collected signatures does not match') @@ -45,6 +50,7 @@ async function estimateGas({ // check if all the signatures were made by validators for (let i = 0; i < v.length; i++) { const address = web3.eth.accounts.recover(message, web3.utils.toHex(v[i]), r[i], s[i]) + logger.debug({ address }, 'Check that signature is from a validator') const isValidator = await validatorContract.methods.isValidator(address).call() if (!isValidator) { diff --git a/src/events/processCollectedSignatures/index.js b/src/events/processCollectedSignatures/index.js index 43c521e..090e8da 100644 --- a/src/events/processCollectedSignatures/index.js +++ b/src/events/processCollectedSignatures/index.js @@ -75,6 +75,7 @@ function processCollectedSignaturesBuilder(config) { let gasEstimate try { + logger.debug('Estimate gas') gasEstimate = await estimateGas({ foreignBridge, validatorContract, @@ -84,6 +85,7 @@ function processCollectedSignaturesBuilder(config) { message, numberOfCollectedSignatures: NumberOfCollectedSignatures }) + logger.debug({ gasEstimate }, 'Gas estimated') } catch (e) { if (e instanceof HttpListProviderError) { throw new Error( diff --git a/src/events/processSignatureRequests/estimateGas.js b/src/events/processSignatureRequests/estimateGas.js index 666f43f..a73c01d 100644 --- a/src/events/processSignatureRequests/estimateGas.js +++ b/src/events/processSignatureRequests/estimateGas.js @@ -4,6 +4,9 @@ const { AlreadySignedError, InvalidValidatorError } = require('../../utils/errors') +const logger = require('../../services/logger').child({ + module: 'processSignatureRequests:estimateGas' +}) async function estimateGas({ web3, homeBridge, validatorContract, signature, message, address }) { try { @@ -17,6 +20,7 @@ async function estimateGas({ web3, homeBridge, validatorContract, signature, mes } // Check if minimum number of validations was already reached + logger.debug('Check if minimum number of validations was reached') const messageHash = web3.utils.soliditySha3(message) const numMessagesSigned = await homeBridge.methods.numMessagesSigned(messageHash).call() const alreadyProcessed = await homeBridge.methods.isAlreadyProcessed(numMessagesSigned).call() @@ -26,6 +30,7 @@ async function estimateGas({ web3, homeBridge, validatorContract, signature, mes } // Check if transaction was already signed by this validator + logger.debug('Check if transaction was already signed') const validatorMessageHash = web3.utils.soliditySha3(address, web3.utils.soliditySha3(message)) const alreadySigned = await homeBridge.methods.messagesSigned(validatorMessageHash).call() @@ -34,12 +39,14 @@ async function estimateGas({ web3, homeBridge, validatorContract, signature, mes } // Check if address is validator + logger.debug('Check if address is validator') const isValidator = await validatorContract.methods.isValidator(address).call() if (!isValidator) { throw new InvalidValidatorError(`${address} is not a validator`) } + logger.error('Unrecognized error') throw new Error('Unknown error while processing message') } } diff --git a/src/events/processSignatureRequests/index.js b/src/events/processSignatureRequests/index.js index cb8266e..61750ff 100644 --- a/src/events/processSignatureRequests/index.js +++ b/src/events/processSignatureRequests/index.js @@ -64,6 +64,7 @@ function processSignatureRequestsBuilder(config) { let gasEstimate try { + logger.debug('Estimate gas') gasEstimate = await estimateGas({ web3: web3Home, homeBridge, @@ -72,6 +73,7 @@ function processSignatureRequestsBuilder(config) { message, address: config.validatorAddress }) + logger.debug({ gasEstimate }, 'Gas estimated') } catch (e) { if (e instanceof HttpListProviderError) { throw new Error( diff --git a/src/events/processTransfers/index.js b/src/events/processTransfers/index.js index 837ed4f..de622c7 100644 --- a/src/events/processTransfers/index.js +++ b/src/events/processTransfers/index.js @@ -43,6 +43,7 @@ function processTransfersBuilder(config) { let gasEstimate try { + logger.debug('Estimate gas') gasEstimate = await estimateGas({ web3: web3Home, homeBridge, @@ -52,6 +53,7 @@ function processTransfersBuilder(config) { txHash: transfer.transactionHash, address: config.validatorAddress }) + logger.debug({ gasEstimate }, 'Gas estimated') } catch (e) { if (e instanceof HttpListProviderError) { throw new Error( From b66b5683b4324fb49fd397ab5dbf746d15029550 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 14:20:50 -0300 Subject: [PATCH 48/62] Add logs when getting message signatures --- src/events/processCollectedSignatures/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/events/processCollectedSignatures/index.js b/src/events/processCollectedSignatures/index.js index 090e8da..6f08e92 100644 --- a/src/events/processCollectedSignatures/index.js +++ b/src/events/processCollectedSignatures/index.js @@ -63,7 +63,9 @@ function processCollectedSignaturesBuilder(config) { requiredSignatures.fill(0) const [v, r, s] = [[], [], []] + logger.debug('Getting message signatures') const signaturePromises = requiredSignatures.map(async (el, index) => { + logger.debug({ index }, 'Getting message signature') const signature = await homeBridge.methods.signature(messageHash, index).call() const recover = signatureToVRS(signature) v.push(recover.v) From b101794b2e109026169ce9cf54a0f6f8f4e39fb6 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 14:58:54 -0300 Subject: [PATCH 49/62] Update README with MAX_PROCESSING_TIME variable --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fa4fb0f..15edf91 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,7 @@ where the _watcher_ could be one of: | `REDIS_URL` | Redis DB URL used by watchers and senders to communicate to the database. Typically set to: `redis://127.0.0.1:6379`. | local URL | | `REDIS_LOCK_TTL` | Threshold in milliseconds for locking a resource in the Redis DB. Until the threshold is exceeded, the resource is unlocked. Usually it is `1000`. | integer | | `ALLOW_HTTP` | **Only use in test environments - must be omitted in production environments.**. If this parameter is specified and set to `yes`, RPC URLs can be specified in form of HTTP links. A warning that the connection is insecure will be written to the logs. | `yes` / `no` | +| `MAX_PROCESSING_TIME` | If this parameter is specified, the workers processes will be killed if this amount of time (in milliseconds) is ellapsed before they finish processing. | integer | ### Useful Commands for Development From 66738b9005bab77901e2ed5bb17a7bca2e45a8ec Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 22 Oct 2018 15:10:29 -0300 Subject: [PATCH 50/62] Add watchdog for sender --- src/sender.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/sender.js b/src/sender.js index 55d15ed..5a79e86 100644 --- a/src/sender.js +++ b/src/sender.js @@ -7,8 +7,8 @@ const logger = require('./services/logger') const rpcUrlsManager = require('./services/getRpcUrlsManager') const { sendTx } = require('./tx/sendTx') const { getNonce, getChainId } = require('./tx/web3') -const { addExtraGas, checkHTTPS, syncForEach, waitForFunds } = require('./utils/utils') -const { EXTRA_GAS_PERCENTAGE } = require('./utils/constants') +const { addExtraGas, checkHTTPS, syncForEach, waitForFunds, watchdog } = require('./utils/utils') +const { EXIT_CODES, EXTRA_GAS_PERCENTAGE } = require('./utils/constants') const { VALIDATOR_ADDRESS, VALIDATOR_ADDRESS_PRIVATE_KEY, REDIS_LOCK_TTL } = process.env @@ -24,6 +24,8 @@ const nonceLock = `lock:${config.id}:nonce` const nonceKey = `${config.id}:nonce` let chainId = 0 +const maxProcessingTime = process.env.MAX_PROCESSING_TIME + async function initialize() { try { const checkHttps = checkHTTPS(process.env.ALLOW_HTTP) @@ -36,7 +38,16 @@ async function initialize() { chainId = await getChainId(web3Instance) connectSenderToQueue({ queueName: config.queue, - cb: main + cb: options => { + if (maxProcessingTime) { + return watchdog(() => main(options), maxProcessingTime, () => { + logger.fatal('Max processing time reached') + process.exit(EXIT_CODES.MAX_TIME_REACHED) + }) + } + + return main(options) + } }) } catch (e) { logger.error(e.message) From 0f4f9b5b89ac610c2d772e5c0dfbf48a0e1eed40 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 23 Oct 2018 08:45:19 -0300 Subject: [PATCH 51/62] Update poa-bridge-contracts branch on Dockerfile --- e2e/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/Dockerfile b/e2e/Dockerfile index cb54445..477b61e 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -12,7 +12,7 @@ RUN mkdir submodules && \ mv poa-bridge-contracts submodules && \ cd submodules/poa-bridge-contracts && \ git fetch && \ - git checkout erc20-to-native-#79 + git checkout develop RUN npm install --unsafe-perm From 3171c1e6b80ece4c289d677d4081c1da213caa27 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Tue, 23 Oct 2018 18:10:34 -0300 Subject: [PATCH 52/62] Set max processing time to 4 times the polling time --- .env.example | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index bb7bbc9..b9f17c2 100644 --- a/.env.example +++ b/.env.example @@ -29,7 +29,7 @@ HOME_START_BLOCK= FOREIGN_START_BLOCK= LOG_LEVEL=debug -MAX_PROCESSING_TIME=600000 +MAX_PROCESSING_TIME=20000 #testing accs USER_ADDRESS=0x59c4474184579b9c31b5e51445b6eef91cebf370 diff --git a/README.md b/README.md index 1e68e3f..1008cb2 100644 --- a/README.md +++ b/README.md @@ -213,7 +213,7 @@ where the _watcher_ could be one of: | `REDIS_LOCK_TTL` | Threshold in milliseconds for locking a resource in the Redis DB. Until the threshold is exceeded, the resource is unlocked. Usually it is `1000`. | integer | | `ALLOW_HTTP` | **Only use in test environments - must be omitted in production environments.**. If this parameter is specified and set to `yes`, RPC URLs can be specified in form of HTTP links. A warning that the connection is insecure will be written to the logs. | `yes` / `no` | | `LOG_LEVEL` | Set the level of details in the logs. | `trace` / `debug` / `info` / `warn` / `error` / `fatal` | -| `MAX_PROCESSING_TIME` | If this parameter is specified, the workers processes will be killed if this amount of time (in milliseconds) is ellapsed before they finish processing. | integer | +| `MAX_PROCESSING_TIME` | If this parameter is specified, the workers processes will be killed if this amount of time (in milliseconds) is ellapsed before they finish processing. It is recommended to set this value to 4 times the value of the longest polling time (set with the `HOME_POLLING_INTERVAL` and `FOREIGN_POLLING_INTERVAL` variables). | integer | ### Useful Commands for Development From 3d706ddaf7e108b1ce2fe4756364236d845b7a24 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Wed, 24 Oct 2018 08:59:18 -0300 Subject: [PATCH 53/62] Use exit code constant for general errors --- scripts/privateKeyToAddress.js | 3 ++- scripts/resetLastBlock.js | 3 ++- src/sender.js | 4 ++-- src/utils/constants.js | 1 + src/watcher.js | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/privateKeyToAddress.js b/scripts/privateKeyToAddress.js index be63059..3ba23ff 100644 --- a/scripts/privateKeyToAddress.js +++ b/scripts/privateKeyToAddress.js @@ -3,12 +3,13 @@ require('dotenv').config({ path: path.join(__dirname, '..', '.env') }) const { privateKeyToAddress } = require('../src/utils/utils') +const { EXIT_CODES } = require('../src/utils/constants') const privateKey = process.env.VALIDATOR_ADDRESS_PRIVATE_KEY if (!privateKey) { console.error('Environment variable VALIDATOR_ADDRESS_PRIVATE_KEY is not set') - process.exit(1) + process.exit(EXIT_CODES.GENERAL_ERROR) } const address = privateKeyToAddress(privateKey) diff --git a/scripts/resetLastBlock.js b/scripts/resetLastBlock.js index a985677..57feed4 100644 --- a/scripts/resetLastBlock.js +++ b/scripts/resetLastBlock.js @@ -4,6 +4,7 @@ require('dotenv').config({ path: path.join(__dirname, '../.env') }) const { id } = require('../config/base.config') +const { EXIT_CODES } = require('../src/utils/constants') const redis = new Redis(process.env.REDIS_URL) @@ -22,7 +23,7 @@ if (process.argv.length < 4) { function logError(message) { console.log(message) - process.exit(1) + process.exit(EXIT_CODES.GENERAL_ERROR) } function getRedisKey(name) { diff --git a/src/sender.js b/src/sender.js index 799bd21..b6418ab 100644 --- a/src/sender.js +++ b/src/sender.js @@ -23,7 +23,7 @@ const VALIDATOR_ADDRESS = privateKeyToAddress(VALIDATOR_ADDRESS_PRIVATE_KEY) if (process.argv.length < 3) { logger.error('Please check the number of arguments, config file was not provided') - process.exit(1) + process.exit(EXIT_CODES.GENERAL_ERROR) } const config = require(path.join('../config/', process.argv[2])) @@ -60,7 +60,7 @@ async function initialize() { }) } catch (e) { logger.error(e.message) - process.exit(1) + process.exit(EXIT_CODES.GENERAL_ERROR) } } diff --git a/src/utils/constants.js b/src/utils/constants.js index 221fa2c..3bf55dd 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -9,6 +9,7 @@ module.exports = { }, DEFAULT_UPDATE_INTERVAL: 600000, EXIT_CODES: { + GENERAL_ERROR: 1, INCOMPATIBILITY: 10, MAX_TIME_REACHED: 11 } diff --git a/src/watcher.js b/src/watcher.js index 1be269f..938a269 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -12,7 +12,7 @@ const { EXIT_CODES } = require('./utils/constants') if (process.argv.length < 3) { logger.error('Please check the number of arguments, config file was not provided') - process.exit(1) + process.exit(EXIT_CODES.GENERAL_ERROR) } const config = require(path.join('../config/', process.argv[2])) @@ -47,7 +47,7 @@ async function initialize() { }) } catch (e) { logger.error(e) - process.exit(1) + process.exit(EXIT_CODES.GENERAL_ERROR) } } From f38688c869be9fcd5e8dceb36b31637769a6f802 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Wed, 24 Oct 2018 20:35:48 -0300 Subject: [PATCH 54/62] Add default max processing time --- README.md | 2 +- config/base.config.js | 13 ++++++++++++- config/foreign-sender.config.js | 2 ++ config/home-sender.config.js | 2 ++ src/sender.js | 6 ++---- src/watcher.js | 6 ++---- 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1008cb2..92acd78 100644 --- a/README.md +++ b/README.md @@ -213,7 +213,7 @@ where the _watcher_ could be one of: | `REDIS_LOCK_TTL` | Threshold in milliseconds for locking a resource in the Redis DB. Until the threshold is exceeded, the resource is unlocked. Usually it is `1000`. | integer | | `ALLOW_HTTP` | **Only use in test environments - must be omitted in production environments.**. If this parameter is specified and set to `yes`, RPC URLs can be specified in form of HTTP links. A warning that the connection is insecure will be written to the logs. | `yes` / `no` | | `LOG_LEVEL` | Set the level of details in the logs. | `trace` / `debug` / `info` / `warn` / `error` / `fatal` | -| `MAX_PROCESSING_TIME` | If this parameter is specified, the workers processes will be killed if this amount of time (in milliseconds) is ellapsed before they finish processing. It is recommended to set this value to 4 times the value of the longest polling time (set with the `HOME_POLLING_INTERVAL` and `FOREIGN_POLLING_INTERVAL` variables). | integer | +| `MAX_PROCESSING_TIME` | The workers processes will be killed if this amount of time (in milliseconds) is ellapsed before they finish processing. It is recommended to set this value to 4 times the value of the longest polling time (set with the `HOME_POLLING_INTERVAL` and `FOREIGN_POLLING_INTERVAL` variables). To disable this, set the time to 0. | integer | ### Useful Commands for Development diff --git a/config/base.config.js b/config/base.config.js index 258b0f4..ed3799d 100644 --- a/config/base.config.js +++ b/config/base.config.js @@ -45,13 +45,24 @@ switch (process.env.BRIDGE_MODE) { } } +let maxProcessingTime = null +if (String(process.env.MAX_PROCESSING_TIME) === '0') { + maxProcessingTime = 0 +} else if (!process.env.MAX_PROCESSING_TIME) { + maxProcessingTime = + 4 * Math.max(process.env.HOME_POLLING_INTERVAL, process.env.FOREIGN_POLLING_INTERVAL) +} else { + maxProcessingTime = Number(process.env.MAX_PROCESSING_TIME) +} + const bridgeConfig = { homeBridgeAddress: process.env.HOME_BRIDGE_ADDRESS, homeBridgeAbi: homeAbi, foreignBridgeAddress: process.env.FOREIGN_BRIDGE_ADDRESS, foreignBridgeAbi: foreignAbi, eventFilter: {}, - validatorAddress: VALIDATOR_ADDRESS || privateKeyToAddress(VALIDATOR_ADDRESS_PRIVATE_KEY) + validatorAddress: VALIDATOR_ADDRESS || privateKeyToAddress(VALIDATOR_ADDRESS_PRIVATE_KEY), + maxProcessingTime } const homeConfig = { diff --git a/config/foreign-sender.config.js b/config/foreign-sender.config.js index 472c873..43fab9a 100644 --- a/config/foreign-sender.config.js +++ b/config/foreign-sender.config.js @@ -1,8 +1,10 @@ require('dotenv').config() +const baseConfig = require('./base.config') const { web3Foreign } = require('../src/services/web3') module.exports = { + ...baseConfig.bridgeConfig, queue: 'foreign', id: 'foreign', name: 'sender-foreign', diff --git a/config/home-sender.config.js b/config/home-sender.config.js index 6aa65aa..b9a147e 100644 --- a/config/home-sender.config.js +++ b/config/home-sender.config.js @@ -1,8 +1,10 @@ require('dotenv').config() +const baseConfig = require('./base.config') const { web3Home } = require('../src/services/web3') module.exports = { + ...baseConfig.bridgeConfig, queue: 'home', id: 'home', name: 'sender-home', diff --git a/src/sender.js b/src/sender.js index b6418ab..1193f96 100644 --- a/src/sender.js +++ b/src/sender.js @@ -33,8 +33,6 @@ const nonceLock = `lock:${config.id}:nonce` const nonceKey = `${config.id}:nonce` let chainId = 0 -const maxProcessingTime = process.env.MAX_PROCESSING_TIME - async function initialize() { try { const checkHttps = checkHTTPS(process.env.ALLOW_HTTP, logger) @@ -48,8 +46,8 @@ async function initialize() { connectSenderToQueue({ queueName: config.queue, cb: options => { - if (maxProcessingTime) { - return watchdog(() => main(options), maxProcessingTime, () => { + if (config.maxProcessingTime) { + return watchdog(() => main(options), config.maxProcessingTime, () => { logger.fatal('Max processing time reached') process.exit(EXIT_CODES.MAX_TIME_REACHED) }) diff --git a/src/watcher.js b/src/watcher.js index 938a269..939ee1f 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -31,8 +31,6 @@ const eventContract = new web3Instance.eth.Contract(config.eventAbi, config.even const lastBlockRedisKey = `${config.id}:lastProcessedBlock` let lastProcessedBlock = BN.max(config.startBlock.sub(ONE), ZERO) -const maxProcessingTime = process.env.MAX_PROCESSING_TIME - async function initialize() { try { const checkHttps = checkHTTPS(process.env.ALLOW_HTTP, logger) @@ -54,8 +52,8 @@ async function initialize() { async function runMain({ sendToQueue }) { try { if (connection.isConnected() && redis.status === 'ready') { - if (maxProcessingTime) { - await watchdog(() => main({ sendToQueue }), maxProcessingTime, () => { + if (config.maxProcessingTime) { + await watchdog(() => main({ sendToQueue }), config.maxProcessingTime, () => { logger.fatal('Max processing time reached') process.exit(EXIT_CODES.MAX_TIME_REACHED) }) From 962f19ae9fc834eea9e38641510b5b876c092df5 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Thu, 25 Oct 2018 10:21:46 -0300 Subject: [PATCH 55/62] Update getting past events log level to info --- src/tx/web3.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tx/web3.js b/src/tx/web3.js index 6196b02..f010d93 100644 --- a/src/tx/web3.js +++ b/src/tx/web3.js @@ -53,7 +53,10 @@ async function getRequiredBlockConfirmations(contract) { async function getEvents({ contract, event, fromBlock, toBlock, filter }) { try { const contractAddress = contract.options.address - logger.debug({ contractAddress, event }, 'Getting past events') + logger.info( + { contractAddress, event, fromBlock: fromBlock.toString(), toBlock: toBlock.toString() }, + 'Getting past events' + ) const pastEvents = await contract.getPastEvents(event, { fromBlock, toBlock, filter }) logger.debug({ contractAddress, event, count: pastEvents.length }, 'Past events obtained') return pastEvents From 19ec9327fcfd9cf1b889d309e276878d50b7f423 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Thu, 25 Oct 2018 10:23:25 -0300 Subject: [PATCH 56/62] Update transaction nonce log level to info --- src/sender.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sender.js b/src/sender.js index 5cd8a68..dfe462a 100644 --- a/src/sender.js +++ b/src/sender.js @@ -106,7 +106,7 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) { const gasLimit = addExtraGas(job.gasEstimate, EXTRA_GAS_PERCENTAGE) try { - logger.debug(`Sending transaction with nonce ${nonce}`) + logger.info(`Sending transaction with nonce ${nonce}`) const txHash = await sendTx({ chain: config.id, data: job.data, From 39d6f3ff70faedf787ebc4101b9421def8db3704 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Thu, 25 Oct 2018 10:47:28 -0300 Subject: [PATCH 57/62] Add log when getting las processed block --- src/watcher.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/watcher.js b/src/watcher.js index d45848d..7688351 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -64,6 +64,10 @@ async function runMain({ sendToQueue }) { async function getLastProcessedBlock() { const result = await redis.get(lastBlockRedisKey) + logger.debug( + { fromRedis: result, fromConfig: lastProcessedBlock.toString() }, + 'Last Processed block obtained' + ) lastProcessedBlock = result ? toBN(result) : lastProcessedBlock } From bbb2c8506a2bfedd756482416249fed9989aa078 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Thu, 25 Oct 2018 10:49:54 -0300 Subject: [PATCH 58/62] Fix last processed block being log as Hex value --- src/watcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/watcher.js b/src/watcher.js index 7688351..cd13b58 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -137,7 +137,7 @@ async function main({ sendToQueue }) { } } - logger.debug({ lastProcessedBlock: lastBlockToProcess }, 'Updating last processed block') + logger.debug({ lastProcessedBlock: lastBlockToProcess.toString() }, 'Updating last processed block') await updateLastProcessedBlock(lastBlockToProcess) } catch (e) { logger.error(e) From 5d19ccaf560e46130c344ae09e6f47db24888b0e Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Thu, 25 Oct 2018 10:51:50 -0300 Subject: [PATCH 59/62] Fix code formatting --- src/watcher.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/watcher.js b/src/watcher.js index cd13b58..38c38d2 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -137,7 +137,10 @@ async function main({ sendToQueue }) { } } - logger.debug({ lastProcessedBlock: lastBlockToProcess.toString() }, 'Updating last processed block') + logger.debug( + { lastProcessedBlock: lastBlockToProcess.toString() }, + 'Updating last processed block' + ) await updateLastProcessedBlock(lastBlockToProcess) } catch (e) { logger.error(e) From aafd86f193753cff139f5af3f19a0fba0c820320 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Mon, 29 Oct 2018 10:27:37 -0300 Subject: [PATCH 60/62] Add stress testing statistics results --- docs/stress-testing.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/stress-testing.md b/docs/stress-testing.md index 99a8b80..4bc89b8 100644 --- a/docs/stress-testing.md +++ b/docs/stress-testing.md @@ -84,3 +84,25 @@ This will generate a block with 1000 transactions that the bridge will process. After doing all of this, run `node scripts/compute-stats.js`. This will print some statistics about the processed transactions. + +### Statistics results + +**Signature Requests** + +Tests |1|2|3|4|5|AVG +---|---|---|---|---|---|--- +count|1000|1000|1000|1000|1000|1000 +mean|12112|17714|15377|16468|15745|15483 +median|11968|17925|15518|16994|15931|15667 +min|5584|6423|5803|6121|6090|6004 +max|18685|27554|23844|25310|24198|23918 + +**Collected Signatures** + +Tests |1|2|3|4|5|AVG +---|---|---|---|---|---|--- +count|1000|1000|1000|1000|1000|1000 +mean|8564|5399|6653|9684|9605|7981 +median|8771|5971|7295|9854|10056|8389 +min|7301|2783|3003|8331|7165|5716 +max|9156|7453|9492|10889|10687|9535 From 39a90d042d1ee428a80fea7ebb51f59b54edd2d1 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 31 Oct 2018 11:00:14 -0300 Subject: [PATCH 61/62] Increase extra gas percentage --- src/utils/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/constants.js b/src/utils/constants.js index 3bf55dd..4579a21 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -1,5 +1,5 @@ module.exports = { - EXTRA_GAS_PERCENTAGE: 0.25, + EXTRA_GAS_PERCENTAGE: 1, MAX_CONCURRENT_EVENTS: 50, RETRY_CONFIG: { retries: 20, From eafe5bbafbac172190ff1f1d3c24ce120219e74d Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 7 Nov 2018 09:22:56 -0300 Subject: [PATCH 62/62] Update submodule to tag 2.1.0 --- e2e/Dockerfile | 2 +- submodules/poa-bridge-contracts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/Dockerfile b/e2e/Dockerfile index 477b61e..ad1a5b0 100644 --- a/e2e/Dockerfile +++ b/e2e/Dockerfile @@ -12,7 +12,7 @@ RUN mkdir submodules && \ mv poa-bridge-contracts submodules && \ cd submodules/poa-bridge-contracts && \ git fetch && \ - git checkout develop + git checkout 2.1.0 RUN npm install --unsafe-perm diff --git a/submodules/poa-bridge-contracts b/submodules/poa-bridge-contracts index 5d9f594..1f61c69 160000 --- a/submodules/poa-bridge-contracts +++ b/submodules/poa-bridge-contracts @@ -1 +1 @@ -Subproject commit 5d9f5946cda6043d7584b6da49693f7d3391b78d +Subproject commit 1f61c695df23b2a8f79d96e138c6bb5d8cd5b592