Skip to content

Commit

Permalink
feat(store/v2): build the migration manager in the root store factory (
Browse files Browse the repository at this point in the history
…#22336)

Co-authored-by: marbar3778 <marbar3778@yahoo.com>
Co-authored-by: Marko <marko@baricevic.me>
Co-authored-by: Alex | Interchain Labs <alex@skip.money>
  • Loading branch information
4 people authored Jan 13, 2025
1 parent c79e19d commit 064c9ba
Show file tree
Hide file tree
Showing 25 changed files with 4,131 additions and 252 deletions.
2,048 changes: 2,048 additions & 0 deletions api/cosmos/store/v2/commit_info.pulsar.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/grpc/reflection/reflection.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions proto/cosmos/store/v2/commit_info.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
syntax = "proto3";
package cosmos.store.v2;

import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";

option go_package = "cosmossdk.io/store/v2/proof";

// CommitInfo defines commit information used by the multi-store when committing
// a version/height.
message CommitInfo {
int64 version = 1;
repeated StoreInfo store_infos = 2;
google.protobuf.Timestamp timestamp = 3 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
bytes commit_hash = 4;
}

// StoreInfo defines store-specific commit information. It contains a reference
// between a store name and the commit ID.
//
message StoreInfo {
string name = 1;
CommitID commit_id = 2;
string structure = 3;
}

// CommitID defines the commitment information when a specific store is
// committed.
message CommitID {
option (gogoproto.goproto_stringer) = false;

int64 version = 1;
bytes hash = 2;
}
3 changes: 1 addition & 2 deletions scripts/init-simapp-v2.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ $SIMD_BIN config set client keyring-backend test
$SIMD_BIN config set client keyring-default-keyname alice
$SIMD_BIN config set app rest.enable true
$SIMD_BIN config set app telemetry.prometheus-retention-time 600
$SIMD_BIN config set app store.options.sc-type iavl-v2
sed -i '' 's/timeout_commit = "5s"/timeout_commit = "1s"/' "$SIMD_HOME"/config/config.toml
sed -i '' 's/prometheus = false/prometheus = true/' "$SIMD_HOME"/config/config.toml

$SIMD_BIN keys add alice --indiscreet
$SIMD_BIN keys add bob --indiscreet
aliases=""
for i in $(seq 10); do
alias=$(dd if=/dev/urandom bs=16 count=24 2> /dev/null | base32 | head -c 32)
alias=$(dd if=/dev/urandom bs=16 count=24 2> /dev/null | base64 | head -c 32)
$SIMD_BIN keys add "$alias" --indiscreet
aliases="$aliases $alias"
done
Expand Down
2 changes: 1 addition & 1 deletion server/v2/cometbft/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ func assertStoreLatestVersion(t *testing.T, store types.Store, target uint64) {
require.Equal(t, target, version)
commitInfo, err := store.GetStateCommitment().GetCommitInfo(version)
require.NoError(t, err)
require.Equal(t, target, commitInfo.Version)
require.Equal(t, target, uint64(commitInfo.Version))
}

func TestOptimisticExecution(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions server/v2/cometbft/internal/mock/mock_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (s *MockStore) GetLatestVersion() (uint64, error) {
return 0, err
}

return lastCommitID.Version, nil
return uint64(lastCommitID.Version), nil
}

func (s *MockStore) StateLatest() (uint64, corestore.ReaderMap, error) {
Expand Down Expand Up @@ -99,7 +99,7 @@ func (s *MockStore) LastCommitID() (proof.CommitID, error) {
v, err := s.GetStateCommitment().GetLatestVersion()
bz := sha256.Sum256([]byte{})
return proof.CommitID{
Version: v,
Version: int64(v),
Hash: bz[:],
}, err
}
Expand Down
11 changes: 9 additions & 2 deletions server/v2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,15 @@ func (s *Server[T]) Start(ctx context.Context) error {
}()
}

if err := <-resCh; err != nil {
return fmt.Errorf("failed to start servers: %w", err)
for i := 0; i < len(s.components); i++ {
select {
case err := <-resCh:
if err != nil {
return fmt.Errorf("failed to start servers: %w", err)
}
case <-ctx.Done():
return nil
}
}

<-ctx.Done()
Expand Down
12 changes: 5 additions & 7 deletions simapp/v2/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ import (
_ "cosmossdk.io/x/bank" // import for side-effects
banktypes "cosmossdk.io/x/bank/types"
_ "cosmossdk.io/x/bank/v2" // import for side-effects
bankv2types "cosmossdk.io/x/bank/v2/types"
bankmodulev2 "cosmossdk.io/x/bank/v2/types/module"
_ "cosmossdk.io/x/circuit" // import for side-effects
circuittypes "cosmossdk.io/x/circuit/types"
_ "cosmossdk.io/x/consensus" // import for side-effects
Expand Down Expand Up @@ -156,7 +154,7 @@ var (
accounts.ModuleName,
authtypes.ModuleName,
banktypes.ModuleName,
bankv2types.ModuleName,
// bankv2types.ModuleName,
distrtypes.ModuleName,
stakingtypes.ModuleName,
slashingtypes.ModuleName,
Expand Down Expand Up @@ -297,10 +295,10 @@ var (
Name: epochstypes.ModuleName,
Config: appconfig.WrapAny(&epochsmodulev1.Module{}),
},
{
Name: bankv2types.ModuleName,
Config: appconfig.WrapAny(&bankmodulev2.Module{}),
},
// {
// Name: bankv2types.ModuleName,
// Config: appconfig.WrapAny(&bankmodulev2.Module{}),
// },
},
}
)
21 changes: 0 additions & 21 deletions simapp/v2/simdv2/cmd/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"cosmossdk.io/server/v2/cometbft"
"cosmossdk.io/server/v2/store"
banktypes "cosmossdk.io/x/bank/types"
bankv2types "cosmossdk.io/x/bank/v2/types"
stakingtypes "cosmossdk.io/x/staking/types"

"github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -423,13 +422,6 @@ func initGenFiles[T transaction.Tx](
}
appGenState[banktypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&bankGenState)

var bankV2GenState bankv2types.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appGenState[bankv2types.ModuleName], &bankV2GenState)
if len(bankV2GenState.Balances) == 0 {
bankV2GenState = getBankV2GenesisFromV1(bankGenState)
}
appGenState[bankv2types.ModuleName] = clientCtx.Codec.MustMarshalJSON(&bankV2GenState)

appGenStateJSON, err := json.MarshalIndent(appGenState, "", " ")
if err != nil {
return err
Expand Down Expand Up @@ -532,16 +524,3 @@ func writeFile(name, dir string, contents []byte) error {

return os.WriteFile(file, contents, 0o600)
}

// getBankV2GenesisFromV1 clones bank/v1 state to bank/v2
// since we not migrate yet
// TODO: Remove
func getBankV2GenesisFromV1(v1GenesisState banktypes.GenesisState) bankv2types.GenesisState {
var v2GenesisState bankv2types.GenesisState
for _, balance := range v1GenesisState.Balances {
v2Balance := bankv2types.Balance(balance)
v2GenesisState.Balances = append(v2GenesisState.Balances, v2Balance)
v2GenesisState.Supply = v2GenesisState.Supply.Add(balance.Coins...)
}
return v2GenesisState
}
13 changes: 13 additions & 0 deletions store/v2/commitment/iavl/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,16 @@ func (e *Exporter) Close() error {

return nil
}

// EmptyExporter is a Exporter for an empty tree.
type EmptyExporter struct{}

// Next returns ExportDone.
func (e *EmptyExporter) Next() (*snapshotstypes.SnapshotIAVLItem, error) {
return nil, commitment.ErrorExportDone
}

// Close does nothing.
func (e *EmptyExporter) Close() error {
return nil
}
18 changes: 18 additions & 0 deletions store/v2/commitment/iavl/tree.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package iavl

import (
"errors"
"fmt"

"github.com/cosmos/iavl"
Expand All @@ -21,6 +22,8 @@ var (
// IavlTree is a wrapper around iavl.MutableTree.
type IavlTree struct {
tree *iavl.MutableTree
// it is only used for new store key during the migration process.
initialVersion uint64
}

// NewIavlTree creates a new IavlTree instance.
Expand Down Expand Up @@ -65,6 +68,17 @@ func (t *IavlTree) WorkingHash() []byte {

// LoadVersion loads the state at the given version.
func (t *IavlTree) LoadVersion(version uint64) error {
if t.initialVersion > 0 {
// If the initial version is set and the tree is empty,
// we don't need to load the version.
latestVersion, err := t.tree.GetLatestVersion()
if err != nil {
return err
}
if latestVersion == 0 {
return nil
}
}
_, err := t.tree.LoadVersion(int64(version))
return err
}
Expand Down Expand Up @@ -150,6 +164,7 @@ func (t *IavlTree) GetLatestVersion() (uint64, error) {
// SetInitialVersion sets the initial version of the database.
func (t *IavlTree) SetInitialVersion(version uint64) error {
t.tree.SetInitialVersion(version)
t.initialVersion = version
return nil
}

Expand All @@ -169,6 +184,9 @@ func (t *IavlTree) PausePruning(pause bool) {

// Export exports the tree exporter at the given version.
func (t *IavlTree) Export(version uint64) (commitment.Exporter, error) {
if version < t.initialVersion {
return nil, errors.New("version is less than the initial version")
}
tree, err := t.tree.GetImmutable(int64(version))
if err != nil {
return nil, err
Expand Down
53 changes: 38 additions & 15 deletions store/v2/commitment/metadata.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package commitment

import (
"bytes"
"errors"
"fmt"

gogotypes "github.com/cosmos/gogoproto/types"

corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/v2/internal/encoding"
"cosmossdk.io/store/v2/proof"
)

const (
commitInfoKeyFmt = "c/%d" // c/<version>
latestVersionKey = "c/latest"
removedStoreKeyPrefix = "c/removed/" // c/removed/<version>/<store-name>
commitInfoKeyFmt = "s/%d" // s/<version>
latestVersionKey = "s/latest"
removedStoreKeyPrefix = "s/removed/" // s/removed/<version>/<store-name>
)

// MetadataStore is a store for metadata related to the commitment store.
Expand All @@ -39,21 +40,20 @@ func (m *MetadataStore) GetLatestVersion() (uint64, error) {
return 0, nil
}

version, _, err := encoding.DecodeUvarint(value)
if err != nil {
var latestVersion int64
if err := gogotypes.StdInt64Unmarshal(&latestVersion, value); err != nil {
return 0, err
}

return version, nil
return uint64(latestVersion), nil
}

func (m *MetadataStore) setLatestVersion(version uint64) error {
var buf bytes.Buffer
buf.Grow(encoding.EncodeUvarintSize(version))
if err := encoding.EncodeUvarint(&buf, version); err != nil {
bz, err := gogotypes.StdInt64Marshal(int64(version)) // convert uint64 to int64 is safe since there will be no overflow or underflow
if err != nil {
return err
}
return m.kv.Set([]byte(latestVersionKey), buf.Bytes())
return m.kv.Set([]byte(latestVersionKey), bz)
}

// GetCommitInfo returns the commit info for the given version.
Expand All @@ -72,6 +72,10 @@ func (m *MetadataStore) GetCommitInfo(version uint64) (*proof.CommitInfo, error)
return nil, err
}

if err := migrateStoreInfo(cInfo); err != nil {
return nil, err
}

return cInfo, nil
}

Expand All @@ -94,12 +98,11 @@ func (m *MetadataStore) flushCommitInfo(version uint64, cInfo *proof.CommitInfo)
return err
}

var buf bytes.Buffer
buf.Grow(encoding.EncodeUvarintSize(version))
if err := encoding.EncodeUvarint(&buf, version); err != nil {
bz, err := gogotypes.StdInt64Marshal(int64(version)) // convert uint64 to int64 is safe since there will be no overflow or underflow
if err != nil {
return err
}
if err := batch.Set([]byte(latestVersionKey), buf.Bytes()); err != nil {
if err := batch.Set([]byte(latestVersionKey), bz); err != nil {
return err
}

Expand Down Expand Up @@ -172,3 +175,23 @@ func (m *MetadataStore) deleteCommitInfo(version uint64) error {
cInfoKey := []byte(fmt.Sprintf(commitInfoKeyFmt, version))
return m.kv.Delete(cInfoKey)
}

// when in migration mode, we need to add new fields to the store info
// this will only be the case for the storev1 to storev2 migration
func migrateStoreInfo(cInfo *proof.CommitInfo) error {
for _, storeInfo := range cInfo.StoreInfos {
if storeInfo.Structure == "" {
storeInfo.Structure = "iavl"
}
}

if cInfo.CommitHash == nil {
commitHash, _, err := cInfo.GetStoreProof([]byte{})
if err != nil {
return err
}

cInfo.CommitHash = commitHash
}
return nil
}
Loading

0 comments on commit 064c9ba

Please sign in to comment.