-
Notifications
You must be signed in to change notification settings - Fork 1
v1.10.1 upgrade to repair v1.10.0 consensus store issues #101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
f0ca49e
Fix v1.10.1 upgrade store handling
akobrin1 ebfe25c
formatted shell scripts using shfmt
akobrin1 73447f9
resolved copilot suggestion
akobrin1 f4a4a11
fixed issues
akobrin1 eb46aa3
corrected .PHONY
akobrin1 0fadcb2
devnet - skip sn registration in postpone status
akobrin1 a8c633f
devnet - skip sn registration if it is in blocked state
akobrin1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| package upgrades | ||
|
|
||
| import ( | ||
| "sort" | ||
|
|
||
| "cosmossdk.io/log" | ||
| storetypes "cosmossdk.io/store/types" | ||
| upgradetypes "cosmossdk.io/x/upgrade/types" | ||
|
|
||
| "github.com/cosmos/cosmos-sdk/baseapp" | ||
| ) | ||
|
|
||
| const ( | ||
| legacyConsensusStoreKey = "Consensus" | ||
| consensusStoreKey = "consensus" | ||
| ) | ||
|
|
||
| // ConsensusStoreLoader builds a store loader that safely renames the legacy | ||
| // consensus store (if present) and avoids panics when the new store already exists. | ||
| // | ||
| // If expectedStoreNames is provided, the loader will also compute adaptive store | ||
| // upgrades against the existing on-disk stores. | ||
| func ConsensusStoreLoader( | ||
| upgradeHeight int64, | ||
| baseUpgrades *storetypes.StoreUpgrades, | ||
| expectedStoreNames map[string]struct{}, | ||
| logger log.Logger, | ||
| ) baseapp.StoreLoader { | ||
| fallbackLoader := upgradetypes.UpgradeStoreLoader(upgradeHeight, baseUpgrades) | ||
|
|
||
| return func(ms storetypes.CommitMultiStore) error { | ||
| if upgradeHeight != ms.LastCommitID().Version+1 { | ||
| return baseapp.DefaultStoreLoader(ms) | ||
| } | ||
|
|
||
| existingStoreNames, err := loadExistingStoreNames(ms) | ||
| if err != nil { | ||
| logger.Error("Failed to load existing stores; falling back to standard upgrade loader", "error", err) | ||
| return fallbackLoader(ms) | ||
| } | ||
|
|
||
| effective := computeConsensusStoreUpgrades(baseUpgrades, expectedStoreNames, existingStoreNames, logger) | ||
| if len(effective.Added) == 0 && len(effective.Deleted) == 0 && len(effective.Renamed) == 0 { | ||
| logger.Info("No store upgrades required; loading latest version", "height", upgradeHeight) | ||
| return baseapp.DefaultStoreLoader(ms) | ||
| } | ||
|
|
||
| logger.Info( | ||
| "Applying store upgrades", | ||
| "height", upgradeHeight, | ||
| "added", effective.Added, | ||
| "deleted", effective.Deleted, | ||
| "renamed", formatStoreRenames(effective.Renamed), | ||
| ) | ||
|
|
||
| return ms.LoadLatestVersionAndUpgrade(&effective) | ||
| } | ||
| } | ||
|
|
||
| func computeConsensusStoreUpgrades( | ||
| baseUpgrades *storetypes.StoreUpgrades, | ||
| expectedStoreNames map[string]struct{}, | ||
| existingStoreNames map[string]struct{}, | ||
| logger log.Logger, | ||
| ) storetypes.StoreUpgrades { | ||
| var effective storetypes.StoreUpgrades | ||
| if expectedStoreNames != nil { | ||
| effective = computeAdaptiveStoreUpgrades(baseUpgrades, expectedStoreNames, existingStoreNames) | ||
| effective.Renamed = filterStoreRenames(effective.Renamed, existingStoreNames) | ||
| } else { | ||
| effective = cloneStoreUpgrades(baseUpgrades) | ||
| effective.Added = filterStoreAdds(effective.Added, existingStoreNames) | ||
| effective.Deleted = filterStoreDeletes(effective.Deleted, existingStoreNames) | ||
| effective.Renamed = filterStoreRenames(effective.Renamed, existingStoreNames) | ||
| } | ||
|
|
||
| hasLegacy := storeExists(existingStoreNames, legacyConsensusStoreKey) | ||
| hasNew := storeExists(existingStoreNames, consensusStoreKey) | ||
|
|
||
| switch { | ||
| case hasLegacy && !hasNew: | ||
| effective.Added = removeStoreName(effective.Added, consensusStoreKey) | ||
| effective.Deleted = removeStoreName(effective.Deleted, legacyConsensusStoreKey) | ||
| effective.Renamed = append(effective.Renamed, storetypes.StoreRename{ | ||
| OldKey: legacyConsensusStoreKey, | ||
| NewKey: consensusStoreKey, | ||
| }) | ||
akobrin1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| case !hasLegacy && !hasNew: | ||
| if expectedStoreNames == nil { | ||
| effective.Added = append(effective.Added, consensusStoreKey) | ||
| } | ||
| case hasLegacy && hasNew: | ||
| effective.Deleted = removeStoreName(effective.Deleted, legacyConsensusStoreKey) | ||
| logger.Info("Both legacy and new consensus stores exist; skipping rename", "old", legacyConsensusStoreKey, "new", consensusStoreKey) | ||
| } | ||
akobrin1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| effective.Added = uniqueSortedStores(effective.Added) | ||
| effective.Deleted = uniqueSortedStores(effective.Deleted) | ||
|
|
||
| return effective | ||
| } | ||
|
|
||
| func cloneStoreUpgrades(base *storetypes.StoreUpgrades) storetypes.StoreUpgrades { | ||
| if base == nil { | ||
| return storetypes.StoreUpgrades{} | ||
| } | ||
| return storetypes.StoreUpgrades{ | ||
| Added: append([]string(nil), base.Added...), | ||
| Deleted: append([]string(nil), base.Deleted...), | ||
| Renamed: append([]storetypes.StoreRename(nil), base.Renamed...), | ||
| } | ||
| } | ||
|
|
||
| func filterStoreAdds(added []string, existing map[string]struct{}) []string { | ||
| if len(added) == 0 { | ||
| return nil | ||
| } | ||
| out := make([]string, 0, len(added)) | ||
| for _, name := range added { | ||
| if !storeExists(existing, name) { | ||
| out = append(out, name) | ||
| } | ||
| } | ||
| return out | ||
| } | ||
|
|
||
| func filterStoreDeletes(deleted []string, existing map[string]struct{}) []string { | ||
| if len(deleted) == 0 { | ||
| return nil | ||
| } | ||
| out := make([]string, 0, len(deleted)) | ||
| for _, name := range deleted { | ||
| if storeExists(existing, name) { | ||
| out = append(out, name) | ||
| } | ||
| } | ||
| return out | ||
| } | ||
|
|
||
| func filterStoreRenames(renames []storetypes.StoreRename, existing map[string]struct{}) []storetypes.StoreRename { | ||
| if len(renames) == 0 { | ||
| return nil | ||
| } | ||
| out := make([]storetypes.StoreRename, 0, len(renames)) | ||
| for _, rename := range renames { | ||
| if storeExists(existing, rename.OldKey) && !storeExists(existing, rename.NewKey) { | ||
| out = append(out, rename) | ||
| } | ||
| } | ||
| return out | ||
| } | ||
|
|
||
| func storeExists(existing map[string]struct{}, name string) bool { | ||
| if existing == nil { | ||
| return false | ||
| } | ||
| _, ok := existing[name] | ||
| return ok | ||
| } | ||
|
|
||
| func removeStoreName(names []string, target string) []string { | ||
| if len(names) == 0 { | ||
| return nil | ||
| } | ||
| out := names[:0] | ||
| for _, name := range names { | ||
| if name != target { | ||
| out = append(out, name) | ||
| } | ||
| } | ||
| return out | ||
| } | ||
|
|
||
| func uniqueSortedStores(names []string) []string { | ||
| if len(names) == 0 { | ||
| return nil | ||
| } | ||
| set := make(map[string]struct{}, len(names)) | ||
| for _, name := range names { | ||
| set[name] = struct{}{} | ||
| } | ||
| out := make([]string, 0, len(set)) | ||
| for name := range set { | ||
| out = append(out, name) | ||
| } | ||
| sort.Strings(out) | ||
| return out | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package upgrades | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "cosmossdk.io/log" | ||
| storetypes "cosmossdk.io/store/types" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestComputeConsensusStoreUpgrades_RenameWhenLegacyOnly(t *testing.T) { | ||
| expected := setOf("consensus") | ||
| existing := setOf("Consensus", "crisis") | ||
| base := &storetypes.StoreUpgrades{ | ||
| Deleted: []string{"crisis"}, | ||
| } | ||
|
|
||
| effective := computeConsensusStoreUpgrades(base, expected, existing, log.NewNopLogger()) | ||
|
|
||
| require.Len(t, effective.Renamed, 1) | ||
| require.Equal(t, storetypes.StoreRename{OldKey: "Consensus", NewKey: "consensus"}, effective.Renamed[0]) | ||
| require.NotContains(t, effective.Added, "consensus") | ||
| require.NotContains(t, effective.Deleted, "Consensus") | ||
| require.Contains(t, effective.Deleted, "crisis") | ||
| } | ||
akobrin1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| func TestComputeConsensusStoreUpgrades_NoRenameWhenNewExists(t *testing.T) { | ||
| expected := setOf("consensus") | ||
| existing := setOf("consensus") | ||
|
|
||
| effective := computeConsensusStoreUpgrades(nil, expected, existing, log.NewNopLogger()) | ||
|
|
||
| require.Empty(t, effective.Renamed) | ||
| require.Empty(t, effective.Added) | ||
| require.Empty(t, effective.Deleted) | ||
| } | ||
|
|
||
| func TestComputeConsensusStoreUpgrades_AddsConsensusWhenMissingNonAdaptive(t *testing.T) { | ||
| existing := map[string]struct{}{} | ||
|
|
||
| effective := computeConsensusStoreUpgrades(nil, nil, existing, log.NewNopLogger()) | ||
|
|
||
| require.Contains(t, effective.Added, "consensus") | ||
| require.Empty(t, effective.Renamed) | ||
| } | ||
|
|
||
| func TestComputeConsensusStoreUpgrades_NoRenameWhenBothExist(t *testing.T) { | ||
| expected := setOf("consensus") | ||
| existing := setOf("Consensus", "consensus") | ||
|
|
||
| effective := computeConsensusStoreUpgrades(nil, expected, existing, log.NewNopLogger()) | ||
|
|
||
| require.Empty(t, effective.Renamed) | ||
| require.NotContains(t, effective.Deleted, "Consensus") | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.