diff --git a/dockernet/README.md b/dockernet/README.md index b472a850ca..28a8f3cad7 100644 --- a/dockernet/README.md +++ b/dockernet/README.md @@ -72,13 +72,14 @@ ST{CHAIN}_DENOM="st{min_denom}" {CHAIN}_COIN_TYPE=${TYPE}_COIN_TYPE {CHAIN}_RPC_PORT={the one included in the docker-compose above} {CHAIN}_MAIN_CMD="${CHAIN}_CMD --home $DOCKERNET_HOME/state/${${CHAIN}_NODE_PREFIX}1" +{CHAIN}_RECEIVER_ADDRESS={any random address on the chain} # Add *below* the RELAYER section! RELAYER_{CHAIN}_EXEC="docker-compose run --rm relayer-{new-host-zone}" RELAYER_{CHAIN}_ACCT=rly{add one since the account from the last host zone} -# NOTE: Update the HOST_RELAYER_ACCTS variable directly! -HOST_RELAYER_ACCTS=(... $RELAYER_{CHAIN}_ACCT) +# NOTE: Update the RELAYER_ACCTS variable directly! +RELAYER_ACCTS=(... $RELAYER_{CHAIN}_ACCT) # stride1muwz5er4wq7svxnh5dgn2tssm92je5dwthxl7q RELAYER_{CHAIN}_MNEMONIC="science depart where tell bus ski laptop follow child bronze rebel recall brief plug razor ship degree labor human series today embody fury harvest" diff --git a/dockernet/config.sh b/dockernet/config.sh index 27f7db5199..7967a34854 100644 --- a/dockernet/config.sh +++ b/dockernet/config.sh @@ -21,8 +21,14 @@ HOST_CHAINS=() # If no host zones are specified above: # `start-docker` defaults to just GAIA if HOST_CHAINS is empty # `start-docker-all` always runs all hosts +# Available host zones: +# - GAIA +# - JUNO +# - OSMO +# - STARS +# - HOST (Stride chain enabled as a host zone) if [[ "${ALL_HOST_CHAINS:-false}" == "true" ]]; then - HOST_CHAINS=(GAIA JUNO OSMO STARS) + HOST_CHAINS=(GAIA OSMO HOST) elif [[ "${#HOST_CHAINS[@]}" == "0" ]]; then HOST_CHAINS=(GAIA) fi @@ -32,15 +38,17 @@ UPGRADE_NAME="" UPGRADE_OLD_COMMIT_HASH="" # DENOMS -ATOM_DENOM='uatom' -JUNO_DENOM='ujuno' -OSMO_DENOM='uosmo' -STRD_DENOM='ustrd' -STARS_DENOM='ustars' +ATOM_DENOM="uatom" +JUNO_DENOM="ujuno" +OSMO_DENOM="uosmo" +STRD_DENOM="ustrd" +STARS_DENOM="ustars" +WALK_DENOM="uwalk" STATOM_DENOM="stuatom" STJUNO_DENOM="stujuno" STOSMO_DENOM="stuosmo" STSTARS_DENOM="stustars" +STWALK_DENOM="stuwalk" IBC_STRD_DENOM='ibc/FF6C2E86490C1C4FBBD24F55032831D2415B9D7882F85C3CC9C2401D79362BEA' @@ -64,6 +72,11 @@ IBC_STARS_CHANNEL_1_DENOM='ibc/9222203B0B37D076F07B3CAC716533C80E7C4239499B6306C IBC_STARS_CHANNEL_2_DENOM='ibc/C6469BA9DC791E65B3C1596CD2005941324C00659E2DF90D5E08D86B82E7E08B' IBC_STARS_CHANNEL_3_DENOM='ibc/482A30C07803B0455B1492BAF94EC3D600E862D52A814F25A34BCCAAA132FEE9' +IBC_HOST_CHANNEL_0_DENOM='ibc/82DBA832457B89E1A344DA51761D92305F7581B7EA6C18D85037910988953C58' +IBC_HOST_CHANNEL_1_DENOM='ibc/FB7E2520A1ED6890E1632904A4ACA1B3D2883388F8E2B88F2D6A54AA15E4B49E' +IBC_HOST_CHANNEL_2_DENOM='ibc/D664DC1D38648FC4C697D9E9CF2D26369318DFE668B31F81809383A8A88CFCF4' +IBC_HOST_CHANNEL_3_DENOM='ibc/FD7AA7EB2C1D5D97A8693CCD71FFE3F5AFF12DB6756066E11E69873DE91A33EA' + # COIN TYPES # Coin types can be found at https://github.com/satoshilabs/slips/blob/master/slip-0044.md COSMOS_COIN_TYPE=118 @@ -83,6 +96,7 @@ STRIDE_EPOCH_EPOCH_DURATION="40s" HOST_DAY_EPOCH_DURATION="60s" HOST_HOUR_EPOCH_DURATION="60s" HOST_WEEK_EPOCH_DURATION="60s" +HOST_MINT_EPOCH_DURATION="60s" UNBONDING_TIME="120s" MAX_DEPOSIT_PERIOD="30s" VOTING_PERIOD="30s" @@ -121,84 +135,81 @@ STRIDE_FEE_ADDRESS=stride1czvrk3jkvtj8m27kqsqu2yrkhw3h3ykwj3rxh6 # Binaries are contigent on whether we're doing an upgrade or not if [[ "$UPGRADE_NAME" == "" ]]; then - STRIDE_CMD="$DOCKERNET_HOME/../build/strided" + STRIDE_BINARY="$DOCKERNET_HOME/../build/strided" else - STRIDE_CMD="$UPGRADES/binaries/strided1" + STRIDE_BINARY="$UPGRADES/binaries/strided1" fi -STRIDE_MAIN_CMD="$STRIDE_CMD --home $DOCKERNET_HOME/state/${STRIDE_NODE_PREFIX}1" +STRIDE_MAIN_CMD="$STRIDE_BINARY --home $DOCKERNET_HOME/state/${STRIDE_NODE_PREFIX}1" # GAIA GAIA_CHAIN_ID=GAIA GAIA_NODE_PREFIX=gaia GAIA_NUM_NODES=1 -GAIA_CMD="$DOCKERNET_HOME/../build/gaiad" +GAIA_BINARY="$DOCKERNET_HOME/../build/gaiad" GAIA_VAL_PREFIX=gval GAIA_REV_ACCT=grev1 GAIA_ADDRESS_PREFIX=cosmos GAIA_DENOM=$ATOM_DENOM GAIA_RPC_PORT=26557 GAIA_COIN_TYPE=$COSMOS_COIN_TYPE -GAIA_MAIN_CMD="$GAIA_CMD --home $DOCKERNET_HOME/state/${GAIA_NODE_PREFIX}1" +GAIA_MAIN_CMD="$GAIA_BINARY --home $DOCKERNET_HOME/state/${GAIA_NODE_PREFIX}1" GAIA_RECEIVER_ADDRESS='cosmos1g6qdx6kdhpf000afvvpte7hp0vnpzapuyxp8uf' # JUNO JUNO_CHAIN_ID=JUNO JUNO_NODE_PREFIX=juno JUNO_NUM_NODES=1 -JUNO_CMD="$DOCKERNET_HOME/../build/junod" +JUNO_BINARY="$DOCKERNET_HOME/../build/junod" JUNO_VAL_PREFIX=jval JUNO_REV_ACCT=jrev1 JUNO_ADDRESS_PREFIX=juno JUNO_DENOM=$JUNO_DENOM JUNO_RPC_PORT=26457 JUNO_COIN_TYPE=$COSMOS_COIN_TYPE -JUNO_MAIN_CMD="$JUNO_CMD --home $DOCKERNET_HOME/state/${JUNO_NODE_PREFIX}1" +JUNO_MAIN_CMD="$JUNO_BINARY --home $DOCKERNET_HOME/state/${JUNO_NODE_PREFIX}1" JUNO_RECEIVER_ADDRESS='juno1sy0q0jpaw4t3hnf6k5wdd4384g0syzlp7rrtsg' # OSMO OSMO_CHAIN_ID=OSMO OSMO_NODE_PREFIX=osmo OSMO_NUM_NODES=1 -OSMO_CMD="$DOCKERNET_HOME/../build/osmosisd" +OSMO_BINARY="$DOCKERNET_HOME/../build/osmosisd" OSMO_VAL_PREFIX=oval OSMO_REV_ACCT=orev1 OSMO_ADDRESS_PREFIX=osmo OSMO_DENOM=$OSMO_DENOM OSMO_RPC_PORT=26357 OSMO_COIN_TYPE=$COSMOS_COIN_TYPE -OSMO_MAIN_CMD="$OSMO_CMD --home $DOCKERNET_HOME/state/${OSMO_NODE_PREFIX}1" +OSMO_MAIN_CMD="$OSMO_BINARY --home $DOCKERNET_HOME/state/${OSMO_NODE_PREFIX}1" OSMO_RECEIVER_ADDRESS='osmo1w6wdc2684g9h3xl8nhgwr282tcxx4kl06n4sjl' # STARS STARS_CHAIN_ID=STARS STARS_NODE_PREFIX=stars STARS_NUM_NODES=1 -STARS_CMD="$DOCKERNET_HOME/../build/starsd" +STARS_BINARY="$DOCKERNET_HOME/../build/starsd" STARS_VAL_PREFIX=sgval STARS_REV_ACCT=sgrev1 STARS_ADDRESS_PREFIX=stars STARS_DENOM=$STARS_DENOM STARS_RPC_PORT=26257 STARS_COIN_TYPE=$COSMOS_COIN_TYPE -STARS_MAIN_CMD="$STARS_CMD --home $DOCKERNET_HOME/state/${STARS_NODE_PREFIX}1" +STARS_MAIN_CMD="$STARS_BINARY --home $DOCKERNET_HOME/state/${STARS_NODE_PREFIX}1" STARS_RECEIVER_ADDRESS='stars15dywcmy6gzsc8wfefkrx0c9czlwvwrjenqthyq' - -# HERMES -HERMES_CMD="$DOCKERNET_HOME/../build/hermes/release/hermes --config $STATE/hermes/config.toml" -HERMES_EXEC="$DOCKER_COMPOSE run --rm hermes hermes" - -HERMES_STRIDE_ACCT=hrly1 -HERMES_GAIA_ACCT=hrly2 -HERMES_JUNO_ACCT=hrly3 -HERMES_OSMO_ACCT=hrly4 -HERMES_STARS_ACCT=hrly5 - -HERMES_STRIDE_MNEMONIC="alter old invest friend relief slot swear pioneer syrup economy vendor tray focus hedgehog artist legend antenna hair almost donkey spice protect sustain increase" -HERMES_GAIA_MNEMONIC="resemble accident lake amateur physical jewel taxi nut demand magnet person blanket trip entire awkward fiber usual current index limb lady lady depart train" -HERMES_JUNO_MNEMONIC="uphold decorate moon memory taste century work pride force genius width ripple myself year steel ivory type sweet tree ignore danger pudding owner discover" -HERMES_OSMO_MNEMONIC="lawn inside color february double myth depart invite miracle nest silver spider spray recall theme loan exotic puzzle uncover dial young earn disagree fee" -HERMES_STARS_MNEMONIC="inherit shallow bargain explain fence vocal fury perfect jeans figure festival abstract soldier entry bubble ketchup swim useless doctor thing imitate can shock coin" +# HOST (Stride running as a host zone) +HOST_CHAIN_ID=HOST +HOST_NODE_PREFIX=host +HOST_NUM_NODES=1 +HOST_BINARY="$DOCKERNET_HOME/../build/strided" +HOST_VAL_PREFIX=hval +HOST_ADDRESS_PREFIX=stride +HOST_REV_ACCT=hrev1 +HOST_DENOM=$WALK_DENOM +HOST_COIN_TYPE=$COSMOS_COIN_TYPE +HOST_RPC_PORT=26157 +HOST_MAIN_CMD="$HOST_BINARY --home $DOCKERNET_HOME/state/${HOST_NODE_PREFIX}1" +HOST_RECEIVER_ADDRESS='stride1trm75t8g83f26u4y8jfds7pms9l587a7q227k9' # RELAYER RELAYER_CMD="$DOCKERNET_HOME/../build/relayer --home $STATE/relayer" @@ -206,23 +217,27 @@ RELAYER_GAIA_EXEC="$DOCKER_COMPOSE run --rm relayer-gaia" RELAYER_JUNO_EXEC="$DOCKER_COMPOSE run --rm relayer-juno" RELAYER_OSMO_EXEC="$DOCKER_COMPOSE run --rm relayer-osmo" RELAYER_STARS_EXEC="$DOCKER_COMPOSE run --rm relayer-stars" +RELAYER_HOST_EXEC="$DOCKER_COMPOSE run --rm relayer-host" RELAYER_STRIDE_ACCT=rly1 RELAYER_GAIA_ACCT=rly2 RELAYER_JUNO_ACCT=rly3 RELAYER_OSMO_ACCT=rly4 RELAYER_STARS_ACCT=rly5 -HOST_RELAYER_ACCTS=($RELAYER_GAIA_ACCT $RELAYER_JUNO_ACCT $RELAYER_OSMO_ACCT $RELAYER_STARS_ACCT) +RELAYER_HOST_ACCT=rly6 +RELAYER_ACCTS=($RELAYER_GAIA_ACCT $RELAYER_JUNO_ACCT $RELAYER_OSMO_ACCT $RELAYER_STARS_ACCT $RELAYER_HOST_ACCT) RELAYER_GAIA_MNEMONIC="fiction perfect rapid steel bundle giant blade grain eagle wing cannon fever must humble dance kitchen lazy episode museum faith off notable rate flavor" RELAYER_JUNO_MNEMONIC="kiwi betray topple van vapor flag decorate cement crystal fee family clown cry story gain frost strong year blanket remain grass pig hen empower" RELAYER_OSMO_MNEMONIC="unaware wine ramp february bring trust leaf beyond fever inside option dilemma save know captain endless salute radio humble chicken property culture foil taxi" RELAYER_STARS_MNEMONIC="deposit dawn erosion talent old broom flip recipe pill hammer animal hill nice ten target metal gas shoe visual nephew soda harbor child simple" +RELAYER_HOST_MNEMONIC="renew umbrella teach spoon have razor knee sock divert inner nut between immense library inhale dog truly return run remain dune virus diamond clinic" RELAYER_MNEMONICS=( "$RELAYER_GAIA_MNEMONIC" "$RELAYER_JUNO_MNEMONIC" "$RELAYER_OSMO_MNEMONIC" "$RELAYER_STARS_MNEMONIC" + "$RELAYER_HOST_MNEMONIC" ) STRIDE_ADDRESS() { @@ -240,6 +255,9 @@ OSMO_ADDRESS() { STARS_ADDRESS() { $STARS_MAIN_CMD keys show ${STARS_VAL_PREFIX}1 --keyring-backend test -a } +HOST_ADDRESS() { + $HOST_MAIN_CMD keys show ${HOST_VAL_PREFIX}1 --keyring-backend test -a +} CSLEEP() { for i in $(seq $1); do diff --git a/dockernet/config/relayer_config.yaml b/dockernet/config/relayer_config.yaml index 0448700955..34d869c329 100644 --- a/dockernet/config/relayer_config.yaml +++ b/dockernet/config/relayer_config.yaml @@ -74,6 +74,20 @@ chains: timeout: 20s output-format: json sign-mode: direct + host: + type: cosmos + value: + key: rly6 + chain-id: HOST + rpc-addr: http://host1:26657 + account-prefix: stride + keyring-backend: test + gas-adjustment: 1.2 + gas-prices: 0.01uwalk + debug: false + timeout: 20s + output-format: json + sign-mode: direct # {new-host-zone}: # type: cosmos # value: @@ -122,6 +136,14 @@ paths: src-channel-filter: rule: "" channel-list: [] + stride-host: + src: + chain-id: STRIDE + dst: + chain-id: HOST + src-channel-filter: + rule: "" + channel-list: [] # stride-{new-host-zone}: # src: # chain-id: STRIDE diff --git a/dockernet/docker-compose.yml b/dockernet/docker-compose.yml index d3bea3d6b1..d46c824a78 100644 --- a/dockernet/docker-compose.yml +++ b/dockernet/docker-compose.yml @@ -134,6 +134,36 @@ services: image: stridezone:stars volumes: - ./state/stars5:/home/stars/.starsd + + host1: + image: stridezone:stride + volumes: + - ./state/host1:/home/stride/.stride + ports: + - "26157:26657" + - "1267:1317" + - "9040:9090" + + host2: + image: stridezone:stride + volumes: + - ./state/host2:/home/stride/.stride + + host3: + image: stridezone:stride + volumes: + - ./state/host3:/home/stride/.stride + + host4: + image: stridezone:stride + volumes: + - ./state/host4:/home/stride/.stride + + host5: + image: stridezone:stride + volumes: + - ./state/host5:/home/stride/.stride + # Fill in new host zone being tested here hermes: @@ -170,3 +200,10 @@ services: - ./state/relayer-stars:/home/relayer/.relayer restart: always command: [ "bash", "start.sh", "stride-stars" ] + + relayer-host: + image: stridezone:relayer + volumes: + - ./state/relayer-host:/home/relayer/.relayer + restart: always + command: [ "bash", "start.sh", "stride-host" ] diff --git a/dockernet/src/init_chain.sh b/dockernet/src/init_chain.sh index ca1b1cfd0b..9ab9903e82 100644 --- a/dockernet/src/init_chain.sh +++ b/dockernet/src/init_chain.sh @@ -9,7 +9,8 @@ CHAIN="$1" KEYS_LOGS=$DOCKERNET_HOME/logs/keys.log CHAIN_ID=$(GET_VAR_VALUE ${CHAIN}_CHAIN_ID) -CMD=$(GET_VAR_VALUE ${CHAIN}_CMD) +BINARY=$(GET_VAR_VALUE ${CHAIN}_BINARY) +MAIN_CMD=$(GET_VAR_VALUE ${CHAIN}_MAIN_CMD) DENOM=$(GET_VAR_VALUE ${CHAIN}_DENOM) RPC_PORT=$(GET_VAR_VALUE ${CHAIN}_RPC_PORT) NUM_NODES=$(GET_VAR_VALUE ${CHAIN}_NUM_NODES) @@ -34,6 +35,7 @@ set_host_genesis() { jq '(.app_state.epochs.epochs[]? | select(.identifier=="day") ).duration = $epochLen' --arg epochLen $HOST_DAY_EPOCH_DURATION $genesis_config > json.tmp && mv json.tmp $genesis_config jq '(.app_state.epochs.epochs[]? | select(.identifier=="hour") ).duration = $epochLen' --arg epochLen $HOST_HOUR_EPOCH_DURATION $genesis_config > json.tmp && mv json.tmp $genesis_config jq '(.app_state.epochs.epochs[]? | select(.identifier=="week") ).duration = $epochLen' --arg epochLen $HOST_WEEK_EPOCH_DURATION $genesis_config > json.tmp && mv json.tmp $genesis_config + jq '(.app_state.epochs.epochs[]? | select(.identifier=="mint") ).duration = $epochLen' --arg epochLen $HOST_MINT_EPOCH_DURATION $genesis_config > json.tmp && mv json.tmp $genesis_config jq '.app_state.staking.params.unbonding_time = $newVal' --arg newVal "$UNBONDING_TIME" $genesis_config > json.tmp && mv json.tmp $genesis_config # Set the mint start time to the genesis time if the chain configures inflation at the block level (e.g. stars) @@ -56,7 +58,6 @@ set_host_genesis() { MAIN_ID=1 # Node responsible for genesis and persistent_peers MAIN_NODE_NAME="" -MAIN_NODE_CMD="" MAIN_NODE_ID="" MAIN_CONFIG="" MAIN_GENESIS="" @@ -72,10 +73,10 @@ for (( i=1; i <= $NUM_NODES; i++ )); do # If the chains commands are run only from docker, grab the command from the config # Otherwise, if they're run locally, append the home directory - if [[ $CMD == docker-compose* ]]; then - cmd=$CMD + if [[ $BINARY == docker-compose* ]]; then + cmd=$BINARY else - cmd="$CMD --home ${STATE}/$node_name" + cmd="$BINARY --home ${STATE}/$node_name" fi # Initialize the chain @@ -125,52 +126,51 @@ for (( i=1; i <= $NUM_NODES; i++ )); do if [ $i -eq $MAIN_ID ]; then MAIN_NODE_NAME=$node_name - MAIN_NODE_CMD=$cmd MAIN_NODE_ID=$node_id MAIN_CONFIG=$config_toml MAIN_GENESIS=$genesis_json else # also add this account and it's genesis tx to the main node - $MAIN_NODE_CMD add-genesis-account ${val_addr} ${VAL_TOKENS}${DENOM} + $MAIN_CMD add-genesis-account ${val_addr} ${VAL_TOKENS}${DENOM} cp ${STATE}/${node_name}/config/gentx/*.json ${STATE}/${MAIN_NODE_NAME}/config/gentx/ # and add each validator's keys to the first state directory - echo "$val_mnemonic" | $MAIN_NODE_CMD keys add $val_acct --recover --keyring-backend=test &> /dev/null + echo "$val_mnemonic" | $MAIN_CMD keys add $val_acct --recover --keyring-backend=test &> /dev/null fi done if [ "$CHAIN" == "STRIDE" ]; then # add the stride admin account - echo "$STRIDE_ADMIN_MNEMONIC" | $MAIN_NODE_CMD keys add $STRIDE_ADMIN_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 - STRIDE_ADMIN_ADDRESS=$($MAIN_NODE_CMD keys show $STRIDE_ADMIN_ACCT --keyring-backend test -a) - $MAIN_NODE_CMD add-genesis-account ${STRIDE_ADMIN_ADDRESS} ${ADMIN_TOKENS}${DENOM} + echo "$STRIDE_ADMIN_MNEMONIC" | $MAIN_CMD keys add $STRIDE_ADMIN_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 + STRIDE_ADMIN_ADDRESS=$($MAIN_CMD keys show $STRIDE_ADMIN_ACCT --keyring-backend test -a) + $MAIN_CMD add-genesis-account ${STRIDE_ADMIN_ADDRESS} ${ADMIN_TOKENS}${DENOM} # add relayer accounts - for i in "${!HOST_RELAYER_ACCTS[@]}"; do - RELAYER_ACCT="${HOST_RELAYER_ACCTS[i]}" + for i in "${!RELAYER_ACCTS[@]}"; do + RELAYER_ACCT="${RELAYER_ACCTS[i]}" RELAYER_MNEMONIC="${RELAYER_MNEMONICS[i]}" - echo "$RELAYER_MNEMONIC" | $MAIN_NODE_CMD keys add $RELAYER_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 - RELAYER_ADDRESS=$($MAIN_NODE_CMD keys show $RELAYER_ACCT --keyring-backend test -a) - $MAIN_NODE_CMD add-genesis-account ${RELAYER_ADDRESS} ${VAL_TOKENS}${DENOM} + echo "$RELAYER_MNEMONIC" | $MAIN_CMD keys add $RELAYER_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 + RELAYER_ADDRESS=$($MAIN_CMD keys show $RELAYER_ACCT --keyring-backend test -a) + $MAIN_CMD add-genesis-account ${RELAYER_ADDRESS} ${VAL_TOKENS}${DENOM} done else # add a revenue account REV_ACCT_VAR=${CHAIN}_REV_ACCT REV_ACCT=${!REV_ACCT_VAR} - echo $REV_MNEMONIC | $MAIN_NODE_CMD keys add $REV_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 + echo $REV_MNEMONIC | $MAIN_CMD keys add $REV_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 # add a relayer account RELAYER_ACCT=$(GET_VAR_VALUE RELAYER_${CHAIN}_ACCT) RELAYER_MNEMONIC=$(GET_VAR_VALUE RELAYER_${CHAIN}_MNEMONIC) - echo "$RELAYER_MNEMONIC" | $MAIN_NODE_CMD keys add $RELAYER_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 - RELAYER_ADDRESS=$($MAIN_NODE_CMD keys show $RELAYER_ACCT --keyring-backend test -a | tr -cd '[:alnum:]._-') - $MAIN_NODE_CMD add-genesis-account ${RELAYER_ADDRESS} ${VAL_TOKENS}${DENOM} + echo "$RELAYER_MNEMONIC" | $MAIN_CMD keys add $RELAYER_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 + RELAYER_ADDRESS=$($MAIN_CMD keys show $RELAYER_ACCT --keyring-backend test -a | tr -cd '[:alnum:]._-') + $MAIN_CMD add-genesis-account ${RELAYER_ADDRESS} ${VAL_TOKENS}${DENOM} fi # now we process gentx txs on the main node -$MAIN_NODE_CMD collect-gentxs &> /dev/null +$MAIN_CMD collect-gentxs &> /dev/null # wipe out the persistent peers for the main node (these are incorrectly autogenerated for each validator during collect-gentxs) sed -i -E "s|persistent_peers = .*|persistent_peers = \"\"|g" $MAIN_CONFIG diff --git a/dockernet/tests/integration_tests.bats b/dockernet/tests/integration_tests.bats index e2c117cc34..6f94431740 100644 --- a/dockernet/tests/integration_tests.bats +++ b/dockernet/tests/integration_tests.bats @@ -123,11 +123,15 @@ setup_file() { assert_equal "$hval_token_balance_diff" "$TRANSFER_AMOUNT" } -@test "[INTEGRATION-BASIC-$CHAIN_NAME] liquid stake mints stToken" { - # get initial balances +@test "[INTEGRATION-BASIC-$CHAIN_NAME] liquid stake mint and transfer" { + # get initial balances on stride account token_balance_start=$($STRIDE_MAIN_CMD q bank balances $(STRIDE_ADDRESS) --denom $HOST_IBC_DENOM | GETBAL) sttoken_balance_start=$($STRIDE_MAIN_CMD q bank balances $(STRIDE_ADDRESS) --denom st$HOST_DENOM | GETBAL) + # get initial ICA accound balance + delegation_address=$(GET_ICA_ADDR $HOST_CHAIN_ID delegation) + delegation_ica_balance_start=$($HOST_MAIN_CMD q bank balances $delegation_address --denom $HOST_DENOM | GETBAL) + # liquid stake $STRIDE_MAIN_CMD tx stakeibc liquid-stake $STAKE_AMOUNT $HOST_DENOM --from $STRIDE_VAL -y @@ -144,13 +148,8 @@ setup_file() { sttoken_balance_end=$($STRIDE_MAIN_CMD q bank balances $(STRIDE_ADDRESS) --denom st$HOST_DENOM | GETBAL) sttoken_balance_diff=$(($sttoken_balance_end-$sttoken_balance_start)) assert_equal "$sttoken_balance_diff" $STAKE_AMOUNT -} -# check that tokens were transferred to host after liquid stake -@test "[INTEGRATION-BASIC-$CHAIN_NAME] tokens were transferred to $HOST_CHAIN_ID after liquid staking" { - # initial balance of delegation ICA - delegation_address=$(GET_ICA_ADDR $HOST_CHAIN_ID delegation) - delegation_ica_balance_start=$($HOST_MAIN_CMD q bank balances $delegation_address --denom $HOST_DENOM | GETBAL) + # Wait for the transfer to complete WAIT_FOR_BALANCE_CHANGE $CHAIN_NAME $delegation_address $HOST_DENOM # get the new delegation ICA balance diff --git a/dockernet/tests/run_all_tests.sh b/dockernet/tests/run_all_tests.sh index 23e4eae2db..a67a453623 100755 --- a/dockernet/tests/run_all_tests.sh +++ b/dockernet/tests/run_all_tests.sh @@ -6,5 +6,5 @@ BATS=${SCRIPT_DIR}/bats/bats-core/bin/bats INTEGRATION_TEST_FILE=${SCRIPT_DIR}/integration_tests.bats CHAIN_NAME=GAIA TRANSFER_CHANNEL_NUMBER=0 $BATS $INTEGRATION_TEST_FILE -CHAIN_NAME=JUNO TRANSFER_CHANNEL_NUMBER=1 $BATS $INTEGRATION_TEST_FILE -CHAIN_NAME=OSMO TRANSFER_CHANNEL_NUMBER=2 $BATS $INTEGRATION_TEST_FILE \ No newline at end of file +CHAIN_NAME=OSMO TRANSFER_CHANNEL_NUMBER=1 $BATS $INTEGRATION_TEST_FILE +CHAIN_NAME=HOST TRANSFER_CHANNEL_NUMBER=2 $BATS $INTEGRATION_TEST_FILE diff --git a/dockernet/upgrades/README.md b/dockernet/upgrades/README.md index ca35ae9d05..e85ea061a8 100644 --- a/dockernet/upgrades/README.md +++ b/dockernet/upgrades/README.md @@ -35,5 +35,5 @@ bash dockernet/upgrades/submit_upgrade.sh * Run integration tests for GAIA and JUNO (comment out OSMO and STARS in `dockernet/tests/run_all_tests.sh`) * Once the tests pass, grab the current block height, modify `dockernet/upgrades/submit_upgrade.sh` to have an upgrade height ~50 blocks in the future, and run the script * Check the stride logs to confirm the upgrade passes successfully -* Modify `STRIDE_CMD` in `config.sh` to point to the **new** binary (`STRIDE_CMD="$UPGRADES/binaries/strided2"`) +* Modify `STRIDE_BINARY` in `config.sh` to point to the **new** binary (`STRIDE_BINARY="$UPGRADES/binaries/strided2"`) * Finally, run integration tests for OSMO and STARS (comment out GAIA and JUNO in `dockernet/tests/run_all_tests.sh`) diff --git a/x/stakeibc/keeper/get_denom_traces_test.go b/x/stakeibc/keeper/get_denom_traces_test.go index 38e1bcc0d9..78a2870c84 100644 --- a/x/stakeibc/keeper/get_denom_traces_test.go +++ b/x/stakeibc/keeper/get_denom_traces_test.go @@ -5,7 +5,7 @@ package keeper_test // import ( // "fmt" -// transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" +// transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" // ) // func (s *KeeperTestSuite) TestIBCDenom() { diff --git a/x/stakeibc/keeper/icqcallbacks_withdrawal_balance.go b/x/stakeibc/keeper/icqcallbacks_withdrawal_balance.go index 1c0d6a69f0..7c3610804f 100644 --- a/x/stakeibc/keeper/icqcallbacks_withdrawal_balance.go +++ b/x/stakeibc/keeper/icqcallbacks_withdrawal_balance.go @@ -4,6 +4,7 @@ import ( "fmt" sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -30,26 +31,18 @@ func WithdrawalBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icq return sdkerrors.Wrapf(types.ErrHostZoneNotFound, "no registered zone for queried chain ID (%s)", chainId) } - // Unmarshal the query response args into a coin type - withdrawalBalanceCoin := sdk.Coin{} - err := k.cdc.Unmarshal(args, &withdrawalBalanceCoin) + // Unmarshal the query response args to determine the balance + withdrawalBalanceAmount, err := UnmarshalAmountFromBalanceQuery(k.cdc, args) if err != nil { - return sdkerrors.Wrapf(types.ErrUnmarshalFailure, "unable to unmarshal query response into Coin type, err: %s", err.Error()) - } - k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_WithdrawalBalance, "Query response - Coin: %+v", withdrawalBalanceCoin)) - - // Check if the coin is nil (which would indicate the account never had a balance) - if withdrawalBalanceCoin.IsNil() || withdrawalBalanceCoin.Amount.IsNil() { - k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_WithdrawalBalance, - "Balance query returned a nil coin for address %v, meaning the account has never had a balance on the host", - hostZone.WithdrawalAccount.GetAddress())) - return nil + return sdkerrors.Wrap(err, "unable to determine balance from query response") } + k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_WithdrawalBalance, + "Query response - Withdrawal Balance: %v %s", withdrawalBalanceAmount, hostZone.HostDenom)) // Confirm the balance is greater than zero - if withdrawalBalanceCoin.Amount.LTE(sdkmath.ZeroInt()) { + if withdrawalBalanceAmount.LTE(sdkmath.ZeroInt()) { k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_WithdrawalBalance, - "No balance to transfer for address: %v, coin: %v", hostZone.WithdrawalAccount.GetAddress(), withdrawalBalanceCoin.String())) + "No balance to transfer for address: %v, balance: %v", hostZone.WithdrawalAccount.GetAddress(), withdrawalBalanceAmount)) return nil } @@ -81,7 +74,6 @@ func WithdrawalBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icq } // Split out the reinvestment amount from the fee amount - withdrawalBalanceAmount := withdrawalBalanceCoin.Amount feeAmount := strideCommission.Mul(sdk.NewDecFromInt(withdrawalBalanceAmount)).TruncateInt() reinvestAmount := withdrawalBalanceAmount.Sub(feeAmount) @@ -92,8 +84,8 @@ func WithdrawalBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icq } // Prepare MsgSends from the withdrawal account - feeCoin := sdk.NewCoin(withdrawalBalanceCoin.Denom, feeAmount) - reinvestCoin := sdk.NewCoin(withdrawalBalanceCoin.Denom, reinvestAmount) + feeCoin := sdk.NewCoin(hostZone.HostDenom, feeAmount) + reinvestCoin := sdk.NewCoin(hostZone.HostDenom, reinvestAmount) var msgs []sdk.Msg if feeCoin.Amount.GT(sdk.ZeroInt()) { @@ -136,9 +128,44 @@ func WithdrawalBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icq sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute("hostZone", hostZone.ChainId), - sdk.NewAttribute("totalWithdrawalBalance", withdrawalBalanceCoin.Amount.String()), + sdk.NewAttribute("totalWithdrawalBalance", withdrawalBalanceAmount.String()), ), ) return nil } + +// Helper function to unmarshal a Balance query response across SDK versions +// Before SDK v46, the query response returned a sdk.Coin type. SDK v46 returns an int type +// https://github.com/cosmos/cosmos-sdk/pull/9832 +func UnmarshalAmountFromBalanceQuery(cdc codec.BinaryCodec, queryResponseBz []byte) (amount sdkmath.Int, err error) { + // An nil should not be possible, exit immediately if it occurs + if queryResponseBz == nil { + return sdkmath.Int{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "query response is nil") + } + + // If the query response is empty, that means the account was never registed (and thus has a 0 balance) + if len(queryResponseBz) == 0 { + return sdkmath.ZeroInt(), nil + } + + // First attempt to unmarshal as an Int (for SDK v46+) + // If the result was serialized as a `Coin` type, it should contain a string (representing the denom) + // which will cause the unmarshalling to throw an error + intError := amount.Unmarshal(queryResponseBz) + if intError == nil { + return amount, nil + } + + // If the Int unmarshaling was unsuccessful, attempt again using a Coin type (for SDK v45 and below) + // If successful, return the amount field from the coin (if the coin is not nil) + var coin sdk.Coin + coinError := cdc.Unmarshal(queryResponseBz, &coin) + if coinError == nil { + return coin.Amount, nil + } + + // If it failed unmarshaling with either data structure, return an error with the failure messages combined + return sdkmath.Int{}, sdkerrors.Wrapf(types.ErrUnmarshalFailure, + "unable to unmarshal balance query response %v as sdkmath.Int (err: %s) or sdk.Coin (err: %s)", queryResponseBz, intError.Error(), coinError.Error()) +} diff --git a/x/stakeibc/keeper/icqcallbacks_withdrawal_balance_test.go b/x/stakeibc/keeper/icqcallbacks_withdrawal_balance_test.go index 79038a41a4..a3648f3067 100644 --- a/x/stakeibc/keeper/icqcallbacks_withdrawal_balance_test.go +++ b/x/stakeibc/keeper/icqcallbacks_withdrawal_balance_test.go @@ -2,10 +2,12 @@ package keeper_test import ( "fmt" + "testing" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" ibctesting "github.com/cosmos/ibc-go/v5/testing" + "github.com/stretchr/testify/require" icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types" @@ -37,7 +39,7 @@ type WithdrawalBalanceICQCallbackTestCase struct { // the address' balance. This function creates the serialized response func (s *KeeperTestSuite) CreateBalanceQueryResponse(amount int64, denom string) []byte { coin := sdk.NewCoin(denom, sdkmath.NewInt(amount)) - coinBz := s.App.RecordsKeeper.Cdc.MustMarshal(&coin) + coinBz := s.App.AppCodec().MustMarshal(&coin) return coinBz } @@ -54,6 +56,7 @@ func (s *KeeperTestSuite) SetupWithdrawalBalanceCallbackTest() WithdrawalBalance hostZone := stakeibctypes.HostZone{ ChainId: HostChainId, + HostDenom: Atom, ConnectionId: ibctesting.FirstConnectionID, DelegationAccount: &stakeibctypes.ICAAccount{ Address: delegationAddress, @@ -199,9 +202,7 @@ func (s *KeeperTestSuite) TestWithdrawalBalanceCallback_InvalidArgs() { invalidArgs := []byte("random bytes") err := stakeibckeeper.WithdrawalBalanceCallback(s.App.StakeibcKeeper, s.Ctx, invalidArgs, tc.validArgs.query) - expectedErrMsg := "unable to unmarshal query response into Coin type, " - expectedErrMsg += "err: unexpected EOF: unable to unmarshal data structure" - s.Require().EqualError(err, expectedErrMsg) + s.Require().ErrorContains(err, "unable to determine balance from query response") } func (s *KeeperTestSuite) TestWithdrawalBalanceCallback_NoWithdrawalAccount() { @@ -252,3 +253,114 @@ func (s *KeeperTestSuite) TestWithdrawalBalanceCallback_FailedSubmitTx() { s.Require().ErrorContains(err, "Failed to SubmitTxs") s.Require().ErrorContains(err, "invalid connection id, connection-X not found") } + +func TestUnmarshalAmountFromBalanceQuery(t *testing.T) { + type InputType int64 + const ( + rawBytes InputType = iota + coinType + intType + ) + + testCases := []struct { + name string + inputType InputType + raw []byte + coin sdk.Coin + integer sdkmath.Int + expectedAmount sdkmath.Int + expectedError string + }{ + { + name: "full_coin", + inputType: coinType, + coin: sdk.Coin{Denom: "denom", Amount: sdkmath.NewInt(50)}, + expectedAmount: sdkmath.NewInt(50), + }, + { + name: "coin_no_denom", + inputType: coinType, + coin: sdk.Coin{Amount: sdkmath.NewInt(60)}, + expectedAmount: sdkmath.NewInt(60), + }, + { + name: "coin_no_amount", + inputType: coinType, + coin: sdk.Coin{Denom: "denom"}, + expectedAmount: sdkmath.NewInt(0), + }, + { + name: "zero_coin", + inputType: coinType, + coin: sdk.Coin{Amount: sdkmath.NewInt(0)}, + expectedAmount: sdkmath.NewInt(0), + }, + { + name: "empty_coin", + inputType: coinType, + coin: sdk.Coin{}, + expectedAmount: sdkmath.NewInt(0), + }, + { + name: "positive_int", + inputType: intType, + integer: sdkmath.NewInt(20), + expectedAmount: sdkmath.NewInt(20), + }, + { + name: "zero_int", + inputType: intType, + integer: sdkmath.NewInt(0), + expectedAmount: sdkmath.NewInt(0), + }, + { + name: "empty_int", + inputType: intType, + integer: sdkmath.Int{}, + expectedAmount: sdkmath.NewInt(0), + }, + { + name: "empty_bytes", + inputType: rawBytes, + raw: []byte{}, + expectedAmount: sdkmath.NewInt(0), + }, + { + name: "invalid_bytes", + inputType: rawBytes, + raw: []byte{1, 2}, + expectedError: "unable to unmarshal balance query response", + }, + { + name: "nil_bytes", + inputType: rawBytes, + raw: nil, + expectedError: "query response is nil", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var args []byte + var err error + switch tc.inputType { + case rawBytes: + args = tc.raw + case coinType: + args, err = tc.coin.Marshal() + case intType: + args, err = tc.integer.Marshal() + } + require.NoError(t, err) + + if tc.expectedError == "" { + actualAmount, err := stakeibckeeper.UnmarshalAmountFromBalanceQuery(stakeibctypes.ModuleCdc, args) + require.NoError(t, err) + require.Equal(t, tc.expectedAmount.Int64(), actualAmount.Int64()) + } else { + _, err := stakeibckeeper.UnmarshalAmountFromBalanceQuery(stakeibctypes.ModuleCdc, args) + require.ErrorContains(t, err, tc.expectedError) + } + }) + } +}