Skip to content

Commit

Permalink
feat!: Add hooks to allow app modules to add things to state-sync (ba…
Browse files Browse the repository at this point in the history
…ckport cosmos#10961) (cosmos#11267)

* feat!: Add hooks to allow app modules to add things to state-sync (cosmos#10961)

## Description

Closes: cosmos#7340

- Support registering multiple snapshotters in snapshot manager.
- Append the extension snapshotters to existing snapshot stream.

~TODO: testing.~
- existing tests are fixed

---

### 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](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] 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](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) 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)

(cherry picked from commit 7e18e9f)

# Conflicts:
#	api/cosmos/base/snapshots/v1beta1/snapshot.pulsar.go
#	server/mock/store.go
#	snapshots/helpers_test.go
#	snapshots/manager.go
#	store/rootmulti/store_test.go
#	store/v2/multi/store.go

* fix conflicts

* avoid api breakage

* changelog

* fix: rootmulti's Restore don't return the next unknown item as expected (cosmos#11286)

## Description
Solution:
- return the next unknown item and add a unit test to ensure that.

---

### 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](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] 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](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) 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)

Co-authored-by: yihuang <huang@crypto.com>
  • Loading branch information
2 people authored and JeancarloBarrios committed Sep 28, 2024
1 parent 09b5e9c commit e6bf8b7
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 495 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

* [\#9576](https://github.com/cosmos/cosmos-sdk/pull/9576) Add debug error message to query result when enabled
* (types) [\#11200](https://github.com/cosmos/cosmos-sdk/pull/11200) Added `Min()` and `Max()` operations on sdk.Coins.
* [#11267](https://github.com/cosmos/cosmos-sdk/pull/11267) Add hooks to allow app modules to add things to state-sync (backport #10961).

## [v0.45.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.1) - 2022-02-03

Expand Down
7 changes: 5 additions & 2 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,11 @@ func DefaultStoreLoader(ms storetypes.CommitMultiStore) error {

// CommitMultiStore returns the root multi-store.
// App constructor can use this to access the `cms`.
// UNSAFE: must not be used during the abci life cycle.
func (app *BaseApp) CommitMultiStore() storetypes.CommitMultiStore {
// UNSAFE: only safe to use during app initialization.
func (app *BaseApp) CommitMultiStore() sdk.CommitMultiStore {
if app.sealed {
panic("cannot call CommitMultiStore() after baseapp is sealed")
}
return app.cms
}

Expand Down
15 changes: 5 additions & 10 deletions server/mock/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package mock
import (
"io"

protoio "github.com/cosmos/gogoproto/io"
protoio "github.com/gogo/protobuf/io"
dbm "github.com/tendermint/tm-db"

corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/metrics"
pruningtypes "cosmossdk.io/store/pruning/types"
snapshottypes "cosmossdk.io/store/snapshots/types"
storetypes "cosmossdk.io/store/types"
snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
store "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

var _ storetypes.MultiStore = multiStore{}
Expand Down Expand Up @@ -159,10 +158,6 @@ func (ms multiStore) Restore(
panic("not implemented")
}

func (ms multiStore) RollbackToVersion(version int64) error {
panic("not implemented")
}

func (ms multiStore) LatestVersion() int64 {
panic("not implemented")
}
Expand Down
70 changes: 29 additions & 41 deletions store/rootmulti/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,16 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

corestore "cosmossdk.io/core/store"
coretesting "cosmossdk.io/core/testing"
"cosmossdk.io/log"
"cosmossdk.io/store/iavl"
"cosmossdk.io/store/metrics"
"cosmossdk.io/store/rootmulti"
"cosmossdk.io/store/snapshots"
snapshottypes "cosmossdk.io/store/snapshots/types"
"cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/snapshots"
snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
"github.com/cosmos/cosmos-sdk/store/iavl"
"github.com/cosmos/cosmos-sdk/store/rootmulti"
"github.com/cosmos/cosmos-sdk/store/types"
dbm "github.com/tendermint/tm-db"
)

func newMultiStoreWithGeneratedData(db corestore.KVStoreWithBatch, stores uint8, storeKeys uint64) *rootmulti.Store {
multiStore := rootmulti.NewStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics())
func newMultiStoreWithGeneratedData(db dbm.DB, stores uint8, storeKeys uint64) *rootmulti.Store {
multiStore := rootmulti.NewStore(db)
r := rand.New(rand.NewSource(49872768940)) // Fixed seed for deterministic tests

keys := []*types.KVStoreKey{}
Expand All @@ -34,10 +31,7 @@ func newMultiStoreWithGeneratedData(db corestore.KVStoreWithBatch, stores uint8,
multiStore.MountStoreWithDB(key, types.StoreTypeIAVL, nil)
keys = append(keys, key)
}
err := multiStore.LoadLatestVersion()
if err != nil {
panic(err)
}
multiStore.LoadLatestVersion()

for _, key := range keys {
store := multiStore.GetCommitKVStore(key).(*iavl.Store)
Expand All @@ -54,27 +48,23 @@ func newMultiStoreWithGeneratedData(db corestore.KVStoreWithBatch, stores uint8,
}

multiStore.Commit()
err = multiStore.LoadLatestVersion()
if err != nil {
panic(err)
}
multiStore.LoadLatestVersion()

return multiStore
}

func newMultiStoreWithMixedMounts(db corestore.KVStoreWithBatch) *rootmulti.Store {
store := rootmulti.NewStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics())
func newMultiStoreWithMixedMounts(db dbm.DB) *rootmulti.Store {
store := rootmulti.NewStore(db)
store.MountStoreWithDB(types.NewKVStoreKey("iavl1"), types.StoreTypeIAVL, nil)
store.MountStoreWithDB(types.NewKVStoreKey("iavl2"), types.StoreTypeIAVL, nil)
store.MountStoreWithDB(types.NewKVStoreKey("iavl3"), types.StoreTypeIAVL, nil)
store.MountStoreWithDB(types.NewTransientStoreKey("trans1"), types.StoreTypeTransient, nil)
if err := store.LoadLatestVersion(); err != nil {
panic(err)
}
store.LoadLatestVersion()

return store
}

func newMultiStoreWithMixedMountsAndBasicData(db corestore.KVStoreWithBatch) *rootmulti.Store {
func newMultiStoreWithMixedMountsAndBasicData(db dbm.DB) *rootmulti.Store {
store := newMultiStoreWithMixedMounts(db)
store1 := store.GetStoreByName("iavl1").(types.CommitKVStore)
store2 := store.GetStoreByName("iavl2").(types.CommitKVStore)
Expand All @@ -101,7 +91,6 @@ func newMultiStoreWithMixedMountsAndBasicData(db corestore.KVStoreWithBatch) *ro
}

func assertStoresEqual(t *testing.T, expect, actual types.CommitKVStore, msgAndArgs ...interface{}) {
t.Helper()
assert.Equal(t, expect.LastCommitID(), actual.LastCommitID())
expectIter := expect.Iterator(nil, nil)
expectMap := map[string][]byte{}
Expand All @@ -125,7 +114,7 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) {
// This checksum test makes sure that the byte stream remains identical. If the test fails
// without having changed the data (e.g. because the Protobuf or zlib encoding changes),
// snapshottypes.CurrentFormat must be bumped.
store := newMultiStoreWithGeneratedData(coretesting.NewMemDB(), 5, 10000)
store := newMultiStoreWithGeneratedData(dbm.NewMemDB(), 5, 10000)
version := uint64(store.LastCommitID().Version)

testcases := []struct {
Expand All @@ -138,10 +127,11 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) {
"aa048b4ee0f484965d7b3b06822cf0772cdcaad02f3b1b9055e69f2cb365ef3c",
"7921eaa3ed4921341e504d9308a9877986a879fe216a099c86e8db66fcba4c63",
"a4a864e6c02c9fca5837ec80dc84f650b25276ed7e4820cf7516ced9f9901b86",
"980925390cc50f14998ecb1e87de719ca9dd7e72f5fefbe445397bf670f36c31",
"ca2879ac6e7205d257440131ba7e72bef784cd61642e32b847729e543c1928b9",
}},
}
for _, tc := range testcases {
tc := tc
t.Run(fmt.Sprintf("Format %v", tc.format), func(t *testing.T) {
ch := make(chan io.ReadCloser)
go func() {
Expand All @@ -166,7 +156,7 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) {
}

func TestMultistoreSnapshot_Errors(t *testing.T) {
store := newMultiStoreWithMixedMountsAndBasicData(coretesting.NewMemDB())
store := newMultiStoreWithMixedMountsAndBasicData(dbm.NewMemDB())

testcases := map[string]struct {
height uint64
Expand All @@ -176,6 +166,7 @@ func TestMultistoreSnapshot_Errors(t *testing.T) {
"unknown height": {9, nil},
}
for name, tc := range testcases {
tc := tc
t.Run(name, func(t *testing.T) {
err := store.Snapshot(tc.height, nil)
require.Error(t, err)
Expand All @@ -187,8 +178,8 @@ func TestMultistoreSnapshot_Errors(t *testing.T) {
}

func TestMultistoreSnapshotRestore(t *testing.T) {
source := newMultiStoreWithMixedMountsAndBasicData(coretesting.NewMemDB())
target := newMultiStoreWithMixedMounts(coretesting.NewMemDB())
source := newMultiStoreWithMixedMountsAndBasicData(dbm.NewMemDB())
target := newMultiStoreWithMixedMounts(dbm.NewMemDB())
version := uint64(source.LastCommitID().Version)
require.EqualValues(t, 3, version)
dummyExtensionItem := snapshottypes.SnapshotItem{
Expand Down Expand Up @@ -219,8 +210,7 @@ func TestMultistoreSnapshotRestore(t *testing.T) {
require.Equal(t, *dummyExtensionItem.GetExtension(), *nextItem.GetExtension())

assert.Equal(t, source.LastCommitID(), target.LastCommitID())
for _, key := range source.StoreKeysByName() {
sourceStore := source.GetStoreByName(key.Name()).(types.CommitKVStore)
for key, sourceStore := range source.GetStores() {
targetStore := target.GetStoreByName(key.Name()).(types.CommitKVStore)
switch sourceStore.GetStoreType() {
case types.StoreTypeTransient:
Expand All @@ -233,19 +223,18 @@ func TestMultistoreSnapshotRestore(t *testing.T) {
}

func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) {
b.Helper()
b.Skip("Noisy with slow setup time, please see https://github.com/cosmos/cosmos-sdk/issues/8855.")

b.ReportAllocs()
b.StopTimer()
source := newMultiStoreWithGeneratedData(coretesting.NewMemDB(), stores, storeKeys)
source := newMultiStoreWithGeneratedData(dbm.NewMemDB(), stores, storeKeys)
version := source.LastCommitID().Version
require.EqualValues(b, 1, version)
b.StartTimer()

for i := 0; i < b.N; i++ {
target := rootmulti.NewStore(coretesting.NewMemDB(), log.NewNopLogger(), metrics.NewNoOpMetrics())
for _, key := range source.StoreKeysByName() {
target := rootmulti.NewStore(dbm.NewMemDB())
for key := range source.GetStores() {
target.MountStoreWithDB(key, types.StoreTypeIAVL, nil)
}
err := target.LoadLatestVersion()
Expand All @@ -269,19 +258,18 @@ func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) {
}

func benchmarkMultistoreSnapshotRestore(b *testing.B, stores uint8, storeKeys uint64) {
b.Helper()
b.Skip("Noisy with slow setup time, please see https://github.com/cosmos/cosmos-sdk/issues/8855.")

b.ReportAllocs()
b.StopTimer()
source := newMultiStoreWithGeneratedData(coretesting.NewMemDB(), stores, storeKeys)
source := newMultiStoreWithGeneratedData(dbm.NewMemDB(), stores, storeKeys)
version := uint64(source.LastCommitID().Version)
require.EqualValues(b, 1, version)
b.StartTimer()

for i := 0; i < b.N; i++ {
target := rootmulti.NewStore(coretesting.NewMemDB(), log.NewNopLogger(), metrics.NewNoOpMetrics())
for _, key := range source.StoreKeysByName() {
target := rootmulti.NewStore(dbm.NewMemDB())
for key := range source.GetStores() {
target.MountStoreWithDB(key, types.StoreTypeIAVL, nil)
}
err := target.LoadLatestVersion()
Expand Down
Loading

0 comments on commit e6bf8b7

Please sign in to comment.