Skip to content

Commit

Permalink
feat(local-ic): bash driver (#1207)
Browse files Browse the repository at this point in the history
* feat: bash client base

* just data return

* faucet

* GET_PEER

* working foundation

* `ICT_` prefix

* bash e2e

* fix: e2e

* rm unused bash-e2e rust logic

* `bash ./test.bash`

* ICT_POLL_FOR_START

* upload files + cw,

* test: store file

* local-ize bash variables to not leak context

* `;`
  • Loading branch information
Reecepbcups authored Aug 20, 2024
1 parent b2ba0ef commit a2d674e
Show file tree
Hide file tree
Showing 4 changed files with 290 additions and 4 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/local-interchain.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,40 @@ jobs:
name: local-ic
path: ~/go/bin/local-ic

bash-e2e:
name: bash
needs: build
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./local-interchain
strategy:
fail-fast: false

steps:
- name: checkout chain
uses: actions/checkout@v4

- name: Download Tarball Artifact
uses: actions/download-artifact@v3
with:
name: local-ic
path: /tmp

- name: Make local-ic executable
run: chmod +x /tmp/local-ic

- name: Start background ibc local-interchain
run: /tmp/local-ic start juno_ibc --api-port 8080 &

- name: Run Bash Script
run: |
cd bash
bash ./test.bash
- name: Cleanup
run: killall local-ic && exit 0

rust-e2e:
name: rust
needs: build
Expand Down
152 changes: 152 additions & 0 deletions local-interchain/bash/source.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# IMPORT ME WITH: source <(curl -s https://raw.githubusercontent.com/strangelove-ventures/interchaintest/main/local-interchain/bash/source.bash)

# exitIfEmpty "$someKey" someKey
function ICT_exitIfEmpty() {
if [ -z "$1" ]; then
echo "Exiting because ${2} is empty"
exit 1
fi
}

# === BASE ===

# ICT_MAKE_REQUEST http://127.0.0.1:8080 localjuno-1 "q" "bank total"
ICT_MAKE_REQUEST() {
local API=$1 CHAIN_ID=$2 ACTION=$3
shift 3 # get the 4th argument and up as the command
local COMMAND="$*"

DATA=`printf '{"chain_id":"%s","action":"%s","cmd":"MYCOMMAND"}' $CHAIN_ID $ACTION`
DATA=`echo $DATA | sed "s/MYCOMMAND/$COMMAND/g"`

curl "$API" -ss --no-progress-meter --header "Content-Type: application/json" -X POST -d "$DATA"
}

# ICT_QUERY "http://localhost:8080" "localjuno-1" "bank balances juno10r39fueph9fq7a6lgswu4zdsg8t3gxlq670lt0"
ICT_QUERY() {
local API=$1 CHAIN_ID=$2 CMD=$3 # can be multiple words
ICT_MAKE_REQUEST "$API" $CHAIN_ID "q" "$CMD"
}

# ICT_BIN "http://localhost:8080" "localjuno-1" "decode"
ICT_BIN() {
local API=$1 CHAIN_ID=$2 CMD=$3 # can be multiple words
ICT_MAKE_REQUEST "$API" $CHAIN_ID "bin" "$CMD"
}

# ICT_SH_EXEC "http://localhost:8080" "localjuno-1" "ls -l"
# NOTE: if using a /, make sure to escape it with \
ICT_SH_EXEC() {
local API=$1 CHAIN_ID=$2 CMD=$3 # can be multiple words
ICT_MAKE_REQUEST "$API" $CHAIN_ID "exec" "$CMD"
}

# === RELAYER ===

# ICT_RELAYER_STOP http://127.0.0.1 "localjuno-1"
ICT_RELAYER_STOP() {
local API=$1 CHAIN_ID=$2

# TODO: how does this function?
ICT_MAKE_REQUEST $API $CHAIN_ID "stop-relayer" ""
}

# ICT_RELAYER_START http://127.0.0.1 "localjuno-1" "demo-path2 --max-tx-size 10"
ICT_RELAYER_START() {
local API=$1 CHAIN_ID=$2 CMD=$3

ICT_MAKE_REQUEST $API $CHAIN_ID "start-relayer" "$CMD"
}

# RELAYER_EXEC http://127.0.0.1:8080 "localjuno-1" "rly paths list"
ICT_RELAYER_EXEC() {
local API=$1 CHAIN_ID=$2
shift 2 # get the 3rd argument and up as the command
local CMD="$*"

ICT_MAKE_REQUEST $API $CHAIN_ID "relayer-exec" "$CMD"
}

# RELAYER_CHANNELS http://127.0.0.1:8080 "localjuno-1"
ICT_RELAYER_CHANNELS() {
local API=$1 CHAIN_ID=$2

ICT_MAKE_REQUEST $API $CHAIN_ID "get_channels" ""
}

# === COSMWASM ===

# ICT_WASM_DUMP_CONTRACT_STATE "http://localhost:8080" "localjuno-1" "cosmos1contractaddress" "100"
ICT_WASM_DUMP_CONTRACT_STATE() {
local API=$1 CHAIN_ID=$2 CONTRACT=$3 HEIGHT=$4

ICT_MAKE_REQUEST $API $CHAIN_ID "recover-key" "contract=$CONTRACT;height=$HEIGHT"
}

# ICT_WASM_STORE_FILE "http://localhost:8080" "localjuno-1" "/host/absolute/path.wasm" "keyName"
# returns the code_id of the uploaded contract
ICT_WASM_STORE_FILE() {
local API=$1 CHAIN_ID=$2 FILE=$3 KEYNAME=$4

DATA=`printf '{"chain_id":"%s","file_path":"%s","key_name":"%s"}' $CHAIN_ID $FILE $KEYNAME`
curl "$API/upload" --header "Content-Type: application/json" --header "Upload-Type: cosmwasm" -X POST -d "$DATA"
}

# === OTHER ===

# ICT_POLL_FOR_START "http://localhost:8080" 50
ICT_POLL_FOR_START() {
local API=$1 ATTEMPTS_MAX=$2

curl --head -X GET --retry $ATTEMPTS_MAX --retry-connrefused --retry-delay 3 $API
}

# ICT_KILL_ALL "http://localhost:8080" "localjuno-1"
# (Kills all running, keeps local-ic process. `killall local-ic` to kill that as well)
ICT_KILL_ALL() {
local API=$1 CHAIN_ID=$2
ICT_MAKE_REQUEST $API $CHAIN_ID "kill-all" ""
}

# ICT_GET_PEER "http://localhost:8080" "localjuno-1"
ICT_GET_PEER() {
local API=$1 CHAIN_ID=$2

if [[ $API != */info ]]; then
API="$API/info"
fi

curl -G -d "chain_id=$CHAIN_ID" -d "request=peer" $API
}

# ICT_FAUCET_REQUEST "http://localhost:8080" "localjuno-1" "1000000000ujuno" "juno1qk7zqy3k2v3jx2zq2z2zq2zq2zq2zq2zq2zq"
ICT_FAUCET_REQUEST() {
local API=$1 CHAIN_ID=$2 AMOUNT=$3 ADDRESS=$4
ICT_MAKE_REQUEST $API $CHAIN_ID "faucet" "amount=$AMOUNT;address=$ADDRESS"
}

# ICT_ADD_FULL_NODE http://127.0.0.1:8080 "localjuno-1" "1"
ICT_ADD_FULL_NODE() {
local API=$1 CHAIN_ID=$2 AMOUNT=$3

ICT_MAKE_REQUEST $API $CHAIN_ID "add-full-nodes" "amount=$AMOUNT"
}

# ICT_RECOVER_KEY "http://localhost:8080" "localjuno-1" "mykey" "my mnemonic string here"
ICT_RECOVER_KEY() {
local API=$1 CHAIN_ID=$2 KEYNAME=$3
shift 3 # get the 4th argument and up as the command
local MNEMONIC="$*"

ICT_MAKE_REQUEST $API $CHAIN_ID "recover-key" "keyname=$KEYNAME;mnemonic=$MNEMONIC"
}

# ICT_STORE_FILE "http://localhost:8080" "localjuno-1" "/host/absolute/path"
# Uploads any arbitrary host file to the chain node.
ICT_STORE_FILE() {
local API=$1 CHAIN_ID=$2 FILE=$3

DATA=`printf '{"chain_id":"%s","file_path":"%s"}' $CHAIN_ID $FILE`
curl "$API/upload" --header "Content-Type: application/json" -X POST -d "$DATA"
}

88 changes: 88 additions & 0 deletions local-interchain/bash/test.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash
# local-ic start juno_ibc
#
# bash local-interchain/bash/test.bash

# exits if any command is non 0 status
set -e

thisDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
# EXTERNAL: source <(curl -s https://raw.githubusercontent.com/strangelove-ventures/interchaintest/main/local-interchain/bash/source.bash)
source "$thisDir/source.bash"
API_ADDR="http://localhost:8080"

# === BEGIN TESTS ===

ICT_POLL_FOR_START $API_ADDR 50

# Set standard interaction defaults
ICT_BIN "$API_ADDR" "localjuno-1" "config keyring-backend test"
ICT_BIN "$API_ADDR" "localjuno-1" "config output json"

# Get total bank supply
BANK_TOTAL=`ICT_QUERY $API_ADDR "localjuno-1" "bank total"` && echo "BANK_TOTAL: $BANK_TOTAL"
ICT_exitIfEmpty "$BANK_TOTAL" "BANK_TOTAL"
echo $BANK_TOTAL | jq -r '.supply'

# Get total bank supply another way (directly)
BANK_TOTAL=`ICT_MAKE_REQUEST $API_ADDR "localjuno-1" "q" "bank total"` && echo "BANK_TOTAL: $BANK_TOTAL"
ICT_exitIfEmpty "$BANK_TOTAL" "BANK_TOTAL"
echo $BANK_TOTAL | jq -r '.supply'

# faucet to user
FAUCET_RES=`ICT_FAUCET_REQUEST "$API_ADDR" "localjuno-1" "7" "juno10r39fueph9fq7a6lgswu4zdsg8t3gxlq670lt0"` && echo "FAUCET_RES: $FAUCET_RES"
FAUCET_CONFIRM=`ICT_QUERY $API_ADDR "localjuno-1" "bank balances juno10r39fueph9fq7a6lgswu4zdsg8t3gxlq670lt0"` && echo "FAUCET_CONFIRM: $FAUCET_CONFIRM"
ICT_exitIfEmpty "$FAUCET_CONFIRM" "FAUCET_CONFIRM"

if [ $(echo $FAUCET_CONFIRM | jq -r '.balances[0].amount') -lt 7 ]; then
echo "FAUCET_CONFIRM is less than 7"
exit 1
fi

# CosmWasm - Upload source file to chain & store
parent_dir=$(dirname $thisDir) # local-interchain folder
contract_source="$parent_dir/contracts/cw_ibc_example.wasm"
CODE_ID_JSON=`ICT_WASM_STORE_FILE $API_ADDR "localjuno-1" "$contract_source" "acc0"` && echo "CODE_ID_JSON: $CODE_ID_JSON"
CODE_ID=`echo $CODE_ID_JSON | jq -r '.code_id'` && echo "CODE_ID: $CODE_ID"
ICT_exitIfEmpty "$CODE_ID" "CODE_ID"

# Upload random file
FILE_RESP=`ICT_STORE_FILE $API_ADDR "localjuno-1" "$thisDir/test.bash"` && echo "FILE_RESP: $FILE_RESP"
FILE_LOCATION=`echo $FILE_RESP | jq -r '.location'` && echo "FILE_LOCATION: $FILE_LOCATION"
ICT_exitIfEmpty "$FILE_LOCATION" "FILE_LOCATION"

# Verify file contents are there
FILE_LOCATION_ESC=$(echo $FILE_LOCATION | sed 's/\//\\\//g')
MISC_BASH_CMD=`ICT_SH_EXEC "$API_ADDR" "localjuno-1" "cat $FILE_LOCATION_ESC"` && echo "MISC_BASH_CMD: $MISC_BASH_CMD"
ICT_exitIfEmpty "$MISC_BASH_CMD" "MISC_BASH_CMD"

PEER=`ICT_GET_PEER $API_ADDR "localjuno-1"` && echo "PEER: $PEER"
ICT_exitIfEmpty "$PEER" "PEER"

# RELAYER
CHANNELS=`ICT_RELAYER_CHANNELS $API_ADDR "localjuno-1"` && echo "CHANNELS: $CHANNELS"
ICT_exitIfEmpty "$CHANNELS" "CHANNELS"

ICT_RELAYER_EXEC $API_ADDR "localjuno-1" "rly paths list"
ICT_RELAYER_EXEC $API_ADDR "localjuno-1" "rly chains list"
RLY_BALANCE=`ICT_RELAYER_EXEC $API_ADDR "localjuno-1" "rly q balance localjuno-1 --output=json"` && echo "RLY_BALANCE: $RLY_BALANCE"
ICT_exitIfEmpty "$RLY_BALANCE" "RLY_BALANCE"
echo $RLY_BALANCE | jq -r '.balance'


# Recover a key and validate
COSMOS_KEY_STATUS=`ICT_RECOVER_KEY $API_ADDR "localjuno-1" "mynewkey" "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art"` && echo "COSMOS_KEY_STATUS: $COSMOS_KEY_STATUS"

COSMOS_KEY_ADDRESS=`ICT_BIN "$API_ADDR" "localjuno-1" "keys show mynewkey -a"` && echo "COSMOS_KEY_ADDRESS: $COSMOS_KEY_ADDRESS"
ICT_exitIfEmpty "$COSMOS_KEY_ADDRESS" "COSMOS_KEY_ADDRESS"

FULL_NODE_ADDED=`ICT_ADD_FULL_NODE $API_ADDR "localjuno-1" "1"`
ICT_exitIfEmpty "$FULL_NODE_ADDED" "FULL_NODE_ADDED"

# Stop the relayer
ICT_RELAYER_STOP $API_ADDR "localjuno-1"

# Kills all containers, not the local-ic process. Use `killall local-ic` to kill that as well
ICT_KILL_ALL $API_ADDR "localjuno-1"

exit 0
20 changes: 16 additions & 4 deletions local-interchain/interchain/handlers/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,21 +151,29 @@ func (a *actions) PostActions(w http.ResponseWriter, r *http.Request) {

// Relayer Actions if the above is not used.
if len(stdout) == 0 && len(stderr) == 0 && err == nil {
if err := a.relayerCheck(w, r); err != nil {
return
}

switch action {
case "stop-relayer", "stop_relayer", "stopRelayer":
if err := a.relayerCheck(w, r); err != nil {
return
}

err = a.relayer.StopRelayer(a.ctx, a.eRep)

case "start-relayer", "start_relayer", "startRelayer":
if err := a.relayerCheck(w, r); err != nil {
return
}

paths := strings.FieldsFunc(ah.Cmd, func(c rune) bool {
return c == ',' || c == ' '
})
err = a.relayer.StartRelayer(a.ctx, a.eRep, paths...)

case "relayer", "relayer-exec", "relayer_exec", "relayerExec":
if err := a.relayerCheck(w, r); err != nil {
return
}

if !strings.Contains(ah.Cmd, "--home") {
// does this ever change for any other relayer?
cmd = append(cmd, "--home", "/home/relayer")
Expand All @@ -177,6 +185,10 @@ func (a *actions) PostActions(w http.ResponseWriter, r *http.Request) {
err = res.Err

case "get_channels", "get-channels", "getChannels":
if err := a.relayerCheck(w, r); err != nil {
return
}

res, err := a.relayer.GetChannels(a.ctx, a.eRep, chainId)
if err != nil {
util.WriteError(w, err)
Expand Down

0 comments on commit a2d674e

Please sign in to comment.