Improve confirm-relay feature (#582)

This commit is contained in:
Kirill Fedoseev 2021-07-07 16:21:01 +03:00 committed by GitHub
parent c8eb0f1ed8
commit 8ed6550635
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 145 additions and 38 deletions

@ -1,7 +1,7 @@
#!/usr/bin/env bash
cd $(dirname $0)
../e2e-commons/up.sh deploy blocks alm alm-e2e
../e2e-commons/up.sh deploy generate-amb-tx blocks alm alm-e2e
# run oracle amb e2e tests to generate transactions for alm
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run alm

@ -6,8 +6,8 @@ jest.setTimeout(60000)
const statusText = 'Success'
const statusSelector = 'label[data-id="status"]'
const homeToForeignTxURL = 'http://localhost:3004/77/0xbc83d43bdc675a615a2b820e43e52d25857aa5fdd77acf2dd92cd247af2c693c'
const foreignToHomeTxURL = 'http://localhost:3004/42/0x09dfb947dbd17e27bcc117773b6e133829f7cef9646199a93ef019c4f7c0fec6'
const homeToForeignTxURL = 'http://localhost:3004/77/0x295efbe6ae98937ef35d939376c9bd752b4dc6f6899a9d5ddd6a57cea3d76c89'
const foreignToHomeTxURL = 'http://localhost:3004/42/0x7262f7dbe6c30599edded2137fbbe93c271b37f5c54dd27f713f0cf510e3b4dd'
describe('ALM', () => {
let browser

@ -49,6 +49,12 @@
"blockedHomeBox": "0xF9698Eb93702dfdd0e2d802088d4c21822a8A977",
"monitor": "http://monitor-amb:3013/bridge"
},
"amb2": {
"home": "0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9",
"foreign": "0x897527391ad3837604973d78D3514f44c36AB9FC",
"homeBox": "0xb008E9076fCbDB2C3AF84225Bc07Eb35B2bE5ECD",
"foreignBox": "0x4a58D6d8D416a5fBCAcf3dC52eb8bE8948E25127"
},
"homeRPC": {
"URL": "http://parity1:8545",
"ID": "77"

@ -35,3 +35,9 @@ echo -e "\n\n############ Deploying one more test contract for amb ############\
cd "$DEPLOY_PATH"
node src/utils/deployTestBox.js
cd - > /dev/null
echo -e "\n\n############ Deploying one more amb without oracle for confirm relay tests ############\n"
cp "$ENVS_PATH/amb.env" "$DEPLOY_PATH/.env"
cd "$DEPLOY_PATH"
node deploy.js
cd - > /dev/null

@ -93,5 +93,25 @@ while [ "$1" != "" ]; do
startValidator "-p validator3" "$oracle3Values" redis3 rabbit3
fi
if [ "$1" == "generate-amb-tx" ]; then
docker-compose run e2e yarn workspace oracle-e2e run generate-amb-tx
fi
if [ "$1" == "manual-amb-relay" ]; then
env="-e COMMON_HOME_BRIDGE_ADDRESS=0x5A42E119990c3F3A80Fea20aAF4c3Ff4DB240Cc9 -e COMMON_FOREIGN_BRIDGE_ADDRESS=0x897527391ad3837604973d78D3514f44c36AB9FC"
# these tx hash are hardcoded and need to be updated manually
# once e2e environment setup process is changed
echo '0xea625a823bc5018dc3a4efe349f623e5ebb8c987b55f44d50d6556f42af9a400' > txHashes.txt
docker-compose -p validator1 run -v $(pwd)/txHashes.txt:/tmp/txHashes.txt $env oracle-amb yarn confirm:affirmation-request \
/tmp/txHashes.txt \
0x031c42e44485002c9215a5b1b75e9516131485ce29884a58765bf7a0038538f9
docker-compose -p validator1 run $env oracle-amb yarn confirm:signature-request \
0x1506a18af91afe732167ccbc178b55fc2547da4a814d13c015b6f496cf171754 | tee .tmp.log
tx_hash=$(cat .tmp.log | grep generatedTransactionHash | jq -r .generatedTransactionHash)
rm .tmp.log
rm txHashes.txt
docker-compose -p validator1 run $env oracle-amb yarn confirm:collected-signatures $tx_hash
fi
shift # Shift all the parameters down by one
done

@ -5,6 +5,7 @@
"main": "index.js",
"scripts": {
"start": "mocha",
"generate-amb-tx": "node ./scripts/generate-amb-tx.js",
"lint": "eslint . --ignore-path ../.eslintignore",
"amb": "mocha test/amb.js",
"erc-to-native": "mocha test/ercToNative.js",

@ -10,7 +10,7 @@ case "$mode" in
;;
esac
MODE="$mode" ../e2e-commons/up.sh deploy blocks oracle oracle-validator-2 oracle-validator-3
MODE="$mode" ../e2e-commons/up.sh deploy generate-amb-tx manual-amb-relay blocks oracle oracle-validator-2 oracle-validator-3
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run start $script
rc=$?

@ -0,0 +1,29 @@
const Web3 = require('web3')
const { user, homeRPC, foreignRPC, amb2: amb } = require('../../e2e-commons/constants.json')
const { BOX_ABI } = require('../../commons')
const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
const foreignWeb3 = new Web3(new Web3.providers.HttpProvider(foreignRPC.URL))
homeWeb3.eth.accounts.wallet.add(user.privateKey)
foreignWeb3.eth.accounts.wallet.add(user.privateKey)
const opts = {
from: user.address,
gas: 400000,
gasPrice: '1'
}
const homeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.homeBox, opts)
const foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox, opts)
async function main() {
const res1 = await homeBox.methods.setValueOnOtherNetwork(123, amb.home, amb.foreignBox).send()
const res2 = await foreignBox.methods.setValueOnOtherNetwork(456, amb.foreign, amb.homeBox).send()
const res3 = await foreignBox.methods.setValueOnOtherNetwork(789, amb.foreign, amb.homeBox).send()
console.log(res1.transactionHash)
console.log(res2.transactionHash)
console.log(res3.transactionHash)
}
main()

@ -63,6 +63,17 @@ describe('arbitrary message bridging', () => {
}
})
})
describe('Confirm Relay', () => {
it('should process lost affirmation-request via confirm relay', async () => {
const value = await homeBox.methods.value().call()
assert(value === '789', 'incorrect value')
})
it('should process lost signature-request & collected-signatures via confirm relay', async () => {
const value = await foreignBox.methods.value().call()
assert(value === '123', 'incorrect value')
})
})
describe('Home to Foreign', () => {
describe('Subsidized Mode', () => {
it('should bridge message', async () => {
@ -71,12 +82,13 @@ describe('arbitrary message bridging', () => {
const initialValue = await foreignBox.methods.value().call()
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
await homeBox.methods
const res = await homeBox.methods
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
.send()
.catch(e => {
console.error(e)
})
console.log(res.transactionHash)
// check that value changed and balance decreased
await uniformRetry(async retry => {
@ -169,12 +181,13 @@ describe('arbitrary message bridging', () => {
const initialValue = await homeBox.methods.value().call()
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
await foreignBox.methods
const res = await foreignBox.methods
.setValueOnOtherNetwork(newValue, amb.foreign, amb.homeBox)
.send()
.catch(e => {
console.error(e)
})
console.log(res.transactionHash)
// check that value changed and balance decreased
await uniformRetry(async retry => {
@ -268,7 +281,7 @@ describe('arbitrary message bridging', () => {
const selector = homeWeb3.utils.soliditySha3('eth_call(address,bytes,uint256)')
const data1 = homeWeb3.eth.abi.encodeParameters(
['address', 'bytes', 'uint256'],
[amb.foreignBox, foreignBox.methods.value().encodeABI(), 60]
[amb.foreignBox, foreignBox.methods.value().encodeABI(), 25]
)
const data2 = homeWeb3.eth.abi.encodeParameters(
['address', 'bytes', 'uint256'],
@ -446,7 +459,7 @@ describe('arbitrary message bridging', () => {
})
it('should make async eth_getTransactionByHash', async () => {
const txHash = '0x09dfb947dbd17e27bcc117773b6e133829f7cef9646199a93ef019c4f7c0fec6'
const txHash = '0x7262f7dbe6c30599edded2137fbbe93c271b37f5c54dd27f713f0cf510e3b4dd'
const tx = await foreignWeb3.eth.getTransaction(txHash)
const selector = homeWeb3.utils.soliditySha3('eth_getTransactionByHash(bytes32)')
@ -479,7 +492,7 @@ describe('arbitrary message bridging', () => {
})
it('should make async eth_getTransactionReceipt', async () => {
const txHash = '0x09dfb947dbd17e27bcc117773b6e133829f7cef9646199a93ef019c4f7c0fec6'
const txHash = '0x7262f7dbe6c30599edded2137fbbe93c271b37f5c54dd27f713f0cf510e3b4dd'
const receipt = await foreignWeb3.eth.getTransactionReceipt(txHash)
const selector = homeWeb3.utils.soliditySha3('eth_getTransactionReceipt(bytes32)')

@ -6,6 +6,7 @@ module.exports = {
...baseConfig,
main: baseConfig.foreign,
event: 'UserRequestForAffirmation',
sender: 'home',
queue: 'home-prioritized',
name: `watcher-${id}`,
id

@ -6,6 +6,7 @@ module.exports = {
...baseConfig,
main: baseConfig.home,
event: 'CollectedSignatures',
sender: 'foreign',
queue: 'foreign-prioritized',
name: `watcher-${id}`,
id

@ -8,6 +8,7 @@ module.exports = {
web3ForeignArchive: web3ForeignArchive || baseConfig.foreign.web3,
main: baseConfig.home,
event: 'UserRequestForInformation',
sender: 'home',
queue: 'home-prioritized',
name: `watcher-${id}`,
id

@ -6,6 +6,7 @@ module.exports = {
...baseConfig,
main: baseConfig.home,
event: 'UserRequestForSignature',
sender: 'home',
queue: 'home-prioritized',
name: `watcher-${id}`,
id

@ -30,6 +30,7 @@ module.exports = {
},
event: 'Transfer',
eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS },
sender: 'home',
queue: 'home-prioritized',
name: `watcher-${id}`,
id

@ -13,6 +13,10 @@
"sender:home": "./scripts/start-worker.sh sender home-sender",
"sender:foreign": "./scripts/start-worker.sh sender foreign-sender",
"confirm:transfer": "./scripts/start-worker.sh confirmRelay transfer-watcher",
"confirm:affirmation-request": "./scripts/start-worker.sh confirmRelay affirmation-request-watcher",
"confirm:signature-request": "./scripts/start-worker.sh confirmRelay signature-request-watcher",
"confirm:collected-signatures": "./scripts/start-worker.sh confirmRelay collected-signatures-watcher",
"confirm:information-request": "./scripts/start-worker.sh confirmRelay information-request-watcher",
"manager:shutdown": "./scripts/start-worker.sh shutdownManager shutdown-manager",
"dev": "concurrently -n 'watcher:signature-request,watcher:collected-signatures,watcher:affirmation-request,watcher:transfer, sender:home,sender:foreign' -c 'red,green,yellow,blue,magenta,cyan' 'yarn watcher:signature-request' 'yarn watcher:collected-signatures' 'yarn watcher:affirmation-request' 'yarn watcher:transfer' 'yarn sender:home' 'yarn sender:foreign'",
"test": "NODE_ENV=test mocha",

@ -8,12 +8,12 @@ LOGS_DIR="logs/"
WORKER="${WORKERS_DIR}${1}.js"
CONFIG="${2}.config.js"
LOG="${LOGS_DIR}${2}.txt"
TX_HASH="${3}"
TX_HASH=${@:3}
CHECKS=$(node scripts/initialChecks.js)
if [ "${NODE_ENV}" = "production" ]; then
exec node "${WORKER}" "${CONFIG}" "$CHECKS" "$TX_HASH"
exec node "${WORKER}" "${CONFIG}" "$CHECKS" $TX_HASH
else
node "${WORKER}" "${CONFIG}" "$CHECKS" "$TX_HASH" | tee -a "${LOG}" | pino-pretty
node "${WORKER}" "${CONFIG}" "$CHECKS" $TX_HASH | tee -a "${LOG}" | pino-pretty
fi

@ -1,5 +1,6 @@
require('../env')
const path = require('path')
const fs = require('fs')
const { isAttached, connectWatcherToQueue, connection } = require('./services/amqpClient')
const logger = require('./services/logger')
const GasPrice = require('./services/gasPrice')
@ -16,7 +17,22 @@ if (process.argv.length < 5) {
}
const config = require(path.join('../config/', process.argv[2]))
const txHash = process.argv[4]
const { web3, eventContract, chain } = config.main
const isTxHash = txHash => txHash.length === 66 && web3.utils.isHexStrict(txHash)
function readTxHashes(filePath) {
return fs
.readFileSync(filePath)
.toString()
.split('\n')
.map(v => v.trim())
.filter(isTxHash)
}
const txHashesArgs = process.argv.slice(4)
const rawTxHashes = txHashesArgs.filter(isTxHash)
const txHashesFiles = txHashesArgs.filter(path => fs.existsSync(path)).flatMap(readTxHashes)
const txHashes = [...rawTxHashes, ...txHashesFiles]
const processSignatureRequests = require('./events/processSignatureRequests')(config)
const processCollectedSignatures = require('./events/processCollectedSignatures')(config)
@ -27,15 +43,13 @@ const processAMBCollectedSignatures = require('./events/processAMBCollectedSigna
const processAMBAffirmationRequests = require('./events/processAMBAffirmationRequests')(config)
const processAMBInformationRequests = require('./events/processAMBInformationRequests')(config)
const { web3, eventContract } = config.main
let attached
async function initialize() {
try {
const checkHttps = checkHTTPS(ORACLE_ALLOW_HTTP_FOR_RPC, logger)
web3.currentProvider.subProvider.urls.forEach(checkHttps(config.chain))
web3.currentProvider.subProvider.urls.forEach(checkHttps(chain))
attached = await isAttached()
if (attached) {
@ -59,12 +73,12 @@ async function runMain({ sendToQueue }) {
const sendJob = attached ? sendToQueue : sendJobTx
if (!attached || connection.isConnected()) {
if (config.maxProcessingTime) {
await watchdog(() => main({ sendJob, txHash }), config.maxProcessingTime, () => {
await watchdog(() => main({ sendJob, txHashes }), config.maxProcessingTime, () => {
logger.fatal('Max processing time reached')
process.exit(EXIT_CODES.MAX_TIME_REACHED)
})
} else {
await main({ sendJob, txHash })
await main({ sendJob, txHashes })
}
} else {
setTimeout(() => {
@ -99,27 +113,31 @@ function processEvents(events) {
}
}
async function main({ sendJob, txHash }) {
try {
const events = await getEventsFromTx({
web3,
contract: eventContract,
event: config.event,
txHash,
filter: config.eventFilter
})
logger.info(`Found ${events.length} ${config.event} events`)
async function main({ sendJob, txHashes }) {
logger.info(`Processing ${txHashes.length} input transactions`)
for (const txHash of txHashes) {
try {
logger.info({ txHash }, `Processing transaction`)
const events = await getEventsFromTx({
web3,
contract: eventContract,
event: config.event,
txHash,
filter: config.eventFilter
})
logger.info({ txHash }, `Found ${events.length} ${config.event} events`)
if (events.length) {
const job = await processEvents(events)
logger.info('Transactions to send:', job.length)
if (events.length) {
const job = await processEvents(events)
logger.info({ txHash }, 'Transactions to send:', job.length)
if (job.length) {
await sendJob(job)
if (job.length) {
await sendJob(job)
}
}
} catch (e) {
logger.error(e)
}
} catch (e) {
logger.error(e)
}
await connection.close()
@ -128,7 +146,11 @@ async function main({ sendJob, txHash }) {
}
async function sendJobTx(jobs) {
const gasPrice = await GasPrice.start(config.chain, true)
await GasPrice.start(chain, true)
const gasPrice = GasPrice.getPrice().toString(10)
const { web3 } = config.sender === 'foreign' ? config.foreign : config.home
const chainId = await getChainId(web3)
let nonce = await getNonce(web3, ORACLE_VALIDATOR_ADDRESS)
@ -145,7 +167,7 @@ async function sendJobTx(jobs) {
const txHash = await sendTx({
data: job.data,
nonce,
gasPrice: gasPrice.toString(10),
gasPrice,
amount: '0',
gasLimit,
privateKey: ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY,

@ -40,7 +40,7 @@ async function initialize() {
try {
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
web3.currentProvider.subProvider.urls.forEach(checkHttps(config.chain))
web3.currentProvider.subProvider.urls.forEach(checkHttps(config.id))
GasPrice.start(config.id)

@ -102,6 +102,7 @@ async function getEventsFromTx({ web3, contract, event, txHash, filter }) {
const eventAbi = contract.options.jsonInterface.find(abi => abi.name === event)
const decodeAbi = contract._decodeEventABI.bind(eventAbi)
const pastEvents = logs
.filter(event => event.address.toLowerCase() === contractAddress.toLowerCase())
.filter(event => event.topics[0] === eventAbi.signature)
.map(decodeAbi)
.filter(event =>