refactor(genutil): Use sdk types genesis validator (backport #21678) (#22183)

Co-authored-by: son trinh <trinhleson2000@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com>
Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
mergify[bot] 2024-10-09 09:09:07 +02:00 committed by GitHub
parent 1780d7dfa6
commit c3a6f35f80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 462 additions and 69 deletions

53
crypto/codec/pubkey.go Normal file
View File

@ -0,0 +1,53 @@
package codec
import (
"cosmossdk.io/errors"
cryptokeys "github.com/cosmos/cosmos-sdk/crypto/keys"
bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
func PubKeyToProto(pk cryptokeys.JSONPubkey) (cryptotypes.PubKey, error) {
switch pk.KeyType {
case ed25519.PubKeyName:
return &ed25519.PubKey{
Key: pk.Value,
}, nil
case secp256k1.PubKeyName:
return &secp256k1.PubKey{
Key: pk.Value,
}, nil
case bls12_381.PubKeyName:
return &bls12_381.PubKey{
Key: pk.Value,
}, nil
default:
return nil, errors.Wrapf(sdkerrors.ErrInvalidType, "cannot convert %v to proto public key", pk)
}
}
func PubKeyFromProto(pk cryptotypes.PubKey) (cryptokeys.JSONPubkey, error) {
switch pk := pk.(type) {
case *ed25519.PubKey:
return cryptokeys.JSONPubkey{
KeyType: ed25519.PubKeyName,
Value: pk.Bytes(),
}, nil
case *secp256k1.PubKey:
return cryptokeys.JSONPubkey{
KeyType: secp256k1.PubKeyName,
Value: pk.Bytes(),
}, nil
case *bls12_381.PubKey:
return cryptokeys.JSONPubkey{
KeyType: bls12_381.PubKeyName,
Value: pk.Bytes(),
}, nil
default:
return cryptokeys.JSONPubkey{}, errors.Wrapf(sdkerrors.ErrInvalidType, "cannot convert %v from proto public key", pk)
}
}

41
crypto/keys/jsonkey.go Normal file
View File

@ -0,0 +1,41 @@
package keys
import (
"github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/types"
)
// JSONPubKey defines a public key that are parse from JSON file.
// convert PubKey to JSONPubKey needs a in between step
type JSONPubkey struct {
KeyType string `json:"type"`
Value []byte `json:"value"`
}
func (pk JSONPubkey) Address() types.Address {
switch pk.KeyType {
case ed25519.PubKeyName:
ed25519 := ed25519.PubKey{
Key: pk.Value,
}
return ed25519.Address()
case secp256k1.PubKeyName:
secp256k1 := secp256k1.PubKey{
Key: pk.Value,
}
return secp256k1.Address()
case bls12_381.PubKeyName:
bls12_381 := bls12_381.PubKey{
Key: pk.Value,
}
return bls12_381.Address()
default:
return nil
}
}
func (pk JSONPubkey) Bytes() []byte {
return pk.Value
}

View File

@ -6,7 +6,6 @@ import (
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
cmtcrypto "github.com/cometbft/cometbft/crypto"
cmttypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/gogoproto/grpc"
"cosmossdk.io/core/server"
@ -18,6 +17,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server/api"
"github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
)
type (
@ -76,7 +76,7 @@ type (
// AppState is the application state as JSON.
AppState json.RawMessage
// Validators is the exported validator set.
Validators []cmttypes.GenesisValidator
Validators []sdk.GenesisValidator
// Height is the app's latest block height.
Height int64
// ConsensusParams are the exported consensus params for ABCI.

View File

@ -5,7 +5,6 @@ import (
"fmt"
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
cmttypes "github.com/cometbft/cometbft/types"
"cosmossdk.io/collections"
storetypes "cosmossdk.io/store/types"
@ -13,7 +12,6 @@ import (
"cosmossdk.io/x/staking"
stakingtypes "cosmossdk.io/x/staking/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -43,25 +41,10 @@ func (app *SimApp) ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAd
}
validators, err := staking.WriteValidators(ctx, app.StakingKeeper)
cmtValidators := []cmttypes.GenesisValidator{}
for _, val := range validators {
cmtPk, err := cryptocodec.ToCmtPubKeyInterface(val.PubKey)
if err != nil {
return servertypes.ExportedApp{}, err
}
cmtVal := cmttypes.GenesisValidator{
Address: val.Address.Bytes(),
PubKey: cmtPk,
Power: val.Power,
Name: val.Name,
}
cmtValidators = append(cmtValidators, cmtVal)
}
return servertypes.ExportedApp{
AppState: appState,
Validators: cmtValidators,
Validators: validators,
Height: height,
ConsensusParams: app.BaseApp.GetConsensusParams(ctx),
}, err

View File

@ -13,10 +13,12 @@ import (
"cosmossdk.io/log"
"cosmossdk.io/runtime/v2"
serverstore "cosmossdk.io/server/v2/store"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/root"
basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject"
lockupdepinject "cosmossdk.io/x/accounts/defaults/lockup/depinject"
multisigdepinject "cosmossdk.io/x/accounts/defaults/multisig/depinject"
stakingkeeper "cosmossdk.io/x/staking/keeper"
upgradekeeper "cosmossdk.io/x/upgrade/keeper"
"github.com/cosmos/cosmos-sdk/client"
@ -38,10 +40,12 @@ type SimApp[T transaction.Tx] struct {
appCodec codec.Codec
txConfig client.TxConfig
interfaceRegistry codectypes.InterfaceRegistry
store store.RootStore
// required keepers during wiring
// others keepers are all in the app
UpgradeKeeper *upgradekeeper.Keeper
StakingKeeper *stakingkeeper.Keeper
}
func init() {
@ -161,6 +165,7 @@ func NewSimApp[T transaction.Tx](
&app.txConfig,
&app.interfaceRegistry,
&app.UpgradeKeeper,
&app.StakingKeeper,
); err != nil {
panic(err)
}
@ -170,7 +175,8 @@ func NewSimApp[T transaction.Tx](
if err != nil {
panic(err)
}
_, err = storeBuilder.Build(logger, storeConfig)
app.store, err = storeBuilder.Build(logger, storeConfig)
if err != nil {
panic(err)
}
@ -213,7 +219,6 @@ func (app *SimApp[T]) TxConfig() client.TxConfig {
return app.txConfig
}
// GetStore gets the app store.
func (app *SimApp[T]) GetStore() any {
return app.App.GetStore()
func (app *SimApp[T]) GetStore() store.RootStore {
return app.store
}

View File

@ -20,7 +20,6 @@ import (
sdkmath "cosmossdk.io/math"
"cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2"
comettypes "cosmossdk.io/server/v2/cometbft/types"
"cosmossdk.io/store/v2/db"
banktypes "cosmossdk.io/x/bank/types"
@ -74,7 +73,7 @@ func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) {
genesisBytes, err := json.Marshal(genesis)
require.NoError(t, err)
st := app.GetStore().(comettypes.Store)
st := app.GetStore()
ci, err := st.LastCommitID()
require.NoError(t, err)
@ -110,7 +109,7 @@ func MoveNextBlock(t *testing.T, app *SimApp[transaction.Tx], ctx context.Contex
bz := sha256.Sum256([]byte{})
st := app.GetStore().(comettypes.Store)
st := app.GetStore()
ci, err := st.LastCommitID()
require.NoError(t, err)

View File

@ -3,27 +3,46 @@ package simapp
import (
"context"
"cosmossdk.io/runtime/v2/services"
"cosmossdk.io/x/staking"
v2 "github.com/cosmos/cosmos-sdk/x/genutil/v2"
)
// ExportAppStateAndValidators exports the state of the application for a genesis
// file.
func (app *SimApp[T]) ExportAppStateAndValidators(jailAllowedAddrs []string) (v2.ExportedApp, error) {
// as if they could withdraw from the start of the next block
// This is a demonstation of how to export a genesis file. Export may need extended at
// the user discretion for cleaning the genesis state at the end provided with jailAllowedAddrs
func (app *SimApp[T]) ExportAppStateAndValidators(
jailAllowedAddrs []string,
) (v2.ExportedApp, error) {
ctx := context.Background()
var exportedApp v2.ExportedApp
latestHeight, err := app.LoadLatestHeight()
if err != nil {
return v2.ExportedApp{}, err
return exportedApp, err
}
genesis, err := app.ExportGenesis(ctx, latestHeight)
if err != nil {
return v2.ExportedApp{}, err
return exportedApp, err
}
return v2.ExportedApp{
AppState: genesis,
Height: int64(latestHeight),
}, nil
readerMap, err := app.GetStore().StateAt(latestHeight)
if err != nil {
return exportedApp, err
}
genesisCtx := services.NewGenesisContext(readerMap)
err = genesisCtx.Read(ctx, func(ctx context.Context) error {
exportedApp.Validators, err = staking.WriteValidators(ctx, app.StakingKeeper)
return err
})
if err != nil {
return exportedApp, err
}
exportedApp.AppState = genesis
exportedApp.Height = int64(latestHeight)
return exportedApp, nil
}

View File

@ -10,7 +10,7 @@ require (
cosmossdk.io/depinject v1.0.0
cosmossdk.io/log v1.4.1
cosmossdk.io/math v1.3.0
cosmossdk.io/runtime/v2 v2.0.0-20241008175849-325728a9fd6c // main
cosmossdk.io/runtime/v2 v2.0.0-20241009051805-4aeb0539252b // main
cosmossdk.io/server/v2 v2.0.0-20241008175849-325728a9fd6c // main
cosmossdk.io/server/v2/cometbft v0.0.0-00010101000000-000000000000
cosmossdk.io/store/v2 v2.0.0-20241008175849-325728a9fd6c // main

View File

@ -210,8 +210,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM=
cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU=
cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE=
cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k=
cosmossdk.io/runtime/v2 v2.0.0-20241008175849-325728a9fd6c h1:+msBeQ6/bmJOhJPV7fye1bYf86LTaRMJezwTc5LSBUs=
cosmossdk.io/runtime/v2 v2.0.0-20241008175849-325728a9fd6c/go.mod h1:pmne/XLLzEbQ6JeM/nQoZVvK19ZtMvvEMq6qOMp9MHs=
cosmossdk.io/runtime/v2 v2.0.0-20241009051805-4aeb0539252b h1:ncc1ce9iZgUeTNVKkTeJ4tiVEgGGpPRk7I28PhzFqqY=
cosmossdk.io/runtime/v2 v2.0.0-20241009051805-4aeb0539252b/go.mod h1:pmne/XLLzEbQ6JeM/nQoZVvK19ZtMvvEMq6qOMp9MHs=
cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU=
cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ=
cosmossdk.io/server/v2 v2.0.0-20241008175849-325728a9fd6c h1:SobvpV3A/LPlmQ+mM6YrJHt7rRP6Cp7aVOB2ulwEBEc=

View File

@ -31,6 +31,7 @@ import (
"github.com/cosmos/cosmos-sdk/server/types"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
gentestutil "github.com/cosmos/cosmos-sdk/testutil/x/genutil"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
@ -184,7 +185,7 @@ func setupApp(t *testing.T, tempDir string) (*simapp.SimApp, context.Context, ge
ChainID: "theChainId",
AppState: stateBytes,
Consensus: &genutiltypes.ConsensusGenesis{
Validators: nil,
Validators: []sdk.GenesisValidator{},
},
}

View File

@ -3,6 +3,7 @@ package types
import (
"cosmossdk.io/math"
cryptokeys "github.com/cosmos/cosmos-sdk/crypto/keys"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)
@ -98,3 +99,11 @@ type ValidatorI interface {
SharesFromTokens(amt math.Int) (math.LegacyDec, error) // shares worth of delegator's bond
SharesFromTokensTruncated(amt math.Int) (math.LegacyDec, error) // truncated shares worth of delegator's bond
}
// GenesisValidator is an initial validator.
type GenesisValidator struct {
Address ConsAddress `json:"address"`
PubKey cryptokeys.JSONPubkey `json:"pub_key"`
Power int64 `json:"power"`
Name string `json:"name"`
}

View File

@ -13,13 +13,19 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/version"
v052 "github.com/cosmos/cosmos-sdk/x/genutil/migration/v052"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
)
const flagGenesisTime = "genesis-time"
const (
flagGenesisTime = "genesis-time"
v52 = "v0.52"
)
// MigrationMap is a map of SDK versions to their respective genesis migration functions.
var MigrationMap = types.MigrationMap{}
var MigrationMap = types.MigrationMap{
v52: v052.Migrate,
}
// MigrateGenesisCmd returns a command to execute genesis state migration.
// Applications should pass their own migration map to this function.
@ -56,7 +62,17 @@ func MigrateHandler(cmd *cobra.Command, args []string, migrations types.Migratio
}
importGenesis := args[1]
appGenesis, err := types.AppGenesisFromFile(importGenesis)
outputDocument, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
// for v52 we need to migrate the consensus validator address from hex bytes to
// sdk consensus address.
var appGenesis *types.AppGenesis
var err error
if target == v52 {
appGenesis, err = v052.MigrateGenesisFile(importGenesis)
} else {
appGenesis, err = types.AppGenesisFromFile(importGenesis)
}
if err != nil {
return err
}
@ -110,7 +126,6 @@ func MigrateHandler(cmd *cobra.Command, args []string, migrations types.Migratio
return fmt.Errorf("failed to marshal app genesis: %w", err)
}
outputDocument, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
if outputDocument == "" {
cmd.Println(string(bz))
return nil

View File

@ -0,0 +1,173 @@
package migrate
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"time"
cmtjson "github.com/cometbft/cometbft/libs/json"
cmttypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/cosmos-sdk/client"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
)
type legacyAppGenesis struct {
AppName string `json:"app_name"`
AppVersion string `json:"app_version"`
GenesisTime time.Time `json:"genesis_time"`
ChainID string `json:"chain_id"`
InitialHeight int64 `json:"initial_height"`
AppHash []byte `json:"app_hash"`
AppState json.RawMessage `json:"app_state,omitempty"`
Consensus *legacyConsensusGenesis `json:"consensus,omitempty"`
}
type legacyConsensusGenesis struct {
Validators []cmttypes.GenesisValidator `json:"validators,omitempty"`
Params *cmttypes.ConsensusParams `json:"params,omitempty"`
}
func MigrateGenesisFile(oldGenFile string) (*types.AppGenesis, error) {
file, err := os.Open(filepath.Clean(oldGenFile))
if err != nil {
return nil, err
}
defer file.Close()
appGenesis, err := migrateGenesisValidator(file)
if err != nil {
return nil, fmt.Errorf("failed to read genesis from file %s: %w", oldGenFile, err)
}
return appGenesis, nil
}
// migrateGenesisValidator migrate current genesis file genesis validator to match of the
// new genesis validator type.
func migrateGenesisValidator(r io.Reader) (*types.AppGenesis, error) {
var newAg types.AppGenesis
var ag legacyAppGenesis
var err error
if rs, ok := r.(io.ReadSeeker); ok {
err = json.NewDecoder(rs).Decode(&ag)
if err == nil {
vals, err := convertValidators(ag.Consensus.Validators)
if err != nil {
return nil, err
}
newAg = types.AppGenesis{
AppName: ag.AppName,
AppVersion: ag.AppVersion,
GenesisTime: ag.GenesisTime,
ChainID: ag.ChainID,
InitialHeight: ag.InitialHeight,
AppHash: ag.AppHash,
AppState: ag.AppState,
Consensus: &types.ConsensusGenesis{
Validators: vals,
Params: ag.Consensus.Params,
},
}
return &newAg, nil
}
err = fmt.Errorf("error unmarshalling legacy AppGenesis: %w", err)
if _, serr := rs.Seek(0, io.SeekStart); serr != nil {
err = errors.Join(err, fmt.Errorf("error seeking back to the front: %w", serr))
return nil, err
}
}
jsonBlob, ioerr := io.ReadAll(r)
if ioerr != nil {
err = errors.Join(err, fmt.Errorf("failed to read file completely: %w", ioerr))
return nil, err
}
// fallback to comet genesis parsing
var ctmGenesis cmttypes.GenesisDoc
if uerr := cmtjson.Unmarshal(jsonBlob, &ctmGenesis); uerr != nil {
err = errors.Join(err, fmt.Errorf("failed fallback to CometBFT GenDoc: %w", uerr))
return nil, err
}
vals, err := convertValidators(ctmGenesis.Validators)
if err != nil {
return nil, err
}
newAg = types.AppGenesis{
AppName: version.AppName,
GenesisTime: ctmGenesis.GenesisTime,
ChainID: ctmGenesis.ChainID,
InitialHeight: ctmGenesis.InitialHeight,
AppHash: ctmGenesis.AppHash,
AppState: ctmGenesis.AppState,
Consensus: &types.ConsensusGenesis{
Validators: vals,
Params: ctmGenesis.ConsensusParams,
},
}
return &newAg, nil
}
func convertValidators(cmtVals []cmttypes.GenesisValidator) ([]sdk.GenesisValidator, error) {
vals := make([]sdk.GenesisValidator, len(cmtVals))
for i, cmtVal := range cmtVals {
pk, err := cryptocodec.FromCmtPubKeyInterface(cmtVal.PubKey)
if err != nil {
return nil, err
}
jsonPk, err := cryptocodec.PubKeyFromProto(pk)
if err != nil {
return nil, err
}
vals[i] = sdk.GenesisValidator{
Address: cmtVal.Address.Bytes(),
PubKey: jsonPk,
Power: cmtVal.Power,
Name: cmtVal.Name,
}
}
return vals, nil
}
// CometBFT Genesis Handling for JSON,
// this is necessary for json unmarshaling of legacyConsensusGenesis
func (cs *legacyConsensusGenesis) MarshalJSON() ([]byte, error) {
type Alias legacyConsensusGenesis
return cmtjson.Marshal(&Alias{
Validators: cs.Validators,
Params: cs.Params,
})
}
func (cs *legacyConsensusGenesis) UnmarshalJSON(b []byte) error {
type Alias legacyConsensusGenesis
result := Alias{}
if err := cmtjson.Unmarshal(b, &result); err != nil {
return err
}
cs.Params = result.Params
cs.Validators = result.Validators
return nil
}
// since we only need migrate the consensus validators content so there is no
// exported state migration.
func Migrate(appState types.AppMap, _ client.Context) (types.AppMap, error) {
return appState, nil
}

View File

@ -0,0 +1,51 @@
package migrate
import (
"bytes"
"encoding/json"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
)
var oldGenFilePath = "./testdata/old_app_genesis.json"
func TestMigration(t *testing.T) {
tempDir := t.TempDir()
// clean all content on this directory
err := os.RemoveAll(tempDir)
require.NoError(t, err)
// should not be able to get app genesis from new genesis file
// since validators address are still in hex string and not cons address
_, err = types.AppGenesisFromFile(oldGenFilePath)
require.ErrorContains(t, err, "error unmarshalling AppGenesis: decoding bech32 failed")
newAppGenesis, err := MigrateGenesisFile(oldGenFilePath)
require.NoError(t, err)
// save the new app genesis to new temp dir
err = newAppGenesis.SaveAs(tempDir)
require.NoError(t, err)
// read the old app genesis to compare with the new app genesis
var oldAppGenesis legacyAppGenesis
r, err := os.Open(oldGenFilePath)
require.NoError(t, err)
err = json.NewDecoder(r).Decode(&oldAppGenesis)
require.NoError(t, err)
// should be able to get app genesis from new genesis file
newAppGenesis, err = types.AppGenesisFromFile(tempDir)
require.NotNil(t, newAppGenesis)
require.NotNil(t, newAppGenesis.Consensus)
require.True(t, bytes.Equal(oldAppGenesis.AppHash, newAppGenesis.AppHash))
require.True(t, bytes.Equal(oldAppGenesis.Consensus.Validators[0].Address.Bytes(), newAppGenesis.Consensus.Validators[0].Address.Bytes()))
require.True(t, bytes.Equal(oldAppGenesis.Consensus.Validators[0].PubKey.Bytes(), newAppGenesis.Consensus.Validators[0].PubKey.Bytes()))
require.Equal(t, len(oldAppGenesis.Consensus.Validators), len(newAppGenesis.Consensus.Validators), "Number of validators should remain the same after migration")
require.NoError(t, err)
}

File diff suppressed because one or more lines are too long

View File

@ -14,6 +14,8 @@ import (
cmtjson "github.com/cometbft/cometbft/libs/json"
cmttypes "github.com/cometbft/cometbft/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
)
@ -118,6 +120,26 @@ func AppGenesisFromReader(reader io.Reader) (*AppGenesis, error) {
return nil, err
}
vals := []sdk.GenesisValidator{}
for _, cmtVal := range ctmGenesis.Validators {
pk, err := cryptocodec.FromCmtPubKeyInterface(cmtVal.PubKey)
if err != nil {
return nil, err
}
jsonPk, err := cryptocodec.PubKeyFromProto(pk)
if err != nil {
return nil, err
}
val := sdk.GenesisValidator{
Address: cmtVal.Address.Bytes(),
PubKey: jsonPk,
Power: cmtVal.Power,
Name: cmtVal.Name,
}
vals = append(vals, val)
}
ag = AppGenesis{
AppName: version.AppName,
// AppVersion is not filled as we do not know it from a CometBFT genesis
@ -127,7 +149,7 @@ func AppGenesisFromReader(reader io.Reader) (*AppGenesis, error) {
AppHash: ctmGenesis.AppHash,
AppState: ctmGenesis.AppState,
Consensus: &ConsensusGenesis{
Validators: ctmGenesis.Validators,
Validators: vals,
Params: ctmGenesis.ConsensusParams,
},
}
@ -160,13 +182,36 @@ func AppGenesisFromFile(genFile string) (*AppGenesis, error) {
// ToGenesisDoc converts the AppGenesis to a CometBFT GenesisDoc.
func (ag *AppGenesis) ToGenesisDoc() (*cmttypes.GenesisDoc, error) {
cmtValidators := []cmttypes.GenesisValidator{}
for _, val := range ag.Consensus.Validators {
pk, err := cryptocodec.PubKeyToProto(val.PubKey)
if err != nil {
return nil, err
}
cmtPk, err := cryptocodec.ToCmtPubKeyInterface(pk)
if err != nil {
return nil, err
}
cmtVal := cmttypes.GenesisValidator{
Address: val.Address.Bytes(),
PubKey: cmtPk,
Power: val.Power,
Name: val.Name,
}
cmtValidators = append(cmtValidators, cmtVal)
}
// assert nil value for empty validators set
if len(cmtValidators) == 0 {
cmtValidators = nil
}
return &cmttypes.GenesisDoc{
GenesisTime: ag.GenesisTime,
ChainID: ag.ChainID,
InitialHeight: ag.InitialHeight,
AppHash: ag.AppHash,
AppState: ag.AppState,
Validators: ag.Consensus.Validators,
Validators: cmtValidators,
ConsensusParams: ag.Consensus.Params,
}, nil
}
@ -174,13 +219,13 @@ func (ag *AppGenesis) ToGenesisDoc() (*cmttypes.GenesisDoc, error) {
// ConsensusGenesis defines the consensus layer's genesis.
// TODO(@julienrbrt) eventually abstract from CometBFT types
type ConsensusGenesis struct {
Validators []cmttypes.GenesisValidator `json:"validators,omitempty"`
Params *cmttypes.ConsensusParams `json:"params,omitempty"`
Validators []sdk.GenesisValidator `json:"validators,omitempty"`
Params *cmttypes.ConsensusParams `json:"params,omitempty"`
}
// NewConsensusGenesis returns a ConsensusGenesis with given values.
// It takes a proto consensus params so it can called from server export command.
func NewConsensusGenesis(params cmtproto.ConsensusParams, validators []cmttypes.GenesisValidator) *ConsensusGenesis {
func NewConsensusGenesis(params cmtproto.ConsensusParams, validators []sdk.GenesisValidator) *ConsensusGenesis {
return &ConsensusGenesis{
Params: &cmttypes.ConsensusParams{
Block: cmttypes.BlockParams{
@ -211,7 +256,7 @@ func (cs *ConsensusGenesis) MarshalJSON() ([]byte, error) {
func (cs *ConsensusGenesis) UnmarshalJSON(b []byte) error {
type Alias ConsensusGenesis
result := Alias{}
var result Alias
if err := cmtjson.Unmarshal(b, &result); err != nil {
return err
}
@ -241,7 +286,7 @@ func (cs *ConsensusGenesis) ValidateAndComplete() error {
return fmt.Errorf("incorrect address for validator %v in the genesis file, should be %v", v, v.PubKey.Address())
}
if len(v.Address) == 0 {
cs.Validators[i].Address = v.PubKey.Address()
cs.Validators[i].Address = v.PubKey.Address().Bytes()
}
}

File diff suppressed because one or more lines are too long

View File

@ -14,11 +14,11 @@ import (
tmed25519 "github.com/cometbft/cometbft/crypto/ed25519"
"github.com/cometbft/cometbft/p2p"
"github.com/cometbft/cometbft/privval"
cmttypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/go-bip39"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
)
@ -35,7 +35,7 @@ func ExportGenesisFile(genesis *types.AppGenesis, genFile string) error {
// ExportGenesisFileWithTime creates and writes the genesis configuration to disk.
// An error is returned if building or writing the configuration to file fails.
func ExportGenesisFileWithTime(
genFile, chainID string, validators []cmttypes.GenesisValidator, appState json.RawMessage, genTime time.Time,
genFile, chainID string, validators []sdk.GenesisValidator, appState json.RawMessage, genTime time.Time,
) error {
appGenesis := types.NewAppGenesisWithVersion(chainID, appState)
appGenesis.GenesisTime = genTime

View File

@ -76,6 +76,7 @@ func ExportCmd(appExporter v2.AppExporter) *cobra.Command {
appGenesis.AppState = exported.AppState
appGenesis.InitialHeight = exported.Height
appGenesis.Consensus.Validators = exported.Validators
out, err := json.Marshal(appGenesis)
if err != nil {

View File

@ -3,6 +3,8 @@ package v2
import (
"context"
"encoding/json"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// AppExporter is a function that dumps all app state to
@ -20,4 +22,6 @@ type ExportedApp struct {
AppState json.RawMessage
// Height is the app's latest block height.
Height int64
// Validators is the exported validator set.
Validators []sdk.GenesisValidator
}

View File

@ -9,23 +9,12 @@ import (
"cosmossdk.io/x/staking/keeper"
"cosmossdk.io/x/staking/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// TODO: move this to sdk types and use this instead of comet types GenesisValidator
// then we can do pubkey conversion in ToGenesisDoc
//
// this is a temporary work around to avoid import comet directly in staking
type GenesisValidator struct {
Address sdk.ConsAddress
PubKey cryptotypes.PubKey
Power int64
Name string
}
// WriteValidators returns a slice of bonded genesis validators.
func WriteValidators(ctx context.Context, keeper *keeper.Keeper) (vals []GenesisValidator, returnErr error) {
func WriteValidators(ctx context.Context, keeper *keeper.Keeper) (vals []sdk.GenesisValidator, returnErr error) {
err := keeper.LastValidatorPower.Walk(ctx, nil, func(key []byte, _ gogotypes.Int64Value) (bool, error) {
validator, err := keeper.GetValidator(ctx, key)
if err != nil {
@ -37,10 +26,14 @@ func WriteValidators(ctx context.Context, keeper *keeper.Keeper) (vals []Genesis
returnErr = err
return true, err
}
jsonPk, err := cryptocodec.PubKeyFromProto(pk)
if err != nil {
return true, err
}
vals = append(vals, GenesisValidator{
Address: sdk.ConsAddress(pk.Address()),
PubKey: pk,
vals = append(vals, sdk.GenesisValidator{
Address: pk.Address().Bytes(),
PubKey: jsonPk,
Power: validator.GetConsensusPower(keeper.PowerReduction(ctx)),
Name: validator.GetMoniker(),
})