Skip to content
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

feat(store/v2): handle store upgrades in RootStore #18277

Merged
merged 16 commits into from
Nov 1, 2023

Conversation

alexanderbez
Copy link
Contributor

@alexanderbez alexanderbez commented Oct 26, 2023

Description

closes: #18276


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title
  • added ! to the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • followed the guidelines for building modules
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • included comments for documenting Go code
  • updated the relevant documentation or specification
  • reviewed "Files changed" and left comments if necessary
  • run make lint and make test
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed ! in the type prefix if API or client breaking change
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic
  • reviewed API design and naming
  • reviewed documentation is accurate
  • reviewed tests and test coverage
  • manually tested (if applicable)

Summary by CodeRabbit

Refactor:

  • The Reset function across various store modules now requires an additional parameter, enhancing control over version management.
  • The LoadVersion function in the RootStore interface has been updated for improved error handling.
  • The Commit function in the root/store.go now uses a version parameter for resetting the root KVStore, improving data consistency.

New Features:

  • Added LoadVersionAndUpgrade and LoadLatestVersion functions to the RootStore interface, providing more flexibility in version handling.

Tests:

  • Updated test cases in store_test.go files to accommodate the changes in the Reset function.
  • Added a new test function TestLoadVersion in store/root/store_test.go to ensure correct version loading and state querying.

Chores:

  • Introduced a new package in store/upgrade.go with StoreUpgrades and StoreRename types, and associated methods, paving the way for future store transformations.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 26, 2023

Walkthrough

The changes primarily revolve around the modification of the Reset function across multiple files in the store package. The function now takes an additional parameter of type uint64. The store/root package has seen significant changes with the addition of new functions and modifications to existing ones. A new package store/upgrade.go has been introduced with new types and methods.

Changes

File(s) Summary
store/kv/branch/store.go The Reset function now takes an additional uint64 parameter. Error handling has been modified.
store/kv/branch/store_test.go The Reset function in the StoreTestSuite struct and its test cases have been updated to accommodate the new Reset function signature.
store/kv/gas/store.go The Reset function in the Store struct now takes an additional uint64 parameter.
store/kv/gas/store_test.go The TearDownTest function in the StoreTestSuite struct now calls the Reset method of the gasKVStore object with an argument of 1.
store/kv/mem/store.go The Reset function in the Store struct now takes an additional uint64 parameter. The parameter is unused within the function body.
store/kv/mem/store_test.go The Reset function in the StoreTestSuite struct and its test cases have been updated to accommodate the new Reset function signature.
store/kv/trace/store.go The Reset function in the Store struct now takes an additional uint64 parameter. The implementation calls the Reset method of the parent object with the toVersion parameter.
store/root/store.go Significant changes include function reordering, parameter renaming, and the addition of the LoadVersionAndUpgrade function. The Commit function now takes a version parameter. The writeSC function no longer uses the workingHash variable.
store/root/store_test.go A new test function TestLoadVersion has been added to the RootStoreTestSuite struct.
store/store.go Two new functions LoadVersionAndUpgrade and LoadLatestVersion have been added to the RootStore interface. The Reset function in the KVStore interface now takes an additional uint64 parameter.
store/upgrade.go A new package with two new types: StoreUpgrades and StoreRename, and three new methods: IsAdded, IsDeleted, and RenamedFrom.

🐇🍂
As the leaves fall, so does the old code,
Making way for the new, along the same road.
A change in the air, a shift in the season,
Our code evolves, and for good reason.

The Reset function grows, with a parameter anew,
And store/root changes its view.
A new package born, store/upgrade.go,
With types and methods all in a row.

So here's to the changes, big and small,
In the grand scheme of things, they're not so tall.
As the rabbit hops, so does our code,
Onwards and upwards, on this endless road. 🍂🐇


Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai help to get help.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.json

store/store.go Outdated
//
// Note, handling StoreUpgrades is optional depending on the underlying RootStore
// implementation.
LoadVersionAndUpgrade(version uint64, upgrades *StoreUpgrades) error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be a separate interface that we cast a store to? if its optional then its more boiler plate for implementors

Copy link
Contributor Author

@alexanderbez alexanderbez Oct 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more so that the use of the upgrades argument is optional. In such a case, LoadVersionAndUpgrade would behave the same way LoadVersion does.

We can move LoadVersionAndUpgrade to a separate interface if you'd like?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont think it would make such a big ux win, this is an area where lots of changes wont happen

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So move that method to an interface?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am with @tac0turtle that we should move that method to an optional interface perhaps called "UpgradeableStore" or "StoreWithUpgrades" say

type UpgradeableStore inteface {
   Store
   LoadVersionAndUpgrade(version uint64, upgrades *StoreUpgrades) error
}

@alexanderbez alexanderbez marked this pull request as ready for review October 30, 2023 22:09
@alexanderbez alexanderbez requested a review from a team as a code owner October 30, 2023 22:09
@github-prbot github-prbot requested review from a team, facundomedica and julienrbrt and removed request for a team October 30, 2023 22:09
@github-actions
Copy link
Contributor

@alexanderbez your pull request is missing a changelog!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 6

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 88b7666 and f5c7285.
Files selected for processing (11)
  • store/kv/branch/store.go (2 hunks)
  • store/kv/branch/store_test.go (1 hunks)
  • store/kv/gas/store.go (1 hunks)
  • store/kv/gas/store_test.go (1 hunks)
  • store/kv/mem/store.go (1 hunks)
  • store/kv/mem/store_test.go (1 hunks)
  • store/kv/trace/store.go (1 hunks)
  • store/root/store.go (5 hunks)
  • store/root/store_test.go (1 hunks)
  • store/store.go (2 hunks)
  • store/upgrade.go (1 hunks)
Additional comments: 11
store/kv/mem/store_test.go (1)
  • 46-50: The Reset function now takes an additional argument. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, it would be good to add a comment explaining what the 1 argument represents in the Reset function call for better readability and maintainability.
store/kv/branch/store_test.go (1)
  • 66-69: The Reset function now takes an additional argument. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, consider adding a comment to explain what the 1 argument represents for better code readability.
store/kv/gas/store_test.go (1)
  • 38-39: The Reset method now takes an additional parameter. Ensure that the value 1 is the correct value to be passed in all scenarios where this test is run. If the value is context-dependent, consider passing it as a parameter to the test function or retrieving it from a configuration file or environment variable.
err := s.gasKVStore.Reset(1)
s.Require().NoError(err)
store/root/store_test.go (1)
  • 131-196: The TestLoadVersion function seems to be well written and covers a variety of scenarios including writing and committing changesets, loading non-existent and previously committed versions, querying state based on loaded version, and overwriting values. It also checks for the correct latest version after each operation. This is a good practice as it ensures the integrity of the versioning system.
store/store.go (2)
  • 52-67: The new methods LoadVersionAndUpgrade and LoadLatestVersion have been added to the RootStore interface. Ensure that all implementations of this interface have been updated to include these methods. Also, verify that the LoadVersion method no longer returns an error and all its usages have been updated accordingly.

  • 127-131: The Reset method in the KVStore interface now takes an additional parameter v uint64. Ensure that all implementations of this interface have been updated to include this change. Also, verify that all calls to this method throughout the codebase have been updated to match the new signature.

store/kv/trace/store.go (1)
  • 83-85: The Reset function now takes an additional parameter v of type uint64. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, make sure that the Reset function in the parent store properly handles the v parameter.
store/upgrade.go (1)
  • 1-53: The new types and methods introduced in this hunk seem to be well-structured and logically sound. The StoreUpgrades struct and its methods provide a clear way to manage store transformations. The StoreRename struct is a simple and effective way to represent a change in a store key. The use of the slices.Contains function from the golang.org/x/exp/slices package is a good choice for checking if a key should be added or deleted. The RenamedFrom method correctly iterates over the Renamed slice to find if a key was renamed.

However, the slices.Contains function has a time complexity of O(n) which could be a performance issue if the Added or Deleted slices are large. Consider using a data structure with faster lookup times, such as a map, if performance becomes an issue.

store/kv/branch/store.go (2)
  • 1-7: The new import statement for the "fmt" package is fine as it is used for error formatting in the updated Reset function.

  • 88-100: The Reset function now takes an additional parameter v of type uint64. This function sets the latest version of the storage to the value of v and updates the version field of the Store struct accordingly. The error handling in the function has also been modified. Ensure that all calls to this function throughout the codebase have been updated to match the new signature.

store/kv/gas/store.go (1)
  • 65-67: The function signature of Reset has been updated to include a new parameter v. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, make sure that the Reset function in the parent store properly handles this new parameter.

store/root/store.go Outdated Show resolved Hide resolved
store/kv/mem/store.go Show resolved Hide resolved
Copy link
Collaborator

@odeke-em odeke-em left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @alexanderbez for the interesting PR, I've added some feedback, please take a look.

store/kv/branch/store.go Outdated Show resolved Hide resolved
store/store.go Outdated
//
// Note, handling StoreUpgrades is optional depending on the underlying RootStore
// implementation.
LoadVersionAndUpgrade(version uint64, upgrades *StoreUpgrades) error
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am with @tac0turtle that we should move that method to an optional interface perhaps called "UpgradeableStore" or "StoreWithUpgrades" say

type UpgradeableStore inteface {
   Store
   LoadVersionAndUpgrade(version uint64, upgrades *StoreUpgrades) error
}

store/upgrade.go Outdated Show resolved Hide resolved
store/upgrade.go Show resolved Hide resolved
store/upgrade.go Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between f5c7285 and 52bda2a.
Files selected for processing (5)
  • store/kv/branch/store.go (2 hunks)
  • store/kv/gas/store.go (1 hunks)
  • store/kv/trace/store.go (1 hunks)
  • store/store.go (2 hunks)
  • store/upgrade.go (1 hunks)
Additional comments: 6
store/kv/trace/store.go (1)
  • 83-85: The Reset function has been updated to accept a new parameter toVersion. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, make sure that the parent object's Reset method can handle this new parameter correctly.
store/kv/gas/store.go (1)
  • 65-67: The Reset function now takes an additional parameter toVersion of type uint64. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, make sure that the Reset function in the parent store handles this new parameter correctly.
store/kv/branch/store.go (2)
  • 1-7: The new import statement for the "fmt" package is fine.

  • 88-100: The Reset function now takes an additional parameter toVersion uint64 and returns an error. This is a breaking change and all calls to this function throughout the codebase should be updated to match the new signature. Also, ensure that error handling is properly done wherever this function is called. The logic inside the function seems fine.

- func (s *Store) Reset() {
+ func (s *Store) Reset(toVersion uint64) error {
store/store.go (2)
  • 52-67: The new functions LoadVersion, LoadVersionAndUpgrade, and LoadLatestVersion have been added to the RootStore interface. Ensure that all implementations of this interface have been updated to include these new functions. Also, verify that the version parameter in LoadVersion and LoadVersionAndUpgrade is being used correctly in the function implementations.

  • 130-130: The Reset function in the KVStore interface now takes a toVersion parameter. Ensure that all implementations of this interface have been updated to include this new parameter. Also, verify that the toVersion parameter is being used correctly in the function implementations.

store/upgrade.go Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 52bda2a and d527b2e.
Files selected for processing (2)
  • store/root/store.go (5 hunks)
  • store/store.go (3 hunks)
Additional comments: 3
store/store.go (3)
  • 52-60: The new methods LoadVersion and LoadLatestVersion have been added to the RootStore interface. Ensure that all implementations of this interface have been updated to include these methods.

  • 86-98: The new UpgradeableRootStore interface extends the RootStore interface and adds the LoadVersionAndUpgrade method. This is a good example of interface segregation, a principle of SOLID, where a new interface is created instead of adding the method to the existing interface. This ensures that only the stores that need to handle upgrades implement this interface.

  • 137-137: The Reset method in the KVStore interface now takes an additional uint64 parameter. Ensure that all implementations of this interface have been updated to match the new method signature.

store/root/store.go Outdated Show resolved Hide resolved
return s.loadVersion(version, nil)
}

func (s *Store) loadVersion(v uint64, _ *store.StoreUpgrades) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a WIP? couldn't see the call of loadVersion with upgrades.

Copy link
Contributor Author

@alexanderbez alexanderbez Nov 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation doesn't support store upgrades since it's all a single tree/store key. In other words, store keys are ignored in the single tree implementation.

Co-authored-by: cool-developer <[email protected]>
Copy link
Collaborator

@odeke-em odeke-em left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @alexanderbez!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between d527b2e and abf887d.
Files selected for processing (1)
  • store/root/store.go (5 hunks)

Comment on lines 101 to 106
return s.stateCommitment
}

func (s *Store) LoadLatestVersion() error {
lv, err := s.GetLatestVersion()
if err != nil {
return err
}

return s.loadVersion(lv, nil)
}

// LastCommitID returns a CommitID based off of the latest internal CommitInfo.
// If an internal CommitInfo is not set, a new one will be returned with only the
// latest version set, which is based off of the SS view.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function LastCommitID is returning a new CommitID with only the latest version set when lastCommitInfo is nil. This might lead to unexpected behavior if the caller expects a fully populated CommitID. Consider returning an error in this case.

Comment on lines 200 to 220
func (s *Store) loadVersion(v uint64, _ *store.StoreUpgrades) error {
s.logger.Debug("loading version", "version", v)

// Reset the root KVStore s.t. the latest version is v. Any writes will
// overwrite existing versions.
if err := s.rootKVStore.Reset(v); err != nil {
return err
}

if err := s.stateCommitment.LoadVersion(v); err != nil {
return fmt.Errorf("failed to load SS version %d: %w", v, err)
}

// TODO: Complete this method to handle upgrades. See legacy RMS loadVersion()
// for reference.
//
// Ref: https://github.com/cosmos/cosmos-sdk/issues/17314
s.workingHash = nil
s.commitHeader = nil

// set lastCommitInfo explicitly s.t. Commit commits the correct version, i.e. v+1
s.lastCommitInfo = &store.CommitInfo{Version: v}

return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function loadVersion is ignoring the StoreUpgrades parameter. If this is intentional, consider documenting this behavior in the function comment to avoid confusion.

Comment on lines 311 to 317
s.lastCommitInfo.Timestamp = s.commitHeader.GetTime()
}

if err := s.rootKVStore.Reset(); err != nil {
if err := s.rootKVStore.Reset(version); err != nil {
return nil, fmt.Errorf("failed to reset root KVStore: %w", err)
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function Commit is resetting the rootKVStore to the current version after committing the changes. This might lead to data loss if there are uncommitted changes in the rootKVStore. Consider adding a check to ensure that there are no uncommitted changes before resetting the rootKVStore.

Comment on lines 347 to 360
version = previousHeight + 1
}

workingHash := s.stateCommitment.WorkingHash()

s.lastCommitInfo = &store.CommitInfo{
Version: version,
StoreInfos: []store.StoreInfo{
{
Name: defaultStoreKey,
CommitID: store.CommitID{
Version: version,
Hash: workingHash,
Hash: s.stateCommitment.WorkingHash(),
},
},
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function writeSC is creating a new CommitInfo with only one StoreInfo for the default store key. This might lead to unexpected behavior if the caller expects a CommitInfo with all the StoreInfos. Consider adding a check to ensure that all the StoreInfos are included in the CommitInfo.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between abf887d and b32979d.
Files selected for processing (1)
  • store/root/store.go (5 hunks)
Additional comments: 3
store/root/store.go (3)
  • 101-106: The function LastCommitID is returning a new CommitID with only the latest version set when lastCommitInfo is nil. This might lead to unexpected behavior if the caller expects a fully populated CommitID. Consider returning an error in this case.

  • 311-317: The function Commit is resetting the rootKVStore to the current version after committing the changes. This might lead to data loss if there are uncommitted changes in the rootKVStore. Consider adding a check to ensure that there are no uncommitted changes before resetting the rootKVStore.

  • 347-360: The function writeSC is creating a new CommitInfo with only one StoreInfo for the default store key. This might lead to unexpected behavior if the caller expects a CommitInfo with all the StoreInfos. Consider adding a check to ensure that all the StoreInfos are included in the CommitInfo.

@alexanderbez alexanderbez added this pull request to the merge queue Nov 1, 2023
Merged via the queue into main with commit 0867d0a Nov 1, 2023
58 of 59 checks passed
@alexanderbez alexanderbez deleted the bez/18276-store-v2-upgrades branch November 1, 2023 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ensure LoadVersion Handles Upgrades
6 participants