Skip to content

Commit 4c06329

Browse files
Refactor/async call serializers (#588)
1 parent d534526 commit 4c06329

File tree

4 files changed

+118
-60
lines changed

4 files changed

+118
-60
lines changed

oracle-e2e/test/amb.js

Lines changed: 59 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,45 @@ const foreignBox = new foreignWeb3.eth.Contract(BOX_ABI, amb.foreignBox, opts)
2727
const homeBridge = new homeWeb3.eth.Contract(HOME_AMB_ABI, amb.home, opts)
2828
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, amb.foreign, opts)
2929

30+
function validateBlock(web3, serialized, block) {
31+
assert.strictEqual(serialized.length, 2 + 64 * 12)
32+
const values = web3.eth.abi.decodeParameter(
33+
'(uint256,bytes32,address,uint256,uint256,bytes32,bytes32,bytes32,bytes32,uint256,uint256,uint256)',
34+
serialized
35+
)
36+
assert.strictEqual(values[0], block.number.toString(), 'wrong block number returned')
37+
assert.strictEqual(values[1], block.hash, 'wrong block hash returned')
38+
assert.strictEqual(values[2], block.miner, 'wrong block miner returned')
39+
assert.strictEqual(values[3], block.gasUsed.toString(), 'wrong block gasUsed returned')
40+
assert.strictEqual(values[4], block.gasLimit.toString(), 'wrong block gasLimit returned')
41+
assert.strictEqual(values[5], block.parentHash, 'wrong block parentHash returned')
42+
assert.strictEqual(values[6], block.receiptsRoot, 'wrong block receiptsRoot returned')
43+
assert.strictEqual(values[7], block.stateRoot, 'wrong block stateRoot returned')
44+
assert.strictEqual(values[8], block.transactionsRoot, 'wrong block transactionsRoot returned')
45+
assert.strictEqual(values[9], block.timestamp.toString(), 'wrong block timestamp returned')
46+
assert.strictEqual(values[10], block.difficulty, 'wrong block difficulty returned')
47+
assert.strictEqual(values[11], block.totalDifficulty, 'wrong block totalDifficulty returned')
48+
}
49+
50+
function validateTransaction(web3, serialized, tx) {
51+
assert.strictEqual(serialized.length, 64 * 13 + tx.input.length + 56)
52+
const values = web3.eth.abi.decodeParameter(
53+
'(bytes32,uint256,bytes32,uint256,address,address,uint256,uint256,uint256,uint256,bytes)',
54+
serialized
55+
)
56+
assert.strictEqual(values[0], tx.hash, 'wrong txHash returned')
57+
assert.strictEqual(values[1], tx.blockNumber.toString(), 'wrong tx blockNumber returned')
58+
assert.strictEqual(values[2], tx.blockHash.toString(), 'wrong tx blockHash returned')
59+
assert.strictEqual(values[3], tx.transactionIndex.toString(), 'wrong tx transactionIndex returned')
60+
assert.strictEqual(values[4], tx.from, 'wrong tx from returned')
61+
assert.strictEqual(values[5], tx.to, 'wrong tx to returned')
62+
assert.strictEqual(values[6], tx.value, 'wrong tx value returned')
63+
assert.strictEqual(values[7], tx.nonce.toString(), 'wrong tx nonce returned')
64+
assert.strictEqual(values[8], tx.gas.toString(), 'wrong tx gas returned')
65+
assert.strictEqual(values[9], tx.gasPrice, 'wrong tx gasPrice returned')
66+
assert.strictEqual(values[10], tx.input, 'wrong tx data returned')
67+
}
68+
3069
describe('arbitrary message bridging', () => {
3170
let requiredSignatures = 1
3271
before(async () => {
@@ -340,15 +379,8 @@ describe('arbitrary message bridging', () => {
340379

341380
assert(await homeBox.methods.status().call(), 'status is false')
342381
const data = await homeBox.methods.data().call()
343-
assert.strictEqual(data.length, 2 + 64 * 3)
344-
const { 0: number, 1: hash, 2: miner } = homeWeb3.eth.abi.decodeParameters(
345-
['uint256', 'bytes32', 'address'],
346-
data
347-
)
348382
const block = await foreignWeb3.eth.getBlock(blockNumber)
349-
assert.strictEqual(number, blockNumber, 'wrong block number returned')
350-
assert.strictEqual(hash, block.hash, 'wrong block hash returned')
351-
assert.strictEqual(miner, block.miner, 'wrong block miner returned')
383+
validateBlock(homeWeb3, data, block)
352384
})
353385

354386
it('should make async eth_getBlockByNumber and return latest block', async () => {
@@ -358,7 +390,7 @@ describe('arbitrary message bridging', () => {
358390

359391
assert(await homeBox.methods.status().call(), 'status is false')
360392
const data = await homeBox.methods.data().call()
361-
assert.strictEqual(data.length, 2 + 64 * 3)
393+
assert.strictEqual(data.length, 2 + 64 * 12)
362394
})
363395

364396
it('should make async eth_getBlockByHash', async () => {
@@ -370,16 +402,7 @@ describe('arbitrary message bridging', () => {
370402

371403
assert(await homeBox.methods.status().call(), 'status is false')
372404
const data = await homeBox.methods.data().call()
373-
assert.strictEqual(data.length, 2 + 64 * 3)
374-
375-
const { 0: number, 1: hash, 2: miner } = homeWeb3.eth.abi.decodeParameters(
376-
['uint256', 'bytes32', 'address'],
377-
data
378-
)
379-
380-
assert.strictEqual(number, blockNumber, 'wrong block number returned')
381-
assert.strictEqual(hash, block.hash, 'wrong block hash returned')
382-
assert.strictEqual(miner, block.miner, 'wrong block miner returned')
405+
validateBlock(homeWeb3, data, block)
383406
})
384407

385408
it('should make async eth_getBalance', async () => {
@@ -475,28 +498,7 @@ describe('arbitrary message bridging', () => {
475498

476499
assert(await homeBox.methods.status().call(), 'status is false')
477500
const data = await homeBox.methods.data().call()
478-
const dataTypes = [
479-
'bytes32',
480-
'uint256',
481-
'address',
482-
'address',
483-
'uint256',
484-
'uint256',
485-
'uint256',
486-
'uint256',
487-
'bytes'
488-
]
489-
const values = homeWeb3.eth.abi.decodeParameters(dataTypes, data)
490-
491-
assert.strictEqual(values[0], txHash, 'wrong txHash returned')
492-
assert.strictEqual(values[1], tx.blockNumber.toString(), 'wrong tx blockNumber returned')
493-
assert.strictEqual(values[2], tx.from, 'wrong tx from returned')
494-
assert.strictEqual(values[3], tx.to, 'wrong tx to returned')
495-
assert.strictEqual(values[4], tx.value, 'wrong tx value returned')
496-
assert.strictEqual(values[5], tx.nonce.toString(), 'wrong tx nonce returned')
497-
assert.strictEqual(values[6], tx.gas.toString(), 'wrong tx gas returned')
498-
assert.strictEqual(values[7], tx.gasPrice, 'wrong tx gasPrice returned')
499-
assert.strictEqual(values[8], tx.input, 'wrong tx data returned')
501+
validateTransaction(homeWeb3, data, tx)
500502
})
501503

502504
it('should make async eth_getTransactionReceipt', async () => {
@@ -508,18 +510,25 @@ describe('arbitrary message bridging', () => {
508510

509511
assert(await homeBox.methods.status().call(), 'status is false')
510512
const data = await homeBox.methods.data().call()
511-
const dataTypes = ['bytes32', 'uint256', 'bool', '(address,bytes32[],bytes)[]']
512-
const values = homeWeb3.eth.abi.decodeParameters(dataTypes, data)
513+
const values = homeWeb3.eth.abi.decodeParameter(
514+
'(bytes32,uint256,bytes32,uint256,address,address,uint256,bool,(address,bytes32[],bytes)[])',
515+
data
516+
)
513517

514518
assert.strictEqual(values[0], txHash, 'wrong txHash returned')
515519
assert.strictEqual(values[1], receipt.blockNumber.toString(), 'wrong tx blockNumber returned')
516-
assert.strictEqual(values[2], receipt.status, 'wrong tx status returned')
517-
assert.strictEqual(values[3].length, 1, 'wrong logs length returned')
518-
assert.strictEqual(values[3][0][0], receipt.logs[0].address, 'wrong log address returned')
519-
assert.strictEqual(values[3][0][1].length, 2, 'wrong log topics length returned')
520-
assert.strictEqual(values[3][0][1][0], receipt.logs[0].topics[0], 'wrong event signature returned')
521-
assert.strictEqual(values[3][0][1][1], receipt.logs[0].topics[1], 'wrong message id returned')
522-
assert.strictEqual(values[3][0][2], receipt.logs[0].data, 'wrong log data returned')
520+
assert.strictEqual(values[2], receipt.blockHash, 'wrong tx blockHash returned')
521+
assert.strictEqual(values[3], receipt.transactionIndex.toString(), 'wrong tx transactionIndex returned')
522+
assert.strictEqual(values[4].toLowerCase(), receipt.from, 'wrong tx from returned')
523+
assert.strictEqual(values[5].toLowerCase(), receipt.to, 'wrong tx to returned')
524+
assert.strictEqual(values[6], receipt.gasUsed.toString(), 'wrong gasUsed to returned')
525+
assert.strictEqual(values[7], receipt.status, 'wrong tx status returned')
526+
assert.strictEqual(values[8].length, 1, 'wrong logs length returned')
527+
assert.strictEqual(values[8][0][0], receipt.logs[0].address, 'wrong log address returned')
528+
assert.strictEqual(values[8][0][1].length, 2, 'wrong log topics length returned')
529+
assert.strictEqual(values[8][0][1][0], receipt.logs[0].topics[0], 'wrong event signature returned')
530+
assert.strictEqual(values[8][0][1][1], receipt.logs[0].topics[1], 'wrong message id returned')
531+
assert.strictEqual(values[8][0][2], receipt.logs[0].data, 'wrong log data returned')
523532
})
524533

525534
it('should make async eth_getStorageAt', async () => {

oracle/src/events/processAMBInformationRequests/calls/serializers.js

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
11
const { ZERO_ADDRESS } = require('../../../../../commons')
22

33
const serializeBlock = (web3, block) => {
4-
const args = [block.number, block.hash, block.miner]
5-
const types = ['uint256', 'bytes32', 'address']
6-
return web3.eth.abi.encodeParameters(types, args)
4+
const args = [
5+
block.number,
6+
block.hash,
7+
block.miner,
8+
block.gasUsed,
9+
block.gasLimit,
10+
block.parentHash,
11+
block.receiptsRoot,
12+
block.stateRoot,
13+
block.transactionsRoot,
14+
block.timestamp,
15+
block.difficulty,
16+
block.totalDifficulty
17+
]
18+
const type = '(uint256,bytes32,address,uint256,uint256,bytes32,bytes32,bytes32,bytes32,uint256,uint256,uint256)'
19+
return web3.eth.abi.encodeParameter(type, args)
720
}
821

922
const serializeTx = (web3, tx) => {
1023
const args = [
1124
tx.hash,
1225
tx.blockNumber,
26+
tx.blockHash,
27+
tx.transactionIndex,
1328
tx.from,
1429
tx.to || ZERO_ADDRESS,
1530
tx.value,
@@ -18,16 +33,26 @@ const serializeTx = (web3, tx) => {
1833
tx.gasPrice,
1934
tx.input
2035
]
21-
const types = ['bytes32', 'uint256', 'address', 'address', 'uint256', 'uint256', 'uint256', 'uint256', 'bytes']
22-
return web3.eth.abi.encodeParameters(types, args)
36+
const type = '(bytes32,uint256,bytes32,uint256,address,address,uint256,uint256,uint256,uint256,bytes)'
37+
return web3.eth.abi.encodeParameter(type, args)
2338
}
2439

2540
const normalizeLog = log => [log.address, log.topics, log.data]
2641

2742
const serializeReceipt = (web3, receipt) => {
28-
const args = [receipt.transactionHash, receipt.blockNumber, receipt.status, receipt.logs.map(normalizeLog)]
29-
const types = ['bytes32', 'uint256', 'bool', '(address,bytes32[],bytes)[]']
30-
return web3.eth.abi.encodeParameters(types, args)
43+
const args = [
44+
receipt.transactionHash,
45+
receipt.blockNumber,
46+
receipt.blockHash,
47+
receipt.transactionIndex,
48+
receipt.from,
49+
receipt.to || ZERO_ADDRESS,
50+
receipt.gasUsed,
51+
receipt.status,
52+
receipt.logs.map(normalizeLog)
53+
]
54+
const type = '(bytes32,uint256,bytes32,uint256,address,address,uint256,bool,(address,bytes32[],bytes)[])'
55+
return web3.eth.abi.encodeParameter(type, args)
3156
}
3257

3358
module.exports = {

oracle/src/events/processAMBInformationRequests/estimateGas.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@ const logger = require('../../services/logger').child({
66
const { strip0x } = require('../../../../commons')
77
const { AMB_AFFIRMATION_REQUEST_EXTRA_GAS_ESTIMATOR: estimateExtraGas } = require('../../utils/constants')
88

9-
async function estimateGas({ web3, homeBridge, validatorContract, messageId, status, result, address }) {
9+
async function estimateGas({
10+
web3,
11+
homeBridge,
12+
validatorContract,
13+
messageId,
14+
status,
15+
result,
16+
address,
17+
homeBlockNumber
18+
}) {
1019
try {
1120
const gasEstimate = await homeBridge.methods.confirmInformation(messageId, status, result).estimateGas({
1221
from: address
@@ -51,6 +60,20 @@ async function estimateGas({ web3, homeBridge, validatorContract, messageId, sta
5160
throw new InvalidValidatorError(`${address} is not a validator`)
5261
}
5362

63+
logger.debug('Check if InformationRetrieved event for this message already exists')
64+
const logs = await homeBridge.getPastEvents('InformationRetrieved', {
65+
fromBlock: homeBlockNumber,
66+
toBlock: 'latest',
67+
filter: { messageId }
68+
})
69+
if (logs.length > 0) {
70+
logger.warn(
71+
'This particular message was already signed and processed by other validators.' +
72+
'However, evaluated async call result is different from the one recorded on-chain.'
73+
)
74+
throw new AlreadyProcessedError(e.message)
75+
}
76+
5477
throw new Error('Unknown error while processing message')
5578
}
5679
}

oracle/src/events/processAMBInformationRequests/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ function processInformationRequestsBuilder(config) {
108108
messageId,
109109
status,
110110
result,
111-
address: config.validatorAddress
111+
address: config.validatorAddress,
112+
homeBlockNumber: homeBlock.number
112113
})
113114
logger.debug({ gasEstimate }, 'Gas estimated')
114115
} catch (e) {

0 commit comments

Comments
 (0)