Skip to content

Commit

Permalink
feat(upgrade): create v0.26.0 upgrade
Browse files Browse the repository at this point in the history
Signed-off-by: Artur Troian <troian.ap@gmail.com>
  • Loading branch information
troian committed Sep 13, 2023
1 parent 0b90518 commit 0cc785a
Show file tree
Hide file tree
Showing 10 changed files with 297 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
with:
name: logs
path: |
.cache/run/upgrade/.akash*-std*.log
.cache/run/upgrade/validators/logs/*.log
notify-homebrew:
runs-on: ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ jobs:
if: always() && steps.test.outcome != 'skipped'
uses: actions/upload-artifact@v3
with:
name: logs
name: validators-logs
path: |
.cache/run/upgrade/.akash*-std*.log
.cache/run/upgrade/validators/logs/*.log
dispatch-release:
runs-on: ubuntu-latest
Expand Down
5 changes: 5 additions & 0 deletions meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
"skipped": false,
"from_binary": "v0.22.8",
"from_version": "v0.22.0"
},
"v0.26.0": {
"skipped": false,
"from_binary": "v0.24.2",
"from_version": "v0.24.0"
}
}
}
8 changes: 5 additions & 3 deletions script/upgrades.sh
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ function init() {
local cnt=0
local validators_dir=${WORKDIR}/validators

mkdir -p "${WORKDIR}/validators/logs"

for val in $(jq -c '.validators[]' <<<"$config"); do
local valdir=$validators_dir/.akash${cnt}
local cosmovisor_dir=$valdir/cosmovisor
Expand Down Expand Up @@ -284,8 +286,8 @@ function clean() {
local valdir=$validators_dir/.akash${cnt}
local cosmovisor_dir=$valdir/cosmovisor

rm -rf "$validators_dir/.akash${cnt}-stderr.log"
rm -rf "$validators_dir/.akash${cnt}-stdout.log"
rm -rf "$validators_dir/logs/.akash${cnt}-stderr.log"
rm -rf "$validators_dir/logs/.akash${cnt}-stdout.log"

rm -rf "$valdir"/data/*
rm -rf "$cosmovisor_dir/current"
Expand Down Expand Up @@ -336,7 +338,7 @@ test-required)
fi

# shellcheck disable=SC2086
if git tag -l $upgrade_name >/dev/null 2>&1; then
if git show-ref --tags $upgrade_name >/dev/null 2>&1; then
if echo "$meta" | jq -e --arg name $upgrade_name '.revoked_releases[] | contains($name)' >/dev/null 2>&1; then
upgrade_name=v$($semver bump patch $upgrade_name)
else
Expand Down
4 changes: 2 additions & 2 deletions tests/upgrade/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ func executeCommand(ctx context.Context, env []string, cmd string, args ...strin
}

func (l *validator) run() error {
lStdout, err := os.Create(fmt.Sprintf("%s/%s-stdout.log", l.params.home, l.params.name))
lStdout, err := os.Create(fmt.Sprintf("%s/logs/%s-stdout.log", l.params.home, l.params.name))
if err != nil {
return err
}
Expand All @@ -773,7 +773,7 @@ func (l *validator) run() error {
_ = lStdout.Close()
}()

lStderr, err := os.Create(fmt.Sprintf("%s/%s-stderr.log", l.params.home, l.params.name))
lStderr, err := os.Create(fmt.Sprintf("%s/logs/%s-stderr.log", l.params.home, l.params.name))
if err != nil {
return err
}
Expand Down
117 changes: 117 additions & 0 deletions tests/upgrade/v0.26.0/postupgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//go:build e2e.upgrade

// Package v0_26_0
// nolint revive
package v0_26_0

import (
"context"
"fmt"
"strconv"
"strings"
"testing"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/params/types/proposal"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

astaking "github.com/akash-network/akash-api/go/node/staking/v1beta3"

"github.com/akash-network/node/app"
uttypes "github.com/akash-network/node/tests/upgrade/types"
)

func init() {
uttypes.RegisterPostUpgradeWorker("v0.26.0", &postUpgrade{})
}

type postUpgrade struct{}

var _ uttypes.TestWorker = (*postUpgrade)(nil)

func (pu *postUpgrade) Run(ctx context.Context, t *testing.T, params uttypes.TestParams) {
encodingConfig := app.MakeEncodingConfig()

rpcClient, err := client.NewClientFromNode(params.Node)
require.NoError(t, err)

cctx := client.Context{}.
WithCodec(encodingConfig.Marshaler).
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
WithTxConfig(encodingConfig.TxConfig).
WithLegacyAmino(encodingConfig.Amino).
WithAccountRetriever(authtypes.AccountRetriever{}).
WithBroadcastMode(flags.BroadcastBlock).
WithHomeDir(params.Home).
WithChainID(params.ChainID).
WithNodeURI(params.Node).
WithClient(rpcClient)

kr, err := client.NewKeyringFromBackend(cctx, params.KeyringBackend)
require.NoError(t, err)

cctx = cctx.WithKeyring(kr)

pqc := proposal.NewQueryClient(cctx)
res, err := pqc.Params(ctx, &proposal.QueryParamsRequest{
Subspace: stakingtypes.ModuleName,
Key: string(stakingtypes.KeyMaxValidators),
})
require.NoError(t, err)

maxValidators, err := strconv.ParseInt(strings.Trim(res.Param.Value, "\""), 10, 32)
require.NoError(t, err)

res, err = pqc.Params(ctx, &proposal.QueryParamsRequest{
Subspace: astaking.ModuleName,
Key: string(astaking.KeyMinCommissionRate),
})
require.NoError(t, err)

minCommission, err := sdk.NewDecFromStr(strings.Trim(res.Param.Value, "\""))
require.NoError(t, err)

qc := stakingtypes.NewQueryClient(cctx)

var pkey []byte

validators := make(stakingtypes.Validators, 0, maxValidators)

for {
var pgn *query.PageRequest
if pkey != nil {
pgn = &query.PageRequest{
Key: pkey,
}
}

result, err := qc.Validators(ctx, &stakingtypes.QueryValidatorsRequest{
Pagination: pgn,
})
require.NoError(t, err)

validators = append(validators, result.Validators...)

if pg := result.Pagination; pg != nil && len(pg.NextKey) > 0 {
pkey = pg.NextKey
} else {
break
}
}

for _, validator := range validators {
assert.True(t, validator.Commission.Rate.GTE(minCommission),
fmt.Sprintf("invalid commission Rate for validator (%s). (%s%%) < (%s%%)MinCommission",
validator.OperatorAddress, validator.Commission.Rate.String(), minCommission.String()))

assert.True(t, validator.Commission.MaxRate.GTE(minCommission),
fmt.Sprintf("invalid commission MaxRate for validator (%s). (%s%%) < (%s%%)MinCommission",
validator.OperatorAddress, validator.Commission.MaxRate.String(), minCommission.String()))
}
}
7 changes: 7 additions & 0 deletions tests/upgrade/workers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//go:build e2e.upgrade

package upgrade

import (
_ "github.com/akash-network/node/tests/upgrade/v0.26.0"
)
11 changes: 11 additions & 0 deletions upgrades/software/v0.26.0/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Package v0_26_0
// nolint revive
package v0_26_0

import (
utypes "github.com/akash-network/node/upgrades/types"
)

func init() {
utypes.RegisterUpgrade(UpgradeName, initUpgrade)
}
145 changes: 145 additions & 0 deletions upgrades/software/v0.26.0/upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Package v0_26_0
// nolint revive
package v0_26_0

import (
"fmt"
"time"

"github.com/tendermint/tendermint/libs/log"

storetypes "github.com/cosmos/cosmos-sdk/store/types"
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"

apptypes "github.com/akash-network/node/app/types"
utypes "github.com/akash-network/node/upgrades/types"
)

const (
UpgradeName = "v0.26.0"
)

type upgrade struct {
*apptypes.App
log log.Logger
}

var _ utypes.IUpgrade = (*upgrade)(nil)

func initUpgrade(log log.Logger, app *apptypes.App) (utypes.IUpgrade, error) {
up := &upgrade{
App: app,
log: log.With(fmt.Sprintf("upgrade/%s", UpgradeName)),
}

return up, nil
}

func (up *upgrade) StoreLoader() *storetypes.StoreUpgrades {
return &storetypes.StoreUpgrades{}
}

func (up *upgrade) UpgradeHandler() upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
if err := up.enforceMinValidatorCommission(ctx); err != nil {
return nil, err
}

return up.MM.RunMigrations(ctx, up.Configurator, fromVM)
}
}

func (up *upgrade) enforceMinValidatorCommission(ctx sdk.Context) error {
minRate := up.Keepers.Akash.Staking.MinCommissionRate(ctx)
validators := up.Keepers.Cosmos.Staking.GetAllValidators(ctx)

for _, validator := range validators {
if validator.Commission.MaxRate.LT(minRate) || validator.GetCommission().LT(minRate) {
// update MaxRate if it is less than minimum required rate
if validator.Commission.MaxRate.LT(minRate) {
up.log.Info(
fmt.Sprintf(
"validator's `%s` commission MaxRate is %s%% < %[3]s%%(min required). Force updating to %[3]s%%",
validator.OperatorAddress,
validator.Commission.MaxRate,
minRate,
),
)

validator.Commission.MaxRate = minRate
}

if validator.GetCommission().LT(minRate) {
up.log.Info(
fmt.Sprintf(
"validator's `%s` commission Rate is %s%% < %[3]s%%(min required). Force updating to %[3]s%%",
validator.OperatorAddress,
validator.Commission.Rate,
minRate,
),
)

// set max change rate temporarily to 100%
maxRateCh := validator.Commission.MaxChangeRate
validator.Commission.MaxChangeRate = sdk.NewDecWithPrec(1, 0)

newCommission, err := updateValidatorCommission(ctx, validator, minRate)
if err != nil {
return err
}

validator.Commission = newCommission
validator.Commission.MaxChangeRate = maxRateCh
}

up.Keepers.Cosmos.Staking.BeforeValidatorModified(ctx, validator.GetOperator())
up.Keepers.Cosmos.Staking.SetValidator(ctx, validator)
}
}

return nil
}

// updateValidatorCommission use custom implementation of update commission,
// this prevents panic during upgrade if any of validators have changed their
// commission within 24h of upgrade height
func updateValidatorCommission(
ctx sdk.Context,
validator stakingtypes.Validator,
newRate sdk.Dec,
) (stakingtypes.Commission, error) {
commission := validator.Commission
blockTime := ctx.BlockHeader().Time

if err := validateNewRate(commission, newRate, blockTime); err != nil {
return commission, err
}

commission.Rate = newRate
commission.UpdateTime = blockTime

return commission, nil
}

// validateNewRate performs basic sanity validation checks of a new commission
// rate. If validation fails, an SDK error is returned.
func validateNewRate(commission stakingtypes.Commission, newRate sdk.Dec, _ time.Time) error {
switch {
case newRate.IsNegative():
// new rate cannot be negative
return stakingtypes.ErrCommissionNegative

case newRate.GT(commission.MaxRate):
// new rate cannot be greater than the max rate
return stakingtypes.ErrCommissionGTMaxRate

case newRate.Sub(commission.Rate).GT(commission.MaxChangeRate):
// new rate % points change cannot be greater than the max change rate
return stakingtypes.ErrCommissionGTMaxChangeRate
}

return nil
}
2 changes: 2 additions & 0 deletions upgrades/upgrades.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package upgrades

import (
// nolint: revive
_ "github.com/akash-network/node/upgrades/software/v0.26.0"
// nolint: revive
_ "github.com/akash-network/node/upgrades/software/v0.24.0"
// nolint: revive
Expand Down

0 comments on commit 0cc785a

Please sign in to comment.