diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 00000000000..b407223e30f --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,36 @@ +name: E2E Test +# Tests / Code Coverage workflow runs unit tests and uploads a code coverage report +# This workflow is run on pushes to main & every Pull Requests where a .go, .mod, .sum have been changed +on: + pull_request: + push: + branches: + - main + - release/** +jobs: + test-fnsa-fnsa: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v3 + with: + go-version: '1.20' + - name: Display go version + run: go version + - name: Test finschia to finschia + run: | + cd e2e + make test-fnsa-fnsa + test-fnsa-csms: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v3 + with: + go-version: '1.20' + - name: Display go version + run: go version + - name: Test finschia to cosmos + run: | + cd e2e + make test-fnsa-csms diff --git a/CHANGELOG_FNSA.md b/CHANGELOG_FNSA.md index 76d56fdebe4..b44411c0716 100644 --- a/CHANGELOG_FNSA.md +++ b/CHANGELOG_FNSA.md @@ -2,3 +2,4 @@ - [\#18](https://github.com/Finschia/ibc-go/pull/18) Apply finshia-sdk@v0.47.1-0.20230725074611-f8840edecbaa - [\#20](https://github.com/Finschia/ibc-go/pull/20) Update finschia-sdk to v0.48.0-rc1 + - [\#21](https://github.com/Finschia/ibc-go/pull/21) Add e2e ci test diff --git a/e2e/.gitignore b/e2e/.gitignore new file mode 100644 index 00000000000..9f9486dfe64 --- /dev/null +++ b/e2e/.gitignore @@ -0,0 +1,2 @@ +bin +data diff --git a/e2e/Makefile b/e2e/Makefile new file mode 100644 index 00000000000..ae4824ec4ba --- /dev/null +++ b/e2e/Makefile @@ -0,0 +1,41 @@ +RLY_VERSION := 2.3.1 +CSMS_VERSION := 4.3.1 +ARCH := $(shell dpkg --print-architecture) +PATH := $(shell pwd)/bin:$(PATH) + +bin/simd: + @mkdir -p bin && \ + cd ../ && \ + make build && \ + mv build/simd e2e/bin + @simd version --long + +bin/csmssimd: + @mkdir -p bin/cosmos && \ + cd bin/cosmos && \ + curl -L https://github.com/cosmos/ibc-go/releases/download/v$(CSMS_VERSION)/ibc-go_simd_v$(CSMS_VERSION)_linux_$(ARCH).tar.gz --output cosmos_simd.tar.gz && \ + tar -xf cosmos_simd.tar.gz && \ + mv simd ../csmssimd + @csmssimd version --long --log_level=info + +bin/rly: + @mkdir -p bin/relayer && \ + cd bin/relayer && \ + curl -L https://github.com/cosmos/relayer/releases/download/v$(RLY_VERSION)/Cosmos.Relayer_$(RLY_VERSION)_linux_$(ARCH).tar.gz --output relayer.tar.gz && \ + tar -xf relayer.tar.gz --transform 's!^[^/]*!relayer_archive!' && \ + mv relayer_archive/rly ../ + @rly version + +test-fnsa-fnsa: bin/rly bin/simd + @./e2e fnsa-fnsa fnsa-0 simd 438 fnsa-1 simd 438 "skip" + +test-fnsa-csms: bin/rly bin/simd bin/csmssimd + @./e2e fnsa-csms fnsa-0 simd 438 csms-1 csmssimd 118 "skip" + +clean-all: + @rm -rf bin data + +clean-data: + @rm -rf data + +.PHONY: test-fnsa-fnsa test-fnsa-csms clean-all clean-data diff --git a/e2e/configs/chains/csms-1.json b/e2e/configs/chains/csms-1.json new file mode 100644 index 00000000000..9f60774765a --- /dev/null +++ b/e2e/configs/chains/csms-1.json @@ -0,0 +1,18 @@ +{ + "type": "cosmos", + "value": { + "key": "testkey", + "chain-id": "csms-1", + "rpc-addr": "http://localhost:26557", + "grpc-addr": "", + "account-prefix": "cosmos", + "keyring-backend": "test", + "gas-adjustment": 1.5, + "gas-prices": "0.025rice", + "debug": true, + "timeout": "10s", + "output-format": "json", + "sign-mode": "direct" + } +} + diff --git a/e2e/configs/chains/fnsa-0.json b/e2e/configs/chains/fnsa-0.json new file mode 100644 index 00000000000..2f8f93b4b33 --- /dev/null +++ b/e2e/configs/chains/fnsa-0.json @@ -0,0 +1,18 @@ +{ + "type": "cosmos", + "value": { + "key": "testkey", + "chain-id": "fnsa-0", + "rpc-addr": "http://localhost:26657", + "grpc-addr": "", + "account-prefix": "link", + "keyring-backend": "test", + "gas-adjustment": 1.5, + "gas-prices": "0.025stake", + "debug": true, + "timeout": "10s", + "output-format": "json", + "sign-mode": "direct" + } +} + diff --git a/e2e/configs/chains/fnsa-1.json b/e2e/configs/chains/fnsa-1.json new file mode 100644 index 00000000000..1d991f5bb7b --- /dev/null +++ b/e2e/configs/chains/fnsa-1.json @@ -0,0 +1,18 @@ +{ + "type": "cosmos", + "value": { + "key": "testkey", + "chain-id": "fnsa-1", + "rpc-addr": "http://localhost:26557", + "grpc-addr": "", + "account-prefix": "link", + "keyring-backend": "test", + "gas-adjustment": 1.5, + "gas-prices": "0.025rice", + "debug": true, + "timeout": "10s", + "output-format": "json", + "sign-mode": "direct" + } +} + diff --git a/e2e/configs/paths/fnsa-csms.json b/e2e/configs/paths/fnsa-csms.json new file mode 100644 index 00000000000..657613907b3 --- /dev/null +++ b/e2e/configs/paths/fnsa-csms.json @@ -0,0 +1,12 @@ +{ + "src": { + "chain-id": "fnsa-0" + }, + "dst": { + "chain-id": "csms-1" + }, + "src-channel-filter": { + "rule": null, + "channel-list": [] + } +} diff --git a/e2e/configs/paths/fnsa-fnsa.json b/e2e/configs/paths/fnsa-fnsa.json new file mode 100644 index 00000000000..513e4c52a89 --- /dev/null +++ b/e2e/configs/paths/fnsa-fnsa.json @@ -0,0 +1,12 @@ +{ + "src": { + "chain-id": "fnsa-0" + }, + "dst": { + "chain-id": "fnsa-1" + }, + "src-channel-filter": { + "rule": null, + "channel-list": [] + } +} diff --git a/e2e/e2e b/e2e/e2e new file mode 100755 index 00000000000..7a0d3041401 --- /dev/null +++ b/e2e/e2e @@ -0,0 +1,104 @@ +#!/bin/bash -e +RELAYER_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +HOME_DIR="$(pwd)/data" +RLY_HOME="$HOME_DIR/relayer" + +CHAIN_PATH=$1 +CHAIN0_ID=$2 +CHAIN0_BIN=$3 +CHAIN0_COINID=$4 +CHAIN1_ID=$5 +CHAIN1_BIN=$6 +CHAIN1_COINID=$7 + +# Ensure user understands what will be deleted +if ([[ -d $HOME_DIR ]]) && [[ ! "$8" == "skip" ]]; then + read -p "$0 will delete \$HOME/.relayer and \$(pwd)/data folder. Do you wish to continue? (y/n): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# spin up two ibc enabled chains and add relevant config info for relaying +bash scripts/chainz $CHAIN0_ID $CHAIN0_BIN $CHAIN0_COINID $CHAIN1_ID $CHAIN1_BIN $CHAIN1_COINID "$8" + +echo "waiting for blocks..." +sleep 3 + +# creates clients, connections and channels (all this happens in rly tx command) +rly --home $RLY_HOME tx link $CHAIN_PATH -d -t 3s +sleep 2 + +BAL0=$(rly --home $RLY_HOME q bal $CHAIN0_ID) +BAL1=$(rly --home $RLY_HOME q bal $CHAIN1_ID) + +echo "-- Initial balances --" +echo "balance 0 $BAL0" +echo "balance 1 $BAL1" + +if [[ "$BAL0" != *"100000000000samoleans"* ]]; then + echo "balance 0 is wrong" + exit 1 +fi +if [[ "$BAL1" != *"100000000000beans"* ]]; then + echo "balance 1 is wrong" + exit 1 +fi + +echo "-- Sending IBC transaction... --" +rly --home $RLY_HOME tx transfer $CHAIN0_ID $CHAIN1_ID 100000samoleans "$(rly --home $RLY_HOME keys show $CHAIN1_ID)" channel-0 -d +sleep 5 + +# relay remaining packets -- (could also be accomplished by running: `rly start`) +rly --home $RLY_HOME tx relay-packets $CHAIN_PATH channel-0 -d +sleep 5 + +# relay remaining acknowledgments -- (could also be accomplished by running: `rly start`) +rly --home $RLY_HOME tx relay-acknowledgements $CHAIN_PATH channel-0 -d +sleep 5 + +BAL0=$(rly --home $RLY_HOME q bal $CHAIN0_ID) +BAL1=$(rly --home $RLY_HOME q bal $CHAIN1_ID) + +echo "-- Balances after packets are sent --" +echo "balance 0 $BAL0" +echo "balance 1 $BAL1" + +if [[ "$BAL0" != *"{99999900000samoleans"* ]]; then + echo "balance 0 is wrong" + exit 1 +fi +if [[ "$BAL1" != *"100000000000beans,100000transfer/channel-0/samoleans"* ]]; then + echo "balance 1 is wrong" + exit 1 +fi + +echo "-- Sending tokens back to original wallet... --" +rly --home $RLY_HOME tx transfer $CHAIN1_ID $CHAIN0_ID 100000transfer/channel-0/samoleans "$(rly --home $RLY_HOME keys show $CHAIN0_ID)" channel-0 -d +sleep 5 + +rly --home $RLY_HOME tx relay-packets $CHAIN_PATH channel-0 -d +sleep 5 + +rly --home $RLY_HOME tx relay-acknowledgements $CHAIN_PATH channel-0 -d +sleep 5 + +BAL0=$(rly --home $RLY_HOME q bal $CHAIN0_ID) +BAL1=$(rly --home $RLY_HOME q bal $CHAIN1_ID) + +echo "-- Balances after sending packets back --" +echo "balance 0 $BAL0" +echo "balance 1 $BAL1" + +if [[ "$BAL0" != *"100000000000samoleans"* ]]; then + echo "balance 0 is wrong" + exit 1 +fi +if [[ "$BAL1" != *"100000000000beans"* ]]; then + echo "balance 1 is wrong" + exit 1 +fi + +killall simd &> /dev/null || true +killall csmssimd &> /dev/null || true diff --git a/e2e/scripts/chainz b/e2e/scripts/chainz new file mode 100755 index 00000000000..e1c3355d5cb --- /dev/null +++ b/e2e/scripts/chainz @@ -0,0 +1,73 @@ +#!/bin/bash +# two-chainz creates two chains and configures the relayer to + +SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +HOME_DIR="$(pwd)/data" +RLY_HOME="$HOME_DIR/relayer" + +CHAIN0_ID=$1 +CHAIN0_BIN=$2 +CHAIN0_COINID=$3 +CHAIN1_ID=$4 +CHAIN1_BIN=$5 +CHAIN1_COINID=$6 + +# Ensure binary is installed +if ! [ -x "$(which $CHAIN0_BIN)" ]; then + echo "Error: $CHAIN0_BIN is not installed. Try running 'make bin/$CHAIN0_BIN'" >&2 + exit 1 +fi +if ! [ -x "$(which $CHAIN1_BIN)" ]; then + echo "Error: $CHAIN1_BIN is not installed. Try running 'make bin/$CHAIN1_BIN'" >&2 + exit 1 +fi + +# Display software version for testers +echo "BINARY VERSION INFO:" +$CHAIN0_BIN version --long --log_level=info +$CHAIN1_BIN version --long --log_level=info + +# Ensure jq is installed +if [[ ! -x "$(which jq)" ]]; then + echo "jq (a tool for parsing json in the command line) is required..." + echo "https://stedolan.github.io/jq/download/" + exit 1 +fi + +# Ensure user understands what will be deleted +if [[ -d $HOME_DIR ]] && [[ ! "$7" == "skip" ]]; then + read -p "$(basename $0) will delete \$(pwd)/data and \$HOME/.relayer folders. Do you wish to continue? (y/n): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Delete data from old runs +rm -rf $HOME_DIR &> /dev/null + +# Stop existing binary processes +killall simd &> /dev/null +killall csmssimd &> /dev/null + +set -e + +echo "Generating fnsa configurations..." +mkdir -p $HOME_DIR && cd $HOME_DIR && cd ../ +./scripts/one-chain $CHAIN0_BIN $CHAIN0_ID $HOME_DIR 26657 26656 6060 9090 stake samoleans +./scripts/one-chain $CHAIN1_BIN $CHAIN1_ID $HOME_DIR 26557 26556 6061 9091 rice beans + +[ -f $HOME_DIR/$CHAIN0_ID.log ] && echo "$CHAIN0_ID initialized. Watch file $HOME_DIR/$CHAIN0_ID.log to see its execution." +[ -f $HOME_DIR/$CHAIN1_ID.log ] && echo "$CHAIN1_ID initialized. Watch file $HOME_DIR/$CHAIN1_ID.log to see its execution." + +echo "Generating rly configurations..." +rly --home $RLY_HOME config init +rly --home $RLY_HOME chains add-dir configs/chains + +SEED0=$(jq -r '.mnemonic' $HOME_DIR/$CHAIN0_ID/key_seed.json) +SEED1=$(jq -r '.mnemonic' $HOME_DIR/$CHAIN1_ID/key_seed.json) + +echo "Key $(rly --home $RLY_HOME keys restore $CHAIN0_ID testkey "$SEED0" --coin-type $CHAIN0_COINID) imported from CHAIN0_ID to relayer..." +echo "Key $(rly --home $RLY_HOME keys restore $CHAIN1_ID testkey "$SEED1" --coin-type $CHAIN1_COINID) imported from CHAIN1_ID to relayer..." + +rly --home $RLY_HOME paths add-dir configs/paths diff --git a/e2e/scripts/one-chain b/e2e/scripts/one-chain new file mode 100755 index 00000000000..6d65ddd486d --- /dev/null +++ b/e2e/scripts/one-chain @@ -0,0 +1,116 @@ +#!/bin/bash + +display_usage() { + echo "\nMissing $1 parameter. Please check if all parameters were specified." + echo "\nUsage: ./one-chain [BINARY] [CHAIN_ID] [CHAIN_DIR] [RPC_PORT] [P2P_PORT] [PROFILING_PORT] [GRPC_PORT]" + echo "\nExample: ./one-chain $BINARY test-chain-id ./data 26657 26656 6060 9090 \n" + exit 1 +} + +KEYRING=--keyring-backend="test" +SILENT=1 + +redirect() { + if [ "$SILENT" -eq 1 ]; then + "$@" > /dev/null 2>&1 + else + "$@" + fi +} + +BINARY=$1 +CHAINID=$2 +CHAINDIR=$3 +RPCPORT=$4 +P2PPORT=$5 +PROFPORT=$6 +GRPCPORT=$7 +DENOM=$8 +BASEDENOM=$9 + +if [ -z "$1" ]; then + display_usage "[BINARY] ($BINARY|akash)" +fi + +if [ -z "$2" ]; then + display_usage "[CHAIN_ID]" +fi + +if [ -z "$3" ]; then + display_usage "[CHAIN_DIR]" +fi + +if [ -z "$4" ]; then + display_usage "[RPC_PORT]" +fi + +if [ -z "$5" ]; then + display_usage "[P2P_PORT]" +fi + +if [ -z "$6" ]; then + display_usage "[PROFILING_PORT]" +fi + +if [ -z "$7" ]; then + display_usage "[GRPC_PORT]" +fi + +echo "Creating $BINARY instance: home=$CHAINDIR | chain-id=$CHAINID | p2p=:$P2PPORT | rpc=:$RPCPORT | profiling=:$PROFPORT | grpc=:$GRPCPORT" + +# Add dir for chain, exit if error +if ! mkdir -p $CHAINDIR/$CHAINID 2>/dev/null; then + echo "Failed to create chain folder. Aborting..." + exit 1 +fi + +# Build genesis file incl account for passed address +coins="100000000000$DENOM,100000000000$BASEDENOM" +delegate="100000000000$DENOM" + +redirect $BINARY --home $CHAINDIR/$CHAINID --chain-id $CHAINID init $CHAINID +sleep 1 +$BINARY --home $CHAINDIR/$CHAINID keys add validator $KEYRING --output json > $CHAINDIR/$CHAINID/validator_seed.json 2>&1 +sleep 1 +$BINARY --home $CHAINDIR/$CHAINID keys add user $KEYRING --output json > $CHAINDIR/$CHAINID/key_seed.json 2>&1 +sleep 1 +redirect $BINARY --home $CHAINDIR/$CHAINID add-genesis-account $($BINARY --home $CHAINDIR/$CHAINID keys $KEYRING show user -a) $coins +sleep 1 +redirect $BINARY --home $CHAINDIR/$CHAINID add-genesis-account $($BINARY --home $CHAINDIR/$CHAINID keys $KEYRING show validator -a) $coins +sleep 1 +redirect $BINARY --home $CHAINDIR/$CHAINID gentx validator $delegate $KEYRING --chain-id $CHAINID +sleep 1 +redirect $BINARY --home $CHAINDIR/$CHAINID collect-gentxs +sleep 1 + +# Check platform +platform='unknown' +unamestr=`uname` +if [ "$unamestr" = 'Linux' ]; then + platform='linux' +fi + +# Set proper defaults and change ports (use a different sed for Mac or Linux) +echo "Change settings in config.toml and genesis.json files..." +if [ $platform = 'linux' ]; then + sed -i 's#"tcp://127.0.0.1:26657"#"tcp://0.0.0.0:'"$RPCPORT"'"#g' $CHAINDIR/$CHAINID/config/config.toml + sed -i 's#"tcp://0.0.0.0:26656"#"tcp://0.0.0.0:'"$P2PPORT"'"#g' $CHAINDIR/$CHAINID/config/config.toml + sed -i 's#"localhost:6060"#"localhost:'"$P2PPORT"'"#g' $CHAINDIR/$CHAINID/config/config.toml + sed -i 's/timeout_commit = "5s"/timeout_commit = "1s"/g' $CHAINDIR/$CHAINID/config/config.toml + sed -i 's/timeout_propose = "3s"/timeout_propose = "1s"/g' $CHAINDIR/$CHAINID/config/config.toml + sed -i 's/index_all_keys = false/index_all_keys = true/g' $CHAINDIR/$CHAINID/config/config.toml + sed -i 's/"bond_denom": "stake"/"bond_denom": "'"$DENOM"'"/g' $CHAINDIR/$CHAINID/config/genesis.json + # sed -i '' 's#index-events = \[\]#index-events = \["message.action","send_packet.packet_src_channel","send_packet.packet_sequence"\]#g' $CHAINDIR/$CHAINID/config/app.toml +else + sed -i '' 's#"tcp://127.0.0.1:26657"#"tcp://0.0.0.0:'"$RPCPORT"'"#g' $CHAINDIR/$CHAINID/config/config.toml + sed -i '' 's#"tcp://0.0.0.0:26656"#"tcp://0.0.0.0:'"$P2PPORT"'"#g' $CHAINDIR/$CHAINID/config/config.toml + sed -i '' 's#"localhost:6060"#"localhost:'"$P2PPORT"'"#g' $CHAINDIR/$CHAINID/config/config.toml + sed -i '' 's/timeout_commit = "5s"/timeout_commit = "1s"/g' $CHAINDIR/$CHAINID/config/config.toml + sed -i '' 's/timeout_propose = "3s"/timeout_propose = "1s"/g' $CHAINDIR/$CHAINID/config/config.toml + sed -i '' 's/index_all_keys = false/index_all_keys = true/g' $CHAINDIR/$CHAINID/config/config.toml + sed -i '' 's/"bond_denom": "stake"/"bond_denom": "'"$DENOM"'"/g' $CHAINDIR/$CHAINID/config/genesis.json + # sed -i '' 's#index-events = \[\]#index-events = \["message.action","send_packet.packet_src_channel","send_packet.packet_sequence"\]#g' $CHAINDIR/$CHAINID/config/app.toml +fi + +# Start the gaia +$BINARY --home $CHAINDIR/$CHAINID start --pruning=nothing --grpc-web.enable=false --grpc.address="0.0.0.0:$GRPCPORT" > $CHAINDIR/$CHAINID.log 2>&1 &