diff --git a/CHANGELOG.md b/CHANGELOG.md index d63b8cf93e..7aef39401b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## UNRELEASED + +### Improvements + +* (test) [#1380](https://github.com/crypto-org-chain/cronos/pull/1380) Upgrade cosmovisor to 1.5.0 in integration test. +* (versiondb) [#1379](https://github.com/crypto-org-chain/cronos/pull/1379) Flush versiondb when graceful shutdown, make rocksdb upgrade smooth. + *April 8, 2024* ## v1.2.0-rc1 diff --git a/app/app.go b/app/app.go index 3e404344bd..1533139bd9 100644 --- a/app/app.go +++ b/app/app.go @@ -143,7 +143,6 @@ import ( // this line is used by starport scaffolding # stargate/app/moduleImport memiavlstore "github.com/crypto-org-chain/cronos/store" - memiavlrootmulti "github.com/crypto-org-chain/cronos/store/rootmulti" "github.com/crypto-org-chain/cronos/v2/x/cronos" cronosclient "github.com/crypto-org-chain/cronos/v2/x/cronos/client" cronoskeeper "github.com/crypto-org-chain/cronos/v2/x/cronos/keeper" @@ -370,6 +369,8 @@ type App struct { // module configurator configurator module.Configurator + + qms storetypes.MultiStore } // New returns a reference to an initialized chain. @@ -860,10 +861,9 @@ func New( // wire up the versiondb's `StreamingService` and `MultiStore`. streamers := cast.ToStringSlice(appOpts.Get("store.streamers")) - var qms sdk.MultiStore if slices.Contains(streamers, "versiondb") { var err error - qms, err = app.setupVersionDB(homePath, keys, tkeys, memKeys) + app.qms, err = app.setupVersionDB(homePath, keys, tkeys, memKeys) if err != nil { panic(err) } @@ -900,8 +900,8 @@ func New( tmos.Exit(err.Error()) } - if qms != nil { - v1 := qms.LatestVersion() + if app.qms != nil { + v1 := app.qms.LatestVersion() v2 := app.LastBlockHeight() if v1 > 0 && v1 < v2 { // try to prevent gap being created in versiondb @@ -1197,11 +1197,19 @@ func VerifyAddressFormat(bz []byte) error { // Close will be called in graceful shutdown in start cmd func (app *App) Close() error { - err := app.BaseApp.Close() + errs := []error{app.BaseApp.Close()} + + // flush the versiondb + if closer, ok := app.qms.(io.Closer); ok { + errs = append(errs, closer.Close()) + } - if cms, ok := app.CommitMultiStore().(*memiavlrootmulti.Store); ok { - return stderrors.Join(err, cms.Close()) + // mainly to flush memiavl + if closer, ok := app.CommitMultiStore().(io.Closer); ok { + errs = append(errs, closer.Close()) } + err := stderrors.Join(errs...) + app.Logger().Info("Application gracefully shutdown", "error", err) return err } diff --git a/integration_tests/test_upgrade.py b/integration_tests/test_upgrade.py index de48ead79f..e77b80fa0b 100644 --- a/integration_tests/test_upgrade.py +++ b/integration_tests/test_upgrade.py @@ -1,4 +1,6 @@ import json +import shutil +import stat import subprocess from contextlib import contextmanager from datetime import datetime, timedelta @@ -56,8 +58,13 @@ def post_init(path, base_port, config): chain_id, data / SUPERVISOR_CONFIG_FILE, lambda i, _: { - "command": f"cosmovisor start --home %(here)s/node{i}", - "environment": f"DAEMON_NAME=cronosd,DAEMON_HOME=%(here)s/node{i}", + "command": f"cosmovisor run start --home %(here)s/node{i}", + "environment": ( + "DAEMON_NAME=cronosd," + "DAEMON_SHUTDOWN_GRACE=1m," + "UNSAFE_SKIP_BACKUP=true," + f"DAEMON_HOME=%(here)s/node{i}" + ), }, ) @@ -67,21 +74,29 @@ def setup_cronos_test(tmp_path_factory): port = 26200 nix_name = "upgrade-test-package" cfg_name = "cosmovisor" + configdir = Path(__file__).parent cmd = [ "nix-build", - Path(__file__).parent / f"configs/{nix_name}.nix", - "-o", - path / "upgrades", + configdir / f"configs/{nix_name}.nix", ] print(*cmd) subprocess.run(cmd, check=True) + + # copy the content so the new directory is writable. + upgrades = path / "upgrades" + shutil.copytree("./result", upgrades) + mod = stat.S_IRWXU + upgrades.chmod(mod) + for d in upgrades.iterdir(): + d.chmod(mod) + # init with genesis binary with contextmanager(setup_custom_cronos)( path, port, - Path(__file__).parent / f"configs/{cfg_name}.jsonnet", + configdir / f"configs/{cfg_name}.jsonnet", post_init=post_init, - chain_binary=str(path / "upgrades/genesis/bin/cronosd"), + chain_binary=str(upgrades / "genesis/bin/cronosd"), ) as cronos: yield cronos diff --git a/nix/cosmovisor.nix b/nix/cosmovisor.nix new file mode 100644 index 0000000000..16ca179e65 --- /dev/null +++ b/nix/cosmovisor.nix @@ -0,0 +1,21 @@ +{ buildGoModule +, fetchFromGitHub +}: + +let + version = "1.5.0"; + cosmos-sdk = fetchFromGitHub { + owner = "cosmos"; + repo = "cosmos-sdk"; + rev = "tools/cosmovisor/v${version}"; + hash = "sha256-Ov8FGpDOcsqmFLT2s/ubjmTXj17sQjBWRAdxlJ6DNEY="; + }; +in +buildGoModule rec { + name = "cosmovisor"; + version = "1.5.0"; + src = cosmos-sdk + "/tools/cosmovisor"; + subPackages = [ "./cmd/cosmovisor" ]; + vendorHash = "sha256-IkPnnfkofn5w8Oa/uzGxgI1eb5RrJ9haNgj4mBXF+n8="; + doCheck = false; +} diff --git a/nix/default.nix b/nix/default.nix index 7e4ebf444a..e6c1364dc5 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -44,13 +44,7 @@ import sources.nixpkgs { }) (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; }) (_: pkgs: { - cosmovisor = pkgs.buildGo120Module rec { - name = "cosmovisor"; - src = sources.cosmos-sdk + "/cosmovisor"; - subPackages = [ "./cmd/cosmovisor" ]; - vendorHash = "sha256-OAXWrwpartjgSP7oeNvDJ7cTR9lyYVNhEM8HUnv3acE="; - doCheck = false; - }; + cosmovisor = pkgs.callPackage ./cosmovisor.nix { }; }) (_: pkgs: { rly = pkgs.buildGo120Module rec { diff --git a/nix/sources.json b/nix/sources.json index e5819624f1..336932e6c3 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -11,18 +11,6 @@ "url": "https://github.com/crypto-org-chain/chain-main/archive/04e8e094b7d51a8cf92b74c789394b7b34987b10.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, - "cosmos-sdk": { - "branch": "v0.45.0", - "description": ":chains: A Framework for Building High Value Public Blockchains :sparkles:", - "homepage": "https://cosmos.network/", - "owner": "cosmos", - "repo": "cosmos-sdk", - "rev": "b6c77e6c819f8a51166649eaef125d1bfb276f04", - "sha256": "09ns4yfxyfi7c7n5g69zv32m1rdssdl48c1akmv1y2vz6ayz4v02", - "type": "tarball", - "url": "https://github.com/cosmos/cosmos-sdk/archive/b6c77e6c819f8a51166649eaef125d1bfb276f04.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, "dapptools": { "branch": "master", "description": "Dapp, Seth, Hevm, and more", diff --git a/versiondb/multistore.go b/versiondb/multistore.go index 878f6dd08e..8f61075dc7 100644 --- a/versiondb/multistore.go +++ b/versiondb/multistore.go @@ -145,3 +145,8 @@ func (s *MultiStore) LatestVersion() int64 { } return version } + +// Close will flush the versiondb +func (s *MultiStore) Close() error { + return s.versionDB.Flush() +} diff --git a/versiondb/tsrocksdb/store.go b/versiondb/tsrocksdb/store.go index b927ea36b9..be34c74632 100644 --- a/versiondb/tsrocksdb/store.go +++ b/versiondb/tsrocksdb/store.go @@ -205,6 +205,16 @@ func (s Store) Import(version int64, ch <-chan versiondb.ImportEntry) error { return s.SetLatestVersion(version) } +func (s Store) Flush() error { + opts := grocksdb.NewDefaultFlushOptions() + defer opts.Destroy() + + return errors.Join( + s.db.Flush(opts), + s.db.FlushCF(s.cfHandle, opts), + ) +} + func newTSReadOptions(version *int64) *grocksdb.ReadOptions { var ver uint64 if version == nil { diff --git a/versiondb/types.go b/versiondb/types.go index 46bbe88e9e..6c69fbbf94 100644 --- a/versiondb/types.go +++ b/versiondb/types.go @@ -21,6 +21,10 @@ type VersionStore interface { // Import the initial state of the store Import(version int64, ch <-chan ImportEntry) error + + // Flush wal logs, and make the changes persistent, + // mainly for rocksdb version upgrade, sometimes the wal format is not compatible. + Flush() error } type ImportEntry struct {