diff --git a/.gitignore b/.gitignore index 567609b..e660fd9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -build/ +bin/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..137d9c6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lcp"] + path = lcp + url = https://github.com/datachainlab/lcp diff --git a/Makefile b/Makefile index c104233..ee66923 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,14 @@ protoVer=0.13.1 protoImageName=ghcr.io/cosmos/proto-builder:$(protoVer) protoImage=docker run --user 0 --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) +.PHONY: yrly +yrly: + go build -o ./bin/yrly -tags customcert ./relay/bin + +.PHONY: lcp +lcp: + $(MAKE) -C ./lcp -B && mv ./lcp/bin/* ./bin/ + .PHONY: proto-gen proto-update-deps proto-gen: @echo "Generating Protobuf files" diff --git a/README.md b/README.md index 645fae1..a8c820e 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,4 @@ lcp-go includes the followings: ## Compatibility - [lcp v0.2.2](https://github.com/datachainlab/lcp/releases/tag/v0.2.2) -- [ibc v7.2](https://github.com/cosmos/ibc-go/releases/tag/v7.2.0). +- [ibc-go v7.2](https://github.com/cosmos/ibc-go/releases/tag/v7.2.0). diff --git a/lcp b/lcp new file mode 160000 index 0000000..c073f89 --- /dev/null +++ b/lcp @@ -0,0 +1 @@ +Subproject commit c073f89517fcdc4f796c07ad420b0029bbc148db diff --git a/scripts/run_e2e_test.sh b/scripts/run_e2e_test.sh new file mode 100755 index 0000000..b7d5cc2 --- /dev/null +++ b/scripts/run_e2e_test.sh @@ -0,0 +1,27 @@ +#!/bin/sh +set -ex + +LCP_BIN=./bin/lcp +ENCLAVE_PATH=./bin/enclave.signed.so +CERTS_DIR=./lcp/tests/certs + +rm -rf ~/.lcp + +enclave_key=$(${LCP_BIN} --log_level=off enclave generate-key --enclave=${ENCLAVE_PATH}) +./tests/e2e/scripts/gen_rly_config.sh + +if [ -z "$SGX_MODE" -o "$SGX_MODE" = "HW" ]; then + ./bin/lcp attestation ias --enclave=${ENCLAVE_PATH} --enclave_key=${enclave_key} +else + ./bin/lcp attestation simulate --enclave=${ENCLAVE_PATH} --enclave_key=${enclave_key} --signing_cert_path=${CERTS_DIR}/signing.crt.der --signing_key=${CERTS_DIR}/signing.key + export LCP_RA_ROOT_CERT_HEX=$(cat ${CERTS_DIR}/root.crt | xxd -p -c 1000000) +fi + +./bin/lcp --log_level=info service start --enclave=${ENCLAVE_PATH} --address=127.0.0.1:50051 --threads=2 & +LCP_PID=$! + +make -C tests/e2e/cases/tm2tm network +sleep 3 +make -C tests/e2e/cases/tm2tm test +make -C tests/e2e/cases/tm2tm network-down +kill $LCP_PID diff --git a/tests/e2e/cases/docker-compose-test.yaml b/tests/e2e/cases/docker-compose-test.yaml new file mode 100644 index 0000000..b442d96 --- /dev/null +++ b/tests/e2e/cases/docker-compose-test.yaml @@ -0,0 +1,41 @@ +version: '3.5' + +networks: + relayer-e2e: + name: &network-common relayer-e2e + +services: + tendermint-chain0: + container_name: tendermint-chain0 + image: tendermint-chain0:${TAG} + environment: + - LCP_RA_ROOT_CERT_HEX=${LCP_RA_ROOT_CERT_HEX} + ports: + - 26656:26656 + - 26657:26657 + - 6060:6060 + - 9090:9090 + healthcheck: + test: "wget -q -O - http://localhost:26657/health || exit 1" + interval: 30s + timeout: 10s + retries: 5 + networks: + - *network-common + tendermint-chain1: + container_name: tendermint-chain1 + image: tendermint-chain1:${TAG} + environment: + - LCP_RA_ROOT_CERT_HEX=${LCP_RA_ROOT_CERT_HEX} + ports: + - 26566:26656 + - 26557:26657 + - 6061:6060 + - 9091:9090 + healthcheck: + test: "wget -q -O - http://localhost:26657/health || exit 1" + interval: 30s + timeout: 10s + retries: 5 + networks: + - *network-common diff --git a/tests/e2e/cases/tm2tm/.gitignore b/tests/e2e/cases/tm2tm/.gitignore new file mode 100644 index 0000000..67fc140 --- /dev/null +++ b/tests/e2e/cases/tm2tm/.gitignore @@ -0,0 +1 @@ +fixtures/ diff --git a/tests/e2e/cases/tm2tm/Makefile b/tests/e2e/cases/tm2tm/Makefile new file mode 100644 index 0000000..c50a2da --- /dev/null +++ b/tests/e2e/cases/tm2tm/Makefile @@ -0,0 +1,27 @@ +DOCKER ?= docker +DOCKER_COMPOSE ?= docker compose +DOCKER_REPO ?= "" +DOCKER_TAG ?= latest +DOCKER_BUILD ?= $(DOCKER) build --rm --no-cache --pull + +RLY_BIN ?= ../../../../bin/yrly + +.PHONY: network +network: + TAG=${DOCKER_TAG} $(DOCKER_COMPOSE) \ + -f ../docker-compose-test.yaml \ + up -d \ + tendermint-chain0 tendermint-chain1 + +.PHONY: network-down +network-down: + TAG=${DOCKER_TAG} $(DOCKER_COMPOSE) \ + -f ../docker-compose-test.yaml \ + down --volumes --remove-orphans + +.PHONY: test +test: + ./scripts/fixture + RLY_BIN=$(RLY_BIN) ./scripts/init-rly + RLY_BIN=$(RLY_BIN) ./scripts/handshake + RLY_BIN=$(RLY_BIN) ./scripts/test-tx diff --git a/tests/e2e/cases/tm2tm/README.md b/tests/e2e/cases/tm2tm/README.md new file mode 100644 index 0000000..7142d2e --- /dev/null +++ b/tests/e2e/cases/tm2tm/README.md @@ -0,0 +1,7 @@ +## Usage + +```shell +$ make network +$ make test +$ make network-down +``` diff --git a/tests/e2e/cases/tm2tm/configs/.gitignore b/tests/e2e/cases/tm2tm/configs/.gitignore new file mode 100644 index 0000000..40e41d2 --- /dev/null +++ b/tests/e2e/cases/tm2tm/configs/.gitignore @@ -0,0 +1 @@ +demo/*.json diff --git a/tests/e2e/cases/tm2tm/configs/README.md b/tests/e2e/cases/tm2tm/configs/README.md new file mode 100644 index 0000000..76890df --- /dev/null +++ b/tests/e2e/cases/tm2tm/configs/README.md @@ -0,0 +1,4 @@ +# Demo configs + +**WARNING** These configurations are intended only for testing and development. +You must modify them for your environment and security level in production. diff --git a/tests/e2e/cases/tm2tm/configs/path.json b/tests/e2e/cases/tm2tm/configs/path.json new file mode 100644 index 0000000..f8e0b89 --- /dev/null +++ b/tests/e2e/cases/tm2tm/configs/path.json @@ -0,0 +1,23 @@ +{ + "src": { + "chain-id": "ibc0", + "client-id": "lcp-client-0", + "connection-id": "connection-0", + "channel-id": "channel-0", + "port-id": "transfer", + "order": "unordered", + "version": "ics20-1" + }, + "dst": { + "chain-id": "ibc1", + "client-id": "lcp-client-0", + "connection-id": "connection-0", + "channel-id": "channel-0", + "port-id": "transfer", + "order": "unordered", + "version": "ics20-1" + }, + "strategy": { + "type": "naive" + } +} diff --git a/tests/e2e/cases/tm2tm/configs/templates/ibc-0.json.tpl b/tests/e2e/cases/tm2tm/configs/templates/ibc-0.json.tpl new file mode 100644 index 0000000..60f433a --- /dev/null +++ b/tests/e2e/cases/tm2tm/configs/templates/ibc-0.json.tpl @@ -0,0 +1,24 @@ +{ + "chain": { + "@type": "/relayer.chains.tendermint.config.ChainConfig", + "key": "testkey", + "chain_id": "ibc0", + "rpc_addr": "http://localhost:26657", + "account_prefix": "cosmos", + "gas_adjustment": 1.5, + "gas_prices": "0.025stake" + }, + "prover": { + "@type": "/relayer.provers.lcp.config.ProverConfig", + "origin_prover": { + "@type": "/relayer.chains.tendermint.config.ProverConfig", + "trusting_period": "336h" + }, + "lcp_service_address": "localhost:50051", + "mrenclave": "$MRENCLAVE", + "allowed_quote_statuses": ["GROUP_OUT_OF_DATE"], + "allowed_advisory_ids": ["INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00614","INTEL-SA-00615","INTEL-SA-00617"], + "key_expiration": 604800, + "elc_client_id": "07-tendermint-1" + } +} diff --git a/tests/e2e/cases/tm2tm/configs/templates/ibc-1.json.tpl b/tests/e2e/cases/tm2tm/configs/templates/ibc-1.json.tpl new file mode 100644 index 0000000..04e630e --- /dev/null +++ b/tests/e2e/cases/tm2tm/configs/templates/ibc-1.json.tpl @@ -0,0 +1,24 @@ +{ + "chain": { + "@type": "/relayer.chains.tendermint.config.ChainConfig", + "key": "testkey", + "chain_id": "ibc1", + "rpc_addr": "http://localhost:26557", + "account_prefix": "cosmos", + "gas_adjustment": 1.5, + "gas_prices": "0.025stake" + }, + "prover": { + "@type": "/relayer.provers.lcp.config.ProverConfig", + "origin_prover": { + "@type": "/relayer.chains.tendermint.config.ProverConfig", + "trusting_period": "336h" + }, + "lcp_service_address": "localhost:50051", + "mrenclave": "$MRENCLAVE", + "allowed_quote_statuses": ["GROUP_OUT_OF_DATE"], + "allowed_advisory_ids": ["INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00614","INTEL-SA-00615","INTEL-SA-00617"], + "key_expiration": 604800, + "elc_client_id": "07-tendermint-0" + } +} diff --git a/tests/e2e/cases/tm2tm/scripts/fixture b/tests/e2e/cases/tm2tm/scripts/fixture new file mode 100755 index 0000000..027823a --- /dev/null +++ b/tests/e2e/cases/tm2tm/scripts/fixture @@ -0,0 +1,18 @@ +#!/bin/bash +set -eu + +DOCKER=docker +SCRIPT_DIR=$(cd $(dirname $0); pwd) +FIXTURES_DIR=${SCRIPT_DIR}/../fixtures + +## Setup test fixtures + +set +x +rm -rf ${FIXTURES_DIR} +mkdir -p ${FIXTURES_DIR}/tendermint/ibc0 +mkdir -p ${FIXTURES_DIR}/tendermint/ibc1 +set -x + +## copy tendermint's node mnemonic from node container +${DOCKER} cp tendermint-chain0:/root/data/ibc0/key_seed.json ${FIXTURES_DIR}/tendermint/ibc0/key_seed.json +${DOCKER} cp tendermint-chain1:/root/data/ibc1/key_seed.json ${FIXTURES_DIR}/tendermint/ibc1/key_seed.json diff --git a/tests/e2e/cases/tm2tm/scripts/handshake b/tests/e2e/cases/tm2tm/scripts/handshake new file mode 100755 index 0000000..3e5545a --- /dev/null +++ b/tests/e2e/cases/tm2tm/scripts/handshake @@ -0,0 +1,49 @@ +#!/bin/bash + +set -eux + +retry() { + local -r -i max_attempts="$1"; shift + local -r cmd="$@" + local -i attempt_num=1 + + until $cmd + do + if (( attempt_num == max_attempts )) + then + echo "Attempt $attempt_num failed and there are no more attempts left!" + return 1 + else + echo "Attempt $attempt_num failed! Trying again in $attempt_num seconds..." + sleep $(( attempt_num++ )) + fi + done +} + +RLY="${RLY_BIN} --debug" + +CHAINID_ONE=ibc0 +RLYKEY=testkey +CHAINID_TWO=ibc1 +PATH_NAME=ibc01 + +$RLY tendermint keys show $CHAINID_ONE $RLYKEY +$RLY tendermint keys show $CHAINID_TWO $RLYKEY + +# initialize the light client for {{chain_id}} +retry 5 $RLY lcp-tendermint light init $CHAINID_ONE -f +retry 5 $RLY lcp-tendermint light init $CHAINID_TWO -f + +# add a path between chain0 and chain1 +$RLY paths add $CHAINID_ONE $CHAINID_TWO $PATH_NAME --file=./configs/path.json + +retry 5 $RLY tx clients $PATH_NAME +sleep 3 +retry 5 $RLY lcp update-enclave-key $PATH_NAME --src=true +retry 5 $RLY lcp update-enclave-key $PATH_NAME --src=false +sleep 3 +retry 5 $RLY lcp activate-client $PATH_NAME --src=true +retry 5 $RLY lcp activate-client $PATH_NAME --src=false +sleep 3 +retry 5 $RLY tx connection $PATH_NAME +retry 5 $RLY tx channel $PATH_NAME diff --git a/tests/e2e/cases/tm2tm/scripts/init-rly b/tests/e2e/cases/tm2tm/scripts/init-rly new file mode 100755 index 0000000..cf04c5f --- /dev/null +++ b/tests/e2e/cases/tm2tm/scripts/init-rly @@ -0,0 +1,29 @@ +#!/bin/bash + +set -eux + +SCRIPT_DIR=$(cd $(dirname $0); pwd) + +RLY_HOME="$HOME/.yui-relayer" +RLY="${RLY_BIN} --debug" +FIXTURES_DIR=${SCRIPT_DIR}/../fixtures + +echo "Generating ${RLY_BIN} configurations..." + +# Ensure ${RLY_BIN} is installed +if ! [ -x ${RLY_BIN} ]; then + echo "Error: ${RLY_BIN} is not installed." >&2 + exit 1 +fi + +rm -rf ${RLY_HOME} &> /dev/null + +${RLY} config init +${RLY} chains add-dir configs/demo/ + +# setup key for tendermint client +SEED0=$(jq -r '.mnemonic' < ${FIXTURES_DIR}/tendermint/ibc0/key_seed.json) +echo "Key $(${RLY} tendermint keys restore ibc0 testkey "$SEED0") imported from ibc0 to relayer..." + +SEED1=$(jq -r '.mnemonic' < ${FIXTURES_DIR}/tendermint/ibc1/key_seed.json) +echo "Key $(${RLY} tendermint keys restore ibc1 testkey "$SEED1") imported from ibc1 to relayer..." diff --git a/tests/e2e/cases/tm2tm/scripts/test-tx b/tests/e2e/cases/tm2tm/scripts/test-tx new file mode 100755 index 0000000..486fce9 --- /dev/null +++ b/tests/e2e/cases/tm2tm/scripts/test-tx @@ -0,0 +1,26 @@ +#!/bin/bash + +set -eux + +RLY="${RLY_BIN} --debug" + +# XXX set proper value +TX_INTERNAL=3 + +TM_ADDRESS0=$(${RLY} tendermint keys show ibc0 testkey) +TM_ADDRESS1=$(${RLY} tendermint keys show ibc1 testkey) + +echo "!!! ibc0 -> ibc1 !!!" + +echo "Before ibc0 balance: $(${RLY} query balance ibc0 ${TM_ADDRESS0})" +echo "Before ibc1 balance: $(${RLY} query balance ibc1 ${TM_ADDRESS1})" + +${RLY} tx transfer ibc01 ibc0 ibc1 100samoleans ${TM_ADDRESS1} +sleep ${TX_INTERNAL} +${RLY} tx relay ibc01 +sleep ${TX_INTERNAL} +${RLY} tx acks ibc01 +sleep ${TX_INTERNAL} + +echo "After ibc0 balance: $(${RLY} query balance ibc0 ${TM_ADDRESS0})" +echo "After ibc1 balance: $(${RLY} query balance ibc1 ${TM_ADDRESS1})" diff --git a/tests/e2e/scripts/gen_rly_config.sh b/tests/e2e/scripts/gen_rly_config.sh new file mode 100755 index 0000000..c723851 --- /dev/null +++ b/tests/e2e/scripts/gen_rly_config.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -eux +TEMPLATE_DIR=./tests/e2e/cases/tm2tm/configs/templates +CONFIG_DIR=./tests/e2e/cases/tm2tm/configs/demo +mkdir -p $CONFIG_DIR +MRENCLAVE=$(./bin/lcp enclave metadata --enclave=./bin/enclave.signed.so | jq -r .mrenclave) +jq --arg MRENCLAVE ${MRENCLAVE} -r '.prover.mrenclave = $MRENCLAVE' ${TEMPLATE_DIR}/ibc-0.json.tpl > ${CONFIG_DIR}/ibc-0.json +jq --arg MRENCLAVE ${MRENCLAVE} -r '.prover.mrenclave = $MRENCLAVE' ${TEMPLATE_DIR}/ibc-1.json.tpl > ${CONFIG_DIR}/ibc-1.json diff --git a/tests/e2e/scripts/load_docker_images b/tests/e2e/scripts/load_docker_images new file mode 100755 index 0000000..81df440 --- /dev/null +++ b/tests/e2e/scripts/load_docker_images @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -eox pipefail + +source $(cd $(dirname "$0"); pwd)/util + +LOAD_DIR=$1 +if [ ! -d $LOAD_DIR ];then + echo "Directory not exists." + exit 1 +fi + +shift + +for image in "$@"; do + key=$(createDockerImageCacheKey $image) + docker load -i "${LOAD_DIR}/${key}" +done diff --git a/tests/e2e/scripts/save_docker_images b/tests/e2e/scripts/save_docker_images new file mode 100755 index 0000000..579660f --- /dev/null +++ b/tests/e2e/scripts/save_docker_images @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -eox pipefail + +source $(cd $(dirname "$0"); pwd)/util + +echo $@ + +SAVE_DIR=$1 +if [ ! -d $SAVE_DIR ];then + echo "Directory not exists." + mkdir -p $SAVE_DIR +fi + +shift + +for image in "$@"; do + key=$(createDockerImageCacheKey $image) + docker save -o "${SAVE_DIR}/${key}" $image +done diff --git a/tests/e2e/scripts/util b/tests/e2e/scripts/util new file mode 100755 index 0000000..da5df2e --- /dev/null +++ b/tests/e2e/scripts/util @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +createDockerImageCacheKey() { + IMAGE=$1 + ret=${IMAGE//\//_} + echo $ret +} + +retry() { + local -r -i max_attempts="$1"; shift + local -r cmd="$@" + local -i attempt_num=1 + + until $cmd + do + if (( attempt_num == max_attempts )) + then + echo "Attempt $attempt_num failed and there are no more attempts left!" + return 1 + else + echo "Attempt $attempt_num failed! Trying again in $attempt_num seconds..." + sleep $(( attempt_num++ )) + fi + done +} diff --git a/tests/e2e/scripts/wait-for-launch b/tests/e2e/scripts/wait-for-launch new file mode 100755 index 0000000..749aae4 --- /dev/null +++ b/tests/e2e/scripts/wait-for-launch @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +source $(cd $(dirname "$0"); pwd)/util + +MAX_ATTEMPTS=$1 +CONTAINER=$2 + +attempt_num=1 +retry_interval=1 + +until [[ $(docker inspect --format='{{.State.Health.Status}}' $CONTAINER) == 'healthy' ]] +do + if (( attempt_num == MAX_ATTEMPTS )); then + echo "Attempt $attempt_num failed and there are no more attempts left!" + exit 1 + else + echo "Attempt $attempt_num failed! Trying again in $retry_interval seconds..." + sleep $retry_interval + attempt_num=$(( $attempt_num+1 )) + fi +done