feat(store): add working hash (#15712)
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> Co-authored-by: Marko <marbar3778@yahoo.com>
This commit is contained in:
co-authored by
Aleksandr Bezobchuk
Marko
parent
c3fd0e7c64
commit
56705deb22
@@ -27,6 +27,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### Features
|
||||
|
||||
- [#15712](https://github.com/cosmos/cosmos-sdk/pull/15712) Add `WorkingHash` function to the store interface to get the current app hash before commit.
|
||||
* [#14645](https://github.com/cosmos/cosmos-sdk/pull/14645) Add limit to the length of key and value.
|
||||
* [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has.
|
||||
|
||||
|
||||
@@ -143,6 +143,16 @@ func (st *Store) Commit() types.CommitID {
|
||||
}
|
||||
}
|
||||
|
||||
// WorkingHash returns the hash of the current working tree.
|
||||
func (st *Store) WorkingHash() []byte {
|
||||
hash, err := st.tree.WorkingHash()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to retrieve working hash: %w", err))
|
||||
}
|
||||
|
||||
return hash
|
||||
}
|
||||
|
||||
// LastCommitID implements Committer.
|
||||
func (st *Store) LastCommitID() types.CommitID {
|
||||
hash, err := st.tree.Hash()
|
||||
|
||||
@@ -27,6 +27,7 @@ type (
|
||||
DeleteVersions(versions ...int64) error
|
||||
Version() int64
|
||||
Hash() ([]byte, error)
|
||||
WorkingHash() ([]byte, error)
|
||||
VersionExists(version int64) bool
|
||||
GetVersioned(key []byte, version int64) ([]byte, error)
|
||||
GetImmutable(version int64) (*iavl.ImmutableTree, error)
|
||||
@@ -101,3 +102,7 @@ func (it *immutableTree) LoadVersionForOverwriting(targetVersion int64) (int64,
|
||||
func (it *immutableTree) LazyLoadVersionForOverwriting(targetVersion int64) (int64, error) {
|
||||
panic("cannot call 'LazyLoadVersionForOverwriting' on an immutable IAVL tree")
|
||||
}
|
||||
|
||||
func (it *immutableTree) WorkingHash() ([]byte, error) {
|
||||
panic("cannot call 'WorkingHash' on an immutable IAVL tree")
|
||||
}
|
||||
|
||||
@@ -58,3 +58,5 @@ func (s *Store) GetPruning() pruningtypes.PruningOptions {
|
||||
}
|
||||
|
||||
func (s Store) LastCommitID() (id types.CommitID) { return }
|
||||
|
||||
func (s Store) WorkingHash() (hash []byte) { return }
|
||||
|
||||
@@ -9,6 +9,11 @@ import (
|
||||
|
||||
var commithash = []byte("FAKE_HASH")
|
||||
|
||||
var (
|
||||
_ types.KVStore = (*commitDBStoreAdapter)(nil)
|
||||
_ types.Committer = (*commitDBStoreAdapter)(nil)
|
||||
)
|
||||
|
||||
//----------------------------------------
|
||||
// commitDBStoreWrapper should only be used for simulation/debugging,
|
||||
// as it doesn't compute any commit hash, and it cannot load older state.
|
||||
@@ -32,6 +37,10 @@ func (cdsa commitDBStoreAdapter) LastCommitID() types.CommitID {
|
||||
}
|
||||
}
|
||||
|
||||
func (cdsa commitDBStoreAdapter) WorkingHash() []byte {
|
||||
return commithash
|
||||
}
|
||||
|
||||
func (cdsa commitDBStoreAdapter) SetPruning(_ pruningtypes.PruningOptions) {}
|
||||
|
||||
// GetPruning is a no-op as pruning options cannot be directly set on this store.
|
||||
|
||||
@@ -497,6 +497,37 @@ func (rs *Store) Commit() types.CommitID {
|
||||
}
|
||||
}
|
||||
|
||||
// WorkingHash returns the current hash of the store.
|
||||
// it will be used to get the current app hash before commit.
|
||||
func (rs *Store) WorkingHash() []byte {
|
||||
storeInfos := make([]types.StoreInfo, 0, len(rs.stores))
|
||||
storeKeys := keysFromStoreKeyMap(rs.stores)
|
||||
|
||||
for _, key := range storeKeys {
|
||||
store := rs.stores[key]
|
||||
|
||||
if store.GetStoreType() != types.StoreTypeIAVL {
|
||||
continue
|
||||
}
|
||||
|
||||
if !rs.removalMap[key] {
|
||||
si := types.StoreInfo{
|
||||
Name: key.Name(),
|
||||
CommitId: types.CommitID{
|
||||
Hash: store.WorkingHash(),
|
||||
},
|
||||
}
|
||||
storeInfos = append(storeInfos, si)
|
||||
}
|
||||
}
|
||||
|
||||
sort.SliceStable(storeInfos, func(i, j int) bool {
|
||||
return storeInfos[i].Name < storeInfos[j].Name
|
||||
})
|
||||
|
||||
return types.CommitInfo{StoreInfos: storeInfos}.Hash()
|
||||
}
|
||||
|
||||
// CacheWrap implements CacheWrapper/Store/CommitStore.
|
||||
func (rs *Store) CacheWrap() types.CacheWrap {
|
||||
return rs.CacheMultiStore().(types.CacheWrap)
|
||||
|
||||
@@ -128,12 +128,16 @@ func TestHashStableWithEmptyCommit(t *testing.T) {
|
||||
store1 := ms.GetStoreByName("store1").(types.KVStore)
|
||||
store1.Set(k, v)
|
||||
|
||||
workingHash := ms.WorkingHash()
|
||||
cID := ms.Commit()
|
||||
require.Equal(t, int64(1), cID.Version)
|
||||
hash := cID.Hash
|
||||
require.Equal(t, workingHash, hash)
|
||||
|
||||
// make an empty commit, it should update version, but not affect hash
|
||||
workingHash = ms.WorkingHash()
|
||||
cID = ms.Commit()
|
||||
require.Equal(t, workingHash, cID.Hash)
|
||||
require.Equal(t, int64(2), cID.Version)
|
||||
require.Equal(t, hash, cID.Hash)
|
||||
}
|
||||
@@ -159,7 +163,9 @@ func TestMultistoreCommitLoad(t *testing.T) {
|
||||
// Make a few commits and check them.
|
||||
nCommits := int64(3)
|
||||
for i := int64(0); i < nCommits; i++ {
|
||||
workingHash := store.WorkingHash()
|
||||
commitID = store.Commit()
|
||||
require.Equal(t, workingHash, commitID.Hash)
|
||||
expectedCommitID := getExpectedCommitID(store, i+1)
|
||||
checkStore(t, store, expectedCommitID, commitID)
|
||||
}
|
||||
@@ -172,7 +178,9 @@ func TestMultistoreCommitLoad(t *testing.T) {
|
||||
checkStore(t, store, commitID, commitID)
|
||||
|
||||
// Commit and check version.
|
||||
workingHash := store.WorkingHash()
|
||||
commitID = store.Commit()
|
||||
require.Equal(t, workingHash, commitID.Hash)
|
||||
expectedCommitID := getExpectedCommitID(store, nCommits+1)
|
||||
checkStore(t, store, expectedCommitID, commitID)
|
||||
|
||||
@@ -211,7 +219,9 @@ func TestMultistoreLoadWithUpgrade(t *testing.T) {
|
||||
require.Nil(t, s4)
|
||||
|
||||
// do one commit
|
||||
workingHash := store.WorkingHash()
|
||||
commitID := store.Commit()
|
||||
require.Equal(t, workingHash, commitID.Hash)
|
||||
expectedCommitID := getExpectedCommitID(store, 1)
|
||||
checkStore(t, store, expectedCommitID, commitID)
|
||||
|
||||
|
||||
@@ -39,8 +39,12 @@ func (ts *Store) GetPruning() pruningtypes.PruningOptions {
|
||||
}
|
||||
|
||||
// Implements CommitStore
|
||||
func (ts *Store) LastCommitID() (id types.CommitID) {
|
||||
return
|
||||
func (ts *Store) LastCommitID() types.CommitID {
|
||||
return types.CommitID{}
|
||||
}
|
||||
|
||||
func (ts *Store) WorkingHash() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// Implements Store.
|
||||
|
||||
@@ -22,6 +22,9 @@ type Committer interface {
|
||||
Commit() CommitID
|
||||
LastCommitID() CommitID
|
||||
|
||||
// WorkingHash returns the hash of the KVStore's state before commit.
|
||||
WorkingHash() []byte
|
||||
|
||||
SetPruning(pruningtypes.PruningOptions)
|
||||
GetPruning() pruningtypes.PruningOptions
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user