diff --git a/CHANGELOG.md b/CHANGELOG.md index 7352c385c01e..22c1de01c866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes * (x/mint) [#12384](https://github.com/cosmos/cosmos-sdk/pull/12384) Ensure `GoalBonded` must be positive when performing `x/mint` parameter validation. +* (simapp) [#12437](https://github.com/cosmos/cosmos-sdk/pull/12437) fix the non-determinstic behavior in simulations caused by `GenTx` and check +empty coins slice before it is used to create `banktype.MsgSend`. ## [v0.45.6](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.6) - 2022-06-28 diff --git a/simapp/helpers/test_helpers.go b/simapp/helpers/test_helpers.go index 1eb496e57a71..d3465ab7c38e 100644 --- a/simapp/helpers/test_helpers.go +++ b/simapp/helpers/test_helpers.go @@ -2,7 +2,6 @@ package helpers import ( "math/rand" - "time" "github.com/cosmos/cosmos-sdk/client" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -19,12 +18,10 @@ const ( ) // GenTx generates a signed mock transaction. -func GenTx(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums, accSeqs []uint64, priv ...cryptotypes.PrivKey) (sdk.Tx, error) { +func GenTx(r *rand.Rand, gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums, accSeqs []uint64, priv ...cryptotypes.PrivKey) (sdk.Tx, error) { sigs := make([]signing.SignatureV2, len(priv)) // create a random length memo - r := rand.New(rand.NewSource(time.Now().UnixNano())) - memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100)) signMode := gen.SignModeHandler().DefaultMode() diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index 4f45b23eacd2..c3fb4fcfc561 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "math/rand" "strconv" "testing" "time" @@ -327,6 +328,7 @@ func SignCheckDeliver( ) (sdk.GasInfo, *sdk.Result, error) { tx, err := helpers.GenTx( + rand.New(rand.NewSource(time.Now().UnixNano())), txCfg, msgs, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}, @@ -377,6 +379,7 @@ func GenSequenceOfTxs(txGen client.TxConfig, msgs []sdk.Msg, accNums []uint64, i var err error for i := 0; i < numToGenerate; i++ { txs[i], err = helpers.GenTx( + rand.New(rand.NewSource(time.Now().UnixNano())), txGen, msgs, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}, diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go index 9b8e060f0766..3fc5cef37224 100644 --- a/x/authz/simulation/operations.go +++ b/x/authz/simulation/operations.go @@ -115,6 +115,7 @@ func SimulateMsgGrant(ak authz.AccountKeeper, bk authz.BankKeeper, _ keeper.Keep } txCfg := simappparams.MakeTestEncodingConfig().TxConfig tx, err := helpers.GenTx( + r, txCfg, []sdk.Msg{msg}, fees, @@ -181,6 +182,7 @@ func SimulateMsgRevoke(ak authz.AccountKeeper, bk authz.BankKeeper, k keeper.Kee txCfg := simappparams.MakeTestEncodingConfig().TxConfig account := ak.GetAccount(ctx, granterAddr) tx, err := helpers.GenTx( + r, txCfg, []sdk.Msg{&msg}, fees, @@ -239,6 +241,10 @@ func SimulateMsgExec(ak authz.AccountKeeper, bk authz.BankKeeper, k keeper.Keepe granterspendableCoins := bk.SpendableCoins(ctx, granterAddr) coins := simtypes.RandSubsetCoins(r, granterspendableCoins) + // if coins slice is empty, we can not create valid banktype.MsgSend + if len(coins) == 0 { + return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "empty coins slice"), nil, nil + } // Check send_enabled status of each sent coin denom if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, nil @@ -271,6 +277,7 @@ func SimulateMsgExec(ak authz.AccountKeeper, bk authz.BankKeeper, k keeper.Keepe txCfg := simappparams.MakeTestEncodingConfig().TxConfig granteeAcc := ak.GetAccount(ctx, granteeAddr) tx, err := helpers.GenTx( + r, txCfg, []sdk.Msg{&msgExec}, fees, diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go index 43bc50bb8eb1..3e5173afe10d 100644 --- a/x/bank/simulation/operations.go +++ b/x/bank/simulation/operations.go @@ -60,6 +60,10 @@ func SimulateMsgSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operatio accs []simtypes.Account, chainID string, ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { from, to, coins, skip := randomSendFields(r, ctx, accs, bk, ak) + // if coins slice is empty, we can not create valid types.MsgSend + if len(coins) == 0 { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, "empty coins slice"), nil, nil + } // Check send_enabled status of each coin denom if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { @@ -94,6 +98,10 @@ func SimulateMsgSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keeper, mo spendable := bk.SpendableCoins(ctx, from.Address) coins := simtypes.RandSubsetCoins(r, spendable) + // if coins slice is empty, we can not create valid types.MsgSend + if len(coins) == 0 { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSend, "empty coins slice"), nil, nil + } // Check send_enabled status of each coin denom if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { @@ -139,6 +147,7 @@ func sendMsgSend( } txGen := simappparams.MakeTestEncodingConfig().TxConfig tx, err := helpers.GenTx( + r, txGen, []sdk.Msg{msg}, fees, @@ -355,6 +364,7 @@ func sendMsgMultiSend( txGen := simappparams.MakeTestEncodingConfig().TxConfig tx, err := helpers.GenTx( + r, txGen, []sdk.Msg{msg}, fees, diff --git a/x/distribution/simulation/operations.go b/x/distribution/simulation/operations.go index 4aee32eb2f5c..31137cb64a3c 100644 --- a/x/distribution/simulation/operations.go +++ b/x/distribution/simulation/operations.go @@ -231,6 +231,7 @@ func SimulateMsgFundCommunityPool(ak types.AccountKeeper, bk types.BankKeeper, k msg := types.NewMsgFundCommunityPool(fundAmount, funder.Address) txCtx := simulation.OperationInput{ + R: r, App: app, TxGen: simappparams.MakeTestEncodingConfig().TxConfig, Cdc: nil, diff --git a/x/genutil/gentx_test.go b/x/genutil/gentx_test.go index 35390d823e9b..c9758b409983 100644 --- a/x/genutil/gentx_test.go +++ b/x/genutil/gentx_test.go @@ -3,7 +3,9 @@ package genutil_test import ( "encoding/json" "fmt" + "math/rand" "testing" + "time" "github.com/stretchr/testify/suite" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -234,6 +236,7 @@ func (suite *GenTxTestSuite) TestDeliverGenTxs() { msg := banktypes.NewMsgSend(addr1, addr2, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 1)}) tx, err := helpers.GenTx( + rand.New(rand.NewSource(time.Now().UnixNano())), suite.encodingConfig.TxConfig, []sdk.Msg{msg}, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 10)}, diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 214fb9465676..8716a899b94b 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -156,6 +156,7 @@ func SimulateMsgSubmitProposal( txGen := simappparams.MakeTestEncodingConfig().TxConfig tx, err := helpers.GenTx( + r, txGen, []sdk.Msg{msg}, fees, @@ -242,6 +243,7 @@ func SimulateMsgDeposit(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Ke } txCtx := simulation.OperationInput{ + R: r, App: app, TxGen: simappparams.MakeTestEncodingConfig().TxConfig, Cdc: nil, diff --git a/x/simulation/util.go b/x/simulation/util.go index aa348bfd357f..bfe5688de2a4 100644 --- a/x/simulation/util.go +++ b/x/simulation/util.go @@ -101,6 +101,7 @@ func GenAndDeliverTxWithRandFees(txCtx OperationInput) (simtypes.OperationMsg, [ func GenAndDeliverTx(txCtx OperationInput, fees sdk.Coins) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address) tx, err := helpers.GenTx( + txCtx.R, txCtx.TxGen, []sdk.Msg{txCtx.Msg}, fees, diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go index a34cc24bbb57..8782cd0c485b 100644 --- a/x/slashing/simulation/operations.go +++ b/x/slashing/simulation/operations.go @@ -90,6 +90,7 @@ func SimulateMsgUnjail(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Kee txGen := simappparams.MakeTestEncodingConfig().TxConfig tx, err := helpers.GenTx( + r, txGen, []sdk.Msg{msg}, fees, diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go index ce5ef3dc38ac..8df4164fba6a 100644 --- a/x/staking/simulation/operations.go +++ b/x/staking/simulation/operations.go @@ -152,6 +152,7 @@ func SimulateMsgCreateValidator(ak types.AccountKeeper, bk types.BankKeeper, k k } txCtx := simulation.OperationInput{ + R: r, App: app, TxGen: simappparams.MakeTestEncodingConfig().TxConfig, Cdc: nil, @@ -276,6 +277,7 @@ func SimulateMsgDelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper.K msg := types.NewMsgDelegate(simAccount.Address, val.GetOperator(), bondAmt) txCtx := simulation.OperationInput{ + R: r, App: app, TxGen: simappparams.MakeTestEncodingConfig().TxConfig, Cdc: nil,