diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 7dceec3d9e8c..94859275a220 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### API Breaking + +* [#22435](https://github.com/cosmos/cosmos-sdk/pull/22435) Add `Version uint64` field to `store.Changeset` and update `Changeset` constructors to accept a `version uint64` as their first argument. + ### Features * [#22326](https://github.com/cosmos/cosmos-sdk/pull/22326) Introduce codec package in order to facilitate removal of Cosmos SDK dependency in modules. diff --git a/core/store/changeset.go b/core/store/changeset.go index 35837059c627..475a861445b6 100644 --- a/core/store/changeset.go +++ b/core/store/changeset.go @@ -6,6 +6,7 @@ import ( // Changeset is a list of changes to be written to disk type Changeset struct { + Version uint64 Changes []StateChanges } @@ -29,11 +30,11 @@ type KVPair = struct { Remove bool } -func NewChangeset() *Changeset { - return &Changeset{} +func NewChangeset(version uint64) *Changeset { + return &Changeset{Version: version} } -func NewChangesetWithPairs(pairs map[string]KVPairs) *Changeset { +func NewChangesetWithPairs(version uint64, pairs map[string]KVPairs) *Changeset { changes := make([]StateChanges, len(pairs)) i := 0 for storeKey, kvPairs := range pairs { @@ -44,6 +45,7 @@ func NewChangesetWithPairs(pairs map[string]KVPairs) *Changeset { i++ } return &Changeset{ + Version: version, Changes: changes, } } diff --git a/runtime/v2/go.mod b/runtime/v2/go.mod index 88e3b1e19b40..3ef8e79f7cde 100644 --- a/runtime/v2/go.mod +++ b/runtime/v2/go.mod @@ -5,6 +5,7 @@ go 1.23 // server v2 integration replace ( cosmossdk.io/api => ../../api + cosmossdk.io/core => ../../core cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/server/v2/appmanager => ../../server/v2/appmanager cosmossdk.io/server/v2/stf => ../../server/v2/stf diff --git a/runtime/v2/go.sum b/runtime/v2/go.sum index 6d36d303a056..59f78300b39b 100644 --- a/runtime/v2/go.sum +++ b/runtime/v2/go.sum @@ -2,8 +2,6 @@ buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.35.1-20240701160653-fed buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.35.1-20240701160653-fedbb9acfd2f.1/go.mod h1:JTBMfyi+qAXUHumX+rcD2WIq9FNWmdcNh5MjBnSw0L0= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.35.1-20240130113600-88ef6483f90f.1 h1:F78ecjvMtgd1aZ1Aj9cvBjURxVGCYvRM+OOy5eR+pjw= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.35.1-20240130113600-88ef6483f90f.1/go.mod h1:zqi/LZjZhyvjCMTEVIwAf5VRlkLduuCfqmZxgoormq0= -cosmossdk.io/core v1.0.0-alpha.5 h1:McjYXAQ6XcT20v2uHyH7PhoWH8V+mebzfVFqT3GinsI= -cosmossdk.io/core v1.0.0-alpha.5/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.1.0 h1:wLan7LG35VM7Yo6ov0jId3RHWCGRhe8E8bsuARorl5E= cosmossdk.io/depinject v1.1.0/go.mod h1:kkI5H9jCGHeKeYWXTqYdruogYrEeWvBQCw1Pj4/eCFI= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= diff --git a/server/v2/cometbft/abci.go b/server/v2/cometbft/abci.go index 45a5be69da89..7b2f751b6ce2 100644 --- a/server/v2/cometbft/abci.go +++ b/server/v2/cometbft/abci.go @@ -329,7 +329,7 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe IsGenesis: true, } - blockresponse, genesisState, err := c.app.InitGenesis( + blockResponse, genesisState, err := c.app.InitGenesis( ctx, br, req.AppStateBytes, @@ -338,17 +338,16 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe return nil, fmt.Errorf("genesis state init failure: %w", err) } - for _, txRes := range blockresponse.TxResults { + for _, txRes := range blockResponse.TxResults { if err := txRes.Error; err != nil { - space, code, log := errorsmod.ABCIInfo(err, c.cfg.AppTomlConfig.Trace) - c.logger.Warn("genesis tx failed", "codespace", space, "code", code, "log", log) + space, code, txLog := errorsmod.ABCIInfo(err, c.cfg.AppTomlConfig.Trace) + c.logger.Warn("genesis tx failed", "codespace", space, "code", code, "log", txLog) } } - validatorUpdates := intoABCIValidatorUpdates(blockresponse.ValidatorUpdates) + validatorUpdates := intoABCIValidatorUpdates(blockResponse.ValidatorUpdates) - // set the initial version of the store - if err := c.store.SetInitialVersion(uint64(req.InitialHeight)); err != nil { + if err := c.store.SetInitialVersion(uint64(req.InitialHeight - 1)); err != nil { return nil, fmt.Errorf("failed to set initial version: %w", err) } @@ -357,9 +356,10 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe return nil, err } cs := &store.Changeset{ + Version: uint64(req.InitialHeight - 1), Changes: stateChanges, } - stateRoot, err := c.store.WorkingHash(cs) + stateRoot, err := c.store.Commit(cs) if err != nil { return nil, fmt.Errorf("unable to write the changeset: %w", err) } @@ -455,18 +455,6 @@ func (c *Consensus[T]) FinalizeBlock( return nil, err } - // we don't need to deliver the block in the genesis block - if req.Height == int64(c.initialHeight) { - appHash, err := c.store.Commit(store.NewChangeset()) - if err != nil { - return nil, fmt.Errorf("unable to commit the changeset: %w", err) - } - c.lastCommittedHeight.Store(req.Height) - return &abciproto.FinalizeBlockResponse{ - AppHash: appHash, - }, nil - } - // TODO(tip): can we expect some txs to not decode? if so, what we do in this case? this does not seem to be the case, // considering that prepare and process always decode txs, assuming they're the ones providing txs we should never // have a tx that fails decoding. @@ -507,7 +495,7 @@ func (c *Consensus[T]) FinalizeBlock( if err != nil { return nil, err } - appHash, err := c.store.Commit(&store.Changeset{Changes: stateChanges}) + appHash, err := c.store.Commit(&store.Changeset{Version: uint64(req.Height), Changes: stateChanges}) if err != nil { return nil, fmt.Errorf("unable to commit the changeset: %w", err) } diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index d58e87aa9ef9..85433d426cfe 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -32,6 +32,7 @@ import ( var ( sum = sha256.Sum256([]byte("test-hash")) + emptyHash = sha256.Sum256([]byte("")) DefaulConsensusParams = &v1.ConsensusParams{ Block: &v1.BlockParams{ MaxGas: 5000000, @@ -124,6 +125,7 @@ func TestConsensus_InitChain_Without_UpdateParam(t *testing.T) { _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 1, + Hash: emptyHash[:], }) require.NoError(t, err) assertStoreLatestVersion(t, mockStore, 1) @@ -144,6 +146,7 @@ func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 1, + Hash: emptyHash[:], }) require.NoError(t, err) @@ -159,15 +162,16 @@ func TestConsensus_InitChain_Invalid_Height(t *testing.T) { InitialHeight: 2, }) require.NoError(t, err) - assertStoreLatestVersion(t, mockStore, 0) + assertStoreLatestVersion(t, mockStore, 1) - // Shouldn't be able to commit genesis block 2 + // Shouldn't be able to commit genesis block 3 _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), - Height: 2, + Height: 3, + Hash: emptyHash[:], }) require.Error(t, err) - require.True(t, strings.Contains(err.Error(), "unable to commit the changeset")) + require.True(t, strings.Contains(err.Error(), "invalid height")) } func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { @@ -182,12 +186,14 @@ func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 1, + Hash: emptyHash[:], }) require.NoError(t, err) _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 3, + Hash: emptyHash[:], }) require.Error(t, err) } @@ -206,6 +212,7 @@ func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 1, + Hash: emptyHash[:], }) require.NoError(t, err) @@ -236,6 +243,7 @@ func TestConsensus_FinalizeBlock_MultiTxs_OutOfGas(t *testing.T) { _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 1, + Hash: emptyHash[:], }) require.NoError(t, err) @@ -267,6 +275,7 @@ func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 1, + Hash: emptyHash[:], }) require.NoError(t, err) @@ -554,6 +563,7 @@ func TestConsensus_Info(t *testing.T) { _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 1, + Hash: emptyHash[:], }) require.NoError(t, err) @@ -570,7 +580,8 @@ func TestConsensus_Query(t *testing.T) { c := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) // Write data to state storage - err := c.store.GetStateStorage().ApplyChangeset(1, &store.Changeset{ + err := c.store.GetStateStorage().ApplyChangeset(&store.Changeset{ + Version: 1, Changes: []store.StateChanges{ { Actor: actorName, @@ -597,6 +608,7 @@ func TestConsensus_Query(t *testing.T) { Time: time.Now(), Height: 1, Txs: [][]byte{mockTx.Bytes()}, + Hash: emptyHash[:], }) require.NoError(t, err) @@ -687,22 +699,19 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. nil, ) - return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", am, func() error { return nil }, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") + return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", am, func() error { return nil }, + mempool, map[string]struct{}{}, nil, mockStore, + Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") } // Check target version same with store's latest version // And should have commit info of target version -// If block 0, commitInfo returned should be nil func assertStoreLatestVersion(t *testing.T, store types.Store, target uint64) { t.Helper() version, err := store.GetLatestVersion() require.NoError(t, err) - require.Equal(t, version, target) + require.Equal(t, target, version) commitInfo, err := store.GetStateCommitment().GetCommitInfo(version) require.NoError(t, err) - if target != 0 { - require.Equal(t, commitInfo.Version, target) - } else { - require.Nil(t, commitInfo) - } + require.Equal(t, target, commitInfo.Version) } diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 2c2f2ae412e0..a47ca619bbd9 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -4,6 +4,7 @@ go 1.23.1 replace ( cosmossdk.io/api => ../../../api + cosmossdk.io/core => ../../../core cosmossdk.io/core/testing => ../../../core/testing cosmossdk.io/server/v2 => ../ cosmossdk.io/server/v2/appmanager => ../appmanager diff --git a/server/v2/cometbft/go.sum b/server/v2/cometbft/go.sum index 0cb1fbfcece9..a5e4f50bc25d 100644 --- a/server/v2/cometbft/go.sum +++ b/server/v2/cometbft/go.sum @@ -6,8 +6,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.5 h1:McjYXAQ6XcT20v2uHyH7PhoWH8V+mebzfVFqT3GinsI= -cosmossdk.io/core v1.0.0-alpha.5/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.1.0 h1:wLan7LG35VM7Yo6ov0jId3RHWCGRhe8E8bsuARorl5E= cosmossdk.io/depinject v1.1.0/go.mod h1:kkI5H9jCGHeKeYWXTqYdruogYrEeWvBQCw1Pj4/eCFI= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= diff --git a/server/v2/cometbft/internal/mock/mock_store.go b/server/v2/cometbft/internal/mock/mock_store.go index 765659ce6042..e9f7be3edcb3 100644 --- a/server/v2/cometbft/internal/mock/mock_store.go +++ b/server/v2/cometbft/internal/mock/mock_store.go @@ -59,8 +59,7 @@ func (s *MockStore) StateLatest() (uint64, corestore.ReaderMap, error) { } func (s *MockStore) Commit(changeset *corestore.Changeset) (corestore.Hash, error) { - v, _, _ := s.StateLatest() - err := s.Storage.ApplyChangeset(v, changeset) + err := s.Storage.ApplyChangeset(changeset) if err != nil { return []byte{}, err } @@ -70,8 +69,7 @@ func (s *MockStore) Commit(changeset *corestore.Changeset) (corestore.Hash, erro return []byte{}, err } - commitInfo, err := s.Committer.Commit(v + 1) - fmt.Println("commitInfo", commitInfo, err) + _, err = s.Committer.Commit(changeset.Version) return []byte{}, err } @@ -127,17 +125,3 @@ func (s *MockStore) LastCommitID() (proof.CommitID, error) { func (s *MockStore) SetInitialVersion(v uint64) error { return s.Committer.SetInitialVersion(v) } - -func (s *MockStore) WorkingHash(changeset *corestore.Changeset) (corestore.Hash, error) { - v, _, _ := s.StateLatest() - err := s.Storage.ApplyChangeset(v, changeset) - if err != nil { - return []byte{}, err - } - - err = s.Committer.WriteChangeset(changeset) - if err != nil { - return []byte{}, err - } - return []byte{}, nil -} diff --git a/server/v2/cometbft/types/store.go b/server/v2/cometbft/types/store.go index 3e603ff18ced..b78dbf8f102c 100644 --- a/server/v2/cometbft/types/store.go +++ b/server/v2/cometbft/types/store.go @@ -19,10 +19,6 @@ type Store interface { // SetInitialVersion sets the initial version of the store. SetInitialVersion(uint64) error - // WorkingHash writes the provided changeset to the state and returns - // the working hash of the state. - WorkingHash(*store.Changeset) (store.Hash, error) - // Commit commits the provided changeset and returns // the new state root of the state. Commit(*store.Changeset) (store.Hash, error) diff --git a/server/v2/go.mod b/server/v2/go.mod index a7864aff5b7f..fa0350ebfa21 100644 --- a/server/v2/go.mod +++ b/server/v2/go.mod @@ -4,6 +4,7 @@ go 1.23 replace ( cosmossdk.io/api => ../../api + cosmossdk.io/core => ../../core cosmossdk.io/server/v2/appmanager => ./appmanager cosmossdk.io/server/v2/stf => ./stf cosmossdk.io/store/v2 => ../../store/v2 diff --git a/server/v2/go.sum b/server/v2/go.sum index 43324a9d3bcf..dc39111546ed 100644 --- a/server/v2/go.sum +++ b/server/v2/go.sum @@ -1,7 +1,5 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.5 h1:McjYXAQ6XcT20v2uHyH7PhoWH8V+mebzfVFqT3GinsI= -cosmossdk.io/core v1.0.0-alpha.5/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= diff --git a/server/v2/store/server.go b/server/v2/store/server.go index fb327839859d..247ee624251e 100644 --- a/server/v2/store/server.go +++ b/server/v2/store/server.go @@ -47,7 +47,7 @@ func (s *Server[T]) Start(context.Context) error { } func (s *Server[T]) Stop(context.Context) error { - return s.store.Close() + return nil } func (s *Server[T]) CLICommands() serverv2.CLIConfig { diff --git a/simapp/v2/app_test.go b/simapp/v2/app_test.go index c3c51489a7e5..3ea361e3becb 100644 --- a/simapp/v2/app_test.go +++ b/simapp/v2/app_test.go @@ -94,6 +94,7 @@ func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) { ChainId: "theChain", AppHash: ci.Hash, IsGenesis: true, + Height: 1, }, genesisBytes, nil, @@ -103,7 +104,7 @@ func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) { changes, err := newState.GetStateChanges() require.NoError(t, err) - _, err = st.Commit(&store.Changeset{Changes: changes}) + _, err = st.Commit(&store.Changeset{Version: 1, Changes: changes}) require.NoError(t, err) return app, ctx @@ -119,6 +120,7 @@ func MoveNextBlock(t *testing.T, app *SimApp[transaction.Tx], ctx context.Contex require.NoError(t, err) height, err := app.LoadLatestHeight() + height++ require.NoError(t, err) // TODO: this is a hack to set the comet info in the context for distribution module dependency. @@ -132,7 +134,7 @@ func MoveNextBlock(t *testing.T, app *SimApp[transaction.Tx], ctx context.Contex _, newState, err := app.DeliverBlock( ctx, &server.BlockRequest[transaction.Tx]{ - Height: height + 1, + Height: height, Time: time.Now(), Hash: bz[:], AppHash: ci.Hash, @@ -142,7 +144,7 @@ func MoveNextBlock(t *testing.T, app *SimApp[transaction.Tx], ctx context.Contex changes, err := newState.GetStateChanges() require.NoError(t, err) - _, err = st.Commit(&store.Changeset{Changes: changes}) + _, err = st.Commit(&store.Changeset{Version: height, Changes: changes}) require.NoError(t, err) } diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index 610a6b237333..fea702067c84 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -291,6 +291,7 @@ replace ( // server v2 integration replace ( cosmossdk.io/api => ../../api + cosmossdk.io/core => ../../core cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/runtime/v2 => ../../runtime/v2 cosmossdk.io/server/v2 => ../../server/v2 diff --git a/simapp/v2/go.sum b/simapp/v2/go.sum index 86779e5cdc7c..615dac0f37c8 100644 --- a/simapp/v2/go.sum +++ b/simapp/v2/go.sum @@ -192,8 +192,6 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/core v1.0.0-alpha.5 h1:McjYXAQ6XcT20v2uHyH7PhoWH8V+mebzfVFqT3GinsI= -cosmossdk.io/core v1.0.0-alpha.5/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.1.0 h1:wLan7LG35VM7Yo6ov0jId3RHWCGRhe8E8bsuARorl5E= cosmossdk.io/depinject v1.1.0/go.mod h1:kkI5H9jCGHeKeYWXTqYdruogYrEeWvBQCw1Pj4/eCFI= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= diff --git a/store/v2/commitment/iavl/tree.go b/store/v2/commitment/iavl/tree.go index 62e6d4a5e62c..5503218e66a1 100644 --- a/store/v2/commitment/iavl/tree.go +++ b/store/v2/commitment/iavl/tree.go @@ -51,7 +51,14 @@ func (t *IavlTree) Hash() []byte { return t.tree.Hash() } +// Version returns the current version of the tree. +func (t *IavlTree) Version() uint64 { + return uint64(t.tree.Version()) +} + // WorkingHash returns the working hash of the tree. +// Danger! iavl.MutableTree.WorkingHash() is a mutating operation! +// It advances the tree version by 1. func (t *IavlTree) WorkingHash() []byte { return t.tree.WorkingHash() } diff --git a/store/v2/commitment/mem/tree.go b/store/v2/commitment/mem/tree.go index 7610ab3bf62d..cbc28ce7d9ae 100644 --- a/store/v2/commitment/mem/tree.go +++ b/store/v2/commitment/mem/tree.go @@ -26,8 +26,8 @@ func (t *Tree) Hash() []byte { return nil } -func (t *Tree) WorkingHash() []byte { - return nil +func (t *Tree) Version() uint64 { + return 0 } func (t *Tree) LoadVersion(version uint64) error { diff --git a/store/v2/commitment/store.go b/store/v2/commitment/store.go index 5b3c7d43fa90..e9f2ee8379c7 100644 --- a/store/v2/commitment/store.go +++ b/store/v2/commitment/store.go @@ -82,28 +82,6 @@ func (c *CommitStore) WriteChangeset(cs *corestore.Changeset) error { return nil } -func (c *CommitStore) WorkingCommitInfo(version uint64) *proof.CommitInfo { - storeInfos := make([]proof.StoreInfo, 0, len(c.multiTrees)) - for storeKey, tree := range c.multiTrees { - if internal.IsMemoryStoreKey(storeKey) { - continue - } - bz := []byte(storeKey) - storeInfos = append(storeInfos, proof.StoreInfo{ - Name: bz, - CommitID: proof.CommitID{ - Version: version, - Hash: tree.WorkingHash(), - }, - }) - } - - return &proof.CommitInfo{ - Version: version, - StoreInfos: storeInfos, - } -} - func (c *CommitStore) LoadVersion(targetVersion uint64) error { storeKeys := make([]string, 0, len(c.multiTrees)) for storeKey := range c.multiTrees { @@ -184,7 +162,10 @@ func (c *CommitStore) loadVersion(targetVersion uint64, storeKeys []string) erro // If the target version is greater than the latest version, it is the snapshot // restore case, we should create a new commit info for the target version. if targetVersion > latestVersion { - cInfo := c.WorkingCommitInfo(targetVersion) + cInfo, err := c.GetCommitInfo(targetVersion) + if err != nil { + return err + } return c.metadata.flushCommitInfo(targetVersion, cInfo) } @@ -198,29 +179,16 @@ func (c *CommitStore) Commit(version uint64) (*proof.CommitInfo, error) { if internal.IsMemoryStoreKey(storeKey) { continue } - // If a commit event execution is interrupted, a new iavl store's version - // will be larger than the RMS's metadata, when the block is replayed, we - // should avoid committing that iavl store again. - var commitID proof.CommitID - v, err := tree.GetLatestVersion() + hash, cversion, err := tree.Commit() if err != nil { return nil, err } - if v >= version { - commitID.Version = version - commitID.Hash = tree.Hash() - } else { - hash, cversion, err := tree.Commit() - if err != nil { - return nil, err - } - if cversion != version { - return nil, fmt.Errorf("commit version %d does not match the target version %d", cversion, version) - } - commitID = proof.CommitID{ - Version: version, - Hash: hash, - } + if cversion != version { + return nil, fmt.Errorf("commit version %d does not match the target version %d", cversion, version) + } + commitID := proof.CommitID{ + Version: version, + Hash: hash, } storeInfos = append(storeInfos, proof.StoreInfo{ Name: []byte(storeKey), @@ -541,7 +509,39 @@ loop: } func (c *CommitStore) GetCommitInfo(version uint64) (*proof.CommitInfo, error) { - return c.metadata.GetCommitInfo(version) + // if the commit info is already stored, return it + ci, err := c.metadata.GetCommitInfo(version) + if err != nil { + return nil, err + } + if ci != nil { + return ci, nil + } + // otherwise built the commit info from the trees + storeInfos := make([]proof.StoreInfo, 0, len(c.multiTrees)) + for storeKey, tree := range c.multiTrees { + if internal.IsMemoryStoreKey(storeKey) { + continue + } + v := tree.Version() + if v != version { + return nil, fmt.Errorf("tree version %d does not match the target version %d", v, version) + } + bz := []byte(storeKey) + storeInfos = append(storeInfos, proof.StoreInfo{ + Name: bz, + CommitID: proof.CommitID{ + Version: v, + Hash: tree.Hash(), + }, + }) + } + + ci = &proof.CommitInfo{ + Version: version, + StoreInfos: storeInfos, + } + return ci, nil } func (c *CommitStore) GetLatestVersion() (uint64, error) { @@ -554,6 +554,5 @@ func (c *CommitStore) Close() error { return err } } - return nil } diff --git a/store/v2/commitment/store_bench_test.go b/store/v2/commitment/store_bench_test.go index 49513e27bda2..c8343d942b72 100644 --- a/store/v2/commitment/store_bench_test.go +++ b/store/v2/commitment/store_bench_test.go @@ -35,8 +35,8 @@ var ( ) func init() { - for i := 0; i < 1000; i++ { - cs := corestore.NewChangeset() + for i := uint64(0); i < 1000; i++ { + cs := corestore.NewChangeset(i) for _, storeKey := range storeKeys { for j := 0; j < 100; j++ { key := make([]byte, 16) diff --git a/store/v2/commitment/store_test_suite.go b/store/v2/commitment/store_test_suite.go index 18b4ef4e2cc0..afb468de8595 100644 --- a/store/v2/commitment/store_test_suite.go +++ b/store/v2/commitment/store_test_suite.go @@ -13,6 +13,7 @@ import ( coretesting "cosmossdk.io/core/testing" "cosmossdk.io/store/v2" dbm "cosmossdk.io/store/v2/db" + "cosmossdk.io/store/v2/proof" "cosmossdk.io/store/v2/snapshots" snapshotstypes "cosmossdk.io/store/v2/snapshots/types" ) @@ -37,6 +38,7 @@ func (s *CommitStoreTestSuite) TestStore_Snapshotter() { latestVersion := uint64(10) kvCount := 10 + var cInfo *proof.CommitInfo for i := uint64(1); i <= latestVersion; i++ { kvPairs := make(map[string]corestore.KVPairs) for _, storeKey := range storeKeys { @@ -47,13 +49,12 @@ func (s *CommitStoreTestSuite) TestStore_Snapshotter() { kvPairs[storeKey] = append(kvPairs[storeKey], corestore.KVPair{Key: key, Value: value}) } } - s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(kvPairs))) + s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(i, kvPairs))) - _, err = commitStore.Commit(i) + cInfo, err = commitStore.Commit(i) s.Require().NoError(err) } - cInfo := commitStore.WorkingCommitInfo(latestVersion) s.Require().Equal(len(storeKeys), len(cInfo.StoreInfos)) // create a snapshot @@ -112,7 +113,8 @@ func (s *CommitStoreTestSuite) TestStore_Snapshotter() { } // check the restored tree hash - targetCommitInfo := targetStore.WorkingCommitInfo(latestVersion) + targetCommitInfo, err := targetStore.GetCommitInfo(latestVersion) + s.Require().NoError(err) for _, storeInfo := range targetCommitInfo.StoreInfos { matched := false for _, latestStoreInfo := range cInfo.StoreInfos { @@ -143,7 +145,7 @@ func (s *CommitStoreTestSuite) TestStore_LoadVersion() { kvPairs[storeKey] = append(kvPairs[storeKey], corestore.KVPair{Key: key, Value: value}) } } - s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(kvPairs))) + s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(i, kvPairs))) _, err = commitStore.Commit(i) s.Require().NoError(err) } @@ -198,7 +200,7 @@ func (s *CommitStoreTestSuite) TestStore_Pruning() { kvPairs[storeKey] = append(kvPairs[storeKey], corestore.KVPair{Key: key, Value: value}) } } - s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(kvPairs))) + s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(i, kvPairs))) _, err = commitStore.Commit(i) s.Require().NoError(err) @@ -231,7 +233,7 @@ func (s *CommitStoreTestSuite) TestStore_GetProof() { // commit some changes for version := uint64(1); version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) @@ -274,7 +276,7 @@ func (s *CommitStoreTestSuite) TestStore_Get() { // commit some changes for version := uint64(1); version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) @@ -316,7 +318,7 @@ func (s *CommitStoreTestSuite) TestStore_Upgrades() { kvPairs[storeKey] = append(kvPairs[storeKey], corestore.KVPair{Key: key, Value: value}) } } - s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(kvPairs))) + s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(i, kvPairs))) _, err = commitStore.Commit(i) s.Require().NoError(err) } @@ -365,7 +367,7 @@ func (s *CommitStoreTestSuite) TestStore_Upgrades() { kvPairs[storeKey] = append(kvPairs[storeKey], corestore.KVPair{Key: key, Value: value}) } } - s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(kvPairs))) + s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(i, kvPairs))) commitInfo, err := commitStore.Commit(i) s.Require().NoError(err) s.Require().NotNil(commitInfo) @@ -418,7 +420,7 @@ func (s *CommitStoreTestSuite) TestStore_Upgrades() { kvPairs[storeKey] = append(kvPairs[storeKey], corestore.KVPair{Key: key, Value: value}) } } - s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(kvPairs))) + s.Require().NoError(commitStore.WriteChangeset(corestore.NewChangesetWithPairs(i, kvPairs))) commitInfo, err := commitStore.Commit(i) s.Require().NoError(err) s.Require().NotNil(commitInfo) diff --git a/store/v2/commitment/tree.go b/store/v2/commitment/tree.go index c2da72c486f0..f57eabd20724 100644 --- a/store/v2/commitment/tree.go +++ b/store/v2/commitment/tree.go @@ -19,11 +19,10 @@ type Tree interface { Remove(key []byte) error GetLatestVersion() (uint64, error) - // Hash returns the hash of the latest saved version of the tree. + // Hash returns the hash of the current version of the tree Hash() []byte - - // WorkingHash returns the working hash of the tree. - WorkingHash() []byte + // Version returns the current version of the tree + Version() uint64 LoadVersion(version uint64) error Commit() ([]byte, uint64, error) diff --git a/store/v2/database.go b/store/v2/database.go index ca9b993c17de..27d0973ec18e 100644 --- a/store/v2/database.go +++ b/store/v2/database.go @@ -13,9 +13,9 @@ type VersionedWriter interface { VersionedReader SetLatestVersion(version uint64) error - ApplyChangeset(version uint64, cs *corestore.Changeset) error + ApplyChangeset(cs *corestore.Changeset) error - // Close releases associated resources. It should NOT be idempotent. It must + // Closer releases associated resources. It should NOT be idempotent. It must // only be called once and any call after may panic. io.Closer } @@ -44,9 +44,6 @@ type Committer interface { // WriteChangeset writes the changeset to the commitment state. WriteChangeset(cs *corestore.Changeset) error - // WorkingCommitInfo returns the CommitInfo for the working tree. - WorkingCommitInfo(version uint64) *proof.CommitInfo - // GetLatestVersion returns the latest version. GetLatestVersion() (uint64, error) @@ -67,7 +64,7 @@ type Committer interface { Get(storeKey []byte, version uint64, key []byte) ([]byte, error) - // Close releases associated resources. It should NOT be idempotent. It must + // Closer releases associated resources. It should NOT be idempotent. It must // only be called once and any call after may panic. io.Closer } diff --git a/store/v2/go.mod b/store/v2/go.mod index 85319d0174fd..0a93547212b9 100644 --- a/store/v2/go.mod +++ b/store/v2/go.mod @@ -64,3 +64,5 @@ require ( google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace cosmossdk.io/core => ../../core diff --git a/store/v2/go.sum b/store/v2/go.sum index 5b057a303d7e..aa99a8ec9345 100644 --- a/store/v2/go.sum +++ b/store/v2/go.sum @@ -1,5 +1,3 @@ -cosmossdk.io/core v1.0.0-alpha.5 h1:McjYXAQ6XcT20v2uHyH7PhoWH8V+mebzfVFqT3GinsI= -cosmossdk.io/core v1.0.0-alpha.5/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= diff --git a/store/v2/internal/encoding/changeset_test.go b/store/v2/internal/encoding/changeset_test.go index 03313936b9ea..76bd163bd0a8 100644 --- a/store/v2/internal/encoding/changeset_test.go +++ b/store/v2/internal/encoding/changeset_test.go @@ -17,7 +17,7 @@ func TestChangesetMarshal(t *testing.T) { }{ { name: "empty", - changeset: corestore.NewChangeset(), + changeset: corestore.NewChangeset(1), encodedSize: 1, encodedBytes: []byte{0x0}, }, @@ -80,7 +80,7 @@ func TestChangesetMarshal(t *testing.T) { require.Equal(t, encodedBytes, tc.encodedBytes, "encoded bytes mismatch") } // check the unmarshaled changeset - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) require.NoError(t, UnmarshalChangeset(cs, encodedBytes), "unmarshal error") require.Equal(t, len(tc.changeset.Changes), len(cs.Changes), "unmarshaled changeset store size mismatch") for i, changes := range tc.changeset.Changes { diff --git a/store/v2/migration/manager.go b/store/v2/migration/manager.go index 237dbd1e3606..d5118a6313e8 100644 --- a/store/v2/migration/manager.go +++ b/store/v2/migration/manager.go @@ -239,7 +239,7 @@ func (m *Manager) Sync() error { continue } - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) if err := encoding.UnmarshalChangeset(cs, csBytes); err != nil { return fmt.Errorf("failed to unmarshal changeset: %w", err) } @@ -251,7 +251,7 @@ func (m *Manager) Sync() error { return fmt.Errorf("failed to commit changeset to commitment: %w", err) } } - if err := m.stateStorage.ApplyChangeset(version, cs); err != nil { + if err := m.stateStorage.ApplyChangeset(cs); err != nil { return fmt.Errorf("failed to write changeset to storage: %w", err) } diff --git a/store/v2/migration/manager_test.go b/store/v2/migration/manager_test.go index 4e04f6c40514..07a5b15b8350 100644 --- a/store/v2/migration/manager_test.go +++ b/store/v2/migration/manager_test.go @@ -66,7 +66,7 @@ func TestMigrateState(t *testing.T) { toVersion := uint64(100) keyCount := 10 for version := uint64(1); version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) @@ -133,7 +133,7 @@ func TestStartMigrateState(t *testing.T) { changesets := []corestore.Changeset{} for version := uint64(1); version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) diff --git a/store/v2/mock/db_mock.go b/store/v2/mock/db_mock.go index 60f660607929..9b962affb102 100644 --- a/store/v2/mock/db_mock.go +++ b/store/v2/mock/db_mock.go @@ -21,6 +21,7 @@ import ( type MockStateCommitter struct { ctrl *gomock.Controller recorder *MockStateCommitterMockRecorder + isgomock struct{} } // MockStateCommitterMockRecorder is the mock recorder for MockStateCommitter. @@ -197,20 +198,6 @@ func (mr *MockStateCommitterMockRecorder) SetInitialVersion(version any) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetInitialVersion", reflect.TypeOf((*MockStateCommitter)(nil).SetInitialVersion), version) } -// WorkingCommitInfo mocks base method. -func (m *MockStateCommitter) WorkingCommitInfo(version uint64) *proof.CommitInfo { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WorkingCommitInfo", version) - ret0, _ := ret[0].(*proof.CommitInfo) - return ret0 -} - -// WorkingCommitInfo indicates an expected call of WorkingCommitInfo. -func (mr *MockStateCommitterMockRecorder) WorkingCommitInfo(version any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WorkingCommitInfo", reflect.TypeOf((*MockStateCommitter)(nil).WorkingCommitInfo), version) -} - // WriteChangeset mocks base method. func (m *MockStateCommitter) WriteChangeset(cs *store.Changeset) error { m.ctrl.T.Helper() @@ -229,6 +216,7 @@ func (mr *MockStateCommitterMockRecorder) WriteChangeset(cs any) *gomock.Call { type MockStateStorage struct { ctrl *gomock.Controller recorder *MockStateStorageMockRecorder + isgomock struct{} } // MockStateStorageMockRecorder is the mock recorder for MockStateStorage. @@ -249,17 +237,17 @@ func (m *MockStateStorage) EXPECT() *MockStateStorageMockRecorder { } // ApplyChangeset mocks base method. -func (m *MockStateStorage) ApplyChangeset(version uint64, cs *store.Changeset) error { +func (m *MockStateStorage) ApplyChangeset(cs *store.Changeset) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ApplyChangeset", version, cs) + ret := m.ctrl.Call(m, "ApplyChangeset", cs) ret0, _ := ret[0].(error) return ret0 } // ApplyChangeset indicates an expected call of ApplyChangeset. -func (mr *MockStateStorageMockRecorder) ApplyChangeset(version, cs any) *gomock.Call { +func (mr *MockStateStorageMockRecorder) ApplyChangeset(cs any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyChangeset", reflect.TypeOf((*MockStateStorage)(nil).ApplyChangeset), version, cs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyChangeset", reflect.TypeOf((*MockStateStorage)(nil).ApplyChangeset), cs) } // Close mocks base method. diff --git a/store/v2/pruning/manager.go b/store/v2/pruning/manager.go index 1e36abe7a6ed..4e61a7459d08 100644 --- a/store/v2/pruning/manager.go +++ b/store/v2/pruning/manager.go @@ -28,7 +28,7 @@ func NewManager(scPruner, ssPruner store.Pruner, scPruningOption, ssPruningOptio // Prune prunes the SC and SS to the provided version. // -// NOTE: It can be called outside of the store manually. +// NOTE: It can be called outside the store manually. func (m *Manager) Prune(version uint64) error { // Prune the SC. if m.scPruningOption != nil { @@ -51,21 +51,20 @@ func (m *Manager) Prune(version uint64) error { return nil } -// SignalCommit signals to the manager that a commit has started or finished. -// It is used to trigger the pruning of the SC and SS. -// It pauses or resumes the pruning of the SC and SS if the pruner implements -// the PausablePruner interface. -func (m *Manager) SignalCommit(start bool, version uint64) error { +func (m *Manager) signalPruning(pause bool) { if scPausablePruner, ok := m.scPruner.(store.PausablePruner); ok { - scPausablePruner.PausePruning(start) + scPausablePruner.PausePruning(pause) } if ssPausablePruner, ok := m.ssPruner.(store.PausablePruner); ok { - ssPausablePruner.PausePruning(start) + ssPausablePruner.PausePruning(pause) } +} - if !start { - return m.Prune(version) - } +func (m *Manager) PausePruning() { + m.signalPruning(true) +} - return nil +func (m *Manager) ResumePruning(version uint64) error { + m.signalPruning(false) + return m.Prune(version) } diff --git a/store/v2/pruning/manager_test.go b/store/v2/pruning/manager_test.go index c5d137f1d09e..0a0333451ae5 100644 --- a/store/v2/pruning/manager_test.go +++ b/store/v2/pruning/manager_test.go @@ -58,7 +58,7 @@ func (s *PruningManagerTestSuite) TestPrune() { toVersion := uint64(100) keyCount := 10 for version := uint64(1); version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) @@ -68,7 +68,7 @@ func (s *PruningManagerTestSuite) TestPrune() { _, err := s.sc.Commit(version) s.Require().NoError(err) - s.Require().NoError(s.ss.ApplyChangeset(version, cs)) + s.Require().NoError(s.ss.ApplyChangeset(cs)) s.Require().NoError(s.manager.Prune(version)) } @@ -155,7 +155,7 @@ func TestPruningOption(t *testing.T) { func (s *PruningManagerTestSuite) TestSignalCommit() { // commit version 1 - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) for _, storeKey := range storeKeys { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", 1, 0)), []byte(fmt.Sprintf("value-%d-%d", 1, 0)), false) } @@ -164,21 +164,22 @@ func (s *PruningManagerTestSuite) TestSignalCommit() { _, err := s.sc.Commit(1) s.Require().NoError(err) - s.Require().NoError(s.ss.ApplyChangeset(1, cs)) + s.Require().NoError(s.ss.ApplyChangeset(cs)) // commit version 2 for _, storeKey := range storeKeys { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", 2, 0)), []byte(fmt.Sprintf("value-%d-%d", 2, 0)), false) } + cs.Version = 2 // signaling commit has started - s.Require().NoError(s.manager.SignalCommit(true, 2)) + s.manager.PausePruning() s.Require().NoError(s.sc.WriteChangeset(cs)) _, err = s.sc.Commit(2) s.Require().NoError(err) - s.Require().NoError(s.ss.ApplyChangeset(2, cs)) + s.Require().NoError(s.ss.ApplyChangeset(cs)) // try prune before signaling commit has finished s.Require().NoError(s.manager.Prune(2)) @@ -204,7 +205,8 @@ func (s *PruningManagerTestSuite) TestSignalCommit() { s.Require().Equal(val, []byte(fmt.Sprintf("value-%d-%d", 1, 0))) // signaling commit has finished, version 1 should be pruned - s.Require().NoError(s.manager.SignalCommit(false, 2)) + err = s.manager.ResumePruning(2) + s.Require().NoError(err) checkSCPrune = func() bool { count := 0 @@ -224,22 +226,21 @@ func (s *PruningManagerTestSuite) TestSignalCommit() { toVersion := uint64(100) keyCount := 10 for version := uint64(3); version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) } } - s.Require().NoError(s.manager.SignalCommit(true, version)) + s.manager.PausePruning() s.Require().NoError(s.sc.WriteChangeset(cs)) _, err := s.sc.Commit(version) s.Require().NoError(err) - s.Require().NoError(s.ss.ApplyChangeset(version, cs)) - - s.Require().NoError(s.manager.SignalCommit(false, version)) - + s.Require().NoError(s.ss.ApplyChangeset(cs)) + err = s.manager.ResumePruning(version) + s.Require().NoError(err) } // wait for the pruning to finish in the commitment store diff --git a/store/v2/root/builder.go b/store/v2/root/builder.go index 885c41d24484..199184f8e761 100644 --- a/store/v2/root/builder.go +++ b/store/v2/root/builder.go @@ -71,7 +71,7 @@ func (sb *builder) Build( } factoryOptions := &FactoryOptions{ - Logger: logger, + Logger: logger.With("module", "store"), RootDir: config.Home, Options: config.Options, StoreKeys: storeKeys, diff --git a/store/v2/root/migrate_test.go b/store/v2/root/migrate_test.go index 9bd8dfdd2ef8..2d83038b812e 100644 --- a/store/v2/root/migrate_test.go +++ b/store/v2/root/migrate_test.go @@ -50,7 +50,7 @@ func (s *MigrateStoreTestSuite) SetupTest() { toVersion := uint64(200) keyCount := 10 for version := uint64(1); version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) @@ -105,7 +105,7 @@ func (s *MigrateStoreTestSuite) TestMigrateState() { latestVersion := originalLatestVersion + 1 keyCount := 10 for ; latestVersion < 2*originalLatestVersion; latestVersion++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(latestVersion) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", latestVersion, i)), []byte(fmt.Sprintf("value-%d-%d", latestVersion, i)), false) @@ -147,7 +147,7 @@ func (s *MigrateStoreTestSuite) TestMigrateState() { // apply changeset against the migrated store for version := latestVersion + 1; version <= latestVersion+10; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) diff --git a/store/v2/root/store.go b/store/v2/root/store.go index 378cfafa3fdf..59363e2fb35b 100644 --- a/store/v2/root/store.go +++ b/store/v2/root/store.go @@ -1,7 +1,6 @@ package root import ( - "bytes" "crypto/sha256" "errors" "fmt" @@ -11,7 +10,6 @@ import ( "golang.org/x/sync/errgroup" - coreheader "cosmossdk.io/core/header" corelog "cosmossdk.io/core/log" corestore "cosmossdk.io/core/store" "cosmossdk.io/store/v2" @@ -31,8 +29,7 @@ var ( // backend may or may not support multiple store keys and is implementation // dependent. type Store struct { - logger corelog.Logger - initialVersion uint64 + logger corelog.Logger // holds the db instance for closing it dbCloser io.Closer @@ -43,10 +40,6 @@ type Store struct { // stateCommitment reflects the state commitment (SC) backend stateCommitment store.Committer - // commitHeader reflects the header used when committing state - // note, this isn't required and only used for query purposes) - commitHeader *coreheader.Info - // lastCommitInfo reflects the last version/hash that has been committed lastCommitInfo *proof.CommitInfo @@ -83,7 +76,6 @@ func New( return &Store{ dbCloser: dbCloser, logger: logger, - initialVersion: 1, stateStorage: ss, stateCommitment: sc, pruningManager: pm, @@ -103,7 +95,6 @@ func (s *Store) Close() (err error) { s.stateStorage = nil s.stateCommitment = nil s.lastCommitInfo = nil - s.commitHeader = nil return err } @@ -113,8 +104,6 @@ func (s *Store) SetMetrics(m metrics.Metrics) { } func (s *Store) SetInitialVersion(v uint64) error { - s.initialVersion = v - return s.stateCommitment.SetInitialVersion(v) } @@ -323,8 +312,6 @@ func (s *Store) loadVersion(v uint64, upgrades *corestore.StoreUpgrades) error { } } - s.commitHeader = nil - // set lastCommitInfo explicitly s.t. Commit commits the correct version, i.e. v+1 var err error s.lastCommitInfo, err = s.stateCommitment.GetCommitInfo(v) @@ -340,44 +327,6 @@ func (s *Store) loadVersion(v uint64, upgrades *corestore.StoreUpgrades) error { return nil } -func (s *Store) SetCommitHeader(h *coreheader.Info) { - s.commitHeader = h -} - -// WorkingHash writes the changeset to SC and SS and returns the workingHash -// of the CommitInfo. -func (s *Store) WorkingHash(cs *corestore.Changeset) ([]byte, error) { - if s.telemetry != nil { - now := time.Now() - defer s.telemetry.MeasureSince(now, "root_store", "working_hash") - } - - // write the changeset to the SC and SS backends - eg := new(errgroup.Group) - eg.Go(func() error { - if err := s.writeSC(cs); err != nil { - return fmt.Errorf("failed to write SC: %w", err) - } - - return nil - }) - eg.Go(func() error { - if err := s.stateStorage.ApplyChangeset(s.initialVersion, cs); err != nil { - return fmt.Errorf("failed to commit SS: %w", err) - } - - return nil - }) - if err := eg.Wait(); err != nil { - return nil, err - } - - workingHash := s.lastCommitInfo.Hash() - s.lastCommitInfo.Version -= 1 // reset lastCommitInfo to allow Commit() to work correctly - - return workingHash, nil -} - // Commit commits all state changes to the underlying SS and SC backends. It // writes a batch of the changeset to the SC tree, and retrieves the CommitInfo // from the SC tree. Finally, it commits the SC tree and returns the hash of @@ -388,32 +337,22 @@ func (s *Store) Commit(cs *corestore.Changeset) ([]byte, error) { defer s.telemetry.MeasureSince(now, "root_store", "commit") } - // write the changeset to the SC tree and update lastCommitInfo - if err := s.writeSC(cs); err != nil { + if err := s.handleMigration(cs); err != nil { return nil, err } - version := s.lastCommitInfo.Version - - if s.commitHeader != nil && uint64(s.commitHeader.Height) != version { - s.logger.Debug("commit header and version mismatch", "header_height", s.commitHeader.Height, "version", version) - } - // signal to the pruning manager that a new version is about to be committed // this may be required if the SS and SC backends implementation have the - // background pruning process which must be paused during the commit - if err := s.pruningManager.SignalCommit(true, version); err != nil { - s.logger.Error("failed to signal commit to pruning manager", "err", err) - } + // background pruning process (iavl v1 for example) which must be paused during the commit + s.pruningManager.PausePruning() eg := new(errgroup.Group) - // if we're migrating, we don't want to commit to the state storage to avoid - // parallel writes + // if migrating the changeset will be sent to migration manager to fill SS + // otherwise commit to SS async here if !s.isMigrating { - // commit SS async eg.Go(func() error { - if err := s.stateStorage.ApplyChangeset(version, cs); err != nil { + if err := s.stateStorage.ApplyChangeset(cs); err != nil { return fmt.Errorf("failed to commit SS: %w", err) } @@ -422,11 +361,16 @@ func (s *Store) Commit(cs *corestore.Changeset) ([]byte, error) { } // commit SC async + var cInfo *proof.CommitInfo eg.Go(func() error { - if err := s.commitSC(); err != nil { - return fmt.Errorf("failed to commit SC: %w", err) + if err := s.stateCommitment.WriteChangeset(cs); err != nil { + return fmt.Errorf("failed to write batch to SC store: %w", err) + } + var scErr error + cInfo, scErr = s.stateCommitment.Commit(cs.Version) + if scErr != nil { + return fmt.Errorf("failed to commit SC store: %w", scErr) } - return nil }) @@ -434,13 +378,14 @@ func (s *Store) Commit(cs *corestore.Changeset) ([]byte, error) { return nil, err } - // signal to the pruning manager that the commit is done - if err := s.pruningManager.SignalCommit(false, version); err != nil { - s.logger.Error("failed to signal commit done to pruning manager", "err", err) + if cInfo.Version != cs.Version { + return nil, fmt.Errorf("commit version mismatch: got %d, expected %d", cInfo.Version, cs.Version) } + s.lastCommitInfo = cInfo - if s.commitHeader != nil { - s.lastCommitInfo.Timestamp = s.commitHeader.Time + // signal to the pruning manager that the commit is done + if err := s.pruningManager.ResumePruning(s.lastCommitInfo.Version); err != nil { + s.logger.Error("failed to signal commit done to pruning manager", "err", err) } return s.lastCommitInfo.Hash(), nil @@ -475,12 +420,7 @@ func (s *Store) startMigration() { defer mtx.Unlock() } -// writeSC accepts a Changeset and writes that as a batch to the underlying SC -// tree, which allows us to retrieve the working hash of the SC tree. Finally, -// we construct a *CommitInfo and set that as lastCommitInfo. Note, this should -// only be called once per block! -// If migration is in progress, the changeset is sent to the migration manager. -func (s *Store) writeSC(cs *corestore.Changeset) error { +func (s *Store) handleMigration(cs *corestore.Changeset) error { if s.isMigrating { // if the migration manager has already migrated to the version, close the // channels and replace the state commitment @@ -501,49 +441,10 @@ func (s *Store) writeSC(cs *corestore.Changeset) error { } s.logger.Info("migration completed", "version", s.lastCommitInfo.Version) } else { + // queue the next changeset to the migration manager s.chChangeset <- &migration.VersionedChangeset{Version: s.lastCommitInfo.Version + 1, Changeset: cs} } } - - if err := s.stateCommitment.WriteChangeset(cs); err != nil { - return fmt.Errorf("failed to write batch to SC store: %w", err) - } - - var previousHeight, version uint64 - if s.lastCommitInfo.GetVersion() == 0 && s.initialVersion > 1 { - // This case means that no commit has been made in the store, we - // start from initialVersion. - version = s.initialVersion - } else { - // This case can means two things: - // - // 1. There was already a previous commit in the store, in which case we - // increment the version from there. - // 2. There was no previous commit, and initial version was not set, in which - // case we start at version 1. - previousHeight = s.lastCommitInfo.GetVersion() - version = previousHeight + 1 - } - - s.lastCommitInfo = s.stateCommitment.WorkingCommitInfo(version) - - return nil -} - -// commitSC commits the SC store. At this point, a batch of the current changeset -// should have already been written to the SC via writeSC(). This method solely -// commits that batch. An error is returned if commit fails or the hash of the -// committed state does not match the hash of the working state. -func (s *Store) commitSC() error { - cInfo, err := s.stateCommitment.Commit(s.lastCommitInfo.Version) - if err != nil { - return fmt.Errorf("failed to commit SC store: %w", err) - } - - if !bytes.Equal(cInfo.Hash(), s.lastCommitInfo.Hash()) { - return fmt.Errorf("unexpected commit hash; got: %X, expected: %X", cInfo.Hash(), s.lastCommitInfo.Hash()) - } - return nil } diff --git a/store/v2/root/store_mock_test.go b/store/v2/root/store_mock_test.go index 3a14054cd7e4..4b43d52f7f7e 100644 --- a/store/v2/root/store_mock_test.go +++ b/store/v2/root/store_mock_test.go @@ -12,7 +12,6 @@ import ( "cosmossdk.io/store/v2" "cosmossdk.io/store/v2/metrics" "cosmossdk.io/store/v2/mock" - "cosmossdk.io/store/v2/proof" "cosmossdk.io/store/v2/pruning" ) @@ -22,7 +21,6 @@ func newTestRootStore(ss store.VersionedWriter, sc store.Committer) *Store { return &Store{ logger: noopLog, telemetry: metrics.Metrics{}, - initialVersion: 1, stateStorage: ss, stateCommitment: sc, pruningManager: pm, @@ -120,85 +118,3 @@ func TestLoadVersion(t *testing.T) { err = rs.LoadVersionAndUpgrade(uint64(2), v) require.Error(t, err) } - -func TestWorkingHahs(t *testing.T) { - ctrl := gomock.NewController(t) - ss := mock.NewMockStateStorage(ctrl) - sc := mock.NewMockStateCommitter(ctrl) - rs := newTestRootStore(ss, sc) - - cs := corestore.NewChangeset() - // writeSC test - sc.EXPECT().WriteChangeset(cs).Return(errors.New("error")) - err := rs.writeSC(cs) - require.Error(t, err) - sc.EXPECT().WriteChangeset(cs).Return(nil) - sc.EXPECT().WorkingCommitInfo(gomock.Any()).Return(nil) - err = rs.writeSC(cs) - require.NoError(t, err) - - // WorkingHash test - sc.EXPECT().WriteChangeset(cs).Return(nil) - sc.EXPECT().WorkingCommitInfo(gomock.Any()).Return(nil) - ss.EXPECT().ApplyChangeset(gomock.Any(), cs).Return(errors.New("error")) - _, err = rs.WorkingHash(cs) - require.Error(t, err) - sc.EXPECT().WriteChangeset(cs).Return(nil) - sc.EXPECT().WorkingCommitInfo(gomock.Any()).Return(nil) - ss.EXPECT().ApplyChangeset(gomock.Any(), cs).Return(errors.New("error")) - _, err = rs.WorkingHash(cs) - require.Error(t, err) - sc.EXPECT().WriteChangeset(cs).Return(nil) - sc.EXPECT().WorkingCommitInfo(gomock.Any()).Return(&proof.CommitInfo{}) - ss.EXPECT().ApplyChangeset(gomock.Any(), cs).Return(nil) - _, err = rs.WorkingHash(cs) - require.NoError(t, err) -} - -func TestCommit(t *testing.T) { - ctrl := gomock.NewController(t) - ss := mock.NewMockStateStorage(ctrl) - sc := mock.NewMockStateCommitter(ctrl) - rs := newTestRootStore(ss, sc) - - cs := corestore.NewChangeset() - // test commitSC - rs.lastCommitInfo = &proof.CommitInfo{} - sc.EXPECT().Commit(gomock.Any()).Return(nil, errors.New("error")) - err := rs.commitSC() - require.Error(t, err) - sc.EXPECT().Commit(gomock.Any()).Return(&proof.CommitInfo{CommitHash: []byte("wrong hash"), StoreInfos: []proof.StoreInfo{{}}}, nil) // wrong hash - err = rs.commitSC() - require.Error(t, err) - - // Commit test - sc.EXPECT().WriteChangeset(cs).Return(errors.New("error")) - _, err = rs.Commit(cs) - require.Error(t, err) - sc.EXPECT().WriteChangeset(cs).Return(nil) - sc.EXPECT().WorkingCommitInfo(gomock.Any()).Return(&proof.CommitInfo{}) - sc.EXPECT().PausePruning(gomock.Any()).Return() - ss.EXPECT().PausePruning(gomock.Any()).Return() - ss.EXPECT().ApplyChangeset(gomock.Any(), cs).Return(nil) - sc.EXPECT().Commit(gomock.Any()).Return(nil, errors.New("error")) - _, err = rs.Commit(cs) - require.Error(t, err) - sc.EXPECT().WriteChangeset(cs).Return(nil) - sc.EXPECT().WorkingCommitInfo(gomock.Any()).Return(&proof.CommitInfo{}) - sc.EXPECT().PausePruning(gomock.Any()).Return() - ss.EXPECT().PausePruning(gomock.Any()).Return() - ss.EXPECT().ApplyChangeset(gomock.Any(), cs).Return(errors.New("error")) - sc.EXPECT().Commit(gomock.Any()).Return(&proof.CommitInfo{}, nil) - _, err = rs.Commit(cs) - require.Error(t, err) - sc.EXPECT().WriteChangeset(cs).Return(nil) - sc.EXPECT().WorkingCommitInfo(gomock.Any()).Return(&proof.CommitInfo{}) - sc.EXPECT().PausePruning(true).Return() - ss.EXPECT().PausePruning(true).Return() - ss.EXPECT().ApplyChangeset(gomock.Any(), cs).Return(nil) - sc.EXPECT().Commit(gomock.Any()).Return(&proof.CommitInfo{}, nil) - sc.EXPECT().PausePruning(false).Return() - ss.EXPECT().PausePruning(false).Return() - _, err = rs.Commit(cs) - require.NoError(t, err) -} diff --git a/store/v2/root/store_test.go b/store/v2/root/store_test.go index 2d3f5a5b5758..10a3a049d3c0 100644 --- a/store/v2/root/store_test.go +++ b/store/v2/root/store_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/suite" - coreheader "cosmossdk.io/core/header" corestore "cosmossdk.io/core/store" coretesting "cosmossdk.io/core/testing" "cosmossdk.io/store/v2" @@ -116,15 +115,11 @@ func (s *RootStoreTestSuite) TestSetInitialVersion() { initialVersion := uint64(5) s.Require().NoError(s.rootStore.SetInitialVersion(initialVersion)) - // perform the initial commit - cs := corestore.NewChangeset() + // perform an initial, empty commit + cs := corestore.NewChangeset(initialVersion) cs.Add(testStoreKeyBytes, []byte("foo"), []byte("bar"), false) - - wHash, err := s.rootStore.WorkingHash(cs) - s.Require().NoError(err) - cHash, err := s.rootStore.Commit(corestore.NewChangeset()) + _, err := s.rootStore.Commit(corestore.NewChangeset(initialVersion)) s.Require().NoError(err) - s.Require().Equal(wHash, cHash) // check the latest version lVersion, err := s.rootStore.GetLatestVersion() @@ -135,8 +130,9 @@ func (s *RootStoreTestSuite) TestSetInitialVersion() { rInitialVersion := uint64(100) s.Require().NoError(s.rootStore.SetInitialVersion(rInitialVersion)) + // TODO fix version munging here // perform the commit - cs = corestore.NewChangeset() + cs = corestore.NewChangeset(initialVersion + 1) cs.Add(testStoreKey2Bytes, []byte("foo"), []byte("bar"), false) _, err = s.rootStore.Commit(cs) s.Require().NoError(err) @@ -147,23 +143,12 @@ func (s *RootStoreTestSuite) TestSetInitialVersion() { s.Require().Equal(initialVersion+1, lVersion) } -func (s *RootStoreTestSuite) TestSetCommitHeader() { - h := &coreheader.Info{ - Height: 100, - Hash: []byte("foo"), - ChainID: "test", - } - s.rootStore.SetCommitHeader(h) - - s.Require().Equal(h, s.rootStore.(*Store).commitHeader) -} - func (s *RootStoreTestSuite) TestQuery() { _, err := s.rootStore.Query([]byte{}, 1, []byte("foo"), true) s.Require().Error(err) // write and commit a changeset - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) cs.Add(testStoreKeyBytes, []byte("foo"), []byte("bar"), false) commitHash, err := s.rootStore.Commit(cs) @@ -181,14 +166,13 @@ func (s *RootStoreTestSuite) TestGetFallback() { sc := s.rootStore.GetStateCommitment() // create a changeset and commit it to SC ONLY - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) cs.Add(testStoreKeyBytes, []byte("foo"), []byte("bar"), false) err := sc.WriteChangeset(cs) s.Require().NoError(err) - ci := sc.WorkingCommitInfo(1) - _, err = sc.Commit(ci.Version) + _, err = sc.Commit(cs.Version) s.Require().NoError(err) // ensure we can query for the key, which should fallback to SC @@ -203,7 +187,7 @@ func (s *RootStoreTestSuite) TestGetFallback() { } func (s *RootStoreTestSuite) TestQueryProof() { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) // testStoreKey cs.Add(testStoreKeyBytes, []byte("key1"), []byte("value1"), false) cs.Add(testStoreKeyBytes, []byte("key2"), []byte("value2"), false) @@ -233,10 +217,10 @@ func (s *RootStoreTestSuite) TestQueryProof() { func (s *RootStoreTestSuite) TestLoadVersion() { // write and commit a few changesets - for v := 1; v <= 5; v++ { + for v := uint64(1); v <= 5; v++ { val := fmt.Sprintf("val%03d", v) // val001, val002, ..., val005 - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(v) cs.Add(testStoreKeyBytes, []byte("key"), []byte(val), false) commitHash, err := s.rootStore.Commit(cs) @@ -276,7 +260,7 @@ func (s *RootStoreTestSuite) TestLoadVersion() { for v := 4; v <= 5; v++ { val := fmt.Sprintf("overwritten_val%03d", v) // overwritten_val004, overwritten_val005 - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(uint64(v)) cs.Add(testStoreKeyBytes, []byte("key"), []byte(val), false) commitHash, err := s.rootStore.Commit(cs) @@ -306,7 +290,7 @@ func (s *RootStoreTestSuite) TestCommit() { s.Require().Zero(lv) // perform changes - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) for i := 0; i < 100; i++ { key := fmt.Sprintf("key%03d", i) // key000, key001, ..., key099 val := fmt.Sprintf("val%03d", i) // val000, val001, ..., val099 @@ -344,7 +328,7 @@ func (s *RootStoreTestSuite) TestStateAt() { // write keys over multiple versions for v := uint64(1); v <= 5; v++ { // perform changes - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(v) for i := 0; i < 100; i++ { key := fmt.Sprintf("key%03d", i) // key000, key001, ..., key099 val := fmt.Sprintf("val%03d_%03d", i, v) // val000_1, val001_1, ..., val099_1 @@ -393,32 +377,9 @@ func (s *RootStoreTestSuite) TestStateAt() { } } -func (s *RootStoreTestSuite) TestWorkingHash() { - // write keys over multiple versions - for v := uint64(1); v <= 5; v++ { - // perform changes - cs := corestore.NewChangeset() - for _, storeKeyBytes := range [][]byte{testStoreKeyBytes, testStoreKey2Bytes, testStoreKey3Bytes} { - for i := 0; i < 100; i++ { - key := fmt.Sprintf("key_%x_%03d", i, storeKeyBytes) // key000, key001, ..., key099 - val := fmt.Sprintf("val%03d_%03d", i, v) // val000_1, val001_1, ..., val099_1 - - cs.Add(storeKeyBytes, []byte(key), []byte(val), false) - } - } - - wHash, err := s.rootStore.WorkingHash(cs) - s.Require().NoError(err) - // execute Commit with empty changeset - cHash, err := s.rootStore.Commit(corestore.NewChangeset()) - s.Require().NoError(err) - s.Require().Equal(wHash, cHash) - } -} - func (s *RootStoreTestSuite) TestPrune() { // perform changes - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) for i := 0; i < 10; i++ { key := fmt.Sprintf("key%03d", i) // key000, key001, ..., key099 val := fmt.Sprintf("val%03d", i) // val000, val001, ..., val099 @@ -462,6 +423,7 @@ func (s *RootStoreTestSuite) TestPrune() { // write keys over multiple versions for i := int64(0); i < tc.numVersions; i++ { // execute Commit + cs.Version = uint64(i + 1) cHash, err := s.rootStore.Commit(cs) s.Require().NoError(err) s.Require().NotNil(cHash) @@ -500,7 +462,7 @@ func (s *RootStoreTestSuite) TestPrune() { func (s *RootStoreTestSuite) TestMultiStore_Pruning_SameHeightsTwice() { // perform changes - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) cs.Add(testStoreKeyBytes, []byte("key"), []byte("val"), false) const ( @@ -517,6 +479,7 @@ func (s *RootStoreTestSuite) TestMultiStore_Pruning_SameHeightsTwice() { for i := uint64(0); i < numVersions; i++ { // execute Commit + cs.Version = i + 1 cHash, err := s.rootStore.Commit(cs) s.Require().NoError(err) s.Require().NotNil(cHash) @@ -544,21 +507,23 @@ func (s *RootStoreTestSuite) TestMultiStore_Pruning_SameHeightsTwice() { } // Get latest - err = s.rootStore.LoadVersion(numVersions - 1) + err = s.rootStore.LoadVersion(numVersions) s.Require().NoError(err) // Test pruning the same heights again + cs.Version++ _, err = s.rootStore.Commit(cs) s.Require().NoError(err) // Ensure that can commit one more height with no panic + cs.Version++ _, err = s.rootStore.Commit(cs) s.Require().NoError(err) } func (s *RootStoreTestSuite) TestMultiStore_PruningRestart() { // perform changes - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) cs.Add(testStoreKeyBytes, []byte("key"), []byte("val"), false) pruneOpt := &store.PruningOption{ @@ -585,8 +550,9 @@ func (s *RootStoreTestSuite) TestMultiStore_PruningRestart() { // Commit enough to build up heights to prune, where on the next block we should // batch delete. - for i := uint64(0); i < 10; i++ { + for i := uint64(1); i <= 10; i++ { // execute Commit + cs.Version = i cHash, err := s.rootStore.Commit(cs) s.Require().NoError(err) s.Require().NotNil(cHash) @@ -623,6 +589,7 @@ func (s *RootStoreTestSuite) TestMultiStore_PruningRestart() { // commit one more block and ensure the heights have been pruned // execute Commit + cs.Version++ cHash, err := s.rootStore.Commit(cs) s.Require().NoError(err) s.Require().NotNil(cHash) @@ -672,7 +639,7 @@ func (s *RootStoreTestSuite) TestMultiStoreRestart() { // perform changes for i := 1; i < 3; i++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(uint64(i)) key := fmt.Sprintf("key%03d", i) // key000, key001, ..., key099 val := fmt.Sprintf("val%03d_%03d", i, 1) // val000_1, val001_1, ..., val099_1 @@ -699,7 +666,7 @@ func (s *RootStoreTestSuite) TestMultiStoreRestart() { } // more changes - cs1 := corestore.NewChangeset() + cs1 := corestore.NewChangeset(3) key := fmt.Sprintf("key%03d", 3) // key000, key001, ..., key099 val := fmt.Sprintf("val%03d_%03d", 3, 1) // val000_1, val001_1, ..., val099_1 @@ -719,7 +686,7 @@ func (s *RootStoreTestSuite) TestMultiStoreRestart() { s.Require().NoError(err) s.Require().Equal(uint64(3), latestVer) - cs2 := corestore.NewChangeset() + cs2 := corestore.NewChangeset(4) key = fmt.Sprintf("key%03d", 4) // key000, key001, ..., key099 val = fmt.Sprintf("val%03d_%03d", 4, 3) // val000_1, val001_1, ..., val099_1 @@ -782,7 +749,7 @@ func (s *RootStoreTestSuite) TestMultiStoreRestart() { func (s *RootStoreTestSuite) TestHashStableWithEmptyCommitAndRestart() { err := s.rootStore.LoadLatestVersion() - s.Require().Nil(err) + s.Require().NoError(err) emptyHash := sha256.Sum256([]byte{}) appHash := emptyHash[:] @@ -790,9 +757,11 @@ func (s *RootStoreTestSuite) TestHashStableWithEmptyCommitAndRestart() { lastCommitID, err := s.rootStore.LastCommitID() s.Require().Nil(err) - s.Require().Equal(commitID, lastCommitID) + // the hash of a store with no commits is the root hash of a tree with empty hashes as leaves. + // it should not be equal an empty hash. + s.Require().NotEqual(commitID, lastCommitID) - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(1) cs.Add(testStoreKeyBytes, []byte("key"), []byte("val"), false) cHash, err := s.rootStore.Commit(cs) @@ -804,7 +773,7 @@ func (s *RootStoreTestSuite) TestHashStableWithEmptyCommitAndRestart() { s.Require().Equal(uint64(1), latestVersion) // make an empty commit, it should update version, but not affect hash - cHash, err = s.rootStore.Commit(corestore.NewChangeset()) + cHash, err = s.rootStore.Commit(corestore.NewChangeset(2)) s.Require().Nil(err) s.Require().NotNil(cHash) latestVersion, err = s.rootStore.GetLatestVersion() diff --git a/store/v2/root/upgrade_test.go b/store/v2/root/upgrade_test.go index 47c2882dc2ef..400ddb2c4d65 100644 --- a/store/v2/root/upgrade_test.go +++ b/store/v2/root/upgrade_test.go @@ -57,7 +57,7 @@ func (s *UpgradeStoreTestSuite) SetupTest() { toVersion := uint64(20) keyCount := 10 for version := uint64(1); version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range storeKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) @@ -127,7 +127,7 @@ func (s *UpgradeStoreTestSuite) TestLoadVersionAndUpgrade() { newStoreKeys := []string{"newStore1", "newStore2"} toVersion := uint64(40) for version := v + 1; version <= toVersion; version++ { - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for _, storeKey := range newStoreKeys { for i := 0; i < keyCount; i++ { cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false) diff --git a/store/v2/storage/storage_bench_test.go b/store/v2/storage/storage_bench_test.go index 35ffbbf5f8ae..2e2030bec6bb 100644 --- a/store/v2/storage/storage_bench_test.go +++ b/store/v2/storage/storage_bench_test.go @@ -69,12 +69,12 @@ func BenchmarkGet(b *testing.B) { _ = db.Close() }() - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{string(storeKey1): {}}) + cs := corestore.NewChangesetWithPairs(1, map[string]corestore.KVPairs{string(storeKey1): {}}) for i := 0; i < numKeyVals; i++ { cs.AddKVPair(storeKey1, corestore.KVPair{Key: keys[i], Value: vals[i]}) } - require.NoError(b, db.ApplyChangeset(1, cs)) + require.NoError(b, db.ApplyChangeset(cs)) b.Run(fmt.Sprintf("backend_%s", ty), func(b *testing.B) { b.ResetTimer() @@ -105,7 +105,8 @@ func BenchmarkApplyChangeset(b *testing.B) { for i := 0; i < b.N; i++ { b.StopTimer() - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{string(storeKey1): {}}) + ver := uint64(b.N + 1) + cs := corestore.NewChangesetWithPairs(ver, map[string]corestore.KVPairs{string(storeKey1): {}}) for j := 0; j < 1000; j++ { key := make([]byte, 128) val := make([]byte, 128) @@ -119,7 +120,7 @@ func BenchmarkApplyChangeset(b *testing.B) { } b.StartTimer() - require.NoError(b, db.ApplyChangeset(uint64(b.N+1), cs)) + require.NoError(b, db.ApplyChangeset(cs)) } }) } @@ -152,12 +153,12 @@ func BenchmarkIterate(b *testing.B) { b.StopTimer() - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{string(storeKey1): {}}) + cs := corestore.NewChangesetWithPairs(1, map[string]corestore.KVPairs{string(storeKey1): {}}) for i := 0; i < numKeyVals; i++ { cs.AddKVPair(storeKey1, corestore.KVPair{Key: keys[i], Value: vals[i]}) } - require.NoError(b, db.ApplyChangeset(1, cs)) + require.NoError(b, db.ApplyChangeset(cs)) sort.Slice(keys, func(i, j int) bool { return bytes.Compare(keys[i], keys[j]) < 0 diff --git a/store/v2/storage/storage_test_suite.go b/store/v2/storage/storage_test_suite.go index fb5ff24a0c90..4d38efe7931e 100644 --- a/store/v2/storage/storage_test_suite.go +++ b/store/v2/storage/storage_test_suite.go @@ -61,7 +61,8 @@ func (s *StorageTestSuite) TestDatabase_VersionedKeys() { defer db.Close() for i := uint64(1); i <= 100; i++ { - s.Require().NoError(db.ApplyChangeset(i, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + i, map[string]corestore.KVPairs{ storeKey1: {{Key: []byte("key"), Value: []byte(fmt.Sprintf("value%03d", i))}}, }, @@ -81,7 +82,8 @@ func (s *StorageTestSuite) TestDatabase_GetVersionedKey() { defer db.Close() // store a key at version 1 - s.Require().NoError(db.ApplyChangeset(1, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 1, map[string]corestore.KVPairs{ storeKey1: {{Key: []byte("key"), Value: []byte("value001")}}, }, @@ -97,7 +99,8 @@ func (s *StorageTestSuite) TestDatabase_GetVersionedKey() { s.Require().True(ok) // chain progresses to version 11 with an update to key - s.Require().NoError(db.ApplyChangeset(11, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 11, map[string]corestore.KVPairs{ storeKey1: {{Key: []byte("key"), Value: []byte("value011")}}, }, @@ -122,7 +125,8 @@ func (s *StorageTestSuite) TestDatabase_GetVersionedKey() { } // chain progresses to version 15 with a delete to key - s.Require().NoError(db.ApplyChangeset(15, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 15, map[string]corestore.KVPairs{storeKey1: {{Key: []byte("key"), Remove: true}}}, ))) @@ -154,7 +158,7 @@ func (s *StorageTestSuite) TestDatabase_ApplyChangeset() { s.Require().NoError(err) defer db.Close() - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{storeKey1: {}}) + cs := corestore.NewChangesetWithPairs(1, map[string]corestore.KVPairs{storeKey1: {}}) for i := 0; i < 100; i++ { cs.AddKVPair(storeKey1Bytes, corestore.KVPair{Key: []byte(fmt.Sprintf("key%03d", i)), Value: []byte("value")}) } @@ -165,7 +169,7 @@ func (s *StorageTestSuite) TestDatabase_ApplyChangeset() { } } - s.Require().NoError(db.ApplyChangeset(1, cs)) + s.Require().NoError(db.ApplyChangeset(cs)) lv, err := db.GetLatestVersion() s.Require().NoError(err) @@ -241,7 +245,7 @@ func (s *StorageTestSuite) TestDatabase_Iterator() { s.Require().NoError(err) defer db.Close() - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{storeKey1: {}}) + cs := corestore.NewChangesetWithPairs(1, map[string]corestore.KVPairs{storeKey1: {}}) for i := 0; i < 100; i++ { key := fmt.Sprintf("key%03d", i) // key000, key001, ..., key099 val := fmt.Sprintf("val%03d", i) // val000, val001, ..., val099 @@ -249,7 +253,7 @@ func (s *StorageTestSuite) TestDatabase_Iterator() { cs.AddKVPair(storeKey1Bytes, corestore.KVPair{Key: []byte(key), Value: []byte(val), Remove: false}) } - s.Require().NoError(db.ApplyChangeset(1, cs)) + s.Require().NoError(db.ApplyChangeset(cs)) // iterator without an end key over multiple versions for v := uint64(1); v < 5; v++ { @@ -310,7 +314,8 @@ func (s *StorageTestSuite) TestDatabase_Iterator_RangedDeletes() { s.Require().NoError(err) defer db.Close() - s.Require().NoError(db.ApplyChangeset(1, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 1, map[string]corestore.KVPairs{ storeKey1: { {Key: []byte("key001"), Value: []byte("value001"), Remove: false}, @@ -319,13 +324,15 @@ func (s *StorageTestSuite) TestDatabase_Iterator_RangedDeletes() { }, ))) - s.Require().NoError(db.ApplyChangeset(5, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 5, map[string]corestore.KVPairs{ storeKey1: {{Key: []byte("key002"), Value: []byte("value002"), Remove: false}}, }, ))) - s.Require().NoError(db.ApplyChangeset(10, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 10, map[string]corestore.KVPairs{ storeKey1: {{Key: []byte("key002"), Remove: true}}, }, @@ -353,7 +360,7 @@ func (s *StorageTestSuite) TestDatabase_IteratorMultiVersion() { // for versions 1-49, set all 10 keys for v := uint64(1); v < 50; v++ { - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{storeKey1: {}}) + cs := corestore.NewChangesetWithPairs(v, map[string]corestore.KVPairs{storeKey1: {}}) for i := 0; i < 10; i++ { key := fmt.Sprintf("key%03d", i) val := fmt.Sprintf("val%03d-%03d", i, v) @@ -361,12 +368,12 @@ func (s *StorageTestSuite) TestDatabase_IteratorMultiVersion() { cs.AddKVPair(storeKey1Bytes, corestore.KVPair{Key: []byte(key), Value: []byte(val)}) } - s.Require().NoError(db.ApplyChangeset(v, cs)) + s.Require().NoError(db.ApplyChangeset(cs)) } // for versions 50-100, only update even keys for v := uint64(50); v <= 100; v++ { - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{storeKey1: {}}) + cs := corestore.NewChangesetWithPairs(v, map[string]corestore.KVPairs{storeKey1: {}}) for i := 0; i < 10; i++ { if i%2 == 0 { key := fmt.Sprintf("key%03d", i) @@ -376,7 +383,7 @@ func (s *StorageTestSuite) TestDatabase_IteratorMultiVersion() { } } - s.Require().NoError(db.ApplyChangeset(v, cs)) + s.Require().NoError(db.ApplyChangeset(cs)) } itr, err := db.Iterator(storeKey1Bytes, 69, []byte("key000"), nil) @@ -519,7 +526,7 @@ func (s *StorageTestSuite) TestDatabase_IteratorNoDomain() { // for versions 1-50, set all 10 keys for v := uint64(1); v <= 50; v++ { - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{storeKey1: {}}) + cs := corestore.NewChangesetWithPairs(v, map[string]corestore.KVPairs{storeKey1: {}}) for i := 0; i < 10; i++ { key := fmt.Sprintf("key%03d", i) val := fmt.Sprintf("val%03d-%03d", i, v) @@ -527,7 +534,7 @@ func (s *StorageTestSuite) TestDatabase_IteratorNoDomain() { cs.AddKVPair(storeKey1Bytes, corestore.KVPair{Key: []byte(key), Value: []byte(val), Remove: false}) } - s.Require().NoError(db.ApplyChangeset(v, cs)) + s.Require().NoError(db.ApplyChangeset(cs)) } // create an iterator over the entire domain @@ -559,7 +566,7 @@ func (s *StorageTestSuite) TestDatabase_Prune() { // for versions 1-50, set 10 keys for v := uint64(1); v <= 50; v++ { - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{storeKey1: {}}) + cs := corestore.NewChangesetWithPairs(v, map[string]corestore.KVPairs{storeKey1: {}}) for i := 0; i < 10; i++ { key := fmt.Sprintf("key%03d", i) val := fmt.Sprintf("val%03d-%03d", i, v) @@ -567,7 +574,7 @@ func (s *StorageTestSuite) TestDatabase_Prune() { cs.AddKVPair(storeKey1Bytes, corestore.KVPair{Key: []byte(key), Value: []byte(val)}) } - s.Require().NoError(db.ApplyChangeset(v, cs)) + s.Require().NoError(db.ApplyChangeset(cs)) } // prune the first 25 versions @@ -625,13 +632,16 @@ func (s *StorageTestSuite) TestDatabase_Prune_KeepRecent() { key := []byte("key") // write a key at three different versions - s.Require().NoError(db.ApplyChangeset(1, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 1, map[string]corestore.KVPairs{storeKey1: {{Key: key, Value: []byte("val001"), Remove: false}}}, ))) - s.Require().NoError(db.ApplyChangeset(100, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 100, map[string]corestore.KVPairs{storeKey1: {{Key: key, Value: []byte("val100"), Remove: false}}}, ))) - s.Require().NoError(db.ApplyChangeset(200, corestore.NewChangesetWithPairs( + s.Require().NoError(db.ApplyChangeset(corestore.NewChangesetWithPairs( + 200, map[string]corestore.KVPairs{storeKey1: {{Key: key, Value: []byte("val200"), Remove: false}}}, ))) @@ -677,7 +687,7 @@ func (s *StorageTestSuite) TestDatabase_Restore() { // for versions 1-10, set 10 keys for v := uint64(1); v <= toVersion; v++ { - cs := corestore.NewChangesetWithPairs(map[string]corestore.KVPairs{storeKey1: {}}) + cs := corestore.NewChangesetWithPairs(v, map[string]corestore.KVPairs{storeKey1: {}}) for i := 0; i < keyCount; i++ { key := fmt.Sprintf("key%03d", i) val := fmt.Sprintf("val%03d-%03d", i, v) @@ -685,7 +695,7 @@ func (s *StorageTestSuite) TestDatabase_Restore() { cs.AddKVPair(storeKey1Bytes, corestore.KVPair{Key: []byte(key), Value: []byte(val)}) } - s.Require().NoError(db.ApplyChangeset(v, cs)) + s.Require().NoError(db.ApplyChangeset(cs)) } latestVersion, err := db.GetLatestVersion() @@ -1032,7 +1042,7 @@ func dbApplyChangeset( require.Greater(t, version, uint64(0)) require.Equal(t, len(keys), len(vals)) - cs := corestore.NewChangeset() + cs := corestore.NewChangeset(version) for i := 0; i < len(keys); i++ { remove := false if vals[i] == nil { @@ -1042,5 +1052,5 @@ func dbApplyChangeset( cs.AddKVPair([]byte(storeKey), corestore.KVPair{Key: keys[i], Value: vals[i], Remove: remove}) } - require.NoError(t, db.ApplyChangeset(version, cs)) + require.NoError(t, db.ApplyChangeset(cs)) } diff --git a/store/v2/storage/store.go b/store/v2/storage/store.go index aa1095cd11aa..5ca5a30132b7 100644 --- a/store/v2/storage/store.go +++ b/store/v2/storage/store.go @@ -47,8 +47,8 @@ func (ss *StorageStore) Get(storeKey []byte, version uint64, key []byte) ([]byte } // ApplyChangeset applies the given changeset to the storage. -func (ss *StorageStore) ApplyChangeset(version uint64, cs *corestore.Changeset) error { - b, err := ss.db.NewBatch(version) +func (ss *StorageStore) ApplyChangeset(cs *corestore.Changeset) error { + b, err := ss.db.NewBatch(cs.Version) if err != nil { return err } diff --git a/store/v2/store.go b/store/v2/store.go index 24ba636e10aa..124d7de579a1 100644 --- a/store/v2/store.go +++ b/store/v2/store.go @@ -3,7 +3,6 @@ package store import ( "io" - coreheader "cosmossdk.io/core/header" corestore "cosmossdk.io/core/store" "cosmossdk.io/store/v2/metrics" "cosmossdk.io/store/v2/proof" @@ -41,17 +40,6 @@ type RootStore interface { // SetInitialVersion sets the initial version on the RootStore. SetInitialVersion(v uint64) error - // SetCommitHeader sets the commit header for the next commit. This call and - // implementation is optional. However, it must be supported in cases where - // queries based on block time need to be supported. - SetCommitHeader(h *coreheader.Info) - - // WorkingHash returns the current WIP commitment hash by applying the Changeset - // to the SC backend. It is only used to get the hash of the intermediate state - // before committing, the typical use case is for the genesis block. - // NOTE: It also writes the changeset to the SS backend. - WorkingHash(cs *corestore.Changeset) ([]byte, error) - // Commit should be responsible for taking the provided changeset and flushing // it to disk. Note, it will overwrite the changeset if WorkingHash() was called. // Commit() should ensure the changeset is committed to all SC and SS backends diff --git a/tests/go.mod b/tests/go.mod index 677510942e5f..6e00a26185f5 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -248,6 +248,7 @@ replace ( cosmossdk.io/api => ../api cosmossdk.io/client/v2 => ../client/v2 cosmossdk.io/collections => ../collections + cosmossdk.io/core => ../core cosmossdk.io/core/testing => ../core/testing cosmossdk.io/indexer/postgres => ../indexer/postgres cosmossdk.io/runtime/v2 => ../runtime/v2 diff --git a/tests/go.sum b/tests/go.sum index fc64bfb55e16..2244df84bcac 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -192,8 +192,6 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/core v1.0.0-alpha.5 h1:McjYXAQ6XcT20v2uHyH7PhoWH8V+mebzfVFqT3GinsI= -cosmossdk.io/core v1.0.0-alpha.5/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/depinject v1.1.0 h1:wLan7LG35VM7Yo6ov0jId3RHWCGRhe8E8bsuARorl5E= cosmossdk.io/depinject v1.1.0/go.mod h1:kkI5H9jCGHeKeYWXTqYdruogYrEeWvBQCw1Pj4/eCFI= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= diff --git a/tests/integration/v2/app.go b/tests/integration/v2/app.go index 7684a539a209..aa5420d425dd 100644 --- a/tests/integration/v2/app.go +++ b/tests/integration/v2/app.go @@ -180,12 +180,12 @@ func NewApp( if store == nil { return nil, fmt.Errorf("failed to build store: %w", err) } - err = store.SetInitialVersion(1) + err = store.SetInitialVersion(0) if err != nil { return nil, fmt.Errorf("failed to set initial version: %w", err) } - integrationApp := &App{App: app, Store: store, txConfig: txConfig, lastHeight: 1} + integrationApp := &App{App: app, Store: store, txConfig: txConfig, lastHeight: 0} if startupConfig.GenesisBehavior == Genesis_SKIP { return integrationApp, nil } @@ -316,7 +316,7 @@ func (a *App) Commit(state corestore.WriterMap) ([]byte, error) { if err != nil { return nil, fmt.Errorf("failed to get state changes: %w", err) } - cs := &corestore.Changeset{Changes: changes} + cs := &corestore.Changeset{Version: a.lastHeight, Changes: changes} return a.Store.Commit(cs) }