Support of manual lane in the AMB oracle (#483)
This commit is contained in:
parent
f8d85b14de
commit
0228fc7d5f
@ -5,7 +5,8 @@
|
||||
],
|
||||
"rules": {
|
||||
"no-unused-expressions": "off",
|
||||
"import/no-extraneous-dependencies": "off"
|
||||
"import/no-extraneous-dependencies": "off",
|
||||
"no-bitwise": "off"
|
||||
},
|
||||
"env": {
|
||||
"mocha": true
|
||||
|
@ -6,17 +6,30 @@ function addTxHashToData({ encodedData, transactionHash }) {
|
||||
return encodedData.slice(0, 2) + strip0x(transactionHash) + encodedData.slice(2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the datatype byte from the AMB message.
|
||||
* First (the most significant bit) denotes if the message should be forwarded to the manual lane.
|
||||
* @param dataType: number datatype of the received AMB message.
|
||||
* @return {{manualLane: boolean}}
|
||||
*/
|
||||
const decodeAMBDataType = dataType => ({
|
||||
manualLane: (dataType & 128) === 128
|
||||
})
|
||||
|
||||
function parseAMBMessage(message) {
|
||||
message = strip0x(message)
|
||||
|
||||
const messageId = `0x${message.slice(0, 64)}`
|
||||
const sender = `0x${message.slice(64, 104)}`
|
||||
const executor = `0x${message.slice(104, 144)}`
|
||||
const dataType = parseInt(message.slice(156, 158), 16)
|
||||
|
||||
return {
|
||||
sender,
|
||||
executor,
|
||||
messageId
|
||||
messageId,
|
||||
dataType,
|
||||
decodedDataType: decodeAMBDataType(dataType)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit dd46135248dbb4684752735aab3cf64db170a405
|
||||
Subproject commit 1748f94757c07ce99d13d99a0a5d1d738b292354
|
@ -1 +1,2 @@
|
||||
0xc9e38bfdB9c635F0796ad83CC8705dc379F41c04
|
||||
0x612E8bd50A7b1F009F43f2b8679E9B8eD91eb5CE
|
||||
|
@ -23,3 +23,4 @@ ORACLE_FOREIGN_RPC_POLLING_INTERVAL=500
|
||||
ORACLE_ALLOW_HTTP_FOR_RPC=yes
|
||||
ORACLE_HOME_START_BLOCK=1
|
||||
ORACLE_FOREIGN_START_BLOCK=1
|
||||
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST=/mono/oracle/access-lists/block_list.txt
|
||||
|
@ -63,6 +63,7 @@
|
||||
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
|
||||
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||
"blockedHomeBox": "0x612E8bd50A7b1F009F43f2b8679E9B8eD91eb5CE",
|
||||
"monitor": "http://monitor-amb:3013/bridge"
|
||||
},
|
||||
"ambStakeErcToErc": {
|
||||
|
@ -61,6 +61,9 @@ services:
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
command: "true"
|
||||
volumes:
|
||||
- '../e2e-commons/access-lists/block_list.txt:/mono/oracle/access-lists/block_list.txt'
|
||||
- '../e2e-commons/access-lists/allowance_list.txt:/mono/oracle/access-lists/allowance_list.txt'
|
||||
networks:
|
||||
- ultimate
|
||||
ui:
|
||||
|
@ -53,3 +53,8 @@ node deploy.js
|
||||
cd - > /dev/null
|
||||
node setupStakeTokens.js
|
||||
cd - > /dev/null
|
||||
|
||||
echo -e "\n\n############ Deploying one more test contract for amb ############\n"
|
||||
cd "$DEPLOY_PATH"
|
||||
node src/utils/deployTestBox.js
|
||||
cd - > /dev/null
|
||||
|
@ -17,21 +17,29 @@ docker-compose up -d parity1 parity2 e2e
|
||||
startValidator () {
|
||||
docker-compose $1 run -d --name $4 redis
|
||||
docker-compose $1 run -d --name $5 rabbit
|
||||
if [[ -z "$MODE" || "$MODE" == native-to-erc ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle yarn watcher:affirmation-request
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-erc ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:affirmation-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20 yarn watcher:transfer
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == erc-to-native ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:affirmation-request
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn watcher:transfer
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn worker:convert-to-chai
|
||||
fi
|
||||
if [[ -z "$MODE" || "$MODE" == amb ]]; then
|
||||
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:signature-request
|
||||
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:collected-signatures
|
||||
docker-compose $1 run $2 $3 -d oracle-amb yarn watcher:affirmation-request
|
||||
fi
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:home
|
||||
docker-compose $1 run $2 $3 -d oracle-erc20-native yarn sender:foreign
|
||||
}
|
||||
@ -48,25 +56,7 @@ startAMBValidator () {
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
if [ "$1" == "oracle" ]; then
|
||||
docker-compose up -d redis rabbit
|
||||
|
||||
docker-compose run -d oracle yarn watcher:signature-request
|
||||
docker-compose run -d oracle yarn watcher:collected-signatures
|
||||
docker-compose run -d oracle yarn watcher:affirmation-request
|
||||
docker-compose run -d oracle-erc20 yarn watcher:signature-request
|
||||
docker-compose run -d oracle-erc20 yarn watcher:collected-signatures
|
||||
docker-compose run -d oracle-erc20 yarn watcher:affirmation-request
|
||||
docker-compose run -d oracle-erc20 yarn watcher:transfer
|
||||
docker-compose run -d oracle-erc20-native yarn watcher:signature-request
|
||||
docker-compose run -d oracle-erc20-native yarn watcher:collected-signatures
|
||||
docker-compose run -d oracle-erc20-native yarn watcher:affirmation-request
|
||||
docker-compose run -d oracle-erc20-native yarn watcher:transfer
|
||||
docker-compose run -d oracle-erc20-native yarn worker:convert-to-chai
|
||||
docker-compose run -d oracle-amb yarn watcher:signature-request
|
||||
docker-compose run -d oracle-amb yarn watcher:collected-signatures
|
||||
docker-compose run -d oracle-amb yarn watcher:affirmation-request
|
||||
docker-compose run -d oracle yarn sender:home
|
||||
docker-compose run -d oracle yarn sender:foreign
|
||||
startValidator "" "" "" "redis" "rabbit"
|
||||
fi
|
||||
|
||||
if [ "$1" == "oracle-validator-2" ]; then
|
||||
|
@ -1,8 +1,24 @@
|
||||
cd $(dirname $0)
|
||||
|
||||
../e2e-commons/up.sh deploy blocks oracle oracle-validator-2 oracle-validator-3
|
||||
mode="$1"
|
||||
case "$mode" in
|
||||
amb)
|
||||
script=./test/amb.js
|
||||
;;
|
||||
native-to-erc)
|
||||
script=./test/nativeToErc.js
|
||||
;;
|
||||
erc-to-erc)
|
||||
script=./test/ercToErc.js
|
||||
;;
|
||||
erc-to-native)
|
||||
script=./test/ercToNative.js
|
||||
;;
|
||||
esac
|
||||
|
||||
docker-compose -f ../e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run start
|
||||
MODE="$mode" ../e2e-commons/up.sh deploy 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=$?
|
||||
|
||||
../e2e-commons/down.sh
|
||||
|
@ -3,7 +3,7 @@ const assert = require('assert')
|
||||
const { user, homeRPC, foreignRPC, amb, validator } = require('../../e2e-commons/constants.json')
|
||||
const { uniformRetry } = require('../../e2e-commons/utils')
|
||||
const { BOX_ABI, HOME_AMB_ABI, FOREIGN_AMB_ABI } = require('../../commons')
|
||||
const { setRequiredSignatures } = require('./utils')
|
||||
const { delay, setRequiredSignatures } = require('./utils')
|
||||
|
||||
const { toBN } = Web3.utils
|
||||
|
||||
@ -19,14 +19,17 @@ foreignWeb3.eth.accounts.wallet.add(user.privateKey)
|
||||
foreignWeb3.eth.accounts.wallet.add(validator.privateKey)
|
||||
|
||||
const homeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.homeBox)
|
||||
const blockHomeBox = new homeWeb3.eth.Contract(BOX_ABI, amb.blockedHomeBox)
|
||||
const foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox)
|
||||
const homeBridge = new homeWeb3.eth.Contract(HOME_AMB_ABI, COMMON_HOME_BRIDGE_ADDRESS)
|
||||
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
|
||||
|
||||
describe('arbitrary message bridging', () => {
|
||||
let requiredSignatures = 1
|
||||
before(async () => {
|
||||
// Only 1 validator is used in ultimate tests
|
||||
if (process.env.ULTIMATE !== 'true') {
|
||||
requiredSignatures = 2
|
||||
// Set 2 required signatures for home bridge
|
||||
await setRequiredSignatures({
|
||||
bridgeContract: homeBridge,
|
||||
@ -76,6 +79,82 @@ describe('arbitrary message bridging', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('should confirm but not relay message from blocked contract', async () => {
|
||||
const newValue = 4
|
||||
|
||||
const initialValue = await foreignBox.methods.value().call()
|
||||
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||
|
||||
const signatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
await blockHomeBox.methods
|
||||
.setValueOnOtherNetwork(newValue, amb.home, amb.foreignBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
gas: '400000'
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
await delay(5000)
|
||||
|
||||
const newSignatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
assert(
|
||||
newSignatures.length === signatures.length + requiredSignatures,
|
||||
`Incorrect amount of signatures submitted, got ${newSignatures.length}, expected ${signatures.length +
|
||||
requiredSignatures}`
|
||||
)
|
||||
|
||||
const value = await foreignBox.methods.value().call()
|
||||
assert(!toBN(value).eq(toBN(newValue)), 'Message should not be relayed by oracle automatically')
|
||||
})
|
||||
|
||||
it('should confirm but not relay message from manual lane', async () => {
|
||||
const newValue = 5
|
||||
|
||||
const initialValue = await foreignBox.methods.value().call()
|
||||
assert(!toBN(initialValue).eq(toBN(newValue)), 'initial value should be different from new value')
|
||||
|
||||
const signatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
await homeBox.methods
|
||||
.setValueOnOtherNetworkUsingManualLane(newValue, amb.home, amb.foreignBox)
|
||||
.send({
|
||||
from: user.address,
|
||||
gas: '400000'
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
await delay(5000)
|
||||
|
||||
const newSignatures = await homeBridge.getPastEvents('SignedForUserRequest', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
assert(
|
||||
newSignatures.length === signatures.length + requiredSignatures,
|
||||
`Incorrect amount of signatures submitted, got ${newSignatures.length}, expected ${signatures.length +
|
||||
requiredSignatures}`
|
||||
)
|
||||
|
||||
const value = await foreignBox.methods.value().call()
|
||||
assert(!toBN(value).eq(toBN(newValue)), 'Message should not be relayed by oracle automatically')
|
||||
})
|
||||
})
|
||||
})
|
||||
describe('Foreign to Home', () => {
|
||||
|
@ -1,5 +1,9 @@
|
||||
const { BRIDGE_VALIDATORS_ABI } = require('../../commons')
|
||||
|
||||
async function delay(ms) {
|
||||
return new Promise(res => setTimeout(res, ms))
|
||||
}
|
||||
|
||||
const setRequiredSignatures = async ({ bridgeContract, web3, requiredSignatures, options }) => {
|
||||
const validatorAddress = await bridgeContract.methods.validatorContract().call()
|
||||
const validatorContract = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, validatorAddress)
|
||||
@ -8,5 +12,6 @@ const setRequiredSignatures = async ({ bridgeContract, web3, requiredSignatures,
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
delay,
|
||||
setRequiredSignatures
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ const bridgeValidatorsABI = require('../../../../contracts/build/contracts/Bridg
|
||||
const rootLogger = require('../../services/logger')
|
||||
const { web3Home, web3Foreign } = require('../../services/web3')
|
||||
const { signatureToVRS, packSignatures } = require('../../utils/message')
|
||||
const { readAccessListFile } = require('../../utils/utils')
|
||||
const { parseAMBMessage } = require('../../../../commons')
|
||||
const estimateGas = require('./estimateGas')
|
||||
const { AlreadyProcessedError, IncompatibleContractError, InvalidValidatorError } = require('../../utils/errors')
|
||||
@ -12,7 +13,11 @@ const { MAX_CONCURRENT_EVENTS, EXTRA_GAS_ABSOLUTE } = require('../../utils/const
|
||||
|
||||
const limit = promiseLimit(MAX_CONCURRENT_EVENTS)
|
||||
|
||||
const { ORACLE_ALWAYS_RELAY_SIGNATURES } = process.env
|
||||
const {
|
||||
ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST,
|
||||
ORACLE_HOME_TO_FOREIGN_BLOCK_LIST,
|
||||
ORACLE_ALWAYS_RELAY_SIGNATURES
|
||||
} = process.env
|
||||
|
||||
let validatorContract = null
|
||||
|
||||
@ -50,6 +55,41 @@ function processCollectedSignaturesBuilder(config) {
|
||||
|
||||
logger.info(`Processing CollectedSignatures ${colSignature.transactionHash}`)
|
||||
const message = await homeBridge.methods.message(messageHash).call()
|
||||
const parsedMessage = parseAMBMessage(message)
|
||||
|
||||
if (ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST || ORACLE_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||
const sender = parsedMessage.sender.toLowerCase()
|
||||
const executor = parsedMessage.executor.toLowerCase()
|
||||
|
||||
if (ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST) {
|
||||
const allowanceList = await readAccessListFile(ORACLE_HOME_TO_FOREIGN_ALLOWANCE_LIST, logger)
|
||||
if (!allowanceList.includes(executor) && !allowanceList.includes(sender)) {
|
||||
logger.info(
|
||||
{ sender, executor },
|
||||
'Validator skips a message. Neither sender nor executor addresses are in the allowance list.'
|
||||
)
|
||||
return
|
||||
}
|
||||
} else if (ORACLE_HOME_TO_FOREIGN_BLOCK_LIST) {
|
||||
const blockList = await readAccessListFile(ORACLE_HOME_TO_FOREIGN_BLOCK_LIST, logger)
|
||||
if (blockList.includes(executor)) {
|
||||
logger.info({ executor }, 'Validator skips a message. Executor address is in the block list.')
|
||||
return
|
||||
}
|
||||
if (blockList.includes(sender)) {
|
||||
logger.info({ sender }, 'Validator skips a message. Sender address is in the block list.')
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedMessage.decodedDataType.manualLane) {
|
||||
logger.info(
|
||||
{ dataType: parsedMessage.dataType },
|
||||
'Validator skips a message. Message was forwarded to the manual lane by the extension'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
logger.debug({ NumberOfCollectedSignatures }, 'Number of signatures to get')
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
"build:ui": "yarn workspace ui run build",
|
||||
"build:alm": "yarn workspace alm run build",
|
||||
"build:plugin": "yarn workspace burner-wallet-plugin run build",
|
||||
"lint": "yarn wsrun --exclude token-bridge-contracts lint",
|
||||
"lint": "yarn wsrun --exclude tokenbridge-contracts lint",
|
||||
"test": "yarn wsrun --exclude oracle-e2e --exclude ui-e2e --exclude monitor-e2e --exclude alm-e2e test",
|
||||
"oracle-e2e": "./oracle-e2e/run-tests.sh",
|
||||
"ui-e2e": "./ui-e2e/run-tests.sh",
|
||||
@ -47,7 +47,7 @@
|
||||
"monitor-e2e": "./monitor-e2e/run-tests.sh",
|
||||
"alm-e2e": "./alm-e2e/run-tests.sh",
|
||||
"clean": "rm -rf ./node_modules ./**/node_modules ./**/**/node_modules ./**/build ./**/**/dist",
|
||||
"compile:contracts": "yarn workspace token-bridge-contracts run compile",
|
||||
"compile:contracts": "yarn workspace tokenbridge-contracts run compile",
|
||||
"install:deploy": "cd contracts/deploy && npm install --unsafe-perm --silent",
|
||||
"postinstall": "test -n \"$NOYARNPOSTINSTALL\" || ln -sf $(pwd)/node_modules/openzeppelin-solidity/ contracts/node_modules/openzeppelin-solidity"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user