Skip to content
This repository has been archived by the owner on Dec 5, 2021. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'omgx_alt_messenger/master' into inomurk…
Browse files Browse the repository at this point in the history
…o/alt_messenger
  • Loading branch information
InoMurko committed May 25, 2021
2 parents 6af7317 + 0b9be24 commit 7c2fd94
Show file tree
Hide file tree
Showing 18 changed files with 14,841 additions and 0 deletions.
23 changes: 23 additions & 0 deletions packages/omgx/alt_messenger/.gitignore
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
32 changes: 32 additions & 0 deletions packages/omgx/alt_messenger/README.md
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 packages/omgx/alt_messenger/contracts/OVM_L1CrossDomainMessenger.sol
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");
}
}
Loading

0 comments on commit 7c2fd94

Please sign in to comment.