Skip to content

Commit

Permalink
feat: upgrade hanlder
Browse files Browse the repository at this point in the history
  • Loading branch information
emidev98 committed Jul 23, 2024
1 parent 64ea546 commit 2329180
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 2 deletions.
1 change: 1 addition & 0 deletions app/upgrade_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func (app *TerraApp) RegisterUpgradeHandlers() {
v2_12.CreateUpgradeHandler(
app.GetModuleManager(),
app.GetConfigurator(),
app.Keepers,
),
)
}
Expand Down
100 changes: 100 additions & 0 deletions app/upgrades/v2.12/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,119 @@ package v2_12
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/terra-money/core/v2/app/keepers"
)

type EscrowUpdate struct {
EscrowAddress sdk.AccAddress
Assets []sdk.Coin
}

// To test this upgrade handler set the following address "terra1v0eee20gjl68fuk0chyrkch2z7suw2mhg3wkxf"
// on the variables below: addr and multisigAddr.
// then run: npm run test:chain:upgrade:v12
func CreateUpgradeHandler(
mm *module.Manager,
cfg module.Configurator,
k keepers.TerraAppKeepers,
) upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
if ctx.ChainID() != "phoenix-1" {
return mm.RunMigrations(ctx, cfg, vm)
}
addr := sdk.MustAccAddressFromBech32("")
multisigAddr := sdk.MustAccAddressFromBech32("")

// Iterate delegations and unbond all shares
// burning the coins immediately
k.StakingKeeper.IterateDelegatorDelegations(ctx, addr, func(d stakingtypes.Delegation) (stop bool) {
valAddr, err := sdk.ValAddressFromBech32(d.ValidatorAddress)
if err != nil {
panic(err)
}
// Use this method without adding unbonding to the unbondings queue
// because it's not necessary to wait for the unbonding period
// (basically burn the shares and coins immediately)
_, err = k.StakingKeeper.Unbond(ctx, addr, valAddr, d.Shares)
if err != nil {
panic(err)
}
return false
})

// Given one of the states can be undelegating, we need to iterate over all unbonding delegations
// and remove them manually to ensure that the undelegated coins are burned.
bondDenom := k.StakingKeeper.GetParams(ctx).BondDenom
k.StakingKeeper.IterateDelegatorUnbondingDelegations(ctx, addr, func(ubd stakingtypes.UnbondingDelegation) (stop bool) {
balances := sdk.NewCoins()
for i := 0; i < len(ubd.Entries); i++ {
entry := ubd.Entries[i]
ubd.RemoveEntry(int64(i))
i--
k.StakingKeeper.DeleteUnbondingIndex(ctx, entry.UnbondingId)

// track undelegation only when remaining or truncated shares are non-zero
if !entry.Balance.IsZero() {
amt := sdk.NewCoin(bondDenom, entry.Balance)
if err := k.BankKeeper.UndelegateCoinsFromModuleToAccount(
ctx, stakingtypes.NotBondedPoolName, addr, sdk.NewCoins(amt),
); err != nil {
panic(err)
}

balances = balances.Add(amt)
}
}
k.StakingKeeper.RemoveUnbondingDelegation(ctx, ubd)
return false
})

// Redelegations are two queues but no coins are custodied in any "redelegations_pool",
// so we can just iterate over all redelegations and remove the indices to prevent issues.
k.StakingKeeper.IterateDelegatorRedelegations(ctx, addr, func(red stakingtypes.Redelegation) (stop bool) {
balances := sdk.NewCoins()
for i := 0; i < len(red.Entries); i++ {
entry := red.Entries[i]
red.RemoveEntry(int64(i))
i--
k.StakingKeeper.DeleteUnbondingIndex(ctx, entry.UnbondingId)

if !entry.InitialBalance.IsZero() {
balances = balances.Add(sdk.NewCoin(bondDenom, entry.InitialBalance))
}
}
k.StakingKeeper.RemoveRedelegation(ctx, red)
return false
})

// Burn all coins in the addr
k.BankKeeper.IterateAccountBalances(ctx, addr, func(balance sdk.Coin) bool {
err := k.BankKeeper.SendCoinsFromAccountToModule(ctx, addr, stakingtypes.NotBondedPoolName, sdk.NewCoins(balance))
if err != nil {
panic(err)
}
err = k.BankKeeper.BurnCoins(ctx, stakingtypes.NotBondedPoolName, sdk.NewCoins(balance))
if err != nil {
panic(err)
}
return false
})

// Burn all coins from the multisig account
k.BankKeeper.IterateAccountBalances(ctx, multisigAddr, func(balance sdk.Coin) bool {
err := k.BankKeeper.SendCoinsFromAccountToModule(ctx, multisigAddr, stakingtypes.NotBondedPoolName, sdk.NewCoins(balance))
if err != nil {
panic(err)
}
err = k.BankKeeper.BurnCoins(ctx, stakingtypes.NotBondedPoolName, sdk.NewCoins(balance))
if err != nil {
panic(err)
}
return false
})

return mm.RunMigrations(ctx, cfg, vm)
}
}
1 change: 1 addition & 0 deletions integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"test:init" : "bash src/setup/init-test-framework.sh",
"test:relayer": "bash src/setup/relayer/init-relayer.sh",
"test:chain:upgrade" : "bash src/setup/chain-upgrade/chain-upgrade.sh",
"test:chain:upgrade:v12" : "bash src/setup/chain-upgrade/upgrade-simulation-12.sh",
"test:start" : "jest --runInBand --detectOpenHandles",
"start": "npm run test:init && npm run test:relayer && npm run test:start",
"test:clean": "rm -rf src/test-data chain-upgrade-data && pkill terrad && pkill terrad && pkill relayer"
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/src/setup/chain-upgrade/chain-upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ fi
# init genesis
$OLD_BINARY init test --home $CHAIN_HOME --chain-id=$CHAIN_ID
echo $VAL_MNEMONIC_1 | $OLD_BINARY keys add val1 --home $CHAIN_HOME --recover --keyring-backend=test
VAL_ADDR_1=$($OLD_BINARY keys list emi --output=json | jq .[0].address -r)
VAL_ADDR_1=$($OLD_BINARY keys list val1 --output=json | jq .[0].address -r)

echo $WALLET_MNEMONIC_1 | $OLD_BINARY keys add wallet1 --home $CHAIN_HOME --recover --keyring-backend=test
WALLET_ADDR_1=$($OLD_BINARY keys list emi --output=json | jq .[0].address -r)
WALLET_ADDR_1=$($OLD_BINARY keys list wallet1 --output=json | jq .[0].address -r)

$OLD_BINARY genesis add-genesis-account $($OLD_BINARY --home $CHAIN_HOME keys show val1 --keyring-backend test -a) 100000000000uluna --home $CHAIN_HOME
$OLD_BINARY genesis gentx val1 1000000000uluna --home $CHAIN_HOME --chain-id $CHAIN_ID --keyring-backend test
Expand Down
170 changes: 170 additions & 0 deletions integration-tests/src/setup/chain-upgrade/upgrade-simulation-12.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#!/bin/bash

OLD_VERSION=release/v2.11
UPGRADE_HEIGHT=35
CHAIN_ID=phoenix-1
CHAIN_HOME=$(pwd)/chain-upgrade-data
DENOM=uluna
SOFTWARE_UPGRADE_NAME="v2.12"
GOV_PERIOD="3s"

VAL_MNEMONIC_1="clock post desk civil pottery foster expand merit dash seminar song memory figure uniform spice circle try happy obvious trash crime hybrid hood cushion"
VAL_MNEMONIC_2="alley afraid soup fall idea toss can goose become valve initial strong forward bright dish figure check leopard decide warfare hub unusual join cart"
WALLET_MNEMONIC_1="banner spread envelope side kite person disagree path silver will brother under couch edit food venture squirrel civil budget number acquire point work mass"

export OLD_BINARY=$CHAIN_HOME/terrad_old
export NEW_BINARY=$CHAIN_HOME/terrad_new

rm -rf /tmp/terra
rm -r $CHAIN_HOME
mkdir $CHAIN_HOME
killall terrad_old
killall terrad_new

# install old binary
if ! command -v $OLD_BINARY &> /dev/null
then
mkdir -p /tmp/terra
cd /tmp/terra
git clone https://github.com/terra-money/core
cd core
git checkout $OLD_VERSION
make build
cp /tmp/terra/core/build/terrad $CHAIN_HOME/terrad_old
cd $CHAIN_HOME
fi

# install new binary
if ! command -v $NEW_BINARY &> /dev/null
then
cd ../..
make build
cp build/terrad $NEW_BINARY
fi

# init genesis
$OLD_BINARY init test --home $CHAIN_HOME --chain-id=$CHAIN_ID
echo $VAL_MNEMONIC_1 | $OLD_BINARY keys add val1 --home $CHAIN_HOME --recover --keyring-backend=test
VAL_ADDR_1=$($OLD_BINARY keys show val1 --home $CHAIN_HOME --keyring-backend=test --output=json | jq .address -r)

echo $WALLET_MNEMONIC_1 | $OLD_BINARY keys add wallet1 --home $CHAIN_HOME --recover --keyring-backend=test
WALLET_ADDR_1=$($OLD_BINARY keys show wallet1 --home $CHAIN_HOME --keyring-backend=test --output=json | jq .address -r)

$OLD_BINARY genesis add-genesis-account $($OLD_BINARY --home $CHAIN_HOME keys show val1 --keyring-backend test -a) 100000000000uluna --home $CHAIN_HOME

CURRENT_TIME=$(date +%s)
echo "Current time: $CURRENT_TIME"
$OLD_BINARY genesis add-genesis-account $($OLD_BINARY --home $CHAIN_HOME keys show wallet1 --keyring-backend test -a) 100000000000uluna --vesting-amount 100000uluna --vesting-start-time $CURRENT_TIME --vesting-end-time $(($CURRENT_TIME + 10000)) --home $CHAIN_HOME

$OLD_BINARY genesis gentx val1 1000000000uluna --home $CHAIN_HOME --chain-id $CHAIN_ID --keyring-backend test
$OLD_BINARY genesis collect-gentxs --home $CHAIN_HOME

sed -i -e "s/\"max_deposit_period\": \"172800s\"/\"max_deposit_period\": \"$GOV_PERIOD\"/g" $CHAIN_HOME/config/genesis.json
sed -i -e "s/\"voting_period\": \"172800s\"/\"voting_period\": \"$GOV_PERIOD\"/g" $CHAIN_HOME/config/genesis.json

sed -i -e 's/timeout_commit = "5s"/timeout_commit = "1s"/g' $CHAIN_HOME/config/config.toml
sed -i -e 's/timeout_propose = "3s"/timeout_propose = "1s"/g' $CHAIN_HOME/config/config.toml
sed -i -e 's/index_all_keys = false/index_all_keys = true/g' $CHAIN_HOME/config/config.toml
sed -i -e 's/enable = false/enable = true/g' $CHAIN_HOME/config/app.toml
sed -i -e 's/swagger = false/swagger = true/g' $CHAIN_HOME/config/app.toml

# run old node
echo "Starting old binary on a separate process"
if [[ "$OSTYPE" == "darwin"* ]]; then
screen -L -dmS node1 $OLD_BINARY start --log_level trace --log_format json --home $CHAIN_HOME --pruning=nothing
else
screen -L -Logfile $CHAIN_HOME/log-screen.log -dmS node1 $OLD_BINARY start --log_level trace --log_format json --home $CHAIN_HOME --pruning=nothing
fi

sleep 15

VALOPER_ADDR_1=$($OLD_BINARY q staking validators --output=json | jq .validators[0].operator_address -r)

# Stake and assert it is staked
echo "Delegate"
NO_ECHO=$($OLD_BINARY tx staking delegate $VALOPER_ADDR_1 100000000uluna --keyring-backend test --chain-id $CHAIN_ID --home $CHAIN_HOME --from wallet1 -y)
sleep 2
DELEGATIONS=$($OLD_BINARY query staking delegations $WALLET_ADDR_1 --output=json | jq ".delegation_responses | length")
if [[ "$DELEGATIONS" == "0" ]]; then
echo "Delegation failed"
exit 1
fi

# Unbond and assert the unbonding delegation
echo "Unbond"
NO_ECHO=$($OLD_BINARY tx staking unbond $VALOPER_ADDR_1 1000000uluna --keyring-backend test --chain-id $CHAIN_ID --home $CHAIN_HOME --from wallet1 -y)
sleep 2
UNBONDINGS=$($OLD_BINARY query staking unbonding-delegations $WALLET_ADDR_1 --output=json | jq ".unbonding_responses | length" )
if [[ "$UNBONDINGS" == "0" ]]; then
echo "Unbonding failed"
exit 1
fi

GOV_ADDRESS=$($OLD_BINARY query auth module-account gov --output json | jq .account.base_account.address -r)
echo '{
"messages": [
{
"@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade",
"authority" : "'"$GOV_ADDRESS"'",
"plan" : {
"name": "'"$SOFTWARE_UPGRADE_NAME"'",
"time": "0001-01-01T00:00:00Z",
"height": "'"$UPGRADE_HEIGHT"'",
"upgraded_client_state": null
}
}
],
"metadata": "",
"deposit": "550000000'$DENOM'",
"title": "Upgrade to '$SOFTWARE_UPGRADE_NAME'",
"summary": "Source Code Version https://github.com/terra-money/core"
}' > $CHAIN_HOME/software-upgrade.json

echo "Submit proposal"
NO_ECHO=$($OLD_BINARY tx gov submit-proposal $CHAIN_HOME/software-upgrade.json --from val1 --keyring-backend test --chain-id $CHAIN_ID --home $CHAIN_HOME -y)
sleep 2
echo "Vote"
NO_ECHO=$($OLD_BINARY tx gov vote 1 yes --from val1 --keyring-backend test --chain-id $CHAIN_ID --home $CHAIN_HOME -y)

## determine block_height to halt
while true; do
BLOCK_HEIGHT=$($OLD_BINARY status | jq '.SyncInfo.latest_block_height' -r)
if [ $BLOCK_HEIGHT = "$UPGRADE_HEIGHT" ]; then
# assuming running only 1 terrad
echo "BLOCK HEIGHT = $UPGRADE_HEIGHT REACHED, STOPPING OLD BINARY"
pkill terrad_old
break
else
STATUS=$($OLD_BINARY query gov proposal 1 --output=json | jq ".status" -r)
echo "BLOCK_HEIGHT = $BLOCK_HEIGHT $STATUS"
sleep 1
fi
done
sleep 1

# run new binary
echo "Starting new binary"
if [[ "$OSTYPE" == "darwin"* ]]; then
screen -L -dmS node1 $NEW_BINARY start --log_level trace --log_format json --home $CHAIN_HOME --pruning=nothing
else
screen -L -Logfile $CHAIN_HOME/log-screen.log -dmS node1 $NEW_BINARY start --log_level trace --log_format json --home $CHAIN_HOME --pruning=nothing
fi
sleep 15

DELEGATIONS=$($NEW_BINARY query staking delegations $WALLET_ADDR_1 --output=json | jq ".delegation_responses | length")
echo "DELEGATIONS $DELEGATIONS"
if [[ "$DELEGATIONS" == "0" ]]; then
echo "Delegations removed when upgrading"
fi

UNBONDINGS=$($NEW_BINARY query staking unbonding-delegations $WALLET_ADDR_1 --output=json | jq ".unbonding_responses | length")
echo "UNBONDINGS $UNBONDINGS"
if [[ "$UNBONDINGS" == "0" ]]; then
echo "Unbondings removed when upgrading"
fi

BALANCES=$($NEW_BINARY query bank balances $WALLET_ADDR_1 --output=json | jq ".balances | length")
echo "BALANCES $BALANCES"
if [[ "$BALANCES" == "0" ]]; then
echo "Balance removed when upgrading"
fi

0 comments on commit 2329180

Please sign in to comment.