From 8604be960b0565df66a6c4da79371f713ca62798 Mon Sep 17 00:00:00 2001 From: Evan Forbes <42654277+evan-forbes@users.noreply.github.com> Date: Fri, 18 Nov 2022 16:39:46 -0600 Subject: [PATCH] chore!: refactor the testnode to expose the genesis state (#1038) ## Overview We need to be able to modify the genesis state when using the testnode. This PR refactors the testnode to allow for that. It also includes a helper function that handles creation of this genesis state and simplify the process of starting an in process node. closes #1037 part of/blocking #658 spun out of and blocking #1029 ## Checklist - [x] New and updated code has appropriate documentation - [x] New and updated code has new and/or updated testing - [x] Required CI checks are passing - [x] Visual proof for any user facing features like CLI or documentation updates - [x] Linked issues closed with keywords Co-authored-by: Rootul P --- testutil/testnode/full_node.go | 94 +++++++++++++++++++++++++---- testutil/testnode/full_node_test.go | 5 +- testutil/testnode/node_init.go | 21 ------- 3 files changed, 85 insertions(+), 35 deletions(-) diff --git a/testutil/testnode/full_node.go b/testutil/testnode/full_node.go index a19189f1a4..bed9a9042a 100644 --- a/testutil/testnode/full_node.go +++ b/testutil/testnode/full_node.go @@ -1,6 +1,7 @@ package testnode import ( + "encoding/json" "os" "testing" "time" @@ -8,11 +9,14 @@ import ( "github.com/celestiaorg/celestia-app/app" "github.com/celestiaorg/celestia-app/app/encoding" "github.com/celestiaorg/celestia-app/cmd/celestia-appd/cmd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" "github.com/cosmos/cosmos-sdk/server" srvtypes "github.com/cosmos/cosmos-sdk/server/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/libs/log" tmrand "github.com/tendermint/tendermint/libs/rand" @@ -26,12 +30,19 @@ import ( ) // New creates a ready to use tendermint node that operates a single validator -// celestia-app network. The passed account names in fundedAccounts are used to -// generate new private keys, which are included as funded accounts in the -// genesis file. These keys are stored in the keyring that is returned in the -// client.Context. NOTE: the forced delay between blocks, TimeIotaMs in the -// consensus parameters, is set to the lowest possible value (1ms). -func New(t *testing.T, cparams *tmproto.ConsensusParams, tmCfg *config.Config, supressLog bool, fundedAccounts ...string) (*node.Node, srvtypes.Application, Context, error) { +// celestia-app network using the provided genesis state. The provided keyring +// is stored in the client.Context that is returned. +// +// NOTE: the forced delay between blocks, TimeIotaMs in the consensus +// parameters, is set to the lowest possible value (1ms). +func New( + t *testing.T, + cparams *tmproto.ConsensusParams, + tmCfg *config.Config, + supressLog bool, + genState map[string]json.RawMessage, + kr keyring.Keyring, +) (*node.Node, srvtypes.Application, Context, error) { var logger log.Logger if supressLog { logger = log.NewNopLogger() @@ -49,12 +60,6 @@ func New(t *testing.T, cparams *tmproto.ConsensusParams, tmCfg *config.Config, s encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) - genState := app.ModuleBasics.DefaultGenesis(encCfg.Codec) - - fundedAccounts = append(fundedAccounts, "validator") - - kr, bankBals, authAccs := fundKeyringAccounts(encCfg.Codec, fundedAccounts...) - nodeKey, err := p2p.LoadOrGenNodeKey(tmCfg.NodeKeyFile()) if err != nil { return nil, nil, Context{}, err @@ -70,7 +75,7 @@ func New(t *testing.T, cparams *tmproto.ConsensusParams, tmCfg *config.Config, s return nil, nil, Context{}, err } - err = initGenFiles(cparams, genState, encCfg.Codec, authAccs, bankBals, tmCfg.GenesisFile(), chainID) + err = initGenFiles(cparams, genState, encCfg.Codec, tmCfg.GenesisFile(), chainID) if err != nil { return nil, nil, Context{}, err } @@ -135,3 +140,66 @@ func DefaultTendermintConfig() *config.Config { tmCfg.Mempool.MaxTxBytes = 22020096 // 21MB return tmCfg } + +// DefaultGenesisState returns a default genesis state and a keyring with +// accounts that have coins. The keyring accounts are based on the +// fundedAccounts parameter. +func DefaultGenesisState(fundedAccounts ...string) (map[string]json.RawMessage, keyring.Keyring, error) { + encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) + state := app.ModuleBasics.DefaultGenesis(encCfg.Codec) + fundedAccounts = append(fundedAccounts, "validator") + kr, bankBals, authAccs := fundKeyringAccounts(encCfg.Codec, fundedAccounts...) + + // set the accounts in the genesis state + var authGenState authtypes.GenesisState + encCfg.Codec.MustUnmarshalJSON(state[authtypes.ModuleName], &authGenState) + + accounts, err := authtypes.PackAccounts(authAccs) + if err != nil { + return nil, nil, err + } + + authGenState.Accounts = append(authGenState.Accounts, accounts...) + state[authtypes.ModuleName] = encCfg.Codec.MustMarshalJSON(&authGenState) + + // set the balances in the genesis state + var bankGenState banktypes.GenesisState + encCfg.Codec.MustUnmarshalJSON(state[banktypes.ModuleName], &bankGenState) + + bankGenState.Balances = append(bankGenState.Balances, bankBals...) + state[banktypes.ModuleName] = encCfg.Codec.MustMarshalJSON(&bankGenState) + + return state, kr, nil +} + +// DefaultNetwork creates an in-process single validator celestia-app network +// using test friendly defaults. These defaults include fast block times and +// funded accounts. The returned client.Context has a keyring with all of the +// funded keys stored in it. +func DefaultNetwork(t *testing.T, blockTime time.Duration) (cleanup func(), accounts []string, cctx Context) { + // we create an arbitrary number of funded accounts + accounts = make([]string, 300) + for i := 0; i < 300; i++ { + accounts[i] = tmrand.Str(9) + } + + tmCfg := DefaultTendermintConfig() + tmCfg.Consensus.TimeoutCommit = blockTime + + genState, kr, err := DefaultGenesisState(accounts...) + require.NoError(t, err) + + tmNode, app, cctx, err := New(t, DefaultParams(), tmCfg, false, genState, kr) + require.NoError(t, err) + + cctx, stopNode, err := StartNode(tmNode, cctx) + require.NoError(t, err) + + cctx, cleanupGRPC, err := StartGRPCServer(app, DefaultAppConfig(), cctx) + require.NoError(t, err) + + return func() { + stopNode() + cleanupGRPC() + }, accounts, cctx +} diff --git a/testutil/testnode/full_node_test.go b/testutil/testnode/full_node_test.go index 9bc17aa45c..f99af14b08 100644 --- a/testutil/testnode/full_node_test.go +++ b/testutil/testnode/full_node_test.go @@ -36,7 +36,10 @@ func (s *IntegrationTestSuite) SetupSuite() { s.accounts = append(s.accounts, tmrand.Str(9)) } - tmNode, app, cctx, err := New(s.T(), DefaultParams(), DefaultTendermintConfig(), false, s.accounts...) + genState, kr, err := DefaultGenesisState(s.accounts...) + require.NoError(err) + + tmNode, app, cctx, err := New(s.T(), DefaultParams(), DefaultTendermintConfig(), false, genState, kr) require.NoError(err) cctx, stopNode, err := StartNode(tmNode, cctx) diff --git a/testutil/testnode/node_init.go b/testutil/testnode/node_init.go index 921483eaaa..c095803ee4 100644 --- a/testutil/testnode/node_init.go +++ b/testutil/testnode/node_init.go @@ -101,30 +101,9 @@ func initGenFiles( cparams *tmproto.ConsensusParams, state map[string]json.RawMessage, codec codec.Codec, - genAccounts []authtypes.GenesisAccount, - genBalances []banktypes.Balance, file, chainID string, ) error { - // set the accounts in the genesis state - var authGenState authtypes.GenesisState - codec.MustUnmarshalJSON(state[authtypes.ModuleName], &authGenState) - - accounts, err := authtypes.PackAccounts(genAccounts) - if err != nil { - return err - } - - authGenState.Accounts = append(authGenState.Accounts, accounts...) - state[authtypes.ModuleName] = codec.MustMarshalJSON(&authGenState) - - // set the balances in the genesis state - var bankGenState banktypes.GenesisState - codec.MustUnmarshalJSON(state[banktypes.ModuleName], &bankGenState) - - bankGenState.Balances = append(bankGenState.Balances, genBalances...) - state[banktypes.ModuleName] = codec.MustMarshalJSON(&bankGenState) - appGenStateJSON, err := json.MarshalIndent(state, "", " ") if err != nil { return err