diff --git a/.gitignore b/.gitignore index 3f864b31..5f89e09a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ node_modules release .DS_Store -/scripts/ test/.env tmp-* diff --git a/config.yml b/config.yml index 82d0fb61..5d546073 100644 --- a/config.yml +++ b/config.yml @@ -77,12 +77,15 @@ genesis: min_gas_price: "1" gov: params: + voting_period: 120s max_deposit_period: 300s min_deposit: - - amount: "50_000_000_000" + - amount: "50_000" + denom: tkyve + expedited_voting_period: 60s + expedited_min_deposit: + - amount: "100_000" denom: tkyve - voting_period: 20s - quorum: "0.001" mint: params: mint_denom: "tkyve" diff --git a/go.work.sum b/go.work.sum index f4aa37fb..a4accb27 100644 --- a/go.work.sum +++ b/go.work.sum @@ -403,6 +403,8 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -516,8 +518,6 @@ github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+Ro github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= github.com/cosmos/iavl v1.0.1/go.mod h1:8xIUkgVvwvVrBu81scdPty+/Dx9GqwHnAvXz4cwF7RY= -github.com/cosmos/ibc-go/v8 v8.2.0 h1:7oCzyy1sZCcgpeQLnHxC56brsSz3KWwQGKXalXwXFzE= -github.com/cosmos/ibc-go/v8 v8.2.0/go.mod h1:wj3qx75iC/XNnsMqbPDCIGs0G6Y3E/lo3bdqCyoCy+8= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= diff --git a/scripts/commands.sh b/scripts/commands.sh new file mode 100755 index 00000000..0c767fe2 --- /dev/null +++ b/scripts/commands.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# Source this file with `source scripts/commands.sh` to use the functions in your shell. +# First argument can be an alternative binary path, e.g. `source scripts/commands.sh /path/to/kyved`. + +RED="\e[31m" +GREEN="\e[32m" +ENDCOLOR="\e[0m" + +export BINARY=${1:-"kyved"} + +# Check if binary is executable +if ! command -v "$BINARY" &> /dev/null; then + echo -e "$RED✗ $BINARY binary not found. Please install it or use the correct path.$ENDCOLOR" + return +fi + +export CHAIN_ID=$($BINARY status --output json | jq -r '.node_info.network' | tr -d '\"') +if [[ -z "$CHAIN_ID" ]]; then + export CHAIN_ID=$($BINARY status | jq -r '.NodeInfo.network' | tr -d '\"') + if [[ -z "$CHAIN_ID" ]]; then + echo -e "$RED✗ Could not fetch chain ID. Make sure your node is running.$ENDCOLOR" + return + fi +fi + +export TX="--gas 200000 --fees 5000000tkyve --yes --chain-id $CHAIN_ID" +export ALICE_TX="$TX --from alice" +export TESTBACKEND="--keyring-backend test" +export CHAINHOME="--home ~/.chain" +export JSON="--output json" + +check_tx() { + echo "🔍 Checking transaction..." + + local tx_output + local tx_hash + local code + tx_output=$(cat -) + tx_hash=$(echo "$tx_output" | jq -r '.txhash' | tr -d '.') + code=$(echo "$tx_output" | jq -r '.code' | tr -d '.') + + if [[ -z "$tx_hash" || "$code" -ne 0 ]]; then + local raw_log=$(echo "$tx_output" | jq -r '.raw_log') + echo -e "${RED}✗ Transaction failed with code $code:\n$raw_log${ENDCOLOR}" + return "$code" + fi + + local sleep_time=0.5 + local elapsed_seconds=0 + local progress_bar="" + + # Run a loop to check for tx_output + while true; do + local tx_output=$(kyved q tx "$tx_hash" --output json 2>/dev/null) + local code=$(echo "$tx_output" | jq -r '.code') + + if [[ -z "$code" ]]; then + printf "\r⏳ Fetching transaction: %02d seconds | Progress: [%-30s]" "$elapsed_seconds" "$progress_bar" + sleep $sleep_time + ((elapsed_seconds++)) + progress_bar+="=" + else + break + fi + done + + echo "" + + if [[ "$code" -eq 0 ]]; then + echo "✏️ logs:" + echo "$tx_output" | jq '.logs' + echo "" + echo -e "${GREEN}✅ Transaction $tx_hash successful!${ENDCOLOR}" + else + echo "✏️ raw_log:" + echo "$tx_output" | jq '.raw_log' + echo "" + echo -e "${RED}✗ Transaction $tx_hash failed with code $code.${ENDCOLOR}" + fi + return "$code" +} +export -f check_tx + +echo "👋 Welcome to the KYVE CLI!" +echo "" +echo "# Environment variables -> override with your own values" +echo "export TX=\"$TX\"" +echo "export ALICE_TX=\"$ALICE_TX\"" +echo "export TESTBACKEND=\"$TESTBACKEND\"" +echo "export CHAINHOME=\"$CHAINHOME\"" +echo "export JSON=\"$JSON\"" +echo "" +echo "# Add Alice's key" +echo "$BINARY keys add alice --recover \$TESTBACKEND" +echo "# Mnemonic" +echo "expect crisp umbrella hospital firm exhibit future size slot update blood deliver fat happy ghost visa recall usual path purity junior ring ordinary stove" +echo "" +echo "# Send coins" +echo "$BINARY tx bank send alice kyve1jve70gkvgyvdnrxw4q7ry7vq2asu25ac0m48vk 1000tkyve \$CHAINHOME \$TESTBACKEND \$TX \$JSON | check_tx" +echo "" +echo "# Governance" +echo "$BINARY tx gov draft-proposal" +echo "$BINARY tx gov submit-proposal draft_proposal.json \$ALICE_TX \$CHAINHOME \$TESTBACKEND \$TX \$JSON | check_tx" +echo "$BINARY tx gov vote \$($BINARY q gov proposals --page-limit 1 --page-reverse --proposal-status voting-period \$JSON | jq '.proposals[0].id | tonumber') yes \$ALICE_TX \$CHAINHOME \$TESTBACKEND \$JSON | check_tx" +echo "" +echo "# Funders" +echo "$BINARY tx funders create-funder Alice \$CHAINHOME \$TESTBACKEND \$ALICE_TX \$JSON | check_tx" +echo "$BINARY tx funders update-funder Alice \$CHAINHOME \$TESTBACKEND \$ALICE_TX \$JSON | check_tx" diff --git a/scripts/perform-chain-upgrade.sh b/scripts/perform-chain-upgrade.sh new file mode 100755 index 00000000..760b65b4 --- /dev/null +++ b/scripts/perform-chain-upgrade.sh @@ -0,0 +1,156 @@ +#!/bin/bash +# This script is only used for local testing. Do not use it in production. + +RED="\e[31m" +ENDCOLOR="\e[0m" + +# Check if at least upgrade name is provided +if [ $# -lt 1 ]; then + echo -e "$RED✗ Usage: perform-chain-upgrade.sh [upgrade_name] [wait_blocks (default=30)]$ENDCOLOR" + exit 1 +fi + +# Check if wait_blocks is provided +if [ -z "$2" ]; then + WAIT_BLOCKS=30 +else + WAIT_BLOCKS=$2 +fi + +echo "🚀 Upgrading chain to $1 in $WAIT_BLOCKS blocks" + +# Check if binary env is set +if [ -z "$BINARY" ]; then + echo -e "$RED✗ BINARY env not set. Please source commands.sh before running this script$ENDCOLOR" + exit 1 +fi + +get_height() { + local height= + height=$($BINARY status | jq '.sync_info.latest_block_height' | tr -d '\"') + if [ "$height" == "null" ]; then + height=$($BINARY status | jq '.SyncInfo.latest_block_height' | tr -d '\"') + if [[ -z "$height" ]]; then + exit 1 + fi + fi + echo "$height" +} + +PROPOSAL='{ + "messages": [ + { + "@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade", + "authority": "kyve10d07y265gmmuvt4z0w9aw880jnsr700jdv7nah", + "plan": { + "name": "MY_UPGRADE_NAME", + "height": "MY_UPGRADE_height", + "info": "" + } + } + ], + "metadata": "ipfs://QmSbXwSgAnhhkDk5LtvgEwKUf6iUjww5FbMngYs86uGxdG", + "deposit": "50000000000MY_DENOM", + "title": "Upgrade to MY_UPGRADE_NAME", + "summary": "This is an upgrade to MY_UPGRADE_NAME", + "expedited": false +}' + +NAME=$1 +UPGRADE_HEIGHT=`expr "$(get_height)" + $WAIT_BLOCKS` +DENOM="tkyve" + +PROPOSAL="${PROPOSAL//MY_UPGRADE_height/$UPGRADE_HEIGHT}" +PROPOSAL="${PROPOSAL//MY_UPGRADE_NAME/$NAME}" +PROPOSAL="${PROPOSAL//MY_DENOM/$DENOM}" +printf "$PROPOSAL" > /tmp/proposal.json + +# Submit proposal +$BINARY tx gov submit-proposal /tmp/proposal.json $ALICE_TX $CHAINHOME $TESTBACKEND $TX $JSON | check_tx + +# Exit if proposal submission failed +if [ $? -ne 0 ]; then + exit 1 +fi +echo "" +echo "Submitted proposal" +echo "" + +# Get proposal ID +ID=$($BINARY q gov proposals --page-limit 1 --page-reverse --proposal-status voting-period $JSON | jq '.proposals[0].id | tonumber' | tee /dev/null) +if [[ -z "$ID" ]]; then + ID=$($BINARY q gov proposals --limit 1 --reverse --status voting_period $JSON | jq '.proposals[0].id | tonumber') + if [[ -z "$ID" ]]; then + echo -e "$RED✗ Could not fetch proposal ID. Make sure your node is running.$ENDCOLOR" + exit 1 + fi +fi + +# Vote on proposal +$BINARY tx gov vote $ID yes $ALICE_TX $CHAINHOME $TESTBACKEND $JSON | check_tx +echo "" +echo "Voted yes on proposal $ID" +echo "Scheduled upgrade for height $UPGRADE_HEIGHT" + +did_proposal_pass() { + local result=$1 + local status=$(echo "$result" | jq -r '.proposal.status') + + if [ "$status" == "null" ]; then + status=$(echo "$result" | jq -r '.status') + fi + + # status 3 or "PROPOSAL_STATUS_PASSED" is passed + if [[ "$status" -eq 3 || "$status" == "PROPOSAL_STATUS_PASSED" ]]; then + return 0 + else + return 1 + fi +} + +did_proposal_fail() { + local result=$1 + local status=$(echo "$result" | jq -r '.proposal.status') + + if [ "$status" == "null" ]; then + status=$(echo "$result" | jq -r '.status') + fi + + # everything except status 2 (PROPOSAL_STATUS_VOTING_PERIOD) or status 3 (PROPOSAL_STATUS_PASSED) is failed + if [[ "$status" -ne 2 && "$status" -ne 3 && "$status" != "PROPOSAL_STATUS_VOTING_PERIOD" && "$status" != "PROPOSAL_STATUS_PASSED" ]]; then + return 0 + else + return 1 + fi +} + +# Wait for upgrade and poll status +elapsed_seconds=0 +progress_bar_length=$(expr $WAIT_BLOCKS \* 1) +while true; do + result=$($BINARY q gov proposal $ID $JSON) + + if did_proposal_pass "$result"; then + printf "\n\r✅ Upgrade successful! Took %02d seconds\n" "$elapsed_seconds" + break + elif did_proposal_fail "$result"; then + printf "\n\r${RED}✗ Upgrade failed!\nCheck if your voting parameters are correct. They need to have a short voting time and a low quorum threshold.${ENDCOLOR}\n" + break + fi + + height=$(get_height) + remaining_blocks=$(expr $UPGRADE_HEIGHT - $height) + + passed_blocks=$(expr $WAIT_BLOCKS - $remaining_blocks) + progress_bar=$(printf "%0.s=" $(seq 1 $passed_blocks)) + + printf "\r⏳ Waiting for upgrade: %02d seconds | Progress: [%-*s] %02d blocks left" "$elapsed_seconds" "$progress_bar_length" "$progress_bar" "$remaining_blocks" + + if [[ "$remaining_blocks" -le 0 ]]; then + printf "\n\r${RED}✗ Upgrade failed!\nCheck if your voting parameters are correct. They need to have a short voting time and a low quorum threshold.${ENDCOLOR}\n" + exit 1 + fi + + sleep 1 + ((elapsed_seconds++)) +done \ No newline at end of file