Skip to content

Commit

Permalink
Merge branch 'master' into dev/speedup_coin_to_string
Browse files Browse the repository at this point in the history
  • Loading branch information
atheeshp authored Sep 7, 2021
2 parents d09fd3e + 4292552 commit d26aaed
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* [\#10077](https://github.com/cosmos/cosmos-sdk/pull/10077) Remove telemetry on `GasKV` and `CacheKV` store Get/Set operations, significantly improving their performance.
* [\#10022](https://github.com/cosmos/cosmos-sdk/pull/10022) `AuthKeeper` interface in `x/auth` now includes a function `HasAccount`.
* [\#9759](https://github.com/cosmos/cosmos-sdk/pull/9759) `NewAccountKeeeper` in `x/auth` now takes an additional `bech32Prefix` argument that represents `sdk.Bech32MainPrefix`.
* [\#9628](https://github.com/cosmos/cosmos-sdk/pull/9628) Rename `x/{mod}/legacy` to `x/{mod}/migrations`.
Expand Down
70 changes: 70 additions & 0 deletions cosmovisor/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os/exec"
"os/signal"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -64,6 +65,13 @@ func (l Launcher) Run(args []string, stdout, stderr io.Writer) (bool, error) {
return false, err
}

if !SkipUpgrade(args, l.fw.currentInfo) {
err = doPreUpgrade(l.cfg)
if err != nil {
return false, err
}
}

return true, DoUpgrade(l.cfg, l.fw.currentInfo)
}

Expand Down Expand Up @@ -143,3 +151,65 @@ func doBackup(cfg *Config) error {

return nil
}

// doPreUpgrade runs the pre-upgrade command defined by the application
func doPreUpgrade(cfg *Config) error {
bin, err := cfg.CurrentBin()
preUpgradeCmd := exec.Command(bin, "pre-upgrade")

_, err = preUpgradeCmd.Output()

if err != nil {
if err.(*exec.ExitError).ProcessState.ExitCode() == 1 {
fmt.Println("pre-upgrade command does not exist. continuing the upgrade.")
return nil
}
if err.(*exec.ExitError).ProcessState.ExitCode() == 30 {
return fmt.Errorf("pre-upgrade command failed : %w", err)
}
if err.(*exec.ExitError).ProcessState.ExitCode() == 31 {
fmt.Println("pre-upgrade command failed. retrying.")
return doPreUpgrade(cfg)
}
}
fmt.Println("pre-upgrade successful. continuing the upgrade.")
return nil
}

// skipUpgrade checks if pre-upgrade script must be run. If the height in the upgrade plan matches any of the heights provided in --safe-skip-upgrade, the script is not run
func SkipUpgrade(args []string, upgradeInfo UpgradeInfo) bool {
skipUpgradeHeights := UpgradeSkipHeights(args)
for _, h := range skipUpgradeHeights {
if h == int(upgradeInfo.Height) {
return true
}

}
return false
}

// UpgradeSkipHeights gets all the heights provided when
// simd start --unsafe-skip-upgrades <height1> <optional_height_2> ... <optional_height_N>
func UpgradeSkipHeights(args []string) []int {
var heights []int
for i, arg := range args {
if arg == "--unsafe-skip-upgrades" {
j := i + 1

for j < len(args) {
tArg := args[j]
if strings.HasPrefix(tArg, "-") {
break
}
h, err := strconv.Atoi(tArg)
if err == nil {
heights = append(heights, h)
}
j++
}

break
}
}
return heights
}
76 changes: 76 additions & 0 deletions cosmovisor/process_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"testing"

"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

"github.com/cosmos/cosmos-sdk/cosmovisor"
Expand Down Expand Up @@ -127,3 +128,78 @@ func (s *processTestSuite) TestLaunchProcessWithDownloads() {
require.NoError(err)
require.Equal(cfg.UpgradeBin("chain3"), currentBin)
}

// TestSkipUpgrade tests heights that are identified to be skipped and return if upgrade height matches the skip heights
func TestSkipUpgrade(t *testing.T) {
cases := []struct {
args []string
upgradeInfo cosmovisor.UpgradeInfo
expectRes bool
}{{
args: []string{"appb", "start", "--unsafe-skip-upgrades"},
upgradeInfo: cosmovisor.UpgradeInfo{Name: "upgrade1", Info: "some info", Height: 123},
expectRes: false,
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "--abcd"},
upgradeInfo: cosmovisor.UpgradeInfo{Name: "upgrade1", Info: "some info", Height: 123},
expectRes: false,
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "--abcd"},
upgradeInfo: cosmovisor.UpgradeInfo{Name: "upgrade1", Info: "some info", Height: 11},
expectRes: false,
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "20", "--abcd"},
upgradeInfo: cosmovisor.UpgradeInfo{Name: "upgrade1", Info: "some info", Height: 20},
expectRes: true,
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "20", "--abcd", "34"},
upgradeInfo: cosmovisor.UpgradeInfo{Name: "upgrade1", Info: "some info", Height: 34},
expectRes: false,
}}

for i := range cases {
tc := cases[i]
require := require.New(t)
h := cosmovisor.SkipUpgrade(tc.args, tc.upgradeInfo)
require.Equal(h, tc.expectRes)
}
}

// TestUpgradeSkipHeights tests if correct skip upgrade heights are identified from the cli args
func TestUpgradeSkipHeights(t *testing.T) {
cases := []struct {
args []string
expectRes []int
}{{
args: []string{},
expectRes: nil,
}, {
args: []string{"appb", "start"},
expectRes: nil,
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades"},
expectRes: nil,
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "--abcd"},
expectRes: nil,
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "--abcd"},
expectRes: []int{10},
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "20", "--abcd"},
expectRes: []int{10, 20},
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "20", "--abcd", "34"},
expectRes: []int{10, 20},
}, {
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "as", "20", "--abcd"},
expectRes: []int{10, 20},
}}

for i := range cases {
tc := cases[i]
require := require.New(t)
h := cosmovisor.UpgradeSkipHeights(tc.args)
require.Equal(h, tc.expectRes)
}
}
1 change: 1 addition & 0 deletions docs/migrations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ parent:
This folder contains all the migration guides to update your app and modules to Cosmos v0.40 Stargate.

1. [App and Modules Migration](./app_and_modules.md)
1. [Pre Upgrade](./pre-upgrade.md)
1. [Chain Upgrade Guide to v0.40](./chain-upgrade-guide-040.md)
1. [REST Endpoints Migration](./rest.md)
1. [Keyring Migration](./keyring.md)
57 changes: 57 additions & 0 deletions docs/migrations/pre-upgrade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Pre-Upgrade Handling

Cosmovisor supports custom pre-upgrade handling. Use pre-upgrade handling when you need to implement application config changes that are required in the newer version before you perform the upgrade.

Using Cosmovisor pre-upgrade handling is optional. If pre-upgrade handling is not implemented, the upgrade continues.

For example, make the required new-version changes to `app.toml` settings during the pre-upgrade handling. The pre-upgrade handling process means that the file does not have to be manually updated after the upgrade.

Before the application binary is upgraded, Cosmovisor calls a `pre-upgrade` command that can be implemented by the application.

The `pre-upgrade` command does not take in any command-line arguments and is expected to terminate with the following exit codes:


| Exit status code | How it is handled in Cosmosvisor |
|------------------|---------------------------------------------------------------------------------------------------------------------|
| `0` | Assumes `pre-upgrade` command executed successfully and continues the upgrade. |
| `1` | Default exit code when `pre-upgrade` command has not been implemented. |
| `30` | `pre-upgrade` command was executed but failed. This fails the entire upgrade. |
| `31` | `pre-upgrade` command was executed but failed. But the command is retried until exit code `1` or `30` are returned. |


## Sample

Here is a sample structure of the `pre-upgrade` command:

```go
func preUpgradeCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "pre-upgrade",
Short: "Pre-upgrade command",
Long: "Pre-upgrade command to implement custom pre-upgrade handling",
Run: func(cmd *cobra.Command, args []string) {

err := HandlePreUpgrade()

if err != nil {
os.Exit(30)
}

os.Exit(0)

},
}

return cmd
}
```


Ensure that the pre-upgrade command has been registered in the application:
```go
rootCmd.AddCommand(
// ..
preUpgradeCommand(),
// ..
)
```
2 changes: 0 additions & 2 deletions store/cachekv/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func (store *Store) GetStoreType() types.StoreType {
func (store *Store) Get(key []byte) (value []byte) {
store.mtx.Lock()
defer store.mtx.Unlock()
defer telemetry.MeasureSince(time.Now(), "store", "cachekv", "get")

types.AssertValidKey(key)

Expand All @@ -74,7 +73,6 @@ func (store *Store) Get(key []byte) (value []byte) {
func (store *Store) Set(key []byte, value []byte) {
store.mtx.Lock()
defer store.mtx.Unlock()
defer telemetry.MeasureSince(time.Now(), "store", "cachekv", "set")

types.AssertValidKey(key)
types.AssertValidValue(value)
Expand Down
4 changes: 0 additions & 4 deletions store/gaskv/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ func (gs *Store) GetStoreType() types.StoreType {

// Implements KVStore.
func (gs *Store) Get(key []byte) (value []byte) {
defer telemetry.MeasureSince(time.Now(), "store", "gaskv", "get")

gs.gasMeter.ConsumeGas(gs.gasConfig.ReadCostFlat, types.GasReadCostFlatDesc)
value = gs.parent.Get(key)

Expand All @@ -48,8 +46,6 @@ func (gs *Store) Get(key []byte) (value []byte) {

// Implements KVStore.
func (gs *Store) Set(key []byte, value []byte) {
defer telemetry.MeasureSince(time.Now(), "store", "gaskv", "set")

types.AssertValidKey(key)
types.AssertValidValue(value)
gs.gasMeter.ConsumeGas(gs.gasConfig.WriteCostFlat, types.GasWriteCostFlatDesc)
Expand Down

0 comments on commit d26aaed

Please sign in to comment.