refactor(store/v2): simplify genesis flow (#22435)
Co-authored-by: Marko <marko@baricevic.me>
This commit is contained in:
parent
406f977be0
commit
43e28b43ad
@ -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.
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) PausePruning() {
|
||||
m.signalPruning(true)
|
||||
}
|
||||
|
||||
func (m *Manager) ResumePruning(version uint64) error {
|
||||
m.signalPruning(false)
|
||||
return m.Prune(version)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
_, err := s.rootStore.Commit(corestore.NewChangeset(initialVersion))
|
||||
s.Require().NoError(err)
|
||||
cHash, err := s.rootStore.Commit(corestore.NewChangeset())
|
||||
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()
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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))
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user