diff --git a/.github/workflows/release-relayer.yml b/.github/workflows/release-relayer.yml index 7ea4a56521..2e5910de4c 100644 --- a/.github/workflows/release-relayer.yml +++ b/.github/workflows/release-relayer.yml @@ -7,6 +7,10 @@ on: - release-v1.0.0 workflow_dispatch: +env: + REGISTRY: ghcr.io + IMAGE_NAME: snowfork/snowbridge-relay + jobs: release-relayer: runs-on: snowbridge-runner @@ -19,12 +23,12 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v2 with: - node-version: '14' + node-version: "14" - name: Setup go uses: actions/checkout@v4 with: - go-version: '^1.21.0' + go-version: "^1.21.0" - name: Install Go tools run: > @@ -68,7 +72,7 @@ jobs: # Get the most recent tag in the format relayer-<branchname>-<version> current_version=$(git tag --list "relayer-${{ steps.branch_name.outputs.branch }}-*" --sort=-v:refname | head -n 1 | sed -E 's/relayer-${{ steps.branch_name.outputs.branch }}-//') echo "Current version: $current_version" - + # If there is no current version, set it to 1.0.0 if [ -z "$current_version" ]; then new_version="1.0.0" @@ -117,3 +121,17 @@ jobs: asset_path: ./relayer/build/snowbridge-relay asset_name: snowbridge-relay asset_content_type: application/octet-stream + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: ./relayer + push: true + tags: ${{ steps.create_tag.outputs.tag }} diff --git a/relayer/.dockerignore b/relayer/.dockerignore index 722d5e71d9..6f27dc31ad 100644 --- a/relayer/.dockerignore +++ b/relayer/.dockerignore @@ -1 +1,2 @@ .vscode +.env diff --git a/relayer/.env.example b/relayer/.env.example new file mode 100644 index 0000000000..8084fb3478 --- /dev/null +++ b/relayer/.env.example @@ -0,0 +1,6 @@ +PARACHAIN_RELAY_ASSETHUB_ETH_KEY= +EXECUTION_RELAY_ASSETHUB_SUB_KEY= +CONFIG_DIR=/tmp/snowbridge +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_REGION=eu-central-1 diff --git a/relayer/.gitignore b/relayer/.gitignore index 10f3f2330f..2299552e47 100644 --- a/relayer/.gitignore +++ b/relayer/.gitignore @@ -2,3 +2,4 @@ /.envrc build/ .vscode/ +.env diff --git a/relayer/Dockerfile b/relayer/Dockerfile index bd36948d25..db94c72bad 100644 --- a/relayer/Dockerfile +++ b/relayer/Dockerfile @@ -1,8 +1,9 @@ -FROM golang:1.14 +FROM golang:1.21 WORKDIR /opt/relayer ADD . . RUN go build -v -o build/snowbridge-relay main.go -FROM parity/subkey:2.0.0 +FROM ubuntu:22.04 COPY --from=0 /opt/relayer/build/snowbridge-relay /usr/local/bin/ +VOLUME ["/config"] ENTRYPOINT ["/usr/local/bin/snowbridge-relay"] diff --git a/relayer/README.md b/relayer/README.md index 32f6d88fbc..9616997262 100644 --- a/relayer/README.md +++ b/relayer/README.md @@ -55,6 +55,7 @@ Note: For local development and testing, we use our E2E test stack described [he For an example configuration, please consult the [setup script](https://github.com/Snowfork/snowbridge/blob/main/web/packages/test/scripts/start-services.sh) for our local development stack. Specifically the `start_relayer` bash function. + ## Tests To run both unit and integration tests, start a local E2E test stack and run the following command: @@ -62,3 +63,76 @@ To run both unit and integration tests, start a local E2E test stack and run the ```bash mage test ``` + +## Running + +### Run message relayer with multiple instances + +Configuration required for different relayers to coordinate. Take `execution-relay` which relayes message from Ethereum to AssetHub for example, assuming there are 3 instances deployed: + + +`execution-relay-asset-hub-0.json` + +``` + +{ + ... + "schedule": { + "id": 0, + "totalRelayerCount": 3, + "sleepInterval": 20 + } +} + +``` + +`execution-relay-asset-hub-1.json` + +``` + +{ + ... + "schedule": { + "id": 1, + "totalRelayerCount": 3, + "sleepInterval": 20 + } +} + +``` + +`execution-relay-asset-hub-2.json` + +``` + +{ + ... + "schedule": { + "id": 2, + "totalRelayerCount": 3, + "sleepInterval": 20 + } +} + +``` + +- id: ID of current relayer(start from 0) +- totalRelayerCount: Number of total count of all relayers +- sleepInterval: Sleep interval(in seconds) to check if message(nonce) has already been relayed + +The configuration above applies also to multiple instances of `parachain-relay` which relayes message from AssetHub to Ethereum. + + +### Cost Analysis + +#### Running Ethereum message relayer + +For Ethereum message relayer take [extrinsic](https://bridgehub-polkadot.subscan.io/extrinsic/3264574-2) for example: + +As we can see it will cost 0.041163771 DOT as transaction fee and the reward is 0.053783 DOT, so it's about 0.012 DOT as incentive for each message. + +#### Running Parachain message relayer + +For Parachain message relayer take [transaction]( https://dashboard.tenderly.co/snowfork/snowbridge-polkadot/tx/1/0x2dbcf28f8d80c43acd3f08e15b0ec2e3c2c8a929d50e0cba2e3bba5d39738bce) for example: + +As we can see it will cost 0.000628 ETH as transaction fee and the reward is 0.000942 ETH, so it's about 0.0003 ETH as incentive for each message. diff --git a/relayer/docker-compose.yml b/relayer/docker-compose.yml new file mode 100644 index 0000000000..13b653143c --- /dev/null +++ b/relayer/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3" + +services: + execution-assethub: + platform: linux/amd64 + image: ghcr.io/snowfork/snowbridge-relay + build: + context: . + command: run execution --config /config/execution-relay-asset-hub-0.json --substrate.private-key ${EXECUTION_RELAY_ASSETHUB_SUB_KEY} + volumes: + - ${CONFIG_DIR}:/config + env_file: + - .env + restart: on-failure + + parachain-assethub: + platform: linux/amd64 + image: ghcr.io/snowfork/snowbridge-relay + command: run parachain --config /config/parachain-relay-asset-hub-0.json --ethereum.private-key ${PARACHAIN_RELAY_ASSETHUB_ETH_KEY} + volumes: + - ${CONFIG_DIR}:/config + env_file: + - .env + restart: on-failure diff --git a/relayer/start-relayer-in-docker.sh b/relayer/start-relayer-in-docker.sh new file mode 100755 index 0000000000..f6558cbcf0 --- /dev/null +++ b/relayer/start-relayer-in-docker.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +set -eu + +source ../web/packages/test/scripts/set-env.sh + +start_relayer() +{ + docker compose up -d +} + +stop_relayer() +{ + docker compose down +} + +build_image() +{ + docker build -f Dockerfile -t snowbridge-relayer . +} + +if [ -z "${from_start_services:-}" ]; then + echo "start relayers only!" + trap kill_all SIGINT SIGTERM EXIT + start_relayer + wait +fi diff --git a/web/packages/test/scripts/deploy-ethereum.sh b/web/packages/test/scripts/deploy-ethereum.sh index e91846437f..b96ad21213 100755 --- a/web/packages/test/scripts/deploy-ethereum.sh +++ b/web/packages/test/scripts/deploy-ethereum.sh @@ -20,6 +20,7 @@ start_geth() { --miner.etherbase=0xBe68fC2d8249eb60bfCf0e71D5A0d2F2e292c4eD \ --authrpc.addr="127.0.0.1" \ --http.addr="0.0.0.0" \ + --ws.addr="0.0.0.0" \ --http.corsdomain '*' \ --allow-insecure-unlock \ --authrpc.jwtsecret config/jwtsecret \ @@ -58,6 +59,7 @@ start_lodestar() { --genesisTime $timestamp \ --startValidators "0..7" \ --enr.ip6 "127.0.0.1" \ + --rest.address "0.0.0.0" \ --eth1.providerUrls "http://127.0.0.1:8545" \ --execution.urls "http://127.0.0.1:8551" \ --dataDir "$ethereum_data_dir" \