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:
cool-developer
2023-04-13 09:18:36 +00:00
committed by GitHub
co-authored by Aleksandr Bezobchuk Marko
parent c3fd0e7c64
commit 56705deb22
9 changed files with 77 additions and 2 deletions
+1
View File
@@ -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.
+10
View File
@@ -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()
+5
View File
@@ -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")
}
+2
View File
@@ -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
View File
@@ -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.
+31
View File
@@ -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)
+10
View File
@@ -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)
+6 -2
View File
@@ -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.
+3
View File
@@ -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
}