Allow to make new AMB requests while processing other messages (#572)

This commit is contained in:
Kirill Fedoseev 2021-01-21 23:42:43 +03:00 committed by GitHub
parent 11d5ec35ef
commit a85d9ab343
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 2 deletions

View File

@ -10,6 +10,7 @@ contract BasicAMB is BasicBridge, VersionableAMB {
bytes32 internal constant SOURCE_CHAIN_ID_LENGTH = 0xe504ae1fd6471eea80f18b8532a61a9bb91fba4f5b837f80a1cfb6752350af44; // keccak256(abi.encodePacked("sourceChainIdLength"))
bytes32 internal constant DESTINATION_CHAIN_ID = 0xbbd454018e72a3f6c02bbd785bacc49e46292744f3f6761276723823aa332320; // keccak256(abi.encodePacked("destinationChainId"))
bytes32 internal constant DESTINATION_CHAIN_ID_LENGTH = 0xfb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d4989692811594; // keccak256(abi.encodePacked("destinationChainIdLength"))
bytes32 internal constant ALLOW_REENTRANT_REQUESTS = 0xffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd6; // keccak256(abi.encodePacked("allowReentrantRequests"))
/**
* Initializes AMB contract
@ -82,6 +83,24 @@ contract BasicAMB is BasicBridge, VersionableAMB {
_setChainIds(_sourceChainId, _destinationChainId);
}
/**
* Sets the flag to allow passing new AMB requests in the opposite direction,
* while other AMB message is being processed.
* Only owner can call this method.
* @param _enable true, if reentrant requests are allowed.
*/
function setAllowReentrantRequests(bool _enable) external onlyOwner {
boolStorage[ALLOW_REENTRANT_REQUESTS] = _enable;
}
/**
* Tells if passing reentrant requests is allowed.
* @return true, if reentrant requests are allowed.
*/
function allowReentrantRequests() public view returns (bool) {
return boolStorage[ALLOW_REENTRANT_REQUESTS];
}
/**
* Internal function for retrieving current nonce value
* @return nonce value

View File

@ -30,8 +30,8 @@ contract MessageDelivery is BasicAMB, MessageProcessor {
*/
function _sendMessage(address _contract, bytes _data, uint256 _gas, uint256 _dataType) public returns (bytes32) {
// it is not allowed to pass messages while other messages are processed
require(messageId() == bytes32(0));
// if other is not explicitly configured
require(messageId() == bytes32(0) || allowReentrantRequests());
require(_gas >= getMinimumGasUsage(_data) && _gas <= maxGasPerTx());
bytes32 _messageId;

View File

@ -736,6 +736,33 @@ contract('ForeignAMB', async accounts => {
// means that call to requireToPassMessage inside MessageProcessor reverted, since messageId flag was set up
expect(await foreignBridge.messageCallStatus(messageId)).to.be.equal(false)
})
it('should allow to pass message back through the bridge if configured', async () => {
const user = accounts[8]
await foreignBridge.setAllowReentrantRequests(true, { from: user }).should.be.rejected
await foreignBridge.setAllowReentrantRequests(true, { from: owner }).should.be.fulfilled
expect(await foreignBridge.allowReentrantRequests()).to.be.equal(true)
const data = await foreignBridge.contract.methods
.requireToPassMessage(box.address, setValueData, 100000)
.encodeABI()
// Use these calls to simulate home bridge on home network
const resultPassMessageTx = await homeBridge.requireToPassMessage(foreignBridge.address, data, 821254, {
from: user
})
const { encodedData: message, messageId } = resultPassMessageTx.logs[0].args
const signature = await sign(authorities[0], message)
const vrs = signatureToVRS(signature)
const signatures = packSignatures([vrs])
await foreignBridge.executeSignatures(message, signatures, {
from: authorities[0],
gasPrice
}).should.be.fulfilled
expect(await foreignBridge.messageCallStatus(messageId)).to.be.equal(true)
})
})
describe('gasToken functionality', async () => {

View File

@ -666,6 +666,27 @@ contract('HomeAMB', async accounts => {
// means that call to requireToPassMessage inside MessageProcessor reverted, since messageId flag was set up
expect(await homeBridge.messageCallStatus(messageId)).to.be.equal(false)
})
it('should allow to pass message back through the bridge if configured', async () => {
const user = accounts[8]
await homeBridge.setAllowReentrantRequests(true, { from: user }).should.be.rejected
await homeBridge.setAllowReentrantRequests(true, { from: owner }).should.be.fulfilled
expect(await homeBridge.allowReentrantRequests()).to.be.equal(true)
const data = await homeBridge.contract.methods.requireToPassMessage(box.address, setValueData, 100000).encodeABI()
// Use these calls to simulate home bridge on home network
const resultPassMessageTx = await foreignBridge.requireToPassMessage(homeBridge.address, data, 821254, {
from: user
})
const { encodedData: message, messageId } = resultPassMessageTx.logs[0].args
await homeBridge.executeAffirmation(message, {
from: authorities[0],
gasPrice
}).should.be.fulfilled
expect(await homeBridge.messageCallStatus(messageId)).to.be.equal(true)
})
})
describe('submitSignature', () => {
let homeBridge