From f1599fde600d0e0a926e7253dc6e11dac045c30c Mon Sep 17 00:00:00 2001 From: Evan Forbes <42654277+evan-forbes@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:57:18 -0500 Subject: [PATCH] chore: rebase and cherry pick again --- app/test/block_production_test.go | 2 +- app/test/integration_test.go | 8 +- app/test/max_total_blob_size_test.go | 2 +- app/test/prepare_proposal_context_test.go | 2 +- app/test/priority_test.go | 7 +- app/test/qgb_rpc_test.go | 6 +- app/test/square_size_test.go | 5 +- app/test/std_sdk_test.go | 16 +- test/cmd/txsim/cli_test.go | 6 +- test/txsim/run_test.go | 9 +- test/util/genesis/accounts.go | 139 ++++++++++++++ test/util/genesis/document.go | 115 ++++++++++++ test/util/genesis/files.go | 69 +++++++ test/util/genesis/genesis.go | 212 ++++++++++++++++++++++ test/util/genesis/modifier.go | 89 +++++++++ test/util/genesis/util.go | 23 +++ test/util/malicious/app_test.go | 2 +- test/util/test_app.go | 4 +- test/util/testnode/config.go | 100 +++++----- test/util/testnode/full_node.go | 106 +---------- test/util/testnode/full_node_test.go | 10 +- test/util/testnode/genesis_options.go | 43 ----- test/util/testnode/node_init.go | 189 ------------------- x/qgb/integration_test.go | 2 +- x/upgrade/test/integration_test.go | 6 +- 25 files changed, 767 insertions(+), 405 deletions(-) create mode 100644 test/util/genesis/accounts.go create mode 100644 test/util/genesis/document.go create mode 100644 test/util/genesis/files.go create mode 100644 test/util/genesis/genesis.go create mode 100644 test/util/genesis/modifier.go create mode 100644 test/util/genesis/util.go delete mode 100644 test/util/testnode/genesis_options.go delete mode 100644 test/util/testnode/node_init.go diff --git a/app/test/block_production_test.go b/app/test/block_production_test.go index 11674b3e95..f8bfb5435a 100644 --- a/app/test/block_production_test.go +++ b/app/test/block_production_test.go @@ -36,7 +36,7 @@ func (s *BlockProductionTestSuite) SetupSuite() { } cfg := testnode.DefaultConfig(). - WithAccounts(accounts). + WithFundedAccounts(accounts...). WithTimeoutCommit(s.timeoutCommit) cctx, _, _ := testnode.NewNetwork(t, cfg) diff --git a/app/test/integration_test.go b/app/test/integration_test.go index dabaafaeb0..b2422040d2 100644 --- a/app/test/integration_test.go +++ b/app/test/integration_test.go @@ -59,7 +59,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.accounts[i] = tmrand.Str(20) } - cfg := testnode.DefaultConfig().WithAccounts(s.accounts) + cfg := testnode.DefaultConfig().WithFundedAccounts(s.accounts...) cctx, _, _ := testnode.NewNetwork(t, cfg) @@ -250,9 +250,9 @@ func (s *IntegrationTestSuite) TestSubmitPayForBlob() { { "medium random with timeout height", mustNewBlob(ns1, tmrand.Bytes(100000), appconsts.ShareVersionZero), - []blobtypes.TxBuilderOption{ - blobtypes.SetTimeoutHeight(1000), - blobtypes.SetGasLimit(1_000_000_000), + []user.TxOption{ + user.SetTimeoutHeight(10000), + user.SetGasLimit(1_000_000_000), }, }, } diff --git a/app/test/max_total_blob_size_test.go b/app/test/max_total_blob_size_test.go index f497f364ae..9d7f481c3d 100644 --- a/app/test/max_total_blob_size_test.go +++ b/app/test/max_total_blob_size_test.go @@ -53,7 +53,7 @@ func (s *MaxTotalBlobSizeSuite) SetupSuite() { cParams.Block.MaxBytes = 10 * mebibyte cfg := testnode.DefaultConfig(). - WithAccounts(s.accounts). + WithFundedAccounts(s.accounts...). WithTendermintConfig(tmConfig). WithConsensusParams(cParams) diff --git a/app/test/prepare_proposal_context_test.go b/app/test/prepare_proposal_context_test.go index fd6e6e27b8..ff52880fa6 100644 --- a/app/test/prepare_proposal_context_test.go +++ b/app/test/prepare_proposal_context_test.go @@ -33,7 +33,7 @@ func TestTimeInPrepareProposalContext(t *testing.T) { for i := 0; i < len(accounts); i++ { accounts[i] = tmrand.Str(9) } - cfg := testnode.DefaultConfig().WithAccounts(accounts) + cfg := testnode.DefaultConfig().WithFundedAccounts(accounts...) cctx, _, _ := testnode.NewNetwork(t, cfg) ecfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) vestAccName := "vesting" diff --git a/app/test/priority_test.go b/app/test/priority_test.go index 87639ef180..3d6ac1f171 100644 --- a/app/test/priority_test.go +++ b/app/test/priority_test.go @@ -44,7 +44,8 @@ func (s *PriorityTestSuite) SetupSuite() { t := s.T() cfg := testnode.DefaultConfig(). - WithAccounts(testfactory.GenerateAccounts(10)). + WithFundedAccounts(testfactory.GenerateAccounts(10)...). + // use a long block time to guarantee that some transactions are included in the same block WithTimeoutCommit(time.Second) cctx, _, _ := testnode.NewNetwork(t, cfg) @@ -54,8 +55,8 @@ func (s *PriorityTestSuite) SetupSuite() { require.NoError(t, cctx.WaitForNextBlock()) - for _, acc := range cfg.Accounts { - addr := testfactory.GetAddress(s.cctx.Keyring, acc) + for _, acc := range cfg.Genesis.Accounts() { + addr := testfactory.GetAddress(s.cctx.Keyring, acc.Name) signer, err := user.SetupSigner(s.cctx.GoContext(), s.cctx.Keyring, s.cctx.GRPCClient, addr, s.ecfg) signer.SetPollTime(time.Millisecond * 300) require.NoError(t, err) diff --git a/app/test/qgb_rpc_test.go b/app/test/qgb_rpc_test.go index 62e4395be2..aca37baeaf 100644 --- a/app/test/qgb_rpc_test.go +++ b/app/test/qgb_rpc_test.go @@ -5,6 +5,9 @@ import ( "testing" "time" + "github.com/celestiaorg/celestia-app/app" + "github.com/celestiaorg/celestia-app/app/encoding" + "github.com/celestiaorg/celestia-app/test/util/genesis" "github.com/celestiaorg/celestia-app/test/util/testnode" "github.com/celestiaorg/celestia-app/x/qgb/types" "github.com/stretchr/testify/assert" @@ -15,7 +18,8 @@ func TestQGBRPCQueries(t *testing.T) { if testing.Short() { t.Skip("skipping QGB integration test in short mode.") } - cfg := testnode.DefaultConfig() + ecfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) + cfg := testnode.DefaultConfig().WithModifiers(genesis.SetDataCommitmentWindow(ecfg.Codec, 100)) cctx, _, _ := testnode.NewNetwork(t, cfg) diff --git a/app/test/square_size_test.go b/app/test/square_size_test.go index 21a8c6d64e..18999da33e 100644 --- a/app/test/square_size_test.go +++ b/app/test/square_size_test.go @@ -10,6 +10,9 @@ import ( "github.com/celestiaorg/celestia-app/app/encoding" "github.com/celestiaorg/celestia-app/pkg/appconsts" "github.com/celestiaorg/celestia-app/test/txsim" + "github.com/celestiaorg/celestia-app/test/util/blobfactory" + "github.com/celestiaorg/celestia-app/test/util/genesis" + "github.com/celestiaorg/celestia-app/test/util/testfactory" "github.com/celestiaorg/celestia-app/test/util/testnode" blobtypes "github.com/celestiaorg/celestia-app/x/blob/types" "github.com/cosmos/cosmos-sdk/baseapp" @@ -44,7 +47,7 @@ func (s *SquareSizeIntegrationTest) SetupSuite() { t.Log("setting up square size integration test") s.ecfg = encoding.MakeConfig(app.ModuleEncodingRegisters...) cfg := testnode.DefaultConfig(). - WithGenesisOptions(testnode.ImmediateProposals(s.ecfg.Codec)) + WithModifiers(genesis.ImmediateProposals(s.ecfg.Codec)) cctx, rpcAddr, grpcAddr := testnode.NewNetwork(t, cfg) diff --git a/app/test/std_sdk_test.go b/app/test/std_sdk_test.go index ca85e9ced2..e1041278ab 100644 --- a/app/test/std_sdk_test.go +++ b/app/test/std_sdk_test.go @@ -48,14 +48,14 @@ func (s *StandardSDKIntegrationTestSuite) SetupSuite() { t := s.T() t.Log("setting up integration test suite") - accounts := make([]string, 300) + accounts := make([]string, 35) for i := 0; i < len(accounts); i++ { accounts[i] = tmrand.Str(9) } - cfg := testnode.DefaultConfig().WithAccounts(accounts) + cfg := testnode.DefaultConfig().WithFundedAccounts(accounts...) cctx, _, _ := testnode.NewNetwork(t, cfg) - s.accounts = cfg.Accounts + s.accounts = accounts s.ecfg = encoding.MakeConfig(app.ModuleEncodingRegisters...) s.cctx = cctx } @@ -106,7 +106,7 @@ func (s *StandardSDKIntegrationTestSuite) TestStandardSDK() { { name: "delegate 1 TIA", msgFunc: func() (msgs []sdk.Msg, signer string) { - valopAddr := sdk.ValAddress(getAddress("validator", s.cctx.Keyring)) + valopAddr := sdk.ValAddress(testfactory.GetAddress(s.cctx.Keyring, testnode.DefaultValidatorAccountName)) account1 := s.unusedAccount() account1Addr := getAddress(account1, s.cctx.Keyring) msg := stakingtypes.NewMsgDelegate(account1Addr, valopAddr, sdk.NewCoin(app.BondDenom, sdk.NewInt(1000000))) @@ -117,10 +117,10 @@ func (s *StandardSDKIntegrationTestSuite) TestStandardSDK() { { name: "undelegate 1 TIA", msgFunc: func() (msgs []sdk.Msg, signer string) { - valAccAddr := getAddress("validator", s.cctx.Keyring) + valAccAddr := testfactory.GetAddress(s.cctx.Keyring, testnode.DefaultValidatorAccountName) valopAddr := sdk.ValAddress(valAccAddr) msg := stakingtypes.NewMsgUndelegate(valAccAddr, valopAddr, sdk.NewCoin(app.BondDenom, sdk.NewInt(1000000))) - return []sdk.Msg{msg}, "validator" + return []sdk.Msg{msg}, testnode.DefaultValidatorAccountName }, expectedCode: abci.CodeTypeOK, }, @@ -134,10 +134,10 @@ func (s *StandardSDKIntegrationTestSuite) TestStandardSDK() { msg, err := stakingtypes.NewMsgCreateValidator( valopAddr, pv.PrivKey.PubKey(), - sdk.NewCoin(app.BondDenom, sdk.NewInt(1000000)), + sdk.NewCoin(app.BondDenom, sdk.NewInt(1)), stakingtypes.NewDescription("taco tuesday", "my keybase", "www.celestia.org", "ping @celestiaorg on twitter", "fake validator"), stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(6, 0o2), sdk.NewDecWithPrec(12, 0o2), sdk.NewDecWithPrec(1, 0o2)), - sdk.NewInt(1000000), + sdk.NewInt(1), ) require.NoError(t, err) return []sdk.Msg{msg}, account diff --git a/test/cmd/txsim/cli_test.go b/test/cmd/txsim/cli_test.go index 2654c5f84a..0f2f692995 100644 --- a/test/cmd/txsim/cli_test.go +++ b/test/cmd/txsim/cli_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/celestiaorg/celestia-app/pkg/appconsts" + "github.com/celestiaorg/celestia-app/test/util/genesis" "github.com/celestiaorg/celestia-app/test/util/testfactory" "github.com/celestiaorg/celestia-app/test/util/testnode" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -62,7 +63,10 @@ func setup(t testing.TB) (keyring.Keyring, string, string) { cfg := testnode.DefaultConfig(). WithConsensusParams(cparams). - WithAccounts([]string{testfactory.TestAccName}) + WithFundedAccounts(testfactory.TestAccName). + WithModifiers( + genesis.FundAccounts(cdc, []sdk.AccAddress{testnode.TestAddress()}, sdk.NewCoin(app.BondDenom, sdk.NewIntFromUint64(1e15))), + ) cctx, rpcAddr, grpcAddr := testnode.NewNetwork(t, cfg) diff --git a/test/txsim/run_test.go b/test/txsim/run_test.go index b56a57f358..d05c28e669 100644 --- a/test/txsim/run_test.go +++ b/test/txsim/run_test.go @@ -100,6 +100,13 @@ func TestTxSimulator(t *testing.T) { keyring, rpcAddr, grpcAddr := Setup(t) + opts := txsim.DefaultOptions(). + SuppressLogs(). + WithPollTime(time.Millisecond * 100) + if tc.useFeegrant { + opts.UseFeeGrant() + } + err := txsim.Run( ctx, []string{rpcAddr}, @@ -137,7 +144,7 @@ func TestTxSimulator(t *testing.T) { func Setup(t testing.TB) (keyring.Keyring, string, string) { t.Helper() - cfg := testnode.DefaultConfig() + cfg := testnode.DefaultConfig().WithTimeoutCommit(300 * time.Millisecond).WithFundedAccounts("txsim-master") cctx, rpcAddr, grpcAddr := testnode.NewNetwork(t, cfg) diff --git a/test/util/genesis/accounts.go b/test/util/genesis/accounts.go new file mode 100644 index 0000000000..6605949443 --- /dev/null +++ b/test/util/genesis/accounts.go @@ -0,0 +1,139 @@ +package genesis + +import ( + "fmt" + mrand "math/rand" + "time" + + "github.com/celestiaorg/celestia-app/app" + "github.com/celestiaorg/celestia-app/app/encoding" + "github.com/cosmos/cosmos-sdk/client/tx" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/tendermint/tendermint/crypto" +) + +type Account struct { + Name string + InitialTokens int64 +} + +func NewAccounts(initBal int64, names ...string) []Account { + accounts := make([]Account, len(names)) + for i, name := range names { + accounts[i] = Account{ + Name: name, + InitialTokens: initBal, + } + } + return accounts +} + +func (ga *Account) ValidateBasic() error { + if ga.Name == "" { + return fmt.Errorf("name cannot be empty") + } + if ga.InitialTokens <= 0 { + return fmt.Errorf("initial tokens must be positive") + } + return nil +} + +type Validator struct { + Account + Stake int64 + + // ConsensusKey is the key used by the validator to sign votes. + ConsensusKey crypto.PrivKey + NetworkKey crypto.PrivKey +} + +func NewDefaultValidator(name string) Validator { + r := mrand.New(mrand.NewSource(time.Now().UnixNano())) + return Validator{ + Account: Account{ + Name: name, + InitialTokens: 999_999_999_999_999_999, + }, + Stake: 99_999_999_999_999_999, // save some tokens for fees + ConsensusKey: GenerateEd25519(NewSeed(r)), + NetworkKey: GenerateEd25519(NewSeed(r)), + } +} + +// ValidateBasic performs stateless validation on the validitor +func (v *Validator) ValidateBasic() error { + if err := v.Account.ValidateBasic(); err != nil { + return err + } + if v.Stake <= 0 { + return fmt.Errorf("stake must be positive") + } + if v.ConsensusKey == nil { + return fmt.Errorf("consensus key cannot be empty") + } + if v.Stake > v.InitialTokens { + return fmt.Errorf("stake cannot be greater than initial tokens") + } + return nil +} + +// GenTx generates a genesis transaction to create a validator as configured by +// the validator struct. It assumes the validator's genesis account has already +// been added to the keyring and that the sequence for that account is 0. +func (v *Validator) GenTx(ecfg encoding.Config, kr keyring.Keyring, chainID string) (sdk.Tx, error) { + rec, err := kr.Key(v.Name) + if err != nil { + return nil, err + } + addr, err := rec.GetAddress() + if err != nil { + return nil, err + } + + commission, err := sdk.NewDecFromStr("0.5") + if err != nil { + return nil, err + } + + pk, err := cryptocodec.FromTmPubKeyInterface(v.ConsensusKey.PubKey()) + if err != nil { + return nil, fmt.Errorf("converting public key for node %s: %w", v.Name, err) + } + + createValMsg, err := stakingtypes.NewMsgCreateValidator( + sdk.ValAddress(addr), + pk, + sdk.NewCoin(app.BondDenom, sdk.NewInt(v.Stake)), + stakingtypes.NewDescription(v.Name, "", "", "", ""), + stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()), + sdk.NewInt(v.Stake/2), + ) + if err != nil { + return nil, err + } + + fee := sdk.NewCoins(sdk.NewCoin(app.BondDenom, sdk.NewInt(1))) + txBuilder := ecfg.TxConfig.NewTxBuilder() + err = txBuilder.SetMsgs(createValMsg) + if err != nil { + return nil, err + } + txBuilder.SetFeeAmount(fee) // Arbitrary fee + txBuilder.SetGasLimit(1000000) // Need at least 100386 + + txFactory := tx.Factory{} + txFactory = txFactory. + WithChainID(chainID). + WithKeybase(kr). + WithTxConfig(ecfg.TxConfig) + + err = tx.Sign(txFactory, v.Name, txBuilder, true) + if err != nil { + return nil, err + } + + return txBuilder.GetTx(), nil +} diff --git a/test/util/genesis/document.go b/test/util/genesis/document.go new file mode 100644 index 0000000000..4c18840dc1 --- /dev/null +++ b/test/util/genesis/document.go @@ -0,0 +1,115 @@ +package genesis + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/celestiaorg/celestia-app/app" + "github.com/celestiaorg/celestia-app/app/encoding" + "github.com/celestiaorg/celestia-app/pkg/appconsts" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + 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" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + coretypes "github.com/tendermint/tendermint/types" +) + +// Document will create a valid genesis doc with funded addresses. +func Document( + ecfg encoding.Config, + params *tmproto.ConsensusParams, + chainID string, + gentxs []json.RawMessage, + addrs []string, + pubkeys []cryptotypes.PubKey, + mods ...Modifier, +) (*coretypes.GenesisDoc, error) { + genutilGenState := genutiltypes.DefaultGenesisState() + genutilGenState.GenTxs = gentxs + + genBals, genAccs, err := accountsToSDKTypes(addrs, pubkeys) + if err != nil { + return nil, err + } + + accounts, err := authtypes.PackAccounts(genAccs) + if err != nil { + return nil, err + } + + authGenState := authtypes.DefaultGenesisState() + bankGenState := banktypes.DefaultGenesisState() + authGenState.Accounts = append(authGenState.Accounts, accounts...) + bankGenState.Balances = append(bankGenState.Balances, genBals...) + bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) + + // perform some basic validation of the genesis state + if err := authtypes.ValidateGenesis(*authGenState); err != nil { + return nil, err + } + if err := bankGenState.Validate(); err != nil { + return nil, err + } + if err := genutiltypes.ValidateGenesis(genutilGenState, ecfg.TxConfig.TxJSONDecoder()); err != nil { + return nil, err + } + + state := app.ModuleBasics.DefaultGenesis(ecfg.Codec) + state[authtypes.ModuleName] = ecfg.Codec.MustMarshalJSON(authGenState) + state[banktypes.ModuleName] = ecfg.Codec.MustMarshalJSON(bankGenState) + state[genutiltypes.ModuleName] = ecfg.Codec.MustMarshalJSON(genutilGenState) + + for _, modifer := range mods { + state = modifer(state) + } + + stateBz, err := json.MarshalIndent(state, "", " ") + if err != nil { + return nil, err + } + + // Create the genesis doc + genesisDoc := &coretypes.GenesisDoc{ + ChainID: chainID, + GenesisTime: time.Now(), + ConsensusParams: params, + AppState: stateBz, + } + + return genesisDoc, nil +} + +// accountsToSDKTypes converts the genesis accounts to native SDK types. +func accountsToSDKTypes(addrs []string, pubkeys []cryptotypes.PubKey) ([]banktypes.Balance, []authtypes.GenesisAccount, error) { + if len(addrs) != len(pubkeys) { + return nil, nil, fmt.Errorf("length of addresses and public keys are not equal") + } + genBals := make([]banktypes.Balance, len(addrs)) + genAccs := make([]authtypes.GenesisAccount, len(addrs)) + hasMap := make(map[string]bool) + for i, addr := range addrs { + if hasMap[addr] { + return nil, nil, fmt.Errorf("duplicate account address %s", addr) + } + hasMap[addr] = true + + pubKey := pubkeys[i] + + balances := sdk.NewCoins( + sdk.NewCoin(appconsts.BondDenom, sdk.NewInt(999_999_999_999_999_999)), + ) + + genBals[i] = banktypes.Balance{Address: addr, Coins: balances.Sort()} + + parsedAddress, err := sdk.AccAddressFromBech32(addr) + if err != nil { + return nil, nil, err + } + + genAccs[i] = authtypes.NewBaseAccount(parsedAddress, pubKey, uint64(i), 0) + } + return genBals, genAccs, nil +} diff --git a/test/util/genesis/files.go b/test/util/genesis/files.go new file mode 100644 index 0000000000..3272b46537 --- /dev/null +++ b/test/util/genesis/files.go @@ -0,0 +1,69 @@ +package genesis + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/tendermint/tendermint/config" + tmos "github.com/tendermint/tendermint/libs/os" + "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/privval" +) + +// InitFiles initializes the files for a new tendermint node with the provided +// genesis. It will use the validatorIndex to save the validator's consensus +// key. +func InitFiles( + dir string, + tmCfg *config.Config, + g *Genesis, + validatorIndex int, +) (string, error) { + val, has := g.Validator(validatorIndex) + if !has { + return "", fmt.Errorf("validator %d not found", validatorIndex) + } + + basePath := filepath.Join(dir, ".celestia-app") + tmCfg.SetRoot(basePath) + + // save the genesis file + configPath := filepath.Join(basePath, "config") + err := os.MkdirAll(configPath, os.ModePerm) + if err != nil { + return "", err + } + gDoc, err := g.Export() + if err != nil { + return "", err + } + err = gDoc.SaveAs(tmCfg.GenesisFile()) + if err != nil { + return "", err + } + + pvStateFile := tmCfg.PrivValidatorStateFile() + if err := tmos.EnsureDir(filepath.Dir(pvStateFile), 0o777); err != nil { + return "", err + } + pvKeyFile := tmCfg.PrivValidatorKeyFile() + if err := tmos.EnsureDir(filepath.Dir(pvKeyFile), 0o777); err != nil { + return "", err + } + filePV := privval.NewFilePV(val.ConsensusKey, pvKeyFile, pvStateFile) + filePV.Save() + + nodeKeyFile := tmCfg.NodeKeyFile() + if err := tmos.EnsureDir(filepath.Dir(nodeKeyFile), 0o777); err != nil { + return "", err + } + nodeKey := &p2p.NodeKey{ + PrivKey: val.NetworkKey, + } + if err := nodeKey.SaveAs(nodeKeyFile); err != nil { + return "", err + } + + return basePath, nil +} diff --git a/test/util/genesis/genesis.go b/test/util/genesis/genesis.go new file mode 100644 index 0000000000..560d20291d --- /dev/null +++ b/test/util/genesis/genesis.go @@ -0,0 +1,212 @@ +package genesis + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/celestiaorg/celestia-app/app" + "github.com/celestiaorg/celestia-app/app/encoding" + "github.com/celestiaorg/celestia-app/pkg/appconsts" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + tmrand "github.com/tendermint/tendermint/libs/rand" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + coretypes "github.com/tendermint/tendermint/types" +) + +// Genesis manages the creation of the genesis state of a network. It is meant +// to be used as the first step to any test that requires a network. +type Genesis struct { + ecfg encoding.Config + // ConsensusParams are the consensus parameters of the network. + ConsensusParams *tmproto.ConsensusParams + // ChainID is the chain ID of the network. + ChainID string + // GenesisTime is the genesis time of the network. + GenesisTime time.Time + + // kr is the keyring used to generate the genesis accounts and validators. + // Transaction keys for all genesis accounts are stored in this keyring and + // are indexed by account name. Public keys and addresses can be derived + // from those keys using the existing keyring API. + kr keyring.Keyring + + // accounts are the genesis accounts that will be included in the genesis. + accounts []Account + // validators are the validators of the network. Note that each validator + // also has a genesis account. + validators []Validator + // genTxs are the genesis transactions that will be included in the genesis. + // Transactions are generated upon adding a validator to the genesis. + genTxs []sdk.Tx + genOps []Modifier +} + +// NewDefaultGenesis creates a new default genesis with no accounts or validators. +func NewDefaultGenesis() *Genesis { + ecfg := encoding.MakeConfig(app.ModuleBasics) + g := &Genesis{ + ecfg: ecfg, + ConsensusParams: DefaultConsensusParams(), + ChainID: tmrand.Str(6), + GenesisTime: time.Now(), + kr: keyring.NewInMemory(ecfg.Codec), + genOps: []Modifier{}, + } + return g +} + +func (g *Genesis) WithModifiers(ops ...Modifier) *Genesis { + g.genOps = append(g.genOps, ops...) + return g +} + +func (g *Genesis) WithConsensusParams(params *tmproto.ConsensusParams) *Genesis { + g.ConsensusParams = params + return g +} + +func (g *Genesis) WithChainID(chainID string) *Genesis { + g.ChainID = chainID + return g +} + +func (g *Genesis) WithGenesisTime(genesisTime time.Time) *Genesis { + g.GenesisTime = genesisTime + return g +} + +func (g *Genesis) WithValidators(vals ...Validator) *Genesis { + for _, val := range vals { + err := g.AddValidator(val) + if err != nil { + panic(err) + } + } + return g +} + +func (g *Genesis) WithAccounts(accs ...Account) *Genesis { + for _, acc := range accs { + err := g.AddAccount(acc) + if err != nil { + panic(err) + } + } + return g +} + +func (g *Genesis) AddAccount(acc Account) error { + _, err := g.kr.Key(acc.Name) + if err == nil { + return fmt.Errorf("account with name %s already exists", acc.Name) + } + if err := acc.ValidateBasic(); err != nil { + return err + } + _, _, err = g.kr.NewMnemonic(acc.Name, keyring.English, "", "", hd.Secp256k1) + if err != nil { + return err + } + g.accounts = append(g.accounts, acc) + return nil +} + +func (g *Genesis) AddValidator(val Validator) error { + if err := val.ValidateBasic(); err != nil { + return err + } + + // Add the validator's genesis account + if err := g.AddAccount(val.Account); err != nil { + return err + } + + // Add the validator's genesis transaction + gentx, err := val.GenTx(g.ecfg, g.kr, g.ChainID) + if err != nil { + return err + } + + // install the validator + g.genTxs = append(g.genTxs, gentx) + g.validators = append(g.validators, val) + return nil +} + +func (g *Genesis) Accounts() []Account { + return g.accounts +} + +func (g *Genesis) Export() (*coretypes.GenesisDoc, error) { + addrs := make([]string, 0, len(g.accounts)) + pubKeys := make([]cryptotypes.PubKey, 0, len(g.accounts)) + gentxs := make([]json.RawMessage, 0, len(g.genTxs)) + + for _, acc := range g.Accounts() { + rec, err := g.kr.Key(acc.Name) + if err != nil { + return nil, err + } + + addr, err := rec.GetAddress() + if err != nil { + return nil, err + } + + addrs = append(addrs, addr.String()) + + pubK, err := rec.GetPubKey() + if err != nil { + return nil, err + } + + pubKeys = append(pubKeys, pubK) + } + + for _, genTx := range g.genTxs { + bz, err := g.ecfg.TxConfig.TxJSONEncoder()(genTx) + if err != nil { + return nil, err + } + + gentxs = append(gentxs, json.RawMessage(bz)) + } + + return Document( + g.ecfg, + g.ConsensusParams, + g.ChainID, + gentxs, + addrs, + pubKeys, + g.genOps..., + ) +} + +func (g *Genesis) Keyring() keyring.Keyring { + return g.kr +} + +func (g *Genesis) Validators() []Validator { + return g.validators +} + +// Validator returns the validator at the given index. False is returned if the +// index is out of bounds. +func (g *Genesis) Validator(i int) (Validator, bool) { + if i < len(g.validators) { + return g.validators[i], true + } + return Validator{}, false +} + +func DefaultConsensusParams() *tmproto.ConsensusParams { + cparams := coretypes.DefaultConsensusParams() + cparams.Block.TimeIotaMs = 1 + cparams.Block.MaxBytes = appconsts.DefaultMaxBytes + return cparams +} diff --git a/test/util/genesis/modifier.go b/test/util/genesis/modifier.go new file mode 100644 index 0000000000..136ca88700 --- /dev/null +++ b/test/util/genesis/modifier.go @@ -0,0 +1,89 @@ +package genesis + +import ( + "encoding/json" + "time" + + "github.com/celestiaorg/celestia-app/app" + blobtypes "github.com/celestiaorg/celestia-app/x/blob/types" + qgbtypes "github.com/celestiaorg/celestia-app/x/qgb/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" +) + +// Modifier allows for arbitrary changes to be made on the genesis state +// after initial accounts have been added. It accepts the genesis state as input +// and is expected to return the modified genesis as output. +type Modifier func(state map[string]json.RawMessage) map[string]json.RawMessage + +// SetBlobParams will set the provided blob params as genesis state. +func SetBlobParams(codec codec.Codec, params blobtypes.Params) Modifier { + return func(state map[string]json.RawMessage) map[string]json.RawMessage { + blobGenState := blobtypes.DefaultGenesis() + blobGenState.Params = params + state[blobtypes.ModuleName] = codec.MustMarshalJSON(blobGenState) + return state + } +} + +// ImmediateProposals sets the thresholds for getting a gov proposal to very low +// levels. +func ImmediateProposals(codec codec.Codec) Modifier { + return func(state map[string]json.RawMessage) map[string]json.RawMessage { + gs := v1.DefaultGenesisState() + gs.DepositParams.MinDeposit = sdk.NewCoins(sdk.NewCoin(app.BondDenom, sdk.NewInt(1))) + gs.TallyParams.Quorum = "0.000001" + gs.TallyParams.Threshold = "0.000001" + vp := time.Second * 5 + gs.VotingParams.VotingPeriod = &vp + state[govtypes.ModuleName] = codec.MustMarshalJSON(gs) + return state + } +} + +// SetDataCommitmentWindow will set the provided data commitment window in the +// qgb module's genesis state. +func SetDataCommitmentWindow(codec codec.Codec, window uint64) Modifier { + return func(state map[string]json.RawMessage) map[string]json.RawMessage { + qgbGenState := qgbtypes.DefaultGenesis() + qgbGenState.Params.DataCommitmentWindow = window + state[qgbtypes.ModuleName] = codec.MustMarshalJSON(qgbGenState) + return state + } +} + +// FundAccounts adds a set of accounts to the genesis and then sets their balance as provided. +// This is good in the case where you have a separate keyring you want to test against and not +// use the one generated by the testnet infra. +func FundAccounts(codec codec.Codec, addresses []sdk.AccAddress, balance sdk.Coin) Modifier { + return func(state map[string]json.RawMessage) map[string]json.RawMessage { + // set the accounts in the genesis state + var authGenState authtypes.GenesisState + codec.MustUnmarshalJSON(state[authtypes.ModuleName], &authGenState) + + genAccounts := make([]authtypes.GenesisAccount, len(addresses)) + genBalances := make([]banktypes.Balance, len(addresses)) + for idx, addr := range addresses { + genAccounts[idx] = authtypes.NewBaseAccount(addr, nil, uint64(idx+len(authGenState.Accounts)), 0) + genBalances[idx] = banktypes.Balance{Address: addr.String(), Coins: sdk.NewCoins(balance)} + } + + accounts, err := authtypes.PackAccounts(genAccounts) + if err != nil { + panic(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) + return state + } +} diff --git a/test/util/genesis/util.go b/test/util/genesis/util.go new file mode 100644 index 0000000000..42d11288d9 --- /dev/null +++ b/test/util/genesis/util.go @@ -0,0 +1,23 @@ +package genesis + +import ( + "io" + mrand "math/rand" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" +) + +func NewSeed(r *mrand.Rand) []byte { + seed := make([]byte, ed25519.SeedSize) + + _, err := io.ReadFull(r, seed) + if err != nil { + panic(err) // this shouldn't happen + } + return seed +} + +func GenerateEd25519(seed []byte) crypto.PrivKey { + return ed25519.GenPrivKeyFromSecret(seed) +} diff --git a/test/util/malicious/app_test.go b/test/util/malicious/app_test.go index c99ae94e53..d1e7956d14 100644 --- a/test/util/malicious/app_test.go +++ b/test/util/malicious/app_test.go @@ -74,7 +74,7 @@ func TestMaliciousTestNode(t *testing.T) { } accounts := testfactory.RandomAccountNames(5) cfg := OutOfOrderNamespaceConfig(5). - WithAccounts(accounts) + WithFundedAccounts(accounts...) cctx, _, _ := testnode.NewNetwork(t, cfg) _, err := cctx.WaitForHeight(6) diff --git a/test/util/test_app.go b/test/util/test_app.go index efa8e478fe..96a24e6ee7 100644 --- a/test/util/test_app.go +++ b/test/util/test_app.go @@ -105,10 +105,10 @@ func SetupTestAppWithGenesisValSet(cparams *tmproto.ConsensusParams, genAccounts return testApp, kr } -// AddGenesisAccount mimics the cli addGenesisAccount command, providing an +// AddAccount mimics the cli addAccount command, providing an // account with an allocation of to "token" and "tia" tokens in the genesis // state -func AddGenesisAccount(addr sdk.AccAddress, appState app.GenesisState, cdc codec.Codec) (map[string]json.RawMessage, error) { +func AddAccount(addr sdk.AccAddress, appState app.GenesisState, cdc codec.Codec) (map[string]json.RawMessage, error) { // create concrete account type based on input parameters var genAccount authtypes.GenesisAccount diff --git a/test/util/testnode/config.go b/test/util/testnode/config.go index 38d591a009..49633f0de3 100644 --- a/test/util/testnode/config.go +++ b/test/util/testnode/config.go @@ -6,7 +6,8 @@ import ( "github.com/celestiaorg/celestia-app/cmd/celestia-appd/cmd" "github.com/celestiaorg/celestia-app/pkg/appconsts" - v1 "github.com/celestiaorg/celestia-app/pkg/appconsts/v1" + "github.com/celestiaorg/celestia-app/test/util/genesis" + pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" "github.com/cosmos/cosmos-sdk/server" srvconfig "github.com/cosmos/cosmos-sdk/server/config" srvtypes "github.com/cosmos/cosmos-sdk/server/types" @@ -16,33 +17,27 @@ import ( "github.com/tendermint/tendermint/types" ) +const ( + DefaultValidatorAccountName = "validator" +) + // Config is the configuration of a test node. type Config struct { - // ChainID is the chain ID of the network. - ChainID string + Genesis *genesis.Genesis // TmConfig is the Tendermint configuration used for the network. TmConfig *tmconfig.Config // AppConfig is the application configuration of the test node. AppConfig *srvconfig.Config - // ConsensusParams are the consensus parameters of the test node. - ConsensusParams *tmproto.ConsensusParams - // AppOptions are the application options of the test node. Portions of the - // app config will automatically be set into the app option when the app - // config is set. + // AppOptions are the application options of the test node. AppOptions *KVAppOptions - // GenesisOptions are the genesis options of the test node. - GenesisOptions []GenesisOption - // Accounts are the accounts of the test node. - Accounts []string // AppCreator is used to create the application for the testnode. AppCreator srvtypes.AppCreator // SupressLogs SupressLogs bool } -// WithChainID sets the ChainID and returns the Config. -func (c *Config) WithChainID(s string) *Config { - c.ChainID = s +func (c *Config) WithGenesis(g *genesis.Genesis) *Config { + c.Genesis = g return c } @@ -63,12 +58,6 @@ func (c *Config) WithAppConfig(conf *srvconfig.Config) *Config { return c } -// WithConsensusParams sets the ConsensusParams and returns the Config. -func (c *Config) WithConsensusParams(params *tmproto.ConsensusParams) *Config { - c.ConsensusParams = params - return c -} - // WithAppOptions sets the AppOptions and returns the Config. // // Warning: If the app config is set after this, it could overwrite some values. @@ -78,18 +67,6 @@ func (c *Config) WithAppOptions(opts *KVAppOptions) *Config { return c } -// WithGenesisOptions sets the GenesisOptions and returns the Config. -func (c *Config) WithGenesisOptions(opts ...GenesisOption) *Config { - c.GenesisOptions = opts - return c -} - -// WithAccounts sets the Accounts and returns the Config. -func (c *Config) WithAccounts(accs []string) *Config { - c.Accounts = accs - return c -} - // WithAppCreator sets the AppCreator and returns the Config. func (c *Config) WithAppCreator(creator srvtypes.AppCreator) *Config { c.AppCreator = creator @@ -102,24 +79,60 @@ func (c *Config) WithSupressLogs(sl bool) *Config { return c } -// WithTimeoutCommit sets the TimeoutCommit and returns the Config. +// WithTimeoutCommit sets the CommitTimeout and returns the Config. func (c *Config) WithTimeoutCommit(d time.Duration) *Config { c.TmConfig.Consensus.TimeoutCommit = d return c } +// WithFundedAccounts sets the genesis accounts and returns the Config. +func (c *Config) WithFundedAccounts(accounts ...string) *Config { + c.Genesis = c.Genesis.WithAccounts( + genesis.NewAccounts(999999999999999999, accounts...)..., + ) + return c +} + +// WithModifiers sets the genesis options and returns the Config. +func (c *Config) WithModifiers(ops ...genesis.Modifier) *Config { + c.Genesis = c.Genesis.WithModifiers(ops...) + return c +} + +// WithGenesisTime sets the genesis time and returns the Config. +func (c *Config) WithGenesisTime(t time.Time) *Config { + c.Genesis = c.Genesis.WithGenesisTime(t) + return c +} + +// WithChainID sets the chain ID and returns the Config. +func (c *Config) WithChainID(id string) *Config { + c.Genesis = c.Genesis.WithChainID(id) + return c +} + +// WithConsensusParams sets the consensus params and returns the Config. +func (c *Config) WithConsensusParams(params *tmproto.ConsensusParams) *Config { + c.Genesis = c.Genesis.WithConsensusParams(params) + return c +} + func DefaultConfig() *Config { tmcfg := DefaultTendermintConfig() tmcfg.Consensus.TimeoutCommit = 1 * time.Millisecond cfg := &Config{} return cfg. - WithAccounts([]string{}). - WithChainID(tmrand.Str(6)). + WithGenesis( + genesis.NewDefaultGenesis(). + WithChainID(tmrand.Str(6)). + WithGenesisTime(time.Now()). + WithConsensusParams(DefaultParams()). + WithModifiers(). + WithValidators(genesis.NewDefaultValidator(DefaultValidatorAccountName)), + ). WithTendermintConfig(DefaultTendermintConfig()). - WithConsensusParams(DefaultConsensusParams()). - WithAppOptions(DefaultAppOptions()). WithAppConfig(DefaultAppConfig()). - WithGenesisOptions(). + WithAppOptions(DefaultAppOptions()). WithAppCreator(cmd.NewAppServer). WithSupressLogs(true) } @@ -197,10 +210,11 @@ func DefaultInitialConsensusParams() *tmproto.ConsensusParams { func DefaultTendermintConfig() *tmconfig.Config { tmCfg := tmconfig.DefaultConfig() - // Reduce the target height duration so that blocks are produced faster - // during tests. - tmCfg.Consensus.TimeoutCommit = 100 * time.Millisecond - tmCfg.Consensus.TimeoutPropose = 200 * time.Millisecond + // TimeoutCommit is the duration the node waits after committing a block + // before starting the next height. This duration influences the time + // interval between blocks. A smaller TimeoutCommit value could lead to + // less time between blocks (i.e. shorter block intervals). + tmCfg.Consensus.TimeoutCommit = 1 * time.Millisecond // set the mempool's MaxTxBytes to allow the testnode to accept a // transaction that fills the entire square. Any blob transaction larger diff --git a/test/util/testnode/full_node.go b/test/util/testnode/full_node.go index b0103c3d59..5c7f45cc44 100644 --- a/test/util/testnode/full_node.go +++ b/test/util/testnode/full_node.go @@ -2,32 +2,22 @@ package testnode import ( "context" - "encoding/json" + "fmt" "net" "os" "path/filepath" "testing" + "github.com/celestiaorg/celestia-app/test/util/genesis" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/crypto/keyring" 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" "github.com/tendermint/tendermint/node" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/privval" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/proxy" dbm "github.com/tendermint/tm-db" - - "github.com/celestiaorg/celestia-app/app" - "github.com/celestiaorg/celestia-app/app/encoding" - "github.com/celestiaorg/celestia-app/test/util/testfactory" - qgbtypes "github.com/celestiaorg/celestia-app/x/qgb/types" ) // NewCometNode creates a ready to use comet node that operates a single @@ -69,81 +59,6 @@ func NewCometNode(t testing.TB, baseDir string, cfg *Config) (*node.Node, srvtyp return tmNode, app, err } -// InitFiles initializes the files for a new tendermint node with the provided -// genesis state and consensus parameters. The provided keyring is used to -// create a validator key and the chainID is used to initialize the genesis -// state. The keyring is returned with the validator account added. -func InitFiles( - t testing.TB, - cparams *tmproto.ConsensusParams, - tmCfg *config.Config, - genState map[string]json.RawMessage, - kr keyring.Keyring, - chainID string, -) (string, keyring.Keyring, error) { - baseDir, err := initFileStructure(t, tmCfg) - if err != nil { - return baseDir, kr, err - } - - encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) - - nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg) - if err != nil { - return baseDir, kr, err - } - - err = createValidator(kr, encCfg, pubKey, "validator", nodeID, chainID, baseDir) - if err != nil { - return baseDir, kr, err - } - - err = initGenFiles(cparams, genState, encCfg.Codec, tmCfg.GenesisFile(), chainID) - if err != nil { - return baseDir, kr, err - } - - return baseDir, kr, collectGenFiles(tmCfg, encCfg, pubKey, nodeID, chainID, baseDir) -} - -// DefaultGenesisState returns a default genesis state and a keyring with -// accounts that have coins. It adds a default "validator" account that is -// funded and used for the valop address of the single validator. 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 := testfactory.FundKeyringAccounts(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) - - // use the minimum data commitment window (100) - var qgbGenState qgbtypes.GenesisState - encCfg.Codec.MustUnmarshalJSON(state[qgbtypes.ModuleName], &qgbGenState) - qgbGenState.Params.DataCommitmentWindow = qgbtypes.MinimumDataCommitmentWindow - state[qgbtypes.ModuleName] = encCfg.Codec.MustMarshalJSON(&qgbGenState) - - return state, kr, nil -} - // NewNetwork starts a single valiator celestia-app network using the provided // configurations. Configured accounts will be funded and their keys can be // accessed in keyring returned client.Context. All rpc, p2p, and grpc addresses @@ -154,22 +69,19 @@ func DefaultGenesisState(fundedAccounts ...string) (map[string]json.RawMessage, func NewNetwork(t testing.TB, cfg *Config) (cctx Context, rpcAddr, grpcAddr string) { t.Helper() - genState, kr, err := DefaultGenesisState(cfg.Accounts...) - require.NoError(t, err) - - for _, opt := range cfg.GenesisOptions { - genState = opt(genState) - } - - chainID := cfg.ChainID + tmCfg := cfg.TmConfig + tmCfg.RPC.ListenAddress = fmt.Sprintf("tcp://127.0.0.1:%d", GetFreePort()) + tmCfg.P2P.ListenAddress = fmt.Sprintf("tcp://127.0.0.1:%d", GetFreePort()) + tmCfg.RPC.GRPCListenAddress = fmt.Sprintf("tcp://127.0.0.1:%d", GetFreePort()) - baseDir, kr, err := InitFiles(t, cfg.ConsensusParams, cfg.TmConfig, genState, kr, chainID) + // initialize the genesis file and validator files for the first validator. + baseDir, err := genesis.InitFiles(t.TempDir(), tmCfg, cfg.Genesis, 0) require.NoError(t, err) tmNode, app, err := NewCometNode(t, baseDir, cfg) require.NoError(t, err) - cctx = NewContext(context.TODO(), kr, cfg.TmConfig, chainID) + cctx = NewContext(context.TODO(), cfg.Genesis.Keyring(), tmCfg, cfg.Genesis.ChainID) cctx, stopNode, err := StartNode(tmNode, cctx) require.NoError(t, err) diff --git a/test/util/testnode/full_node_test.go b/test/util/testnode/full_node_test.go index ac4e6a5794..f109ca8b67 100644 --- a/test/util/testnode/full_node_test.go +++ b/test/util/testnode/full_node_test.go @@ -10,7 +10,7 @@ import ( "github.com/celestiaorg/celestia-app/app/encoding" "github.com/celestiaorg/celestia-app/pkg/appconsts" appns "github.com/celestiaorg/celestia-app/pkg/namespace" - "github.com/celestiaorg/celestia-app/test/util/testfactory" + "github.com/celestiaorg/celestia-app/test/util/genesis" blobtypes "github.com/celestiaorg/celestia-app/x/blob/types" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/stretchr/testify/suite" @@ -36,8 +36,8 @@ func (s *IntegrationTestSuite) SetupSuite() { } t := s.T() - accounts := make([]string, 40) - for i := 0; i < 40; i++ { + accounts := make([]string, 10) + for i := 0; i < 10; i++ { accounts[i] = tmrand.Str(10) } @@ -46,8 +46,8 @@ func (s *IntegrationTestSuite) SetupSuite() { blobGenState.Params.GovMaxSquareSize = uint64(appconsts.DefaultSquareSizeUpperBound) cfg := DefaultConfig(). - WithAccounts(accounts). - WithGenesisOptions(SetBlobParams(ecfg.Codec, blobGenState.Params)) + WithFundedAccounts(accounts...). + WithModifiers(genesis.SetBlobParams(ecfg.Codec, blobGenState.Params)) cctx, _, _ := NewNetwork(t, cfg) s.cctx = cctx diff --git a/test/util/testnode/genesis_options.go b/test/util/testnode/genesis_options.go deleted file mode 100644 index ef34a57a58..0000000000 --- a/test/util/testnode/genesis_options.go +++ /dev/null @@ -1,43 +0,0 @@ -package testnode - -import ( - "encoding/json" - "time" - - "github.com/celestiaorg/celestia-app/app" - blobtypes "github.com/celestiaorg/celestia-app/x/blob/types" - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" -) - -// GenesisOption allows for arbitrary changes to be made on the genesis state -// after initial accounts have been added. It accepts the genesis state as input -// and is expected to return the modifed genesis as output. -type GenesisOption func(state map[string]json.RawMessage) map[string]json.RawMessage - -// SetBlobParams will set the provided blob params as genesis state. -func SetBlobParams(codec codec.Codec, params blobtypes.Params) GenesisOption { - return func(state map[string]json.RawMessage) map[string]json.RawMessage { - blobGenState := blobtypes.DefaultGenesis() - blobGenState.Params = params - state[blobtypes.ModuleName] = codec.MustMarshalJSON(blobGenState) - return state - } -} - -// ImmediateProposals sets the thresholds for getting a gov proposal to very low -// levels. -func ImmediateProposals(codec codec.Codec) GenesisOption { - return func(state map[string]json.RawMessage) map[string]json.RawMessage { - gs := v1.DefaultGenesisState() - gs.DepositParams.MinDeposit = sdk.NewCoins(sdk.NewCoin(app.BondDenom, sdk.NewInt(1))) - gs.TallyParams.Quorum = "0.000001" - gs.TallyParams.Threshold = "0.000001" - vp := time.Second * 5 - gs.VotingParams.VotingPeriod = &vp - state[govtypes.ModuleName] = codec.MustMarshalJSON(gs) - return state - } -} diff --git a/test/util/testnode/node_init.go b/test/util/testnode/node_init.go deleted file mode 100644 index ec5fa91932..0000000000 --- a/test/util/testnode/node_init.go +++ /dev/null @@ -1,189 +0,0 @@ -package testnode - -import ( - "encoding/json" - "fmt" - "net/url" - "os" - "path/filepath" - "testing" - - "github.com/celestiaorg/celestia-app/app" - "github.com/celestiaorg/celestia-app/app/encoding" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/server" - sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/cosmos/cosmos-sdk/x/genutil" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/tendermint/tendermint/config" - tmos "github.com/tendermint/tendermint/libs/os" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - "github.com/tendermint/tendermint/types" - tmtime "github.com/tendermint/tendermint/types/time" -) - -func collectGenFiles(tmCfg *config.Config, encCfg encoding.Config, pubKey cryptotypes.PubKey, nodeID, chainID, rootDir string) error { - gentxsDir := filepath.Join(rootDir, "gentxs") - - genFile := tmCfg.GenesisFile() - genDoc, err := types.GenesisDocFromFile(genFile) - if err != nil { - return err - } - - initCfg := genutiltypes.NewInitConfig(chainID, gentxsDir, nodeID, pubKey) - - appState, err := genutil.GenAppStateFromConfig( - encCfg.Codec, - encCfg.TxConfig, - tmCfg, - initCfg, - *genDoc, - banktypes.GenesisBalancesIterator{}, - ) - if err != nil { - return err - } - - genDoc = &types.GenesisDoc{ - GenesisTime: tmtime.Now(), - ChainID: chainID, - Validators: nil, - AppState: appState, - ConsensusParams: genDoc.ConsensusParams, - } - - if err := genDoc.ValidateAndComplete(); err != nil { - return err - } - - return genDoc.SaveAs(genFile) -} - -func initGenFiles( - cparams *tmproto.ConsensusParams, - state map[string]json.RawMessage, - _ codec.Codec, - file, - chainID string, -) error { - appGenStateJSON, err := json.MarshalIndent(state, "", " ") - if err != nil { - return err - } - - genDoc := types.GenesisDoc{ - ChainID: chainID, - AppState: appGenStateJSON, - ConsensusParams: cparams, - Validators: nil, - } - - return genDoc.SaveAs(file) -} - -func createValidator( - kr keyring.Keyring, - encCfg encoding.Config, - pubKey cryptotypes.PubKey, - valopAcc, - nodeID, - chainID, - baseDir string, -) error { - rec, err := kr.Key(valopAcc) - if err != nil { - return err - } - addr, err := rec.GetAddress() - if err != nil { - return err - } - p2pAddr, _, err := server.FreeTCPAddr() - if err != nil { - return err - } - p2pURL, err := url.Parse(p2pAddr) - if err != nil { - return err - } - commission, err := sdk.NewDecFromStr("0.5") - if err != nil { - return err - } - - createValMsg, err := stakingtypes.NewMsgCreateValidator( - sdk.ValAddress(addr), - pubKey, - sdk.NewCoin(app.BondDenom, sdk.NewInt(100000000)), - stakingtypes.NewDescription("test", "", "", "", ""), - stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()), - sdk.OneInt(), - ) - if err != nil { - return err - } - - memo := fmt.Sprintf("%s@%s:%s", nodeID, p2pURL.Hostname(), p2pURL.Port()) - fee := sdk.NewCoins(sdk.NewCoin(app.BondDenom, sdk.NewInt(1))) - txBuilder := encCfg.TxConfig.NewTxBuilder() - err = txBuilder.SetMsgs(createValMsg) - if err != nil { - return err - } - txBuilder.SetFeeAmount(fee) // Arbitrary fee - txBuilder.SetGasLimit(1000000) // Need at least 100386 - txBuilder.SetMemo(memo) - - txFactory := tx.Factory{} - txFactory = txFactory. - WithChainID(chainID). - WithMemo(memo). - WithKeybase(kr). - WithTxConfig(encCfg.TxConfig) - - err = tx.Sign(txFactory, valopAcc, txBuilder, true) - if err != nil { - return err - } - - txBz, err := encCfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) - if err != nil { - return err - } - gentxsDir := filepath.Join(baseDir, "gentxs") - return writeFile(fmt.Sprintf("%v.json", "test"), gentxsDir, txBz) -} - -func writeFile(name string, dir string, contents []byte) error { - writePath := filepath.Join(dir) - file := filepath.Join(writePath, name) - - err := tmos.EnsureDir(writePath, 0o755) - if err != nil { - return err - } - - err = os.WriteFile(file, contents, 0o644) // nolint: gosec - if err != nil { - return err - } - - return nil -} - -func initFileStructure(t testing.TB, tmCfg *config.Config) (string, error) { - basePath := filepath.Join(t.TempDir(), ".celestia-app") - tmCfg.SetRoot(basePath) - configPath := filepath.Join(basePath, "config") - err := os.MkdirAll(configPath, os.ModePerm) - if err != nil { - return "", err - } - return basePath, nil -} diff --git a/x/qgb/integration_test.go b/x/qgb/integration_test.go index 8a071bc965..ae050f119d 100644 --- a/x/qgb/integration_test.go +++ b/x/qgb/integration_test.go @@ -36,7 +36,7 @@ func (s *QGBIntegrationSuite) SetupSuite() { s.accounts = []string{"jimmy"} - cfg := testnode.DefaultConfig().WithAccounts(s.accounts) + cfg := testnode.DefaultConfig().WithFundedAccounts(s.accounts...) cctx, _, _ := testnode.NewNetwork(t, cfg) s.ecfg = encoding.MakeConfig(app.ModuleEncodingRegisters...) s.cctx = cctx diff --git a/x/upgrade/test/integration_test.go b/x/upgrade/test/integration_test.go index e463cb0387..45f49805e1 100644 --- a/x/upgrade/test/integration_test.go +++ b/x/upgrade/test/integration_test.go @@ -7,6 +7,8 @@ import ( "github.com/celestiaorg/celestia-app/app" "github.com/celestiaorg/celestia-app/app/encoding" + "github.com/celestiaorg/celestia-app/test/util/blobfactory" + "github.com/celestiaorg/celestia-app/test/util/genesis" "github.com/celestiaorg/celestia-app/test/util/testnode" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" @@ -60,9 +62,9 @@ func (s *UpgradeTestSuite) SetupSuite() { tmCfg.Consensus.TimeoutCommit = 3 * time.Second cfg := testnode.DefaultConfig(). - WithAccounts(accounts). + WithFundedAccounts(accounts...). WithTendermintConfig(tmCfg). - WithGenesisOptions(testnode.ImmediateProposals(s.ecfg.Codec)) + WithModifiers(genesis.ImmediateProposals(s.ecfg.Codec)) cctx, _, _ := testnode.NewNetwork(t, cfg)