feat: add application genesis (#15031)
This commit is contained in:
parent
57653f8e60
commit
832517befc
@ -39,7 +39,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### Features
|
||||
|
||||
* (cli) [#14659](https://github.com/cosmos/cosmos-sdk/pull/14659) Added ability to query blocks by events with queries directly passed to Tendermint, which will allow for full query operator support, e.g. `>`.
|
||||
* (x/genutil) [#15301](https://github.com/cosmos/cosmos-sdk/pull/15031) Add application genesis. The genesis is now entirely managed by the application and passed to CometBFT at note instantiation. Functions that were taking a `cmttypes.GenesisDoc{}` now takes a `genutiltypes.AppGenesis{}`.
|
||||
* (cli) [#14659](https://github.com/cosmos/cosmos-sdk/pull/14659) Added ability to query blocks by events with queries directly passed to Tendermint, which will allow for full query operator support, e.g. `>`.
|
||||
* [#14897](https://github.com/cosmos/cosmos-sdk/pull/14897) Migrate the Cosmos SDK to CometBFT.
|
||||
* (x/gov) [#14720](https://github.com/cosmos/cosmos-sdk/pull/14720) Upstream expedited proposals from Osmosis.
|
||||
* (x/auth) [#14650](https://github.com/cosmos/cosmos-sdk/pull/14650) Add Textual SignModeHandler. It is however **NOT** enabled by default, and should only be used for **TESTING** purposes until `SIGN_MODE_TEXTUAL` is fully released.
|
||||
|
||||
@ -15,4 +15,4 @@ message GenesisState {
|
||||
(amino.field_name) = "gentxs",
|
||||
(amino.dont_omitempty) = true
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -1,16 +1,15 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
cmtjson "github.com/cometbft/cometbft/libs/json"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/server/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -18,7 +17,6 @@ const (
|
||||
FlagForZeroHeight = "for-zero-height"
|
||||
FlagJailAllowedAddrs = "jail-allowed-addrs"
|
||||
FlagModulesToExport = "modules-to-export"
|
||||
FlagOutputDocument = "output-document"
|
||||
)
|
||||
|
||||
// ExportCmd dumps app state to JSON.
|
||||
@ -66,58 +64,36 @@ func ExportCmd(appExporter types.AppExporter, defaultNodeHome string) *cobra.Com
|
||||
forZeroHeight, _ := cmd.Flags().GetBool(FlagForZeroHeight)
|
||||
jailAllowedAddrs, _ := cmd.Flags().GetStringSlice(FlagJailAllowedAddrs)
|
||||
modulesToExport, _ := cmd.Flags().GetStringSlice(FlagModulesToExport)
|
||||
outputDocument, _ := cmd.Flags().GetString(FlagOutputDocument)
|
||||
outputDocument, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
|
||||
|
||||
exported, err := appExporter(serverCtx.Logger, db, traceWriter, height, forZeroHeight, jailAllowedAddrs, serverCtx.Viper, modulesToExport)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error exporting state: %v", err)
|
||||
}
|
||||
|
||||
doc, err := cmttypes.GenesisDocFromFile(serverCtx.Config.GenesisFile())
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(serverCtx.Config.GenesisFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
doc.AppState = exported.AppState
|
||||
doc.Validators = exported.Validators
|
||||
doc.InitialHeight = exported.Height
|
||||
doc.ConsensusParams = &cmttypes.ConsensusParams{
|
||||
Block: cmttypes.BlockParams{
|
||||
MaxBytes: exported.ConsensusParams.Block.MaxBytes,
|
||||
MaxGas: exported.ConsensusParams.Block.MaxGas,
|
||||
},
|
||||
Evidence: cmttypes.EvidenceParams{
|
||||
MaxAgeNumBlocks: exported.ConsensusParams.Evidence.MaxAgeNumBlocks,
|
||||
MaxAgeDuration: exported.ConsensusParams.Evidence.MaxAgeDuration,
|
||||
MaxBytes: exported.ConsensusParams.Evidence.MaxBytes,
|
||||
},
|
||||
Validator: cmttypes.ValidatorParams{
|
||||
PubKeyTypes: exported.ConsensusParams.Validator.PubKeyTypes,
|
||||
},
|
||||
}
|
||||
appGenesis.AppState = exported.AppState
|
||||
appGenesis.InitialHeight = exported.Height
|
||||
appGenesis.Consensus = genutiltypes.NewConsensusGenesis(exported.ConsensusParams, exported.Validators)
|
||||
|
||||
// NOTE: CometBFT uses a custom JSON decoder for GenesisDoc
|
||||
// (except for stuff inside AppState). Inside AppState, we're free
|
||||
// to encode as protobuf or amino.
|
||||
encoded, err := cmtjson.Marshal(doc)
|
||||
out, err := json.Marshal(appGenesis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
cmd.SetErr(cmd.OutOrStderr())
|
||||
out := sdk.MustSortJSON(encoded)
|
||||
|
||||
if outputDocument == "" {
|
||||
cmd.Println(string(out))
|
||||
return nil
|
||||
}
|
||||
|
||||
var exportedGenDoc cmttypes.GenesisDoc
|
||||
if err = cmtjson.Unmarshal(out, &exportedGenDoc); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = exportedGenDoc.SaveAs(outputDocument); err != nil {
|
||||
if err = appGenesis.SaveAs(outputDocument); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -130,7 +106,7 @@ func ExportCmd(appExporter types.AppExporter, defaultNodeHome string) *cobra.Com
|
||||
cmd.Flags().Bool(FlagForZeroHeight, false, "Export state to start at height zero (perform preproccessing)")
|
||||
cmd.Flags().StringSlice(FlagJailAllowedAddrs, []string{}, "Comma-separated list of operator addresses of jailed validators to unjail")
|
||||
cmd.Flags().StringSlice(FlagModulesToExport, []string{}, "Comma-separated list of modules to export. If empty, will export all modules")
|
||||
cmd.Flags().String(FlagOutputDocument, "", "Exported state is written to the given file instead of STDOUT")
|
||||
cmd.Flags().String(flags.FlagOutputDocument, "", "Exported state is written to the given file instead of STDOUT")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import (
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
"github.com/cometbft/cometbft/types"
|
||||
db "github.com/cosmos/cosmos-db"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
@ -19,6 +18,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
// NewApp creates a simple mock kvstore app for testing. It should work
|
||||
@ -116,7 +116,7 @@ func InitChainer(key storetypes.StoreKey) func(sdk.Context, abci.RequestInitChai
|
||||
|
||||
// AppGenState can be passed into InitCmd, returns a static string of a few
|
||||
// key-values that can be parsed by InitChainer
|
||||
func AppGenState(_ *codec.LegacyAmino, _ types.GenesisDoc, _ []json.RawMessage) (appState json.RawMessage, err error) {
|
||||
func AppGenState(_ *codec.LegacyAmino, _ genutiltypes.AppGenesis, _ []json.RawMessage) (appState json.RawMessage, err error) {
|
||||
appState = json.RawMessage(`{
|
||||
"values": [
|
||||
{
|
||||
@ -133,7 +133,7 @@ func AppGenState(_ *codec.LegacyAmino, _ types.GenesisDoc, _ []json.RawMessage)
|
||||
}
|
||||
|
||||
// AppGenStateEmpty returns an empty transaction state for mocking.
|
||||
func AppGenStateEmpty(_ *codec.LegacyAmino, _ types.GenesisDoc, _ []json.RawMessage) (appState json.RawMessage, err error) {
|
||||
func AppGenStateEmpty(_ *codec.LegacyAmino, _ genutiltypes.AppGenesis, _ []json.RawMessage) (appState json.RawMessage, err error) {
|
||||
appState = json.RawMessage(``)
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,10 +7,10 @@ import (
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
"github.com/cometbft/cometbft/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
func TestInitApp(t *testing.T) {
|
||||
@ -21,7 +21,7 @@ func TestInitApp(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
appState, err := AppGenState(nil, types.GenesisDoc{}, nil)
|
||||
appState, err := AppGenState(nil, genutiltypes.AppGenesis{}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
req := abci.RequestInitChain{
|
||||
|
||||
@ -8,12 +8,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/cometbft/cometbft/abci/server"
|
||||
tcmd "github.com/cometbft/cometbft/cmd/cometbft/commands"
|
||||
cmtcmd "github.com/cometbft/cometbft/cmd/cometbft/commands"
|
||||
"github.com/cometbft/cometbft/node"
|
||||
"github.com/cometbft/cometbft/p2p"
|
||||
pvm "github.com/cometbft/cometbft/privval"
|
||||
"github.com/cometbft/cometbft/proxy"
|
||||
"github.com/cometbft/cometbft/rpc/client/local"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"google.golang.org/grpc"
|
||||
@ -30,6 +31,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/server/types"
|
||||
"github.com/cosmos/cosmos-sdk/telemetry"
|
||||
"github.com/cosmos/cosmos-sdk/types/mempool"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -204,7 +206,7 @@ is performed. Note, when enabled, gRPC will also be automatically enabled.
|
||||
})
|
||||
|
||||
// add support for all CometBFT-specific command line options
|
||||
tcmd.AddNodeFlags(cmd)
|
||||
cmtcmd.AddNodeFlags(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -301,7 +303,14 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
genDocProvider := node.DefaultGenesisDocProviderFunc(cfg)
|
||||
genDocProvider := func() (*cmttypes.GenesisDoc, error) {
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(cfg.GenesisFile())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return appGenesis.ToGenesisDoc()
|
||||
}
|
||||
|
||||
var (
|
||||
tmNode *node.Node
|
||||
|
||||
@ -9,15 +9,15 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/math/unsafe"
|
||||
cmtconfig "github.com/cometbft/cometbft/config"
|
||||
"github.com/cometbft/cometbft/types"
|
||||
cmttime "github.com/cometbft/cometbft/types/time"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/math/unsafe"
|
||||
"cosmossdk.io/simapp"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
@ -391,15 +391,10 @@ func initGenFiles(
|
||||
return err
|
||||
}
|
||||
|
||||
genDoc := types.GenesisDoc{
|
||||
ChainID: chainID,
|
||||
AppState: appGenStateJSON,
|
||||
Validators: nil,
|
||||
}
|
||||
|
||||
appGenesis := genutiltypes.NewAppGenesisWithVersion(chainID, appGenStateJSON)
|
||||
// generate empty genesis files for each validator and save
|
||||
for i := 0; i < numValidators; i++ {
|
||||
if err := genDoc.SaveAs(genFiles[i]); err != nil {
|
||||
if err := appGenesis.SaveAs(genFiles[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -425,12 +420,12 @@ func collectGenFiles(
|
||||
nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
|
||||
initCfg := genutiltypes.NewInitConfig(chainID, gentxsDir, nodeID, valPubKey)
|
||||
|
||||
genDoc, err := types.GenesisDocFromFile(nodeConfig.GenesisFile())
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(nodeConfig.GenesisFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeAppState, err := genutil.GenAppStateFromConfig(clientCtx.Codec, clientCtx.TxConfig, nodeConfig, initCfg, *genDoc, genBalIterator, genutiltypes.DefaultMessageValidator)
|
||||
nodeAppState, err := genutil.GenAppStateFromConfig(clientCtx.Codec, clientCtx.TxConfig, nodeConfig, initCfg, appGenesis, genBalIterator, genutiltypes.DefaultMessageValidator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
//go:build e2e
|
||||
// +build e2e
|
||||
|
||||
package genutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestE2ETestSuite(t *testing.T) {
|
||||
cfg := network.DefaultConfig(simapp.NewTestNetworkFixture)
|
||||
cfg.NumValidators = 1
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package genutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
)
|
||||
|
||||
func TestGetMigrationCallback(t *testing.T) {
|
||||
for _, version := range cli.GetMigrationVersions() {
|
||||
require.NotNil(t, cli.GetMigrationCallback(version))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestMigrateGenesis() {
|
||||
val0 := s.network.Validators[0]
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
genesis string
|
||||
target string
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
check func(jsonOut string)
|
||||
}{
|
||||
{
|
||||
"migrate 0.37 to 0.42",
|
||||
v037Exported,
|
||||
"v0.42",
|
||||
true, "Make sure that you have correctly migrated all CometBFT consensus params", func(_ string) {},
|
||||
},
|
||||
{
|
||||
"migrate 0.42 to 0.43",
|
||||
v040Valid,
|
||||
"v0.43",
|
||||
false, "",
|
||||
func(jsonOut string) {
|
||||
// Make sure the json output contains the ADR-037 gov weighted votes.
|
||||
s.Require().Contains(jsonOut, "\"weight\":\"1.000000000000000000\"")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
genesisFile := testutil.WriteToNewTempFile(s.T(), tc.genesis)
|
||||
jsonOutput, err := clitestutil.ExecTestCLICmd(val0.ClientCtx, cli.MigrateGenesisCmd(), []string{tc.target, genesisFile.Name()})
|
||||
if tc.expErr {
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
tc.check(jsonOutput.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,143 +0,0 @@
|
||||
package genutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
stakingcli "github.com/cosmos/cosmos-sdk/x/staking/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
}
|
||||
|
||||
func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
return &E2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e test suite")
|
||||
|
||||
var err error
|
||||
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e test suite")
|
||||
s.network.Cleanup()
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestGenTxCmd() {
|
||||
val := s.network.Validators[0]
|
||||
clientCtx := val.ClientCtx
|
||||
amount := sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(12))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
expError bool
|
||||
}{
|
||||
{
|
||||
name: "invalid commission rate returns error",
|
||||
args: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s=1", stakingcli.FlagCommissionRate),
|
||||
val.Moniker,
|
||||
amount.String(),
|
||||
},
|
||||
expError: true,
|
||||
},
|
||||
{
|
||||
name: "valid gentx",
|
||||
args: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
val.Moniker,
|
||||
amount.String(),
|
||||
},
|
||||
expError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid pubkey",
|
||||
args: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s={\"key\":\"BOIkjkFruMpfOFC9oNPhiJGfmY2pHF/gwHdLDLnrnS0=\"}", stakingcli.FlagPubKey),
|
||||
val.Moniker,
|
||||
amount.String(),
|
||||
},
|
||||
expError: true,
|
||||
},
|
||||
{
|
||||
name: "valid pubkey flag",
|
||||
args: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s={\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"BOIkjkFruMpfOFC9oNPhiJGfmY2pHF/gwHdLDLnrnS0=\"}", stakingcli.FlagPubKey),
|
||||
val.Moniker,
|
||||
amount.String(),
|
||||
},
|
||||
expError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
|
||||
dir := s.T().TempDir()
|
||||
genTxFile := filepath.Join(dir, "myTx")
|
||||
tc.args = append(tc.args, fmt.Sprintf("--%s=%s", flags.FlagOutputDocument, genTxFile))
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
cmd := cli.GenTxCmd(
|
||||
module.NewBasicManager(),
|
||||
val.ClientCtx.TxConfig,
|
||||
banktypes.GenesisBalancesIterator{},
|
||||
val.ClientCtx.HomeDir)
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||
|
||||
if tc.expError {
|
||||
s.Require().Error(err)
|
||||
|
||||
_, err = os.Open(genTxFile)
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(err, "test: %s\noutput: %s", tc.name, out.String())
|
||||
|
||||
// validate generated transaction.
|
||||
open, err := os.Open(genTxFile)
|
||||
s.Require().NoError(err)
|
||||
|
||||
all, err := io.ReadAll(open)
|
||||
s.Require().NoError(err)
|
||||
|
||||
tx, err := val.ClientCtx.TxConfig.TxJSONDecoder()(all)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := tx.GetMsgs()
|
||||
s.Require().Len(msgs, 1)
|
||||
|
||||
s.Require().Equal(sdk.MsgTypeURL(&types.MsgCreateValidator{}), sdk.MsgTypeURL(msgs[0]))
|
||||
s.Require().True(val.Address.Equals(msgs[0].GetSigners()[0]))
|
||||
s.Require().Equal(amount, msgs[0].(*types.MsgCreateValidator).Value)
|
||||
s.Require().NoError(tx.ValidateBasic())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
package genutil
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
)
|
||||
|
||||
// An example exported genesis file from a 0.37 chain. Note that evidence
|
||||
// parameters only contains `max_age`.
|
||||
var v037Exported = `{
|
||||
"app_hash": "",
|
||||
"app_state": {},
|
||||
"chain_id": "test",
|
||||
"consensus_params": {
|
||||
"block": {
|
||||
"max_bytes": "22020096",
|
||||
"max_gas": "-1",
|
||||
"time_iota_ms": "1000"
|
||||
},
|
||||
"evidence": { "max_age": "100000" },
|
||||
"validator": { "pub_key_types": ["ed25519"] }
|
||||
},
|
||||
"genesis_time": "2020-09-29T20:16:29.172362037Z",
|
||||
"validators": []
|
||||
}`
|
||||
|
||||
// An example exported genesis file that's 0.40 compatible.
|
||||
// We added the following app_state:
|
||||
//
|
||||
// - x/gov: added votes to test ADR-037 split votes migration.
|
||||
var v040Valid = `{
|
||||
"app_hash": "",
|
||||
"app_state": {
|
||||
"gov": {
|
||||
"starting_proposal_id": "0",
|
||||
"deposits": [],
|
||||
"votes": [
|
||||
{
|
||||
"proposal_id": "5",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh",
|
||||
"option": "VOTE_OPTION_YES"
|
||||
}
|
||||
],
|
||||
"proposals": [],
|
||||
"deposit_params": { "min_deposit": [], "max_deposit_period": "0s" },
|
||||
"voting_params": { "voting_period": "0s" },
|
||||
"tally_params": { "quorum": "0", "threshold": "0", "veto_threshold": "0" }
|
||||
}
|
||||
},
|
||||
"chain_id": "test",
|
||||
"consensus_params": {
|
||||
"block": {
|
||||
"max_bytes": "22020096",
|
||||
"max_gas": "-1",
|
||||
"time_iota_ms": "1000"
|
||||
},
|
||||
"evidence": {
|
||||
"max_age_num_blocks": "100000",
|
||||
"max_age_duration": "172800000000000",
|
||||
"max_bytes": "0"
|
||||
},
|
||||
"validator": { "pub_key_types": ["ed25519"] }
|
||||
},
|
||||
"genesis_time": "2020-09-29T20:16:29.172362037Z",
|
||||
"validators": []
|
||||
}`
|
||||
|
||||
func (s *E2ETestSuite) TestValidateGenesis() {
|
||||
val0 := s.network.Validators[0]
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
genesis string
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
"exported 0.37 genesis file",
|
||||
v037Exported,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid 0.40 genesis file",
|
||||
v040Valid,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
genesisFile := testutil.WriteToNewTempFile(s.T(), tc.genesis)
|
||||
_, err := clitestutil.ExecTestCLICmd(val0.ClientCtx, cli.ValidateGenesisCmd(nil), []string{genesisFile.Name()})
|
||||
if tc.expErr {
|
||||
s.Require().Contains(err.Error(), "Make sure that you have correctly migrated all CometBFT consensus params")
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -6,23 +6,21 @@ package server_test
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
cmtjson "github.com/cometbft/cometbft/libs/json"
|
||||
cmtlog "github.com/cometbft/cometbft/libs/log"
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
@ -30,31 +28,29 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/server/types"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
func TestExportCmd_ConsensusParams(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
|
||||
_, ctx, _, cmd := setupApp(t, tempDir)
|
||||
|
||||
output := &bytes.Buffer{}
|
||||
cmd.SetOut(output)
|
||||
cmd.SetArgs([]string{fmt.Sprintf("--%s=%s", flags.FlagHome, tempDir)})
|
||||
require.NoError(t, cmd.ExecuteContext(ctx))
|
||||
assert.NilError(t, cmd.ExecuteContext(ctx))
|
||||
|
||||
var exportedGenDoc cmttypes.GenesisDoc
|
||||
err := cmtjson.Unmarshal(output.Bytes(), &exportedGenDoc)
|
||||
if err != nil {
|
||||
t.Fatalf("error unmarshaling exported genesis doc: %s", err)
|
||||
}
|
||||
var exportedAppGenesis genutiltypes.AppGenesis
|
||||
err := json.Unmarshal(output.Bytes(), &exportedAppGenesis)
|
||||
assert.NilError(t, err)
|
||||
|
||||
require.Equal(t, simtestutil.DefaultConsensusParams.Block.MaxBytes, exportedGenDoc.ConsensusParams.Block.MaxBytes)
|
||||
require.Equal(t, simtestutil.DefaultConsensusParams.Block.MaxGas, exportedGenDoc.ConsensusParams.Block.MaxGas)
|
||||
assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Block.MaxBytes, exportedAppGenesis.Consensus.Params.Block.MaxBytes)
|
||||
assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Block.MaxGas, exportedAppGenesis.Consensus.Params.Block.MaxGas)
|
||||
|
||||
require.Equal(t, simtestutil.DefaultConsensusParams.Evidence.MaxAgeDuration, exportedGenDoc.ConsensusParams.Evidence.MaxAgeDuration)
|
||||
require.Equal(t, simtestutil.DefaultConsensusParams.Evidence.MaxAgeNumBlocks, exportedGenDoc.ConsensusParams.Evidence.MaxAgeNumBlocks)
|
||||
assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Evidence.MaxAgeDuration, exportedAppGenesis.Consensus.Params.Evidence.MaxAgeDuration)
|
||||
assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Evidence.MaxAgeNumBlocks, exportedAppGenesis.Consensus.Params.Evidence.MaxAgeNumBlocks)
|
||||
|
||||
require.Equal(t, simtestutil.DefaultConsensusParams.Validator.PubKeyTypes, exportedGenDoc.ConsensusParams.Validator.PubKeyTypes)
|
||||
assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Validator.PubKeyTypes, exportedAppGenesis.Consensus.Params.Validator.PubKeyTypes)
|
||||
}
|
||||
|
||||
func TestExportCmd_HomeDir(t *testing.T) {
|
||||
@ -63,7 +59,7 @@ func TestExportCmd_HomeDir(t *testing.T) {
|
||||
cmd.SetArgs([]string{fmt.Sprintf("--%s=%s", flags.FlagHome, "foobar")})
|
||||
|
||||
err := cmd.ExecuteContext(ctx)
|
||||
require.EqualError(t, err, "stat foobar/config/genesis.json: no such file or directory")
|
||||
assert.ErrorContains(t, err, "stat foobar/config/genesis.json: no such file or directory")
|
||||
}
|
||||
|
||||
func TestExportCmd_Height(t *testing.T) {
|
||||
@ -109,15 +105,12 @@ func TestExportCmd_Height(t *testing.T) {
|
||||
cmd.SetOut(output)
|
||||
args := append(tc.flags, fmt.Sprintf("--%s=%s", flags.FlagHome, tempDir))
|
||||
cmd.SetArgs(args)
|
||||
require.NoError(t, cmd.ExecuteContext(ctx))
|
||||
assert.NilError(t, cmd.ExecuteContext(ctx))
|
||||
|
||||
var exportedGenDoc cmttypes.GenesisDoc
|
||||
err := cmtjson.Unmarshal(output.Bytes(), &exportedGenDoc)
|
||||
if err != nil {
|
||||
t.Fatalf("error unmarshaling exported genesis doc: %s", err)
|
||||
}
|
||||
|
||||
require.Equal(t, tc.expHeight, exportedGenDoc.InitialHeight)
|
||||
var exportedAppGenesis genutiltypes.AppGenesis
|
||||
err := json.Unmarshal(output.Bytes(), &exportedAppGenesis)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, tc.expHeight, exportedAppGenesis.InitialHeight)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -131,7 +124,7 @@ func TestExportCmd_Output(t *testing.T) {
|
||||
{
|
||||
"should export state to the specified file",
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=%s", server.FlagOutputDocument, "foobar.json"),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagOutputDocument, "foobar.json"),
|
||||
},
|
||||
"foobar.json",
|
||||
},
|
||||
@ -146,53 +139,54 @@ func TestExportCmd_Output(t *testing.T) {
|
||||
cmd.SetOut(output)
|
||||
args := append(tc.flags, fmt.Sprintf("--%s=%s", flags.FlagHome, tempDir))
|
||||
cmd.SetArgs(args)
|
||||
require.NoError(t, cmd.ExecuteContext(ctx))
|
||||
assert.NilError(t, cmd.ExecuteContext(ctx))
|
||||
|
||||
var exportedGenDoc cmttypes.GenesisDoc
|
||||
var exportedAppGenesis genutiltypes.AppGenesis
|
||||
f, err := os.ReadFile(tc.outputDocument)
|
||||
if err != nil {
|
||||
t.Fatalf("error reading exported genesis doc: %s", err)
|
||||
}
|
||||
require.NoError(t, cmtjson.Unmarshal(f, &exportedGenDoc))
|
||||
assert.NilError(t, err)
|
||||
assert.NilError(t, json.Unmarshal(f, &exportedAppGenesis))
|
||||
|
||||
// Cleanup
|
||||
if err = os.Remove(tc.outputDocument); err != nil {
|
||||
t.Fatalf("error removing exported genesis doc: %s", err)
|
||||
}
|
||||
assert.NilError(t, os.Remove(tc.outputDocument))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func setupApp(t *testing.T, tempDir string) (*simapp.SimApp, context.Context, *cmttypes.GenesisDoc, *cobra.Command) {
|
||||
func setupApp(t *testing.T, tempDir string) (*simapp.SimApp, context.Context, genutiltypes.AppGenesis, *cobra.Command) {
|
||||
t.Helper()
|
||||
|
||||
if err := createConfigFolder(tempDir); err != nil {
|
||||
t.Fatalf("error creating config folder: %s", err)
|
||||
}
|
||||
err := createConfigFolder(tempDir)
|
||||
assert.NilError(t, err)
|
||||
|
||||
logger := cmtlog.NewTMLogger(cmtlog.NewSyncWriter(os.Stdout))
|
||||
db := dbm.NewMemDB()
|
||||
app := simapp.NewSimApp(logger, db, nil, true, simtestutil.NewAppOptionsWithFlagHome(tempDir))
|
||||
|
||||
genesisState := simapp.GenesisStateWithSingleValidator(t, app)
|
||||
stateBytes, err := cmtjson.MarshalIndent(genesisState, "", " ")
|
||||
require.NoError(t, err)
|
||||
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
||||
assert.NilError(t, err)
|
||||
|
||||
serverCtx := server.NewDefaultContext()
|
||||
serverCtx.Config.RootDir = tempDir
|
||||
|
||||
clientCtx := client.Context{}.WithCodec(app.AppCodec())
|
||||
genDoc := &cmttypes.GenesisDoc{}
|
||||
genDoc.ChainID = "theChainId"
|
||||
genDoc.Validators = nil
|
||||
genDoc.AppState = stateBytes
|
||||
appGenesis := genutiltypes.AppGenesis{
|
||||
ChainID: "theChainId",
|
||||
AppState: stateBytes,
|
||||
Consensus: &genutiltypes.ConsensusGenesis{
|
||||
Validators: nil,
|
||||
},
|
||||
}
|
||||
|
||||
// save genesis file
|
||||
err = genutil.ExportGenesisFile(&appGenesis, serverCtx.Config.GenesisFile())
|
||||
assert.NilError(t, err)
|
||||
|
||||
require.NoError(t, saveGenesisFile(genDoc, serverCtx.Config.GenesisFile()))
|
||||
app.InitChain(
|
||||
abci.RequestInitChain{
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
ConsensusParams: simtestutil.DefaultConsensusParams,
|
||||
AppStateBytes: genDoc.AppState,
|
||||
AppStateBytes: appGenesis.AppState,
|
||||
},
|
||||
)
|
||||
app.Commit()
|
||||
@ -202,7 +196,6 @@ func setupApp(t *testing.T, tempDir string) (*simapp.SimApp, context.Context, *c
|
||||
var simApp *simapp.SimApp
|
||||
if height != -1 {
|
||||
simApp = simapp.NewSimApp(logger, db, nil, false, appOptions)
|
||||
|
||||
if err := simApp.LoadHeight(height); err != nil {
|
||||
return types.ExportedApp{}, err
|
||||
}
|
||||
@ -217,18 +210,9 @@ func setupApp(t *testing.T, tempDir string) (*simapp.SimApp, context.Context, *c
|
||||
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
|
||||
ctx = context.WithValue(ctx, server.ServerContextKey, serverCtx)
|
||||
|
||||
return app, ctx, genDoc, cmd
|
||||
return app, ctx, appGenesis, cmd
|
||||
}
|
||||
|
||||
func createConfigFolder(dir string) error {
|
||||
return os.Mkdir(path.Join(dir, "config"), 0o700)
|
||||
}
|
||||
|
||||
func saveGenesisFile(genDoc *cmttypes.GenesisDoc, dir string) error {
|
||||
err := genutil.ExportGenesisFile(genDoc, dir)
|
||||
if err != nil {
|
||||
return errorsmod.Wrap(err, "error creating file")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ import (
|
||||
pvm "github.com/cometbft/cometbft/privval"
|
||||
"github.com/cometbft/cometbft/proxy"
|
||||
"github.com/cometbft/cometbft/rpc/client/local"
|
||||
"github.com/cometbft/cometbft/types"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
cmttime "github.com/cometbft/cometbft/types/time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/server/api"
|
||||
@ -40,14 +40,21 @@ func startInProcess(cfg Config, val *Validator) error {
|
||||
}
|
||||
|
||||
app := cfg.AppConstructor(*val)
|
||||
genDocProvider := node.DefaultGenesisDocProviderFunc(cmtCfg)
|
||||
appGenesisProvider := func() (*cmttypes.GenesisDoc, error) {
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(cmtCfg.GenesisFile())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return appGenesis.ToGenesisDoc()
|
||||
}
|
||||
|
||||
tmNode, err := node.NewNode( //resleak:notresource
|
||||
cmtCfg,
|
||||
pvm.LoadOrGenFilePV(cmtCfg.PrivValidatorKeyFile(), cmtCfg.PrivValidatorStateFile()),
|
||||
nodeKey,
|
||||
proxy.NewLocalClientCreator(app),
|
||||
genDocProvider,
|
||||
appGenesisProvider,
|
||||
node.DefaultDBProvider,
|
||||
node.DefaultMetricsProvider(cmtCfg.Instrumentation),
|
||||
logger.With("module", val.Moniker),
|
||||
@ -123,13 +130,13 @@ func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error {
|
||||
initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey)
|
||||
|
||||
genFile := cmtCfg.GenesisFile()
|
||||
genDoc, err := types.GenesisDocFromFile(genFile)
|
||||
appGenesis, err := genutiltypes.AppGenesisFromFile(genFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
appState, err := genutil.GenAppStateFromConfig(cfg.Codec, cfg.TxConfig,
|
||||
cmtCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{}, genutiltypes.DefaultMessageValidator)
|
||||
cmtCfg, initCfg, appGenesis, banktypes.GenesisBalancesIterator{}, genutiltypes.DefaultMessageValidator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -168,15 +175,17 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance
|
||||
return err
|
||||
}
|
||||
|
||||
genDoc := types.GenesisDoc{
|
||||
ChainID: cfg.ChainID,
|
||||
AppState: appGenStateJSON,
|
||||
Validators: nil,
|
||||
appGenesis := genutiltypes.AppGenesis{
|
||||
ChainID: cfg.ChainID,
|
||||
AppState: appGenStateJSON,
|
||||
Consensus: &genutiltypes.ConsensusGenesis{
|
||||
Validators: nil,
|
||||
},
|
||||
}
|
||||
|
||||
// generate empty genesis files for each validator and save
|
||||
for i := 0; i < cfg.NumValidators; i++ {
|
||||
if err := genDoc.SaveAs(genFiles[i]); err != nil {
|
||||
if err := appGenesis.SaveAs(genFiles[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/errors"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
)
|
||||
@ -156,7 +156,7 @@ func NewPubKeyFromHex(pk string) (res cryptotypes.PubKey) {
|
||||
panic(err)
|
||||
}
|
||||
if len(pkBytes) != ed25519.PubKeySize {
|
||||
panic(errorsmod.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size"))
|
||||
panic(errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "invalid pubkey size"))
|
||||
}
|
||||
return &ed25519.PubKey{Key: pkBytes}
|
||||
}
|
||||
|
||||
@ -9,8 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
cmtjson "github.com/cometbft/cometbft/libs/json"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
@ -19,6 +17,7 @@ import (
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
@ -211,15 +210,14 @@ func AppStateRandomizedFn(
|
||||
|
||||
// AppStateFromGenesisFileFn util function to generate the genesis AppState
|
||||
// from a genesis.json file.
|
||||
func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (cmttypes.GenesisDoc, []simtypes.Account, error) {
|
||||
func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (genutiltypes.AppGenesis, []simtypes.Account, error) {
|
||||
bytes, err := os.ReadFile(genesisFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var genesis cmttypes.GenesisDoc
|
||||
// NOTE: CometBFT uses a custom JSON decoder for GenesisDoc
|
||||
if err = cmtjson.Unmarshal(bytes, &genesis); err != nil {
|
||||
var genesis genutiltypes.AppGenesis
|
||||
if err = json.Unmarshal(bytes, &genesis); err != nil {
|
||||
return genesis, nil, err
|
||||
}
|
||||
|
||||
|
||||
@ -69,7 +69,7 @@ func AddGenesisAccount(
|
||||
return fmt.Errorf("failed to validate new genesis account: %w", err)
|
||||
}
|
||||
|
||||
appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genesisFileURL)
|
||||
appState, appGenesis, err := genutiltypes.GenesisStateFromGenFile(genesisFileURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal genesis state: %w", err)
|
||||
}
|
||||
@ -132,6 +132,6 @@ func AddGenesisAccount(
|
||||
return fmt.Errorf("failed to marshal application genesis state: %w", err)
|
||||
}
|
||||
|
||||
genDoc.AppState = appStateJSON
|
||||
return genutil.ExportGenesisFile(genDoc, genesisFileURL)
|
||||
appGenesis.AppState = appStateJSON
|
||||
return genutil.ExportGenesisFile(appGenesis, genesisFileURL)
|
||||
}
|
||||
|
||||
60
x/genutil/README.md
Normal file
60
x/genutil/README.md
Normal file
@ -0,0 +1,60 @@
|
||||
# `x/genutil`
|
||||
|
||||
## Concepts
|
||||
|
||||
The `genutil` package contains a variaety of genesis utility functionalities for usage within a blockchain application. Namely:
|
||||
|
||||
* Genesis transactions related (gentx)
|
||||
* Commands for collection and creation of gentxs
|
||||
* `InitChain` processing of gentxs
|
||||
* Genesis file validation
|
||||
* Genesis file migration
|
||||
* CometBFT related initialization
|
||||
* Translation of an app genesis to a CometBFT genesis
|
||||
|
||||
## Client
|
||||
|
||||
### CLI
|
||||
|
||||
The genutil commands are available under the `genesis` subcommand.
|
||||
|
||||
#### add-genesis-account
|
||||
|
||||
Add a genesis account to `genesis.json`. Learn more [here](https://docs.cosmos.network/main/run-node/run-node#adding-genesis-accounts).
|
||||
|
||||
#### collect-gentxs
|
||||
|
||||
Collect genesis txs and output a `genesis.json` file.
|
||||
|
||||
```shell
|
||||
simd genesis collect-gentxs
|
||||
```
|
||||
|
||||
This will create a new `genesis.json` file that includes data from all the validators (we sometimes call it the "super genesis file" to distinguish it from single-validator genesis files).
|
||||
|
||||
#### gentx
|
||||
|
||||
Generate a genesis tx carrying a self delegation.
|
||||
|
||||
```shell
|
||||
simd genesis gentx [key_name] [amount] --chain-id [chain-id]
|
||||
```
|
||||
|
||||
This will create the genesis transaction for your new chain. Here `amount` should be at least `1000000000stake`.
|
||||
If you provide too much or too little, you will encounter an error when starting a node.
|
||||
|
||||
#### migrate
|
||||
|
||||
Migrate genesis to a specified target (SDK) version.
|
||||
|
||||
```shell
|
||||
simd genesis migrate [target-version]
|
||||
```
|
||||
|
||||
#### validate-genesis
|
||||
|
||||
Validates the genesis file at the default location or at the location passed as an argument.
|
||||
|
||||
```shell
|
||||
simd genesis validate-genesis
|
||||
```
|
||||
@ -4,10 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"cosmossdk.io/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
@ -36,7 +35,7 @@ func CollectGenTxsCmd(genBalIterator types.GenesisBalancesIterator, defaultNodeH
|
||||
return errors.Wrap(err, "failed to initialize node validator files")
|
||||
}
|
||||
|
||||
genDoc, err := cmttypes.GenesisDocFromFile(config.GenesisFile())
|
||||
appGenesis, err := types.AppGenesisFromFile(config.GenesisFile())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to read genesis doc from file")
|
||||
}
|
||||
@ -47,12 +46,10 @@ func CollectGenTxsCmd(genBalIterator types.GenesisBalancesIterator, defaultNodeH
|
||||
genTxsDir = filepath.Join(config.RootDir, "config", "gentx")
|
||||
}
|
||||
|
||||
toPrint := newPrintInfo(config.Moniker, genDoc.ChainID, nodeID, genTxsDir, json.RawMessage(""))
|
||||
initCfg := types.NewInitConfig(genDoc.ChainID, genTxsDir, nodeID, valPubKey)
|
||||
toPrint := newPrintInfo(config.Moniker, appGenesis.ChainID, nodeID, genTxsDir, json.RawMessage(""))
|
||||
initCfg := types.NewInitConfig(appGenesis.ChainID, genTxsDir, nodeID, valPubKey)
|
||||
|
||||
appMessage, err := genutil.GenAppStateFromConfig(cdc,
|
||||
clientCtx.TxConfig,
|
||||
config, initCfg, *genDoc, genBalIterator, validator)
|
||||
appMessage, err := genutil.GenAppStateFromConfig(cdc, clientCtx.TxConfig, config, initCfg, appGenesis, genBalIterator, validator)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get genesis app state from config")
|
||||
}
|
||||
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"cosmossdk.io/errors"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
@ -81,13 +80,13 @@ $ %s gentx my-key-name 1000000stake --home=/path/to/home/dir --keyring-backend=o
|
||||
}
|
||||
}
|
||||
|
||||
genDoc, err := cmttypes.GenesisDocFromFile(config.GenesisFile())
|
||||
appGenesis, err := types.AppGenesisFromFile(config.GenesisFile())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read genesis doc file %s", config.GenesisFile())
|
||||
}
|
||||
|
||||
var genesisState map[string]json.RawMessage
|
||||
if err = json.Unmarshal(genDoc.AppState, &genesisState); err != nil {
|
||||
if err = json.Unmarshal(appGenesis.AppState, &genesisState); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal genesis state")
|
||||
}
|
||||
|
||||
@ -109,7 +108,7 @@ $ %s gentx my-key-name 1000000stake --home=/path/to/home/dir --keyring-backend=o
|
||||
}
|
||||
|
||||
// set flags for creating a gentx
|
||||
createValCfg, err := cli.PrepareConfigForTxCreateValidator(cmd.Flags(), moniker, nodeID, genDoc.ChainID, valPubKey)
|
||||
createValCfg, err := cli.PrepareConfigForTxCreateValidator(cmd.Flags(), moniker, nodeID, appGenesis.ChainID, valPubKey)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating configuration to create validator msg")
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ import (
|
||||
"cosmossdk.io/math/unsafe"
|
||||
cfg "github.com/cometbft/cometbft/config"
|
||||
"github.com/cometbft/cometbft/libs/cli"
|
||||
"github.com/cometbft/cometbft/types"
|
||||
"github.com/cosmos/go-bip39"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -22,7 +21,9 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -134,23 +135,27 @@ func InitCmd(mbm module.BasicManager, defaultNodeHome string) *cobra.Command {
|
||||
return errorsmod.Wrap(err, "Failed to marshal default genesis state")
|
||||
}
|
||||
|
||||
genDoc := &types.GenesisDoc{}
|
||||
appGenesis := &types.AppGenesis{}
|
||||
if _, err := os.Stat(genFile); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
genDoc, err = types.GenesisDocFromFile(genFile)
|
||||
appGenesis, err = types.AppGenesisFromFile(genFile)
|
||||
if err != nil {
|
||||
return errorsmod.Wrap(err, "Failed to read genesis doc from file")
|
||||
}
|
||||
}
|
||||
|
||||
genDoc.ChainID = chainID
|
||||
genDoc.Validators = nil
|
||||
genDoc.AppState = appState
|
||||
appGenesis.AppName = version.AppName
|
||||
appGenesis.AppVersion = version.Version
|
||||
appGenesis.ChainID = chainID
|
||||
appGenesis.AppState = appState
|
||||
appGenesis.Consensus = &types.ConsensusGenesis{
|
||||
Validators: nil,
|
||||
}
|
||||
|
||||
if err = genutil.ExportGenesisFile(genDoc, genFile); err != nil {
|
||||
if err = genutil.ExportGenesisFile(appGenesis, genFile); err != nil {
|
||||
return errorsmod.Wrap(err, "Failed to export genesis file")
|
||||
}
|
||||
|
||||
|
||||
@ -193,7 +193,7 @@ func TestEmptyState(t *testing.T) {
|
||||
|
||||
require.Contains(t, out, "genesis_time")
|
||||
require.Contains(t, out, "chain_id")
|
||||
require.Contains(t, out, "consensus_params")
|
||||
require.Contains(t, out, "consensus")
|
||||
require.Contains(t, out, "app_hash")
|
||||
require.Contains(t, out, "app_state")
|
||||
}
|
||||
|
||||
@ -6,14 +6,11 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/errors"
|
||||
cmtjson "github.com/cometbft/cometbft/libs/json"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/maps"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
v043 "github.com/cosmos/cosmos-sdk/x/genutil/migrations/v043"
|
||||
v046 "github.com/cosmos/cosmos-sdk/x/genutil/migrations/v046"
|
||||
@ -64,22 +61,26 @@ $ %s migrate v0.36 /path/to/genesis.json --chain-id=cosmoshub-3 --genesis-time=2
|
||||
target := args[0]
|
||||
importGenesis := args[1]
|
||||
|
||||
genDoc, err := validateGenDoc(importGenesis)
|
||||
appGenesis, err := types.AppGenesisFromFile(importGenesis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := appGenesis.ValidateAndComplete(); err != nil {
|
||||
return fmt.Errorf("make sure that you have correctly migrated all CometBFT consensus params. Refer the UPGRADING.md (%s): %w", chainUpgradeGuide, err)
|
||||
}
|
||||
|
||||
// Since some default values are valid values, we just print to
|
||||
// make sure the user didn't forget to update these values.
|
||||
if genDoc.ConsensusParams.Evidence.MaxBytes == 0 {
|
||||
fmt.Printf("Warning: consensus_params.evidence.max_bytes is set to 0. If this is"+
|
||||
if appGenesis.Consensus.Params.Evidence.MaxBytes == 0 {
|
||||
fmt.Printf("Warning: consensus.params.evidence.max_bytes is set to 0. If this is"+
|
||||
" deliberate, feel free to ignore this warning. If not, please have a look at the chain"+
|
||||
" upgrade guide at %s.\n", chainUpgradeGuide)
|
||||
}
|
||||
|
||||
var initialState types.AppMap
|
||||
if err := json.Unmarshal(genDoc.AppState, &initialState); err != nil {
|
||||
return errors.Wrap(err, "failed to JSON unmarshal initial genesis state")
|
||||
if err := json.Unmarshal(appGenesis.AppState, &initialState); err != nil {
|
||||
return fmt.Errorf("failed to JSON unmarshal initial genesis state: %w", err)
|
||||
}
|
||||
|
||||
migrationFunc := GetMigrationCallback(target)
|
||||
@ -90,9 +91,9 @@ $ %s migrate v0.36 /path/to/genesis.json --chain-id=cosmoshub-3 --genesis-time=2
|
||||
// TODO: handler error from migrationFunc call
|
||||
newGenState := migrationFunc(initialState, clientCtx)
|
||||
|
||||
genDoc.AppState, err = json.Marshal(newGenState)
|
||||
appGenesis.AppState, err = json.Marshal(newGenState)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to JSON marshal migrated genesis state")
|
||||
return fmt.Errorf("failed to JSON marshal migrated genesis state: %w", err)
|
||||
}
|
||||
|
||||
genesisTime, _ := cmd.Flags().GetString(flagGenesisTime)
|
||||
@ -101,34 +102,39 @@ $ %s migrate v0.36 /path/to/genesis.json --chain-id=cosmoshub-3 --genesis-time=2
|
||||
|
||||
err := t.UnmarshalText([]byte(genesisTime))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal genesis time")
|
||||
return fmt.Errorf("failed to unmarshal genesis time: %w", err)
|
||||
}
|
||||
|
||||
genDoc.GenesisTime = t
|
||||
appGenesis.GenesisTime = t
|
||||
}
|
||||
|
||||
chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
|
||||
if chainID != "" {
|
||||
genDoc.ChainID = chainID
|
||||
appGenesis.ChainID = chainID
|
||||
}
|
||||
|
||||
bz, err := cmtjson.Marshal(genDoc)
|
||||
bz, err := json.Marshal(appGenesis)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to marshal genesis doc")
|
||||
return fmt.Errorf("failed to marshal app genesis: %w", err)
|
||||
}
|
||||
|
||||
sortedBz, err := sdk.SortJSON(bz)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to sort JSON genesis doc")
|
||||
outputDocument, _ := cmd.Flags().GetString(flags.FlagOutputDocument)
|
||||
if outputDocument == "" {
|
||||
cmd.Println(string(bz))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = appGenesis.SaveAs(outputDocument); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Println(string(sortedBz))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String(flagGenesisTime, "", "override genesis_time with this flag")
|
||||
cmd.Flags().String(flags.FlagChainID, "", "override chain_id with this flag")
|
||||
cmd.Flags().String(flagGenesisTime, "", "Override genesis_time with this flag")
|
||||
cmd.Flags().String(flags.FlagChainID, "", "Override chain_id with this flag")
|
||||
cmd.Flags().String(flags.FlagOutputDocument, "", "Exported state is written to the given file instead of STDOUT")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
@ -16,7 +18,7 @@ func TestGetMigrationCallback(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CLITestSuite) TestMigrateGenesis() {
|
||||
func TestMigrateGenesis(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
genesis string
|
||||
@ -29,29 +31,41 @@ func (s *CLITestSuite) TestMigrateGenesis() {
|
||||
"migrate 0.37 to 0.42",
|
||||
v037Exported,
|
||||
"v0.42",
|
||||
true, "Make sure that you have correctly migrated all CometBFT consensus params", func(_ string) {},
|
||||
true, "make sure that you have correctly migrated all CometBFT consensus params", func(_ string) {},
|
||||
},
|
||||
{
|
||||
"migrate 0.42 to 0.43",
|
||||
v040Valid,
|
||||
"v0.43",
|
||||
false, "",
|
||||
func(jsonOut string) {
|
||||
// Make sure the json output contains the ADR-037 gov weighted votes.
|
||||
s.Require().Contains(jsonOut, "\"weight\":\"1.000000000000000000\"")
|
||||
},
|
||||
"invalid target version",
|
||||
func() string {
|
||||
bz, err := os.ReadFile("../../types/testdata/app_genesis.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(bz)
|
||||
}(),
|
||||
"v0.10",
|
||||
true, "unknown migration function for version: v0.10", func(_ string) {},
|
||||
},
|
||||
{
|
||||
"invalid target version",
|
||||
func() string {
|
||||
bz, err := os.ReadFile("../../types/testdata/cmt_genesis.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(bz)
|
||||
}(),
|
||||
"v0.10",
|
||||
true, "unknown migration function for version: v0.10", func(_ string) {},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
genesisFile := testutil.WriteToNewTempFile(s.T(), tc.genesis)
|
||||
jsonOutput, err := clitestutil.ExecTestCLICmd(s.clientCtx, cli.MigrateGenesisCmd(), []string{tc.target, genesisFile.Name()})
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
genesisFile := testutil.WriteToNewTempFile(t, tc.genesis)
|
||||
jsonOutput, err := clitestutil.ExecTestCLICmd(client.Context{}, cli.MigrateGenesisCmd(), []string{tc.target, genesisFile.Name()})
|
||||
if tc.expErr {
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
require.Contains(t, err.Error(), tc.expErrMsg)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
require.NoError(t, err)
|
||||
tc.check(jsonOutput.String())
|
||||
}
|
||||
})
|
||||
|
||||
@ -4,12 +4,12 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
const chainUpgradeGuide = "https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md"
|
||||
@ -17,9 +17,10 @@ const chainUpgradeGuide = "https://github.com/cosmos/cosmos-sdk/blob/main/UPGRAD
|
||||
// ValidateGenesisCmd takes a genesis file, and makes sure that it is valid.
|
||||
func ValidateGenesisCmd(mbm module.BasicManager) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "validate-genesis [file]",
|
||||
Args: cobra.RangeArgs(0, 1),
|
||||
Short: "validates the genesis file at the default location or at the location passed as an arg",
|
||||
Use: "validate [file]",
|
||||
Aliases: []string{"validate-genesis"},
|
||||
Args: cobra.RangeArgs(0, 1),
|
||||
Short: "Validates the genesis file at the default location or at the location passed as an arg",
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
serverCtx := server.GetServerContextFromCmd(cmd)
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
@ -34,13 +35,17 @@ func ValidateGenesisCmd(mbm module.BasicManager) *cobra.Command {
|
||||
genesis = args[0]
|
||||
}
|
||||
|
||||
genDoc, err := validateGenDoc(genesis)
|
||||
appGenesis, err := types.AppGenesisFromFile(genesis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := appGenesis.ValidateAndComplete(); err != nil {
|
||||
return fmt.Errorf("make sure that you have correctly migrated all CometBFT consensus params. Refer the UPGRADING.md (%s): %w", chainUpgradeGuide, err)
|
||||
}
|
||||
|
||||
var genState map[string]json.RawMessage
|
||||
if err = json.Unmarshal(genDoc.AppState, &genState); err != nil {
|
||||
if err = json.Unmarshal(appGenesis.AppState, &genState); err != nil {
|
||||
return fmt.Errorf("error unmarshalling genesis doc %s: %s", genesis, err.Error())
|
||||
}
|
||||
|
||||
@ -53,19 +58,3 @@ func ValidateGenesisCmd(mbm module.BasicManager) *cobra.Command {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// validateGenDoc reads a genesis file and validates that it is a correct
|
||||
// CometBFT GenesisDoc. This function does not do any cosmos-related
|
||||
// validation.
|
||||
func validateGenDoc(importGenesisFile string) (*cmttypes.GenesisDoc, error) {
|
||||
genDoc, err := cmttypes.GenesisDocFromFile(importGenesisFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s. Make sure that"+
|
||||
" you have correctly migrated all CometBFT consensus params, please see the"+
|
||||
" chain migration guide at %s for more info",
|
||||
err.Error(), chainUpgradeGuide,
|
||||
)
|
||||
}
|
||||
|
||||
return genDoc, nil
|
||||
}
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// An example exported genesis file from a 0.37 chain. Note that evidence
|
||||
@ -25,48 +30,7 @@ var v037Exported = `{
|
||||
"validators": []
|
||||
}`
|
||||
|
||||
// An example exported genesis file that's 0.40 compatible.
|
||||
// We added the following app_state:
|
||||
//
|
||||
// - x/gov: added votes to test ADR-037 split votes migration.
|
||||
var v040Valid = `{
|
||||
"app_hash": "",
|
||||
"app_state": {
|
||||
"gov": {
|
||||
"starting_proposal_id": "0",
|
||||
"deposits": [],
|
||||
"votes": [
|
||||
{
|
||||
"proposal_id": "5",
|
||||
"voter": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh",
|
||||
"option": "VOTE_OPTION_YES"
|
||||
}
|
||||
],
|
||||
"proposals": [],
|
||||
"deposit_params": { "min_deposit": [], "max_deposit_period": "0s" },
|
||||
"voting_params": { "voting_period": "0s" },
|
||||
"tally_params": { "quorum": "0", "threshold": "0", "veto_threshold": "0" }
|
||||
}
|
||||
},
|
||||
"chain_id": "test",
|
||||
"consensus_params": {
|
||||
"block": {
|
||||
"max_bytes": "22020096",
|
||||
"max_gas": "-1",
|
||||
"time_iota_ms": "1000"
|
||||
},
|
||||
"evidence": {
|
||||
"max_age_num_blocks": "100000",
|
||||
"max_age_duration": "172800000000000",
|
||||
"max_bytes": "0"
|
||||
},
|
||||
"validator": { "pub_key_types": ["ed25519"] }
|
||||
},
|
||||
"genesis_time": "2020-09-29T20:16:29.172362037Z",
|
||||
"validators": []
|
||||
}`
|
||||
|
||||
func (s *CLITestSuite) TestValidateGenesis() {
|
||||
func TestValidateGenesis(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
genesis string
|
||||
@ -78,21 +42,27 @@ func (s *CLITestSuite) TestValidateGenesis() {
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid 0.40 genesis file",
|
||||
v040Valid,
|
||||
"valid 0.48 genesis file",
|
||||
func() string {
|
||||
bz, err := os.ReadFile("../../types/testdata/app_genesis.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(bz)
|
||||
}(),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
genesisFile := testutil.WriteToNewTempFile(s.T(), tc.genesis)
|
||||
_, err := clitestutil.ExecTestCLICmd(s.clientCtx, cli.ValidateGenesisCmd(nil), []string{genesisFile.Name()})
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
genesisFile := testutil.WriteToNewTempFile(t, tc.genesis)
|
||||
_, err := clitestutil.ExecTestCLICmd(client.Context{}, cli.ValidateGenesisCmd(nil), []string{genesisFile.Name()})
|
||||
if tc.expErr {
|
||||
s.Require().Contains(err.Error(), "Make sure that you have correctly migrated all CometBFT consensus params")
|
||||
require.Contains(t, err.Error(), "make sure that you have correctly migrated all CometBFT consensus params")
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ import (
|
||||
"strings"
|
||||
|
||||
cfg "github.com/cometbft/cometbft/config"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
@ -23,12 +22,12 @@ import (
|
||||
|
||||
// GenAppStateFromConfig gets the genesis app state from the config
|
||||
func GenAppStateFromConfig(cdc codec.JSONCodec, txEncodingConfig client.TxEncodingConfig,
|
||||
config *cfg.Config, initCfg types.InitConfig, genDoc cmttypes.GenesisDoc, genBalIterator types.GenesisBalancesIterator,
|
||||
config *cfg.Config, initCfg types.InitConfig, genesis *types.AppGenesis, genBalIterator types.GenesisBalancesIterator,
|
||||
validator types.MessageValidator,
|
||||
) (appState json.RawMessage, err error) {
|
||||
// process genesis transactions, else create default genesis.json
|
||||
appGenTxs, persistentPeers, err := CollectTxs(
|
||||
cdc, txEncodingConfig.TxJSONDecoder(), config.Moniker, initCfg.GenTxsDir, genDoc, genBalIterator, validator)
|
||||
cdc, txEncodingConfig.TxJSONDecoder(), config.Moniker, initCfg.GenTxsDir, genesis, genBalIterator, validator)
|
||||
if err != nil {
|
||||
return appState, err
|
||||
}
|
||||
@ -42,7 +41,7 @@ func GenAppStateFromConfig(cdc codec.JSONCodec, txEncodingConfig client.TxEncodi
|
||||
}
|
||||
|
||||
// create the app state
|
||||
appGenesisState, err := types.GenesisStateFromGenDoc(genDoc)
|
||||
appGenesisState, err := types.GenesisStateFromAppGenesis(genesis)
|
||||
if err != nil {
|
||||
return appState, err
|
||||
}
|
||||
@ -57,8 +56,8 @@ func GenAppStateFromConfig(cdc codec.JSONCodec, txEncodingConfig client.TxEncodi
|
||||
return appState, err
|
||||
}
|
||||
|
||||
genDoc.AppState = appState
|
||||
err = ExportGenesisFile(&genDoc, config.GenesisFile())
|
||||
genesis.AppState = appState
|
||||
err = ExportGenesisFile(genesis, config.GenesisFile())
|
||||
|
||||
return appState, err
|
||||
}
|
||||
@ -66,13 +65,13 @@ func GenAppStateFromConfig(cdc codec.JSONCodec, txEncodingConfig client.TxEncodi
|
||||
// CollectTxs processes and validates application's genesis Txs and returns
|
||||
// the list of appGenTxs, and persistent peers required to generate genesis.json.
|
||||
func CollectTxs(cdc codec.JSONCodec, txJSONDecoder sdk.TxDecoder, moniker, genTxsDir string,
|
||||
genDoc cmttypes.GenesisDoc, genBalIterator types.GenesisBalancesIterator,
|
||||
genesis *types.AppGenesis, genBalIterator types.GenesisBalancesIterator,
|
||||
validator types.MessageValidator,
|
||||
) (appGenTxs []sdk.Tx, persistentPeers string, err error) {
|
||||
// prepare a map of all balances in genesis state to then validate
|
||||
// against the validators addresses
|
||||
var appState map[string]json.RawMessage
|
||||
if err := json.Unmarshal(genDoc.AppState, &appState); err != nil {
|
||||
if err := json.Unmarshal(genesis.AppState, &appState); err != nil {
|
||||
return appGenTxs, persistentPeers, err
|
||||
}
|
||||
|
||||
|
||||
@ -8,15 +8,13 @@ import (
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
bankexported "github.com/cosmos/cosmos-sdk/x/bank/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
gtypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
type doNothingUnmarshalJSON struct {
|
||||
@ -28,7 +26,7 @@ func (dnj *doNothingUnmarshalJSON) UnmarshalJSON(_ []byte, _ proto.Message) erro
|
||||
}
|
||||
|
||||
type doNothingIterator struct {
|
||||
gtypes.GenesisBalancesIterator
|
||||
types.GenesisBalancesIterator
|
||||
}
|
||||
|
||||
func (dni *doNothingIterator) IterateGenesisBalances(_ codec.JSONCodec, _ map[string]json.RawMessage, _ func(bankexported.GenesisBalance) bool) {
|
||||
@ -49,7 +47,7 @@ func TestCollectTxsHandlesDirectories(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
txDecoder := types.TxDecoder(func(txBytes []byte) (types.Tx, error) {
|
||||
txDecoder := sdk.TxDecoder(func(txBytes []byte) (sdk.Tx, error) {
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
@ -57,11 +55,11 @@ func TestCollectTxsHandlesDirectories(t *testing.T) {
|
||||
srvCtx := server.NewDefaultContext()
|
||||
_ = srvCtx
|
||||
cdc := codec.NewProtoCodec(cdctypes.NewInterfaceRegistry())
|
||||
gdoc := cmttypes.GenesisDoc{AppState: []byte("{}")}
|
||||
genesis := &types.AppGenesis{AppState: []byte("{}")}
|
||||
balItr := new(doNothingIterator)
|
||||
|
||||
dnc := &doNothingUnmarshalJSON{cdc}
|
||||
if _, _, err := genutil.CollectTxs(dnc, txDecoder, "foo", testDir, gdoc, balItr, gtypes.DefaultMessageValidator); err != nil {
|
||||
if _, _, err := genutil.CollectTxs(dnc, txDecoder, "foo", testDir, genesis, balItr, types.DefaultMessageValidator); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,10 @@
|
||||
Package genutil contains a variety of genesis utility functionality
|
||||
for usage within a blockchain application. Namely:
|
||||
- Genesis transactions related (gentx)
|
||||
- commands for collection and creation of gentxs
|
||||
- initchain processing of gentxs
|
||||
- Commands for collection and creation of gentxs
|
||||
- `InitChain` processing of gentxs
|
||||
- Genesis file validation
|
||||
- CometBFT related initialization
|
||||
- Genesis file migration
|
||||
- CometBFT related initialization (Translation of an app genesis to a CometBFT genesis)
|
||||
*/
|
||||
package genutil
|
||||
|
||||
211
x/genutil/types/genesis.go
Normal file
211
x/genutil/types/genesis.go
Normal file
@ -0,0 +1,211 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
cmtjson "github.com/cometbft/cometbft/libs/json"
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
cmttime "github.com/cometbft/cometbft/types/time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
)
|
||||
|
||||
const (
|
||||
// MaxChainIDLen is the maximum length of a chain ID.
|
||||
MaxChainIDLen = cmttypes.MaxChainIDLen
|
||||
)
|
||||
|
||||
// AppGenesis defines the app's genesis.
|
||||
type AppGenesis 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 *ConsensusGenesis `json:"consensus,omitempty"`
|
||||
}
|
||||
|
||||
// NewAppGenesisWithVersion returns a new AppGenesis with the app name and app version already.
|
||||
func NewAppGenesisWithVersion(chainID string, appState json.RawMessage) *AppGenesis {
|
||||
return &AppGenesis{
|
||||
AppName: version.AppName,
|
||||
AppVersion: version.Version,
|
||||
ChainID: chainID,
|
||||
AppState: appState,
|
||||
Consensus: &ConsensusGenesis{
|
||||
Validators: nil,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateAndComplete performs validation and completes the AppGenesis.
|
||||
func (ag *AppGenesis) ValidateAndComplete() error {
|
||||
if ag.ChainID == "" {
|
||||
return errors.New("genesis doc must include non-empty chain_id")
|
||||
}
|
||||
|
||||
if len(ag.ChainID) > MaxChainIDLen {
|
||||
return fmt.Errorf("chain_id in genesis doc is too long (max: %d)", MaxChainIDLen)
|
||||
}
|
||||
|
||||
if ag.InitialHeight < 0 {
|
||||
return fmt.Errorf("initial_height cannot be negative (got %v)", ag.InitialHeight)
|
||||
}
|
||||
|
||||
if ag.InitialHeight == 0 {
|
||||
ag.InitialHeight = 1
|
||||
}
|
||||
|
||||
if ag.GenesisTime.IsZero() {
|
||||
ag.GenesisTime = cmttime.Now()
|
||||
}
|
||||
|
||||
if err := ag.Consensus.ValidateAndComplete(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveAs is a utility method for saving AppGenesis as a JSON file.
|
||||
func (ag *AppGenesis) SaveAs(file string) error {
|
||||
appGenesisBytes, err := json.MarshalIndent(ag, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(file, appGenesisBytes, 0o600)
|
||||
}
|
||||
|
||||
// AppGenesisFromFile reads the AppGenesis from the provided file.
|
||||
func AppGenesisFromFile(genFile string) (*AppGenesis, error) {
|
||||
jsonBlob, err := os.ReadFile(genFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't read AppGenesis file (%s): %w", genFile, err)
|
||||
}
|
||||
|
||||
var appGenesis AppGenesis
|
||||
if err := json.Unmarshal(jsonBlob, &appGenesis); err != nil {
|
||||
// fallback to CometBFT genesis
|
||||
var ctmGenesis cmttypes.GenesisDoc
|
||||
if err2 := cmtjson.Unmarshal(jsonBlob, &ctmGenesis); err2 != nil {
|
||||
return nil, fmt.Errorf("error unmarshalling AppGenesis at %s: %w\n failed fallback to CometBFT GenDoc: %w", genFile, err, err2)
|
||||
}
|
||||
|
||||
appGenesis = AppGenesis{
|
||||
GenesisTime: ctmGenesis.GenesisTime,
|
||||
ChainID: ctmGenesis.ChainID,
|
||||
InitialHeight: ctmGenesis.InitialHeight,
|
||||
AppHash: ctmGenesis.AppHash,
|
||||
AppState: ctmGenesis.AppState,
|
||||
Consensus: &ConsensusGenesis{
|
||||
Validators: ctmGenesis.Validators,
|
||||
Params: ctmGenesis.ConsensusParams,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return &appGenesis, nil
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// CometBFT Genesis Handling
|
||||
// --------------------------
|
||||
|
||||
// ToGenesisDoc converts the AppGenesis to a CometBFT GenesisDoc.
|
||||
func (ag *AppGenesis) ToGenesisDoc() (*cmttypes.GenesisDoc, error) {
|
||||
return &cmttypes.GenesisDoc{
|
||||
GenesisTime: ag.GenesisTime,
|
||||
ChainID: ag.ChainID,
|
||||
InitialHeight: ag.InitialHeight,
|
||||
AppHash: ag.AppHash,
|
||||
AppState: ag.AppState,
|
||||
Validators: ag.Consensus.Validators,
|
||||
ConsensusParams: ag.Consensus.Params,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return &ConsensusGenesis{
|
||||
Params: &cmttypes.ConsensusParams{
|
||||
Block: cmttypes.BlockParams{
|
||||
MaxBytes: params.Block.MaxBytes,
|
||||
MaxGas: params.Block.MaxGas,
|
||||
},
|
||||
Evidence: cmttypes.EvidenceParams{
|
||||
MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks,
|
||||
MaxAgeDuration: params.Evidence.MaxAgeDuration,
|
||||
MaxBytes: params.Evidence.MaxBytes,
|
||||
},
|
||||
Validator: cmttypes.ValidatorParams{
|
||||
PubKeyTypes: params.Validator.PubKeyTypes,
|
||||
},
|
||||
},
|
||||
Validators: validators,
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ConsensusGenesis) MarshalJSON() ([]byte, error) {
|
||||
type Alias ConsensusGenesis
|
||||
return cmtjson.Marshal(&Alias{
|
||||
Validators: cs.Validators,
|
||||
Params: cs.Params,
|
||||
})
|
||||
}
|
||||
|
||||
func (cs *ConsensusGenesis) UnmarshalJSON(b []byte) error {
|
||||
type Alias ConsensusGenesis
|
||||
|
||||
result := Alias{}
|
||||
if err := cmtjson.Unmarshal(b, &result); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cs.Params = result.Params
|
||||
cs.Validators = result.Validators
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ConsensusGenesis) ValidateAndComplete() error {
|
||||
if cs == nil {
|
||||
return fmt.Errorf("consensus genesis cannot be nil")
|
||||
}
|
||||
|
||||
if cs.Params == nil {
|
||||
cs.Params = cmttypes.DefaultConsensusParams()
|
||||
} else if err := cs.Params.ValidateBasic(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, v := range cs.Validators {
|
||||
if v.Power == 0 {
|
||||
return fmt.Errorf("the genesis file cannot contain validators with no voting power: %v", v)
|
||||
}
|
||||
if len(v.Address) > 0 && !bytes.Equal(v.PubKey.Address(), v.Address) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -5,8 +5,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
@ -62,12 +60,12 @@ func SetGenesisStateInAppState(
|
||||
return appState
|
||||
}
|
||||
|
||||
// GenesisStateFromGenDoc creates the core parameters for genesis initialization
|
||||
// GenesisStateFromAppGenesis creates the core parameters for genesis initialization
|
||||
// for the application.
|
||||
//
|
||||
// NOTE: The pubkey input is this machines pubkey.
|
||||
func GenesisStateFromGenDoc(genDoc cmttypes.GenesisDoc) (genesisState map[string]json.RawMessage, err error) {
|
||||
if err = json.Unmarshal(genDoc.AppState, &genesisState); err != nil {
|
||||
func GenesisStateFromAppGenesis(gesnsis *AppGenesis) (genesisState map[string]json.RawMessage, err error) {
|
||||
if err = json.Unmarshal(gesnsis.AppState, &genesisState); err != nil {
|
||||
return genesisState, err
|
||||
}
|
||||
return genesisState, nil
|
||||
@ -77,19 +75,18 @@ func GenesisStateFromGenDoc(genDoc cmttypes.GenesisDoc) (genesisState map[string
|
||||
// for the application.
|
||||
//
|
||||
// NOTE: The pubkey input is this machines pubkey.
|
||||
func GenesisStateFromGenFile(genFile string) (genesisState map[string]json.RawMessage, genDoc *cmttypes.GenesisDoc, err error) {
|
||||
func GenesisStateFromGenFile(genFile string) (genesisState map[string]json.RawMessage, genesis *AppGenesis, err error) {
|
||||
if _, err := os.Stat(genFile); os.IsNotExist(err) {
|
||||
return genesisState, genDoc,
|
||||
fmt.Errorf("%s does not exist, run `init` first", genFile)
|
||||
return genesisState, genesis, fmt.Errorf("%s does not exist, run `init` first", genFile)
|
||||
}
|
||||
|
||||
genDoc, err = cmttypes.GenesisDocFromFile(genFile)
|
||||
genesis, err = AppGenesisFromFile(genFile)
|
||||
if err != nil {
|
||||
return genesisState, genDoc, err
|
||||
return genesisState, genesis, err
|
||||
}
|
||||
|
||||
genesisState, err = GenesisStateFromGenDoc(*genDoc)
|
||||
return genesisState, genDoc, err
|
||||
genesisState, err = GenesisStateFromAppGenesis(genesis)
|
||||
return genesisState, genesis, err
|
||||
}
|
||||
|
||||
// ValidateGenesis validates GenTx transactions
|
||||
|
||||
69
x/genutil/types/genesis_test.go
Normal file
69
x/genutil/types/genesis_test.go
Normal file
@ -0,0 +1,69 @@
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/golden"
|
||||
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
func TestAppGenesis_Marshal(t *testing.T) {
|
||||
genesis := types.AppGenesis{
|
||||
AppName: "simapp",
|
||||
AppVersion: "0.1.0",
|
||||
ChainID: "test",
|
||||
}
|
||||
|
||||
out, err := json.Marshal(&genesis)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, string(out), `{"app_name":"simapp","app_version":"0.1.0","genesis_time":"0001-01-01T00:00:00Z","chain_id":"test","initial_height":0,"app_hash":null}`)
|
||||
}
|
||||
|
||||
func TestAppGenesis_Unmarshal(t *testing.T) {
|
||||
jsonBlob, err := os.ReadFile("testdata/app_genesis.json")
|
||||
assert.NilError(t, err)
|
||||
|
||||
var genesis types.AppGenesis
|
||||
err = json.Unmarshal(jsonBlob, &genesis)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.DeepEqual(t, genesis.ChainID, "demo")
|
||||
assert.DeepEqual(t, genesis.Consensus.Params.Block.MaxBytes, int64(22020096))
|
||||
}
|
||||
|
||||
func TestAppGenesis_ValidGenesis(t *testing.T) {
|
||||
// validate can read cometbft genesis file
|
||||
genesis, err := types.AppGenesisFromFile("testdata/cmt_genesis.json")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.DeepEqual(t, genesis.ChainID, "demo")
|
||||
assert.DeepEqual(t, genesis.Consensus.Validators[0].Name, "test")
|
||||
|
||||
// validate the app genesis can be translated properly to cometbft genesis
|
||||
cmtGenesis, err := genesis.ToGenesisDoc()
|
||||
assert.NilError(t, err)
|
||||
rawCmtGenesis, err := cmttypes.GenesisDocFromFile("testdata/cmt_genesis.json")
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, cmtGenesis, rawCmtGenesis)
|
||||
|
||||
// validate can properly marshal to app genesis file
|
||||
rawAppGenesis, err := json.Marshal(&genesis)
|
||||
assert.NilError(t, err)
|
||||
golden.Assert(t, string(rawAppGenesis), "app_genesis.json")
|
||||
|
||||
// validate the app genesis can be unmarshalled properly
|
||||
var appGenesis types.AppGenesis
|
||||
err = json.Unmarshal(rawAppGenesis, &appGenesis)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, appGenesis.Consensus.Params, genesis.Consensus.Params)
|
||||
|
||||
// validate marshalling of app genesis
|
||||
rawAppGenesis, err = json.Marshal(&appGenesis)
|
||||
assert.NilError(t, err)
|
||||
golden.Assert(t, string(rawAppGenesis), "app_genesis.json")
|
||||
}
|
||||
1
x/genutil/types/testdata/app_genesis.json
vendored
Normal file
1
x/genutil/types/testdata/app_genesis.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
x/genutil/types/testdata/cmt_genesis.json
vendored
Normal file
1
x/genutil/types/testdata/cmt_genesis.json
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -16,36 +16,31 @@ import (
|
||||
|
||||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
// ExportGenesisFile creates and writes the genesis configuration to disk. An
|
||||
// error is returned if building or writing the configuration to file fails.
|
||||
func ExportGenesisFile(genDoc *cmttypes.GenesisDoc, genFile string) error {
|
||||
if err := genDoc.ValidateAndComplete(); err != nil {
|
||||
func ExportGenesisFile(genesis *types.AppGenesis, genFile string) error {
|
||||
if err := genesis.ValidateAndComplete(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return genDoc.SaveAs(genFile)
|
||||
return genesis.SaveAs(genFile)
|
||||
}
|
||||
|
||||
// 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,
|
||||
) error {
|
||||
genDoc := cmttypes.GenesisDoc{
|
||||
GenesisTime: genTime,
|
||||
ChainID: chainID,
|
||||
Validators: validators,
|
||||
AppState: appState,
|
||||
}
|
||||
func ExportGenesisFileWithTime(genFile, chainID string, validators []cmttypes.GenesisValidator, appState json.RawMessage, genTime time.Time) error {
|
||||
appGenesis := types.NewAppGenesisWithVersion(chainID, appState)
|
||||
appGenesis.GenesisTime = genTime
|
||||
appGenesis.Consensus.Validators = validators
|
||||
|
||||
if err := genDoc.ValidateAndComplete(); err != nil {
|
||||
if err := appGenesis.ValidateAndComplete(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return genDoc.SaveAs(genFile)
|
||||
return appGenesis.SaveAs(genFile)
|
||||
}
|
||||
|
||||
// InitializeNodeValidatorFiles creates private validator and p2p configuration files.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user