From 2cbae73866f4c325e2f719c8df9d64ac3cdf223e Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Mon, 17 Jul 2023 15:23:33 +0200 Subject: [PATCH] Add ICS misbehaviour test --- .github/workflows/misbehaviour.yml | 54 ++++ ci/misbehaviour-ics/misbehaviour_test.sh | 391 +++++++++++++++++++++++ 2 files changed, 445 insertions(+) create mode 100644 ci/misbehaviour-ics/misbehaviour_test.sh diff --git a/.github/workflows/misbehaviour.yml b/.github/workflows/misbehaviour.yml index d216b56bf7..b9238108b4 100644 --- a/.github/workflows/misbehaviour.yml +++ b/.github/workflows/misbehaviour.yml @@ -94,3 +94,57 @@ jobs: run: | nix shell .#${{ matrix.chain.package }} -c bash misbehaviour_test.sh + misbehaviour-ics: + runs-on: ubuntu-20.04 + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + chain: + - package: interchain-security + account_prefix: cosmos + steps: + - uses: actions/checkout@v3 + - name: Install Nix + uses: cachix/install-nix-action@v22 + with: + extra_nix_config: | + experimental-features = nix-command flakes + - name: Use cachix cache + uses: cachix/cachix-action@v12 + with: + name: cosmos + - name: Install sconfig + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/sconfig + platform: linux + arch: amd64 + extension-matching: disable + rename-to: sconfig + chmod: 0755 + - name: Install stoml + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/stoml + platform: linux + arch: amd64 + extension-matching: disable + rename-to: stoml + chmod: 0755 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - name: Use Rust cache + uses: Swatinem/rust-cache@v1 + - name: Build Hermes + uses: actions-rs/cargo@v1 + with: + command: build + - name: Run test + working-directory: ci/misbehaviour-ics + run: | + nix shell .#${{ matrix.chain.package }} -c bash misbehaviour_test.sh + diff --git a/ci/misbehaviour-ics/misbehaviour_test.sh b/ci/misbehaviour-ics/misbehaviour_test.sh new file mode 100644 index 0000000000..4fcfa8b374 --- /dev/null +++ b/ci/misbehaviour-ics/misbehaviour_test.sh @@ -0,0 +1,391 @@ +#!/bin/bash +set -eu + +diag() { + echo ">> +>> $@ +>>" 1>&2 +} + +# User balance of stake tokens +USER_COINS="100000000000stake" +# Amount of stake tokens staked +STAKE="100000000stake" +# Node IP address +NODE_IP="127.0.0.1" + +# Home directory +HOME_DIR="/tmp/interchain-security" + +# Hermes path +HERMES="cargo run -q --" + +# Validator moniker +MONIKER="coordinator" + +# Validator directory +PROV_NODE_DIR=${HOME_DIR}/provider-${MONIKER} +CONS_NODE_DIR=${HOME_DIR}/consumer-${MONIKER} +CONS_FORK_NODE_DIR=${HOME_DIR}/consumer-fork-${MONIKER} + +# Coordinator key +PROV_KEY=${MONIKER}-key + + +# Clean start +pkill -f interchain-security-pd &> /dev/null || true +rm -rf ${PROV_NODE_DIR} + +# Build genesis file and node directory structure +interchain-security-pd init $MONIKER --chain-id provider --home ${PROV_NODE_DIR} +jq ".app_state.gov.voting_params.voting_period = \"3s\" | .app_state.staking.params.unbonding_time = \"86400s\"" \ + ${PROV_NODE_DIR}/config/genesis.json > \ + ${PROV_NODE_DIR}/edited_genesis.json && mv ${PROV_NODE_DIR}/edited_genesis.json ${PROV_NODE_DIR}/config/genesis.json + +sleep 1 + +# Create account keypair +interchain-security-pd keys add $PROV_KEY --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY}.json 2>&1 +sleep 1 + +# Add stake to user +PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) +interchain-security-pd add-genesis-account $PROV_ACCOUNT_ADDR $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test +sleep 1 + + +# Stake 1/1000 user's coins +interchain-security-pd gentx $PROV_KEY $STAKE --chain-id provider --home ${PROV_NODE_DIR} --keyring-backend test --moniker $MONIKER +sleep 1 + +interchain-security-pd collect-gentxs --home ${PROV_NODE_DIR} --gentx-dir ${PROV_NODE_DIR}/config/gentx/ +sleep 1 + +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26658\"/" ${PROV_NODE_DIR}/config/client.toml +sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_DIR}/config/config.toml +sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_DIR}/config/config.toml + + +# Start gaia +interchain-security-pd start \ + --home ${PROV_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26658 \ + --grpc.address ${NODE_IP}:9091 \ + --address tcp://${NODE_IP}:26655 \ + --p2p.laddr tcp://${NODE_IP}:26656 \ + --grpc-web.enable=false &> ${PROV_NODE_DIR}/logs & + +sleep 5 + +# Build consumer chain proposal file +tee ${PROV_NODE_DIR}/consumer-proposal.json< /dev/null || true +rm -rf ${CONS_NODE_DIR} +rm -rf ${CONS_FORK_NODE_DIR} + +# Build genesis file and node directory structure +interchain-security-cd init $MONIKER --chain-id consumer --home ${CONS_NODE_DIR} +sleep 1 + +# Create user account keypair +interchain-security-cd keys add $PROV_KEY --home ${CONS_NODE_DIR} --keyring-backend test --output json > ${CONS_NODE_DIR}/${PROV_KEY}.json 2>&1 + +# Add stake to user account +CONS_ACCOUNT_ADDR=$(jq -r '.address' ${CONS_NODE_DIR}/${PROV_KEY}.json) +interchain-security-cd add-genesis-account $CONS_ACCOUNT_ADDR 1000000000stake --home ${CONS_NODE_DIR} + +# Add consumer genesis states to genesis file +interchain-security-pd query provider consumer-genesis consumer --home ${PROV_NODE_DIR} -o json > consumer_gen.json +jq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' ${CONS_NODE_DIR}/config/genesis.json consumer_gen.json > ${CONS_NODE_DIR}/edited_genesis.json \ +&& mv ${CONS_NODE_DIR}/edited_genesis.json ${CONS_NODE_DIR}/config/genesis.json +rm consumer_gen.json + +# Create validator states +echo '{"height": "0","round": 0,"step": 0}' > ${CONS_NODE_DIR}/data/priv_validator_state.json + +# Copy validator key files +cp ${PROV_NODE_DIR}/config/priv_validator_key.json ${CONS_NODE_DIR}/config/priv_validator_key.json +cp ${PROV_NODE_DIR}/config/node_key.json ${CONS_NODE_DIR}/config/node_key.json + +# Set default client port +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26648\"/" ${CONS_NODE_DIR}/config/client.toml + +# Start gaia +interchain-security-cd start --home ${CONS_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26648 \ + --grpc.address ${NODE_IP}:9081 \ + --address tcp://${NODE_IP}:26645 \ + --p2p.laddr tcp://${NODE_IP}:26646 \ + --grpc-web.enable=false \ + &> ${CONS_NODE_DIR}/logs & + +sleep 3 + +# Setup Hermes in packet relayer mode +pkill -f hermes 2> /dev/null || true + +tee $HOME_DIR/config.toml < $HOME_DIR/hermes-logs & + +interchain-security-pd q tendermint-validator-set --home ${PROV_NODE_DIR} +interchain-security-cd q tendermint-validator-set --home ${CONS_NODE_DIR} + +DELEGATIONS=$(interchain-security-pd q staking delegations $PROV_ACCOUNT_ADDR --home ${PROV_NODE_DIR} -o json) + +OPERATOR_ADDR=$(echo $DELEGATIONS | jq -r '.delegation_responses[0].delegation.validator_address') + +interchain-security-pd tx staking delegate $OPERATOR_ADDR 1000000stake \ + --from $PROV_KEY \ + --keyring-backend test \ + --home ${PROV_NODE_DIR} \ + --chain-id provider \ + -y -b block + +sleep 13 + +interchain-security-pd q tendermint-validator-set --home ${PROV_NODE_DIR} +interchain-security-cd q tendermint-validator-set --home ${CONS_NODE_DIR} + +##### Fork consumer + +tee $HOME_DIR/config_fork.toml< ${CONS_FORK_NODE_DIR}/logs & + +sleep 5 + +# Find trusted state before fork +TRUSTED_HEIGHT=$($HERMES --json --config $HOME_DIR/config.toml query client consensus --chain provider --client 07-tendermint-0 | tail -n 1 | jq '.result[2].revision_height') + +# Update client first time +# FIXME: Why doesn't this one get picked up as evidence of misbehaviour? +$HERMES --config $HOME_DIR/config_fork.toml update client --client 07-tendermint-0 --host-chain provider --trusted-height $TRUSTED_HEIGHT + +sleep 10 + +diag "Updating client on forked chain using trusted height $TRUSTED_HEIGHT" +$HERMES --config $HOME_DIR/config_fork.toml update client --client 07-tendermint-0 --host-chain provider --trusted-height $TRUSTED_HEIGHT + +sleep 10 + +# Check the client state on provider and verify it is frozen +FROZEN_HEIGHT=$($HERMES --config $HOME_DIR/config.toml --json query client state --chain provider --client 07-tendermint-0 | tail -n 1 | jq '.result.frozen_height.revision_height') + +diag "Frozen height: $FROZEN_HEIGHT" + +if [ "$FROZEN_HEIGHT" != "null" ]; then + diag "Client is frozen, success!" +else + diag "Client is not frozen, aborting." + exit 1 +fi