This repository has been archived by the owner on Dec 5, 2021. It is now read-only.
forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'omgx_alt_messenger/master' into inomurk…
…o/alt_messenger
- Loading branch information
Showing
18 changed files
with
14,841 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
.DS_Store | ||
node_modules | ||
results | ||
temp | ||
.nyc_output | ||
*.tsbuildinfo | ||
|
||
dist | ||
artifacts | ||
artifacts-ovm | ||
cache | ||
cache-ovm | ||
|
||
l2geth/build/bin | ||
packages/contracts/deployments/custom | ||
packages/contracts/coverage* | ||
|
||
packages/data-transport-layer/db | ||
|
||
# vim | ||
*.swp | ||
|
||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# OMGX_Alt_Messenger | ||
|
||
Customized L1 Cross Domain Messenger without dispute period time restrictions and associated message relayer service. | ||
|
||
The custom `OVM_L1CrossDomainMessenger` works with the default `OVM_L2CrossDomainMessenger`. The messages from the L2_Messenger can be relayed by the custom messenger instead to skip the dispute period and to do that, the bridge/token contract should specify the custom messenger to be the messenger for relays. The custom messenger cannot be used to send cross domain messages. For sending messages the bridge contracts use the default L1_Messenger. | ||
|
||
## Using the custom messenger | ||
|
||
- Deploy `contracts/OVM_L1_CrossDomainMessenger.sol` on L1, this will be the contract used by your contracts for L2->L1 message passing | ||
|
||
- Your bridge/gateway contract must implement `contracts/libraries/OVM_CrossDomainEnabled.sol` instead. This uses the default L1 Messenger to send messages and the custom L1 Messenger to relay. | ||
|
||
## Running the Alt_Relayer | ||
|
||
Env Settings - | ||
|
||
``` | ||
ADDRESS_MANAGER_ADDRESS= <address manager contract address> | ||
L1_NODE_WEB3_URL= <l1 node url> | ||
L2_NODE_WEB3_URL= <l2 node url> | ||
L1_WALLET_KEY= <l1 wallet key> | ||
L1_MESSENGER_ADDRESS= <l1 custom messenger address> | ||
L1_TARGET= <target contract to allow relays to, set to 0x0 to skip> | ||
``` | ||
|
||
Running the message relayer | ||
``` | ||
cd relayer_service | ||
yarn install | ||
yarn build | ||
yarn start | ||
``` |
287 changes: 287 additions & 0 deletions
287
packages/omgx/alt_messenger/contracts/OVM_L1CrossDomainMessenger.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,287 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >0.5.0 <0.8.0; | ||
pragma experimental ABIEncoderV2; | ||
|
||
/* Library Imports */ | ||
import { Lib_OVMCodec } from "enyalabs_contracts/contracts/optimistic-ethereum/libraries/codec/Lib_OVMCodec.sol"; | ||
import { Lib_AddressResolver } from "enyalabs_contracts/contracts/optimistic-ethereum/libraries/resolver/Lib_AddressResolver.sol"; | ||
import { Lib_AddressManager } from "enyalabs_contracts/contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol"; | ||
import { Lib_SecureMerkleTrie } from "enyalabs_contracts/contracts/optimistic-ethereum/libraries/trie/Lib_SecureMerkleTrie.sol"; | ||
|
||
/* Interface Imports */ | ||
import { iOVM_L1CrossDomainMessenger } from "enyalabs_contracts/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol"; | ||
import { iOVM_CanonicalTransactionChain } from "enyalabs_contracts/contracts/optimistic-ethereum/iOVM/chain/iOVM_CanonicalTransactionChain.sol"; | ||
import { iOVM_StateCommitmentChain } from "enyalabs_contracts/contracts/optimistic-ethereum/iOVM/chain/iOVM_StateCommitmentChain.sol"; | ||
|
||
/* Contract Imports */ | ||
import { Abs_BaseCrossDomainMessenger } from "enyalabs_contracts/contracts/optimistic-ethereum/OVM/bridge/messaging/Abs_BaseCrossDomainMessenger.sol"; | ||
|
||
/** | ||
* @title OVM_L1CrossDomainMessenger | ||
* @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages from L2 onto L1. | ||
* In the event that a message sent from L1 to L2 is rejected for exceeding the L2 epoch gas limit, it can be resubmitted | ||
* via this contract's replay function. | ||
* | ||
* Compiler used: solc | ||
* Runtime target: EVM | ||
*/ | ||
contract OVM_L1CrossDomainMessenger is iOVM_L1CrossDomainMessenger, Abs_BaseCrossDomainMessenger, Lib_AddressResolver { | ||
|
||
/*************** | ||
* Constructor * | ||
***************/ | ||
|
||
/** | ||
* Pass a default zero address to the address resolver. This will be updated when initialized. | ||
*/ | ||
constructor() | ||
Lib_AddressResolver(address(0)) | ||
{} | ||
|
||
/** | ||
* @param _libAddressManager Address of the Address Manager. | ||
*/ | ||
function initialize( | ||
address _libAddressManager | ||
) | ||
public | ||
{ | ||
require(address(libAddressManager) == address(0), "L1CrossDomainMessenger already intialized."); | ||
libAddressManager = Lib_AddressManager(_libAddressManager); | ||
xDomainMsgSender = DEFAULT_XDOMAIN_SENDER; | ||
} | ||
|
||
|
||
/********************** | ||
* Function Modifiers * | ||
**********************/ | ||
|
||
/** | ||
* Modifier to enforce that, if configured, only the OVM_L2MessageRelayer contract may successfully call a method. | ||
*/ | ||
modifier onlyRelayer() { | ||
address relayer = resolve("OVM_L2MessageRelayer"); | ||
if (relayer != address(0)) { | ||
require( | ||
msg.sender == relayer, | ||
"Only OVM_L2MessageRelayer can relay L2-to-L1 messages." | ||
); | ||
} | ||
_; | ||
} | ||
|
||
|
||
/******************** | ||
* Public Functions * | ||
********************/ | ||
|
||
/** | ||
* Relays a cross domain message to a contract. | ||
* @inheritdoc iOVM_L1CrossDomainMessenger | ||
*/ | ||
function relayMessage( | ||
address _target, | ||
address _sender, | ||
bytes memory _message, | ||
uint256 _messageNonce, | ||
L2MessageInclusionProof memory _proof | ||
) | ||
override | ||
public | ||
onlyRelayer() | ||
{ | ||
bytes memory xDomainCalldata = _getXDomainCalldata( | ||
_target, | ||
_sender, | ||
_message, | ||
_messageNonce | ||
); | ||
|
||
require( | ||
_verifyXDomainMessage( | ||
xDomainCalldata, | ||
_proof | ||
) == true, | ||
"Provided message could not be verified." | ||
); | ||
|
||
bytes32 xDomainCalldataHash = keccak256(xDomainCalldata); | ||
|
||
require( | ||
successfulMessages[xDomainCalldataHash] == false, | ||
"Provided message has already been received." | ||
); | ||
|
||
xDomainMsgSender = _sender; | ||
(bool success, ) = _target.call(_message); | ||
xDomainMsgSender = DEFAULT_XDOMAIN_SENDER; | ||
|
||
// Mark the message as received if the call was successful. Ensures that a message can be | ||
// relayed multiple times in the case that the call reverted. | ||
if (success == true) { | ||
successfulMessages[xDomainCalldataHash] = true; | ||
emit RelayedMessage(xDomainCalldataHash); | ||
} | ||
|
||
// Store an identifier that can be used to prove that the given message was relayed by some | ||
// user. Gives us an easy way to pay relayers for their work. | ||
bytes32 relayId = keccak256( | ||
abi.encodePacked( | ||
xDomainCalldata, | ||
msg.sender, | ||
block.number | ||
) | ||
); | ||
relayedMessages[relayId] = true; | ||
} | ||
|
||
/** | ||
* Replays a cross domain message to the target messenger. | ||
* @inheritdoc iOVM_L1CrossDomainMessenger | ||
*/ | ||
function replayMessage( | ||
address _target, | ||
address _sender, | ||
bytes memory _message, | ||
uint256 _messageNonce, | ||
uint32 _gasLimit | ||
) | ||
override | ||
public | ||
{ | ||
bytes memory xDomainCalldata = _getXDomainCalldata( | ||
_target, | ||
_sender, | ||
_message, | ||
_messageNonce | ||
); | ||
|
||
require( | ||
sentMessages[keccak256(xDomainCalldata)] == true, | ||
"Provided message has not already been sent." | ||
); | ||
|
||
_sendXDomainMessage(xDomainCalldata, _gasLimit); | ||
} | ||
|
||
|
||
/********************** | ||
* Internal Functions * | ||
**********************/ | ||
|
||
/** | ||
* Verifies that the given message is valid. | ||
* @param _xDomainCalldata Calldata to verify. | ||
* @param _proof Inclusion proof for the message. | ||
* @return Whether or not the provided message is valid. | ||
*/ | ||
function _verifyXDomainMessage( | ||
bytes memory _xDomainCalldata, | ||
L2MessageInclusionProof memory _proof | ||
) | ||
internal | ||
view | ||
returns ( | ||
bool | ||
) | ||
{ | ||
return ( | ||
_verifyStateRootProof(_proof) | ||
&& _verifyStorageProof(_xDomainCalldata, _proof) | ||
); | ||
} | ||
|
||
/** | ||
* Verifies that the state root within an inclusion proof is valid. | ||
* @param _proof Message inclusion proof. | ||
* @return Whether or not the provided proof is valid. | ||
*/ | ||
function _verifyStateRootProof( | ||
L2MessageInclusionProof memory _proof | ||
) | ||
internal | ||
view | ||
returns ( | ||
bool | ||
) | ||
{ | ||
iOVM_StateCommitmentChain ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain")); | ||
|
||
return ( | ||
ovmStateCommitmentChain.verifyStateCommitment( | ||
_proof.stateRoot, | ||
_proof.stateRootBatchHeader, | ||
_proof.stateRootProof | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Verifies that the storage proof within an inclusion proof is valid. | ||
* @param _xDomainCalldata Encoded message calldata. | ||
* @param _proof Message inclusion proof. | ||
* @return Whether or not the provided proof is valid. | ||
*/ | ||
function _verifyStorageProof( | ||
bytes memory _xDomainCalldata, | ||
L2MessageInclusionProof memory _proof | ||
) | ||
internal | ||
view | ||
returns ( | ||
bool | ||
) | ||
{ | ||
bytes32 storageKey = keccak256( | ||
abi.encodePacked( | ||
keccak256( | ||
abi.encodePacked( | ||
_xDomainCalldata, | ||
resolve("OVM_L2CrossDomainMessenger") | ||
) | ||
), | ||
uint256(0) | ||
) | ||
); | ||
|
||
( | ||
bool exists, | ||
bytes memory encodedMessagePassingAccount | ||
) = Lib_SecureMerkleTrie.get( | ||
abi.encodePacked(0x4200000000000000000000000000000000000000), | ||
_proof.stateTrieWitness, | ||
_proof.stateRoot | ||
); | ||
|
||
require( | ||
exists == true, | ||
"Message passing predeploy has not been initialized or invalid proof provided." | ||
); | ||
|
||
Lib_OVMCodec.EVMAccount memory account = Lib_OVMCodec.decodeEVMAccount( | ||
encodedMessagePassingAccount | ||
); | ||
|
||
return Lib_SecureMerkleTrie.verifyInclusionProof( | ||
abi.encodePacked(storageKey), | ||
abi.encodePacked(uint8(1)), | ||
_proof.storageTrieWitness, | ||
account.storageRoot | ||
); | ||
} | ||
|
||
/** | ||
* Sends a cross domain message. | ||
* @param _message Message to send. | ||
* @param _gasLimit OVM gas limit for the message. | ||
*/ | ||
function _sendXDomainMessage( | ||
bytes memory _message, | ||
uint256 _gasLimit | ||
) | ||
override | ||
internal | ||
{ | ||
revert("Sending via this messenger is disabled"); | ||
} | ||
} |
Oops, something went wrong.