github.com/cosmos/cosmos-sdk@v0.50.10/x/genutil/gentx_test.go (about)

     1  package genutil_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"math/rand"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/golang/mock/gomock"
    12  	"github.com/stretchr/testify/suite"
    13  
    14  	"cosmossdk.io/core/genesis"
    15  	"cosmossdk.io/math"
    16  	storetypes "cosmossdk.io/store/types"
    17  
    18  	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
    19  	"github.com/cosmos/cosmos-sdk/testutil"
    20  	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
    21  	sdk "github.com/cosmos/cosmos-sdk/types"
    22  	moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
    23  	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
    24  	"github.com/cosmos/cosmos-sdk/x/genutil"
    25  	genutiltestutil "github.com/cosmos/cosmos-sdk/x/genutil/testutil"
    26  	"github.com/cosmos/cosmos-sdk/x/genutil/types"
    27  	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
    28  )
    29  
    30  var (
    31  	priv1 = secp256k1.GenPrivKey()
    32  	priv2 = secp256k1.GenPrivKey()
    33  	pk1   = priv1.PubKey()
    34  	pk2   = priv2.PubKey()
    35  	addr1 = sdk.AccAddress(pk1.Address())
    36  	addr2 = sdk.AccAddress(pk2.Address())
    37  	desc  = stakingtypes.NewDescription("testname", "", "", "", "")
    38  	comm  = stakingtypes.CommissionRates{}
    39  )
    40  
    41  // GenTxTestSuite is a test suite to be used with gentx tests.
    42  type GenTxTestSuite struct {
    43  	suite.Suite
    44  
    45  	ctx sdk.Context
    46  
    47  	stakingKeeper  *genutiltestutil.MockStakingKeeper
    48  	encodingConfig moduletestutil.TestEncodingConfig
    49  	msg1, msg2     *stakingtypes.MsgCreateValidator
    50  }
    51  
    52  func (suite *GenTxTestSuite) SetupTest() {
    53  	suite.encodingConfig = moduletestutil.MakeTestEncodingConfig(genutil.AppModuleBasic{})
    54  	key := storetypes.NewKVStoreKey("a_Store_Key")
    55  	tkey := storetypes.NewTransientStoreKey("a_transient_store")
    56  	suite.ctx = testutil.DefaultContext(key, tkey)
    57  
    58  	ctrl := gomock.NewController(suite.T())
    59  	suite.stakingKeeper = genutiltestutil.NewMockStakingKeeper(ctrl)
    60  
    61  	stakingtypes.RegisterInterfaces(suite.encodingConfig.InterfaceRegistry)
    62  	banktypes.RegisterInterfaces(suite.encodingConfig.InterfaceRegistry)
    63  
    64  	var err error
    65  	amount := sdk.NewInt64Coin(sdk.DefaultBondDenom, 50)
    66  	one := math.OneInt()
    67  	suite.msg1, err = stakingtypes.NewMsgCreateValidator(
    68  		sdk.ValAddress(pk1.Address()).String(), pk1, amount, desc, comm, one)
    69  	suite.NoError(err)
    70  	suite.msg2, err = stakingtypes.NewMsgCreateValidator(
    71  		sdk.ValAddress(pk2.Address()).String(), pk1, amount, desc, comm, one)
    72  	suite.NoError(err)
    73  }
    74  
    75  func (suite *GenTxTestSuite) setAccountBalance(balances []banktypes.Balance) json.RawMessage {
    76  	bankGenesisState := banktypes.GenesisState{
    77  		Params: banktypes.Params{DefaultSendEnabled: true},
    78  		Balances: []banktypes.Balance{
    79  			{
    80  				Address: "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh",
    81  				Coins:   sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000000)},
    82  			},
    83  			{
    84  				Address: "cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl",
    85  				Coins:   sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 2059726)},
    86  			},
    87  			{
    88  				Address: "cosmos1k5lndq46x9xpejdxq52q3ql3ycrphg4qxlfqn7",
    89  				Coins:   sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000000000000)},
    90  			},
    91  		},
    92  		Supply: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)},
    93  	}
    94  	bankGenesisState.Balances = append(bankGenesisState.Balances, balances...)
    95  	for _, balance := range bankGenesisState.Balances {
    96  		bankGenesisState.Supply.Add(balance.Coins...)
    97  	}
    98  	bankGenesis, err := suite.encodingConfig.Amino.MarshalJSON(bankGenesisState) // TODO switch this to use Marshaler
    99  	suite.Require().NoError(err)
   100  
   101  	return bankGenesis
   102  }
   103  
   104  func (suite *GenTxTestSuite) TestSetGenTxsInAppGenesisState() {
   105  	var (
   106  		txBuilder = suite.encodingConfig.TxConfig.NewTxBuilder()
   107  		genTxs    []sdk.Tx
   108  	)
   109  
   110  	testCases := []struct {
   111  		msg      string
   112  		malleate func()
   113  		expPass  bool
   114  	}{
   115  		{
   116  			"one genesis transaction",
   117  			func() {
   118  				err := txBuilder.SetMsgs(suite.msg1)
   119  				suite.Require().NoError(err)
   120  				tx := txBuilder.GetTx()
   121  				genTxs = []sdk.Tx{tx}
   122  			},
   123  			true,
   124  		},
   125  		{
   126  			"two genesis transactions",
   127  			func() {
   128  				err := txBuilder.SetMsgs(suite.msg1, suite.msg2)
   129  				suite.Require().NoError(err)
   130  				tx := txBuilder.GetTx()
   131  				genTxs = []sdk.Tx{tx}
   132  			},
   133  			true,
   134  		},
   135  	}
   136  
   137  	for _, tc := range testCases {
   138  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   139  			suite.SetupTest()
   140  			cdc := suite.encodingConfig.Codec
   141  			txJSONEncoder := suite.encodingConfig.TxConfig.TxJSONEncoder()
   142  
   143  			tc.malleate()
   144  			appGenesisState, err := genutil.SetGenTxsInAppGenesisState(cdc, txJSONEncoder, make(map[string]json.RawMessage), genTxs)
   145  
   146  			suite.Require().NoError(err)
   147  			suite.Require().NotNil(appGenesisState[types.ModuleName])
   148  
   149  			var genesisState types.GenesisState
   150  			err = cdc.UnmarshalJSON(appGenesisState[types.ModuleName], &genesisState)
   151  			suite.Require().NoError(err)
   152  			suite.Require().NotNil(genesisState.GenTxs)
   153  		})
   154  	}
   155  }
   156  
   157  func (suite *GenTxTestSuite) TestValidateAccountInGenesis() {
   158  	var (
   159  		appGenesisState = make(map[string]json.RawMessage)
   160  		coins           sdk.Coins
   161  	)
   162  
   163  	testCases := []struct {
   164  		msg      string
   165  		malleate func()
   166  		expPass  bool
   167  	}{
   168  		{
   169  			"no accounts",
   170  			func() {
   171  				coins = sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}
   172  			},
   173  			false,
   174  		},
   175  		{
   176  			"account without balance in the genesis state",
   177  			func() {
   178  				coins = sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}
   179  				balances := banktypes.Balance{
   180  					Address: addr2.String(),
   181  					Coins:   sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 50)},
   182  				}
   183  				appGenesisState[banktypes.ModuleName] = suite.setAccountBalance([]banktypes.Balance{balances})
   184  			},
   185  			false,
   186  		},
   187  		{
   188  			"account without enough funds of default bond denom",
   189  			func() {
   190  				coins = sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 50)}
   191  				balances := banktypes.Balance{
   192  					Address: addr1.String(),
   193  					Coins:   sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 25)},
   194  				}
   195  				appGenesisState[banktypes.ModuleName] = suite.setAccountBalance([]banktypes.Balance{balances})
   196  			},
   197  			false,
   198  		},
   199  		{
   200  			"account with enough funds of default bond denom",
   201  			func() {
   202  				coins = sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 10)}
   203  				balances := banktypes.Balance{
   204  					Address: addr1.String(),
   205  					Coins:   sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 25)},
   206  				}
   207  				appGenesisState[banktypes.ModuleName] = suite.setAccountBalance([]banktypes.Balance{balances})
   208  			},
   209  			true,
   210  		},
   211  	}
   212  	for _, tc := range testCases {
   213  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   214  			suite.SetupTest()
   215  			cdc := suite.encodingConfig.Codec
   216  
   217  			stakingGenesis, err := cdc.MarshalJSON(&stakingtypes.GenesisState{Params: stakingtypes.DefaultParams()}) // TODO switch this to use Marshaler
   218  			suite.Require().NoError(err)
   219  			appGenesisState[stakingtypes.ModuleName] = stakingGenesis
   220  
   221  			tc.malleate()
   222  			err = genutil.ValidateAccountInGenesis(
   223  				appGenesisState, banktypes.GenesisBalancesIterator{},
   224  				addr1, coins, cdc,
   225  			)
   226  
   227  			if tc.expPass {
   228  				suite.Require().NoError(err)
   229  			} else {
   230  				suite.Require().Error(err)
   231  			}
   232  		})
   233  	}
   234  }
   235  
   236  func (suite *GenTxTestSuite) TestDeliverGenTxs() {
   237  	var (
   238  		genTxs    []json.RawMessage
   239  		txBuilder = suite.encodingConfig.TxConfig.NewTxBuilder()
   240  	)
   241  
   242  	testCases := []struct {
   243  		msg         string
   244  		malleate    func()
   245  		deliverTxFn genesis.TxHandler
   246  		expPass     bool
   247  	}{
   248  		{
   249  			"no signature supplied",
   250  			func() {
   251  				err := txBuilder.SetMsgs(suite.msg1)
   252  				suite.Require().NoError(err)
   253  
   254  				genTxs = make([]json.RawMessage, 1)
   255  				tx, err := suite.encodingConfig.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
   256  				suite.Require().NoError(err)
   257  				genTxs[0] = tx
   258  			},
   259  			GenesisState1{},
   260  			false,
   261  		},
   262  		{
   263  			"success",
   264  			func() {
   265  				r := rand.New(rand.NewSource(time.Now().UnixNano()))
   266  				msg := banktypes.NewMsgSend(addr1, addr2, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 1)})
   267  				tx, err := simtestutil.GenSignedMockTx(
   268  					r,
   269  					suite.encodingConfig.TxConfig,
   270  					[]sdk.Msg{msg},
   271  					sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 10)},
   272  					simtestutil.DefaultGenTxGas,
   273  					suite.ctx.ChainID(),
   274  					[]uint64{7},
   275  					[]uint64{0},
   276  					priv1,
   277  				)
   278  				suite.Require().NoError(err)
   279  
   280  				genTxs = make([]json.RawMessage, 1)
   281  				genTx, err := suite.encodingConfig.TxConfig.TxJSONEncoder()(tx)
   282  				suite.Require().NoError(err)
   283  				genTxs[0] = genTx
   284  			},
   285  			GenesisState2{},
   286  			true,
   287  		},
   288  	}
   289  
   290  	for _, tc := range testCases {
   291  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   292  			suite.SetupTest()
   293  
   294  			tc.malleate()
   295  
   296  			if tc.expPass {
   297  				suite.stakingKeeper.EXPECT().ApplyAndReturnValidatorSetUpdates(gomock.Any()).Return(nil, nil).AnyTimes()
   298  				suite.Require().NotPanics(func() {
   299  					genutil.DeliverGenTxs(
   300  						suite.ctx, genTxs, suite.stakingKeeper, tc.deliverTxFn,
   301  						suite.encodingConfig.TxConfig,
   302  					)
   303  				})
   304  			} else {
   305  				_, err := genutil.DeliverGenTxs(
   306  					suite.ctx, genTxs, suite.stakingKeeper, tc.deliverTxFn,
   307  					suite.encodingConfig.TxConfig,
   308  				)
   309  
   310  				suite.Require().Error(err)
   311  			}
   312  		})
   313  	}
   314  }
   315  
   316  func TestGenTxTestSuite(t *testing.T) {
   317  	suite.Run(t, new(GenTxTestSuite))
   318  }
   319  
   320  type GenesisState1 struct{}
   321  
   322  func (GenesisState1) ExecuteGenesisTx(_ []byte) error {
   323  	return errors.New("no signatures supplied")
   324  }
   325  
   326  type GenesisState2 struct{}
   327  
   328  func (GenesisState2) ExecuteGenesisTx(tx []byte) error {
   329  	return nil
   330  }