Skip to content

Commit

Permalink
feat(ethereum contracts): Change nonce type and update tests (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
koinov authored Jun 18, 2024
1 parent 90d44c5 commit d42251c
Show file tree
Hide file tree
Showing 12 changed files with 45 additions and 74 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
target/
.vscode
.idea
data/
/proof_storage
_obj
Expand Down
10 changes: 7 additions & 3 deletions ethereum/client/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use alloy_sol_types::sol;
sol! {
#[derive(Debug,PartialEq, Eq)]
struct ContentMessage {
uint256 nonce;
bytes32 nonce;
bytes32 sender;
address receiver;
bytes data;
Expand All @@ -12,7 +12,11 @@ sol! {
#[sol(rpc)]
#[derive(Debug,PartialEq, Eq)]
interface IMessageQueue {
event MessageProcessed(uint256 indexed blockNumber, bytes32 indexed messageHash);
event MessageProcessed(
uint256 indexed blockNumber,
bytes32 indexed messageHash,
bytes32 indexed messageNonce
);

function calculateMerkleRoot(bytes32[] calldata proof, bytes32 hash, uint256 width, uint256 leaf_index) external view returns (bytes32);

Expand All @@ -36,7 +40,7 @@ sol! {
impl ContentMessage {
pub fn to_bytes(&self) -> Vec<u8> {
let mut ret: Vec<u8> = Vec::with_capacity(32 + 32 + 20 + self.data.len());
ret.extend(self.nonce.to_le_bytes::<32>());
ret.extend(self.nonce.to_vec());
ret.extend(self.sender.to_vec());
ret.extend(self.receiver.to_vec());
ret.extend(self.data.to_vec());
Expand Down
8 changes: 7 additions & 1 deletion ethereum/client/src/convert.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use alloy_primitives::{Address, Bytes as aBytes, Uint, B256 as aB256, U256 as aU256};
use primitive_types::U256 as eU256;
use primitive_types::{H256 as eH256, U256 as eU256};

pub trait Convert<T> {
fn convert(self) -> T;
Expand Down Expand Up @@ -56,3 +56,9 @@ impl Convert<aB256> for [u8; 32] {
aB256::new(self)
}
}

impl Convert<aB256> for eH256 {
fn convert(self) -> aB256 {
aB256::from_slice(self.as_fixed_bytes())
}
}
5 changes: 2 additions & 3 deletions ethereum/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ impl Contracts {
U1: Convert<U256>,
U2: Convert<U256>,
U3: Convert<U256>,
N: Convert<Uint<256, 4>>,
N: Convert<B256>,
S: Convert<B256>,
R: Convert<Address>,
P: Convert<Bytes>,
Expand Down Expand Up @@ -281,9 +281,8 @@ impl Contracts {
}

pub async fn is_message_processed(&self, nonce_le: [u8; 32]) -> Result<bool, Error> {
let nonce = U256::from_le_bytes(nonce_le);
let nonce = B256::from(nonce_le);

// TODO: Change isProcessed to accept only nonce.
let processed = self
.message_queue_instance
.isProcessed(ContentMessage {
Expand Down
9 changes: 4 additions & 5 deletions ethereum/src/MessageQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ contract MessageQueue is IMessageQueue {
using Address for address;
using Hasher for VaraMessage;

mapping(uint256 => bool) private _processed_messages;
mapping(bytes32 => bool) private _processed_messages;

/**
* @dev Unpack message from merkle tree and relay it to the receiver.
Expand All @@ -38,8 +38,7 @@ contract MessageQueue is IMessageQueue {
revert MessageAlreadyProcessed(message.nonce);

bytes32 msg_hash = message.hash();
bytes32 merkle_trie_leaf_hash = keccak256(abi.encodePacked(msg_hash));


bytes32 merkle_root = IRelayer(RELAYER_ADDRESS).getMerkleRoot(
block_number
);
Expand All @@ -49,7 +48,7 @@ contract MessageQueue is IMessageQueue {
if (
_calculateMerkleRoot(
proof,
merkle_trie_leaf_hash,
msg_hash,
total_leaves,
leaf_index
) != merkle_root
Expand Down Expand Up @@ -103,7 +102,7 @@ contract MessageQueue is IMessageQueue {
) internal pure returns (bytes32) {
bytes32 hash = leaf;

// TODO: Add check that index < width
assert(index < width);

for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
Expand Down
44 changes: 5 additions & 39 deletions ethereum/src/interfaces/IMessageQueue.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
pragma solidity ^0.8.24;

struct VaraMessage {
uint256 nonce;
bytes32 nonce;
bytes32 sender;
address receiver;
bytes data;
}

interface IMessageQueue {
error AlreadyInitialized();
error MessageAlreadyProcessed(uint256 messageNonce);
error MessageAlreadyProcessed(bytes32 messageNonce);
error MessageNotProcessed();
error MerkleRootNotSet(uint256 blockNumber);
error BadProof();
Expand All @@ -20,7 +20,7 @@ interface IMessageQueue {
event MessageProcessed(
uint256 indexed blockNumber,
bytes32 indexed messageHash,
uint256 indexed messageNonce
bytes32 indexed messageNonce
);

function calculateMerkleRoot(
Expand Down Expand Up @@ -50,45 +50,11 @@ library Hasher {
VaraMessage calldata message
) external pure returns (bytes32) {
bytes memory data = abi.encodePacked(
be_to_le(message.nonce),
message.nonce,
message.sender,
message.receiver,
message.data
);
return keccak256(data);
}

function be_to_le(uint256 input) internal pure returns (uint256 v) {
v = input;
v =
((v &
0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>
8) |
((v &
0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) <<
8);
v =
((v &
0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>
16) |
((v &
0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) <<
16);
v =
((v &
0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>
32) |
((v &
0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) <<
32);
v =
((v &
0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>
64) |
((v &
0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) <<
64);

v = (v >> 128) | (v << 128);
return keccak256(abi.encodePacked(keccak256(data)));
}
}
22 changes: 10 additions & 12 deletions ethereum/test/MessageQueue.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {ProxyContract} from "../src/ProxyContract.sol";
import {TestHelper, OWNER, USER, VARA_ADDRESS_3, VARA_ADDRESS_7, ETH_ADDRESS_3, ETH_ADDRESS_5} from "./TestHelper.t.sol";

import {ERC20Mock} from "../src/mocks/ERC20Mock.sol";

import {GRC_20_GATEWAY_ADDRESS} from "../src/libraries/Environment.sol";

contract MessageQueueTest is TestHelper {
using Address for address;
Expand Down Expand Up @@ -69,8 +69,6 @@ contract MessageQueueTest is TestHelper {

bytes memory proof = bytes(hex"203b6d7ee470fd6201aac1d849603241e3303f0ed38c6caeffeafa7708a700f0219f2065a8517c79e6c5dd7f3cf97709fea069f2e30787d283ea75461bcfb7231020f6d4cda614519936afcfd343abd4ec6620c722ca4ac82facdda42526927724e59115798dae55e08fbb386e18d9d843015168b94802845012f7943dd6e6560e90e844f40e7e20d1bbc1221f997cc57308601436354424e3ad38e5060dff630779a7b023f1af6923d9ec2d5f42ee311c387de28e24a5d4e689af858e8ff8b80182ca8d21874a644a26dafe33531d6f626aadd0436ff341ca72c5bad16506580c7e2ab7d32c38097c5ca47fe23bb118a75963b23ad671eff3edae03b30443ad28b05c94bb33b5dda0601a2e448e9bcff356a20aca2fca8548b3aa589d9ab3cf0661bc6e5fc4a2fd9cf752daa21d89c1c68300e0e6611d3461a6cf5b2111de14006cbc8af011601630a2940a972a880adfbe689f2bec6d53ecbda6a1408dece008702afebed1dbcf1be649d794abb58afac334310a248655ddba60e50076a05a206eaa36097d6572598071e178e79675c05ecf48bf64bb1fd19cb3df06c7c6af129bbdac42d8b090938ea97fc22f6cd607a44e168c625bf19254e1c4fe09b6a600b2f423299b72662a65ef56fce78a3ec88ade6ca54848619bf1da88764804b909d6f1e2d3e60e0b52622b64df9d56f5e743628b82c17a688be2b70cb37aef0211f854d5fa134e51a631225c700746d40ef9fdd8c10324949f4b50ab3ab25f5c1352fbaebb8b145be5c2f287899f0547d47254fd47a68ab2bdb4cfc6e9109d7a14d3b2e41225840451765085cd1799c88f270d6356e3a096cbf53a6f1c7838f5036e02246259487f2f340cd0d41ebe2b403e5596361f90c68fadde8aa891e7200b504aa7ff0b5dff127c695b0f7c33b4e1d4e57c03820ed492dc121796e096cc2ec27ee9037b56e0ca44693352ac335b687b757fdfb87136cfde7cf1865d54b9066ba8e5e9bdbf0fbdab7b1a02840ef1c415a51e74d9ef0812d9bd67e3a413b818d7fbab3649c5a5d8705d896f0a1a3b140d938486b99830c171108a862b0fa72e0943712e094e05cf1b5d50ee5422962bde5d533a4d7cc7ee7b2824148e71d81a3a3a8ec8091f8b52bc11ffe5189516441a01815250defe8d1e1e4150c4852c0ac274e45671a86b35be16b26f69bb60945f40e0caca8efbb998a268cf9db32927fd92d29a36c1b33d7bfe0540580c7a6628bcd28ead55135d8ad785b6e0424d1e870edf3353bad820bf5c7fa6e4fda335793fde58de57e062990001a8a30e07");



relayer.submitMerkleRoot(BLOCK_ID, BLOCK_MERKLE_ROOT, proof);
}

Expand Down Expand Up @@ -147,17 +145,17 @@ contract MessageQueueTest is TestHelper {
VaraMessage memory content_message = VaraMessage({
sender: VARA_ADDRESS_3,
receiver: ETH_ADDRESS_3,
nonce: 3,
nonce: bytes32(uint256(0x03)),
data: payload
});

bytes memory ms = abi.encodePacked(content_message.nonce, content_message.sender, content_message.receiver, content_message.data);


bytes32 expectedMessageHash = keccak256(ms);
bytes32 expectedMessageHash = keccak256(abi.encodePacked(keccak256(ms)));

bytes32 msg_hash = content_message.hash();
assertEq(msg_hash, bytes32(0xa366f34b585366d69a71c36c6831ec5d4588ff1fe04e8fb146865d86a9acead2));
assertEq(msg_hash, bytes32(0xe846804ca285c03c8923a0ed51340c4c29bcc7b005c5eeb7fb5b4b54a3f8bca5));

assertEq(expectedMessageHash, msg_hash);

Expand All @@ -166,7 +164,7 @@ contract MessageQueueTest is TestHelper {

bytes32 root = message_queue.calculateMerkleRoot(proof, expectedMessageHash, 3, 2);

assertEq(root, bytes32(0xf7ac03b7b0c8d3fecf2c7b3a9ce64d064ed0dff9912886ad2f1e51d2fc487367));
assertEq(root, bytes32(0xc739e5c26b49b1a0753fc66f21703ef508ecb53549290219fba0df2819d95aa0));
}

function test_calculate_root_buffer_leaf_2() public {
Expand Down Expand Up @@ -236,7 +234,7 @@ contract MessageQueueTest is TestHelper {
VaraMessage memory content_message = VaraMessage({
sender: VARA_ADDRESS_7,
receiver: ETH_ADDRESS_5,
nonce: 10,
nonce: bytes32(uint256(10)),
data: payload
});

Expand Down Expand Up @@ -266,14 +264,14 @@ contract MessageQueueTest is TestHelper {


VaraMessage memory vara_message = VaraMessage({
sender: VARA_ADDRESS_7,
sender: GRC_20_GATEWAY_ADDRESS,
receiver: address(treasury),
nonce: 10,
nonce: bytes32(uint256(10)),
data: withdraw_msg.pack()
});

bytes32 msg_hash = vara_message.hash();
assertEq(msg_hash, bytes32(0x450c549c1ab481d9e6c247d867086809f1c599a87218ba74a5ab04c2d70f387f));
assertEq(msg_hash, bytes32(0x0b391b6a39429a86fb9bac38e1c8b440e8aafb2cf12a3db4283d2fe652319a3f));


bytes32[] memory proof = new bytes32[](3);
Expand All @@ -286,7 +284,7 @@ contract MessageQueueTest is TestHelper {

bytes32 calculatedRoot = message_queue.calculateMerkleRoot(proof, msg_hash, 101, 100);

assertEq(calculatedRoot, bytes32(0x58b0eab7ac0e2a6f31eb89e3d2d2187d7aa623db11aa0d8cb513b93c4a21df2c));
assertEq(calculatedRoot, bytes32(0x5019b3be4a6a941f6698e74d5fc211ef381db0440d02b6669436e2aabf55b0b4));

bytes memory block_proof = bytes(hex"00");

Expand Down
4 changes: 2 additions & 2 deletions ethereum/test/TestHelper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import {ProxyContract} from "../src/ProxyContract.sol";

import {MessageQueue} from "../src/MessageQueue.sol";
import {ERC20Treasury} from "../src/ERC20Treasury.sol";
import {Verifier} from "../src/Verifier.sol";
import {Verifier} from "../src/mocks/VerifierMock.sol";
import {Relayer} from "../src/Relayer.sol";
import {ERC20Mock} from "../src/mocks/ERC20Mock.sol";

import {IVerifier} from "../src/interfaces/IVerifier.sol";


address constant OWNER = address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
address constant USER = address(0x34A1D3fff3958843C43aD80F30b94c510645C316);
address constant USER = address(0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496);

address constant ETH_ADDRESS_3 = address(0x0303030303030303030303030303030303030303);

Expand Down
6 changes: 3 additions & 3 deletions ethereum/test/Treasury.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {ProxyContract} from "../src/ProxyContract.sol";
import {ERC20Mock} from "../src/mocks/ERC20Mock.sol";

import {TestHelper, VARA_ADDRESS_3, VARA_ADDRESS_7, USER, OWNER} from "./TestHelper.t.sol";

import {GRC_20_GATEWAY_ADDRESS} from "../src/libraries/Environment.sol";

contract TreasuryTest is TestHelper {
using Address for address;
Expand Down Expand Up @@ -51,9 +51,9 @@ contract TreasuryTest is TestHelper {
vm.expectRevert();

VaraMessage memory vara_msg = VaraMessage({
sender: VARA_ADDRESS_7,
sender: GRC_20_GATEWAY_ADDRESS,
receiver: address(treasury),
nonce: 10,
nonce: bytes32(uint256(10)),
data: call_data
});

Expand Down
2 changes: 1 addition & 1 deletion ethereum/test/Verifier.t.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity ^0.8.24;

import {Test, console} from "forge-std/Test.sol";
import {Verifier} from "../src/Verifier.sol";
import {Verifier} from "../src/mocks/VerifierMock.sol";

contract VerifierTest is Test {

Expand Down
5 changes: 2 additions & 3 deletions relayer/src/message_relayer/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{

use ethereum_client::{Contracts as EthApi, TxHash, TxStatus};
use gear_rpc_client::{dto::Message, GearApi};
use primitive_types::H256;
use prometheus::{IntCounter, IntGauge};

use crate::metrics::{impl_metered_service, MeteredService};
Expand Down Expand Up @@ -291,9 +292,7 @@ impl Era {
let tx = &mut self.pending_txs[tx];
let status = eth_api.get_tx_status(tx.hash).await?;

// TODO: Fully decode
let nonce_bytes: &_ = &tx.message.nonce_le[..16];
let nonce = u128::from_le_bytes(nonce_bytes.try_into()?);
let nonce = H256::from(tx.message.nonce_le);

match status {
TxStatus::Finalized => {
Expand Down
3 changes: 1 addition & 2 deletions relayer/src/message_relayer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ async fn submit_message(
.await?;

// TODO: Fully decode
let nonce_bytes = &message.nonce_le[..16];
let nonce = u128::from_le_bytes(nonce_bytes.try_into()?);
let nonce = H256::from(message.nonce_le);

let tx_hash = eth_api
.provide_content_message(
Expand Down

0 comments on commit d42251c

Please sign in to comment.