diff --git a/oracle/package.json b/oracle/package.json index 77c2a600c..7a44fc5c2 100644 --- a/oracle/package.json +++ b/oracle/package.json @@ -13,6 +13,7 @@ "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", + "manual-relay": "./scripts/manual-relay.sh", "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", "test:watch": "NODE_ENV=test mocha --watch --reporter=min", diff --git a/oracle/scripts/manual-relay.sh b/oracle/scripts/manual-relay.sh new file mode 100755 index 000000000..4a0505548 --- /dev/null +++ b/oracle/scripts/manual-relay.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -o pipefail + +TX_HASH=$(node ./scripts/txState.js "${1}") +STATE=$? + +WATCHER="" +if ((200 == STATE)); then + WATCHER="signature-request-watcher" +elif ((201 == STATE)); then + WATCHER="collected-signatures-watcher" +elif ((100 == STATE)); then + WATCHER="affirmation-request-watcher" +else + >&2 echo "an unexpected error occured" + exit 0 +fi + +WORKER="src/confirmRelay.js" +CONFIG="${WATCHER}.config.js" +LOG="logs/${WATCHER}.txt" +CHECKS=$(node scripts/initialChecks.js) + +echo "RUNNING: > node "${WORKER}" "${CONFIG}" "$CHECKS" "$TX_HASH" | tee -a "${LOG}" | pino-pretty " + +node "${WORKER}" "${CONFIG}" "$CHECKS" "$TX_HASH" | tee -a "${LOG}" | pino-pretty \ No newline at end of file diff --git a/oracle/scripts/txState.js b/oracle/scripts/txState.js new file mode 100644 index 000000000..ed537a7ee --- /dev/null +++ b/oracle/scripts/txState.js @@ -0,0 +1,90 @@ +require('../env') +const Web3 = require('web3') + +const { + ORACLE_BRIDGE_MODE, + COMMON_HOME_RPC_URL, + COMMON_HOME_BRIDGE_ADDRESS, +} = process.env + +const { + HOME_AMB_ABI, +} = require('../../commons') + +const txHash = process.argv[2] + +const AFFIRMATION_REQUEST_EXIT_CODE = 100 +const SIGNATURE_REQUEST_EXIT_CODE = 200 +const COLLECTED_SIGNATURES_EXIT_CODE = 201 + +async function getEventsFromTx( contract, event, txReceipt ) { + try { + const { logs } = txReceipt + const eventAbi = contract.options.jsonInterface.find(abi => abi.name === event) + const decodeAbi = contract._decodeEventABI.bind(eventAbi) + const pastEvents = logs + .filter(event => event.topics[0] === eventAbi.signature) + .map(decodeAbi) + return pastEvents + } catch (e) { + throw new Error(`${event} events cannot be obtained`) + } +} + +async function getEvents( web3, eventName, contract, fromBlock, filter = {}){ + const pastEvents = await contract.getPastEvents(eventName, {fromBlock}) + const eventAbi = contract.options.jsonInterface.find(abi => abi.name === eventName) + return pastEvents.filter((event) => { + return eventAbi.inputs.every(arg => { + const encodeParam = param => web3.eth.abi.encodeParameter(arg.type, param) + return !filter[arg.name] || encodeParam(filter[arg.name]) === encodeParam(event.returnValues[arg.name]) + }) + }) +} + +async function main() { + if(ORACLE_BRIDGE_MODE !== 'ARBITRARY_MESSAGE'){ + process.stderr.write(`This process does not support ${ORACLE_BRIDGE_MODE}.`) + return -1 + } + + const homeWeb3 = new Web3(COMMON_HOME_RPC_URL) + const homeBridge = new homeWeb3.eth.Contract(HOME_AMB_ABI ,COMMON_HOME_BRIDGE_ADDRESS) + + let txReceipt = await homeWeb3.eth.getTransactionReceipt(txHash) + + if(txReceipt === null) { + // We rule out UserRequestForSignature and CollectedSignatures. + // so most likely, the tx has a UserRequestForAffirmation on foreign bridge + process.stdout.write(txHash) + return AFFIRMATION_REQUEST_EXIT_CODE + } + + let events = await getEventsFromTx( + homeBridge, + 'UserRequestForSignature', + txReceipt + ) + + if(events.length === 0) { + process.stderr.write('No UserRequestForSignature events found') + return -1 + } + + let messageHash = Web3.utils.sha3(events[0].returnValues.encodedData) + + events = await getEvents(homeWeb3, 'CollectedSignatures', homeBridge, txReceipt.blockNumber, {messageHash}) + if(events.length === 1){ + process.stdout.write(events[0].transactionHash) + return COLLECTED_SIGNATURES_EXIT_CODE + } else { + process.stdout.write(txHash) + return SIGNATURE_REQUEST_EXIT_CODE + } +} + +main() +.then((code) => {process.exit(code)}) +.catch((err) => { + process.exit(-1) +}) \ No newline at end of file