Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ethereum: Move relayer #3866

Merged
merged 12 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
/bitcoin/ @evan-gray
/cosmwasm/ @nik-suri @kcsongor @a5-pickle
/ethereum/ @a5-pickle @gator-boi @kcsongor
/ethereum/contracts/relayer @nonergodic @gator-boi
/ethereum/contracts/interfaces/relayer @nonergodic @gator-boi
/ethereum/forge-test/relayer @nonergodic @gator-boi
/ethereum/ts-scripts/relayer @nonergodic @gator-boi
/relayer/ethereum @nonergodic @gator-boi
/near/ @evan-gray @kcsongor
/solana/ @kcsongor @a5-pickle
/sui/ @kcsongor @a5-pickle @gator-boi
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ jobs:
uses: foundry-rs/foundry-toolchain@v1
- run: cd ethereum && make test-push0 && make test

relayer-ethereum:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "16"
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- run: cd relayer/ethereum && make test-push0 && make test

ethereum-upgrade:
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -316,7 +327,7 @@ jobs:
- uses: streetsidesoftware/cspell-action@214db1e3138f326d33b7a6a51c92852e89ab0618
with:
# For now, only lint markdown files
files: '**/*.md'
files: "**/*.md"
inline: warning
# Only check files in the PR or push
incremental_files_only: true
Expand Down
7 changes: 4 additions & 3 deletions Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -458,11 +458,12 @@ if solana or pythnet:

docker_build(
ref = "eth-node",
context = "./ethereum",
context = ".",
only = ["./ethereum", "./relayer/ethereum"],
dockerfile = "./ethereum/Dockerfile",

# ignore local node_modules (in case they're present)
ignore = ["./node_modules"],
ignore = ["./ethereum/node_modules","./relayer/ethereum/node_modules"],
build_args = {"num_guardians": str(num_guardians), "dev": str(not ci)},

# sync external scripts for incremental development
Expand Down Expand Up @@ -522,7 +523,7 @@ if generic_relayer:
docker_build(
ref = "relayer-engine",
context = ".",
only = ["./relayer/generic_relayer", "./ethereum/ts-scripts/relayer/config"],
only = ["./relayer/generic_relayer", "./relayer/ethereum/ts-scripts/relayer/config"],
dockerfile = "relayer/generic_relayer/relayer-engine-v2/Dockerfile",
build_args = {"dev": str(not ci)}
)
Expand Down
4 changes: 2 additions & 2 deletions devnet/eth-devnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ spec:
command:
- /bin/sh
- -c
- "npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_all_chains.js && npm run deploy-relayers-evm1 && nc -lkn 2000"
- "cd ../../ethereum && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_all_chains.js && cd ../relayer/ethereum && npm run deploy-relayers-evm1 && nc -lkn 2000"
readinessProbe:
periodSeconds: 1
failureThreshold: 300
Expand All @@ -69,6 +69,6 @@ spec:
command:
- /bin/sh
- -c
- "npx truffle exec mine.js"
- "cd ../../ethereum && npx truffle exec mine.js"
---

4 changes: 2 additions & 2 deletions devnet/eth-devnet2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ spec:
command:
- /bin/sh
- -c
- "sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g;s/EVM_CHAIN_ID=1337/EVM_CHAIN_ID=1397/g' .env && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_all_chains.js && npm run deploy-relayers-evm2 && nc -lkn 2000"
- "cd ../../ethereum && sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g;s/EVM_CHAIN_ID=1337/EVM_CHAIN_ID=1397/g' .env && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_all_chains.js && cd ../relayer/ethereum && sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g;s/EVM_CHAIN_ID=1337/EVM_CHAIN_ID=1397/g' .env && npm run deploy-relayers-evm2 && nc -lkn 2000"
readinessProbe:
periodSeconds: 1
failureThreshold: 300
Expand All @@ -70,4 +70,4 @@ spec:
command:
- /bin/sh
- -c
- "npx truffle exec mine.js"
- "cd ../../ethereum && npx truffle exec mine.js"
30 changes: 26 additions & 4 deletions ethereum/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ WORKDIR /home/node/app
# Fix git ssh error
RUN git config --global url."https://".insteadOf ssh://

WORKDIR /home/node/app
WORKDIR /home/node/app/ethereum

# Only invalidate the npm install step if package.json changed
COPY --chown=node:node package.json .
COPY --chown=node:node package-lock.json .
COPY --chown=node:node ethereum/package.json .
COPY --chown=node:node ethereum/package-lock.json .
COPY --from=const-export --chown=node:node .env.0x .env


Expand All @@ -49,7 +49,29 @@ RUN rm -rf node_modules && mv node_modules_cache node_modules
ARG dev
ENV DEV=$dev

COPY --chown=node:node . .
COPY --chown=node:node ethereum .
RUN make build

### RELAYER ###

WORKDIR /home/node/app/relayer/ethereum

COPY --chown=node:node relayer/ethereum/package.json .
COPY --chown=node:node relayer/ethereum/package-lock.json .
COPY --from=const-export --chown=node:node .env.0x .env


RUN --mount=type=cache,uid=1000,gid=1000,target=/home/node/.npm \
--mount=type=cache,uid=1000,gid=1000,target=node_modules \
npm ci && \
cp -R node_modules node_modules_cache

RUN rm -rf node_modules && mv node_modules_cache node_modules

ARG dev
ENV DEV=$dev

COPY --chown=node:node relayer/ethereum .
RUN make build

ARG num_guardians
Expand Down
7 changes: 2 additions & 5 deletions ethereum/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
"scripts": {
"build:core": "truffle compile",
"build:forge": "if [ \"$DEV\" = \"True\" ]; then forge build; else forge build --via-ir; fi",
"build": "npm run build:core && npm run build:forge && typechain --target=ethers-v5 --out-dir=./ethers-contracts \"build-forge/!(test).sol/*.json\"&& npm run erase-types",
"erase-types": "ts-node ./ts-scripts/relayer/eraseTypes.ts ./contracts/interfaces/relayer/IDeliveryProviderTyped.sol ./contracts/interfaces/relayer/IWormholeRelayerTyped.sol",
"build": "npm run build:core && npm run build:forge && typechain --target=ethers-v5 --out-dir=./ethers-contracts \"build-forge/!(test).sol/*.json\"",
"test": "npm run build:core && mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle test --network test --compile-none",
"migrate": "npm run build:core && mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --to 4 --compile-none",
"deploy-bridge-implementation-only": "npm run build:core && mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --f 6 --to 6 --compile-none",
Expand All @@ -31,10 +30,8 @@
"verify": "patch -u -f node_modules/truffle-plugin-verify/constants.js -i truffle-verify-constants.patch; truffle run verify $npm_config_module@$npm_config_contract_address --network $npm_config_network",
"verify-token": "patch -u -f node_modules/truffle-plugin-verify/constants.js -i truffle-verify-constants.patch; truffle run verify BridgeToken@$npm_config_contract_address --forceConstructorArgs string:$npm_config_constructor_args --network $npm_config_network",
"abigen": "truffle run abigen",
"deploy-relayers-evm1": "ENV=kubernetes CONTAINER=evm1 bash ./ts-scripts/relayer/shell/deployInContainer.sh",
"deploy-relayers-evm2": "ENV=kubernetes CONTAINER=evm2 bash ./ts-scripts/relayer/shell/deployInContainer.sh",
"typecheck": "tsc --noEmit --skipLibCheck"
},
},
"author": "",
"license": "ISC",
"dependencies": {
Expand Down
4 changes: 4 additions & 0 deletions relayer/ethereum/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
build-forge/
cache
ethers-contracts
lib
48 changes: 48 additions & 0 deletions relayer/ethereum/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
SOURCE_FILES:=$(shell find contracts -name "*.sol")

.PHONY: dependencies test clean all

all: build

node_modules: package-lock.json
touch -m node_modules
npm ci

# Note: Forge really wants to manage dependencies via submodules, but that
# workflow is a little awkward. There's currently no support for a more
# traditional package manager workflow (with a package manifest file and
# installation into a subdirectory that can be gitignored).
# Instead, we just specify the dependencies here. make will then take care of
# installing them if they are not yet present.
# When adding a new dependency, make sure to specify the exact commit hash, and
# the --no-git and --no-commit flags (see lib/forge-std below)
.PHONY: forge_dependencies
forge_dependencies: lib/forge-std lib/openzeppelin-contracts

lib/forge-std:
forge install foundry-rs/[email protected] --no-git --no-commit

lib/openzeppelin-contracts:
forge install openzeppelin/openzeppelin-contracts@0457042d93d9dfd760dbaa06a4d2f1216fdbe297 --no-git --no-commit

dependencies: node_modules forge_dependencies

build: forge_dependencies node_modules ${SOURCE_FILES}
npm run build

.env: .env.test
cp $< $@

test: test-forge

.PHONY:
test-forge: dependencies
forge test --no-match-test .*_KEVM # ignore KEVM tests (see PROOFS.md)

# Verify that the contracts do not include PUSH0 opcodes
test-push0: dependencies
forge build --extra-output evm.bytecode.opcodes
@if grep -qr --include \*.json PUSH0 ./build-forge; then echo "Contract uses PUSH0 instruction" 1>&2; exit 1; fi

clean:
rm -rf .env node_modules build-forge ethers-contracts lib/forge-std lib/openzeppelin-contracts
39 changes: 39 additions & 0 deletions relayer/ethereum/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Relayer - Ethereum Contracts

These smart contracts allow for relaying on EVM chains.

### Dependencies

The relayer contracts are built with Forge. See below for details on installing forge.

For the required version of `solc`, the required EVM version and the solidity library dependencies see the [config file](foundry.toml)

### Building

To build the contracts do:

```sh
wormhole/relayer/ethereum$ make build
```

### Deploying

For details on deploying the relayer contracts see the scripts [readme](ts-scripts/relayer/README.md).

### Testing

The tests for the relayer contracts reside in `forge-test`. To run the tests do:

```sh
wormhole/relayer/ethereum$ forge test
```

### Installing Forge

Some tests and scripts use [Foundry](https://getfoundry.sh/). It can be installed via the official installer, or by running

```sh
wormhole/relayer/ethereum$ ../../scripts/install-foundry
```

The installer script installs foundry and the appropriate solc version to build the contracts.
142 changes: 142 additions & 0 deletions relayer/ethereum/contracts/interfaces/IWormhole.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// contracts/Messages.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

interface IWormhole {
struct GuardianSet {
address[] keys;
uint32 expirationTime;
}

struct Signature {
bytes32 r;
bytes32 s;
uint8 v;
uint8 guardianIndex;
}

struct VM {
uint8 version;
uint32 timestamp;
uint32 nonce;
uint16 emitterChainId;
bytes32 emitterAddress;
uint64 sequence;
uint8 consistencyLevel;
bytes payload;

uint32 guardianSetIndex;
Signature[] signatures;

bytes32 hash;
}

struct ContractUpgrade {
bytes32 module;
uint8 action;
uint16 chain;

address newContract;
}

struct GuardianSetUpgrade {
bytes32 module;
uint8 action;
uint16 chain;

GuardianSet newGuardianSet;
uint32 newGuardianSetIndex;
}

struct SetMessageFee {
bytes32 module;
uint8 action;
uint16 chain;

uint256 messageFee;
}

struct TransferFees {
bytes32 module;
uint8 action;
uint16 chain;

uint256 amount;
bytes32 recipient;
}

struct RecoverChainId {
bytes32 module;
uint8 action;

uint256 evmChainId;
uint16 newChainId;
}

event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel);
event ContractUpgraded(address indexed oldContract, address indexed newContract);
event GuardianSetAdded(uint32 indexed index);

function publishMessage(
uint32 nonce,
bytes memory payload,
uint8 consistencyLevel
) external payable returns (uint64 sequence);

function initialize() external;

function parseAndVerifyVM(bytes calldata encodedVM) external view returns (VM memory vm, bool valid, string memory reason);

function verifyVM(VM memory vm) external view returns (bool valid, string memory reason);

function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason);

function parseVM(bytes memory encodedVM) external pure returns (VM memory vm);

function quorum(uint numGuardians) external pure returns (uint numSignaturesRequiredForQuorum);

function getGuardianSet(uint32 index) external view returns (GuardianSet memory);

function getCurrentGuardianSetIndex() external view returns (uint32);

function getGuardianSetExpiry() external view returns (uint32);

function governanceActionIsConsumed(bytes32 hash) external view returns (bool);

function isInitialized(address impl) external view returns (bool);

function chainId() external view returns (uint16);

function isFork() external view returns (bool);

function governanceChainId() external view returns (uint16);

function governanceContract() external view returns (bytes32);

function messageFee() external view returns (uint256);

function evmChainId() external view returns (uint256);

function nextSequence(address emitter) external view returns (uint64);

function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu);

function parseGuardianSetUpgrade(bytes memory encodedUpgrade) external pure returns (GuardianSetUpgrade memory gsu);

function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf);

function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf);

function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci);

function submitContractUpgrade(bytes memory _vm) external;

function submitSetMessageFee(bytes memory _vm) external;

function submitNewGuardianSet(bytes memory _vm) external;

function submitTransferFees(bytes memory _vm) external;

function submitRecoverChainId(bytes memory _vm) external;
}
Loading
Loading