-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Conversation
WalkthroughThe changes primarily revolve around the modification of the Changes
TipsChat with CodeRabbit Bot (
|
store/store.go
Outdated
// | ||
// Note, handling StoreUpgrades is optional depending on the underlying RootStore | ||
// implementation. | ||
LoadVersionAndUpgrade(version uint64, upgrades *StoreUpgrades) error |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 your pull request is missing a changelog! |
There was a problem hiding this 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
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 the1
argument represents in theReset
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 the1
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 value1
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
andLoadLatestVersion
have been added to theRootStore
interface. Ensure that all implementations of this interface have been updated to include these methods. Also, verify that theLoadVersion
method no longer returns an error and all its usages have been updated accordingly.127-131: The
Reset
method in theKVStore
interface now takes an additional parameterv 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 parameterv
of typeuint64
. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, make sure that theReset
function in theparent
store properly handles thev
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. TheStoreRename
struct is a simple and effective way to represent a change in a store key. The use of theslices.Contains
function from thegolang.org/x/exp/slices
package is a good choice for checking if a key should be added or deleted. TheRenamedFrom
method correctly iterates over theRenamed
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 theAdded
orDeleted
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 parameterv
of typeuint64
. This function sets the latest version of the storage to the value ofv
and updates theversion
field of theStore
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 parameterv
. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, make sure that theReset
function in theparent
store properly handles this new parameter.
There was a problem hiding this 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/store.go
Outdated
// | ||
// Note, handling StoreUpgrades is optional depending on the underlying RootStore | ||
// implementation. | ||
LoadVersionAndUpgrade(version uint64, upgrades *StoreUpgrades) error |
There was a problem hiding this comment.
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
}
There was a problem hiding this 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
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 parametertoVersion
. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, make sure that theparent
object'sReset
method can handle this new parameter correctly.store/kv/gas/store.go (1)
- 65-67: The
Reset
function now takes an additional parametertoVersion
of typeuint64
. Ensure that all calls to this function throughout the codebase have been updated to match the new signature. Also, make sure that theReset
function in theparent
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 parametertoVersion 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
, andLoadLatestVersion
have been added to theRootStore
interface. Ensure that all implementations of this interface have been updated to include these new functions. Also, verify that theversion
parameter inLoadVersion
andLoadVersionAndUpgrade
is being used correctly in the function implementations.130-130: The
Reset
function in theKVStore
interface now takes atoVersion
parameter. Ensure that all implementations of this interface have been updated to include this new parameter. Also, verify that thetoVersion
parameter is being used correctly in the function implementations.
There was a problem hiding this 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
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
andLoadLatestVersion
have been added to theRootStore
interface. Ensure that all implementations of this interface have been updated to include these methods.86-98: The new
UpgradeableRootStore
interface extends theRootStore
interface and adds theLoadVersionAndUpgrade
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 theKVStore
interface now takes an additionaluint64
parameter. Ensure that all implementations of this interface have been updated to match the new method signature.
store/root/store.go
Outdated
return s.loadVersion(version, nil) | ||
} | ||
|
||
func (s *Store) loadVersion(v uint64, _ *store.StoreUpgrades) error { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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]>
There was a problem hiding this 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!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
There was a problem hiding this comment.
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.
store/root/store.go
Outdated
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 | ||
} |
There was a problem hiding this comment.
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.
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) | ||
} | ||
|
There was a problem hiding this comment.
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
.
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(), | ||
}, | ||
}, | ||
}, |
There was a problem hiding this comment.
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 StoreInfo
s. Consider adding a check to ensure that all the StoreInfo
s are included in the CommitInfo
.
There was a problem hiding this 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
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 newCommitID
with only the latest version set whenlastCommitInfo
isnil
. This might lead to unexpected behavior if the caller expects a fully populatedCommitID
. Consider returning an error in this case.311-317: The function
Commit
is resetting therootKVStore
to the current version after committing the changes. This might lead to data loss if there are uncommitted changes in therootKVStore
. Consider adding a check to ensure that there are no uncommitted changes before resetting therootKVStore
.347-360: The function
writeSC
is creating a newCommitInfo
with only oneStoreInfo
for the default store key. This might lead to unexpected behavior if the caller expects aCommitInfo
with all theStoreInfo
s. Consider adding a check to ensure that all theStoreInfo
s are included in theCommitInfo
.
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...
!
to the type prefix if API or client breaking changeCHANGELOG.md
make lint
andmake test
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...
!
in the type prefix if API or client breaking changeSummary by CodeRabbit
Refactor:
Reset
function across various store modules now requires an additional parameter, enhancing control over version management.LoadVersion
function in theRootStore
interface has been updated for improved error handling.Commit
function in theroot/store.go
now uses aversion
parameter for resetting the root KVStore, improving data consistency.New Features:
LoadVersionAndUpgrade
andLoadLatestVersion
functions to theRootStore
interface, providing more flexibility in version handling.Tests:
store_test.go
files to accommodate the changes in theReset
function.TestLoadVersion
instore/root/store_test.go
to ensure correct version loading and state querying.Chores:
store/upgrade.go
withStoreUpgrades
andStoreRename
types, and associated methods, paving the way for future store transformations.