Skip to content

Commit

Permalink
fix: Simulation is not deterministic due to GenTx (backport cosmos#12374
Browse files Browse the repository at this point in the history
  • Loading branch information
adu-web3 authored and JeancarloBarrios committed Sep 28, 2024
1 parent d1e0f0a commit c983627
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,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

Expand Down
90 changes: 81 additions & 9 deletions simapp/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package simapp
import (
"encoding/json"
"fmt"
"os"
"math/rand"
"strconv"
"testing"

abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
Expand Down Expand Up @@ -233,17 +234,88 @@ func NewTestNetworkFixture() network.TestFixture {
if err != nil {
panic(fmt.Sprintf("failed creating temporary directory: %v", err))
}
defer os.RemoveAll(dir)
if !bytes.Equal(bechres, res) {
return nil, err
}

return res, nil
}

// CheckBalance checks the balance of an account.
func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, balances sdk.Coins) {
ctxCheck := app.BaseApp.NewContext(true, tmproto.Header{})
require.True(t, balances.IsEqual(app.BankKeeper.GetAllBalances(ctxCheck, addr)))
}

// SignCheckDeliver checks a generated signed transaction and simulates a
// block commitment with the given transaction. A test assertion is made using
// the parameter 'expPass' against the result. A corresponding result is
// returned.
func SignCheckDeliver(
t *testing.T, txCfg client.TxConfig, app *bam.BaseApp, header tmproto.Header, msgs []sdk.Msg,
chainID string, accNums, accSeqs []uint64, expSimPass, expPass bool, priv ...cryptotypes.PrivKey,
) (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)},
helpers.DefaultGenTxGas,
chainID,
accNums,
accSeqs,
priv...,
)
require.NoError(t, err)
txBytes, err := txCfg.TxEncoder()(tx)
require.Nil(t, err)

app := NewSimApp(log.NewNopLogger(), coretesting.NewMemDB(), nil, true, simtestutil.NewAppOptionsWithFlagHome(dir))

appCtr := func(val network.ValidatorI) servertypes.Application {
return NewSimApp(
val.GetLogger(), coretesting.NewMemDB(), nil, true,
simtestutil.NewAppOptionsWithFlagHome(client.GetConfigFromViper(val.GetViper()).RootDir),
bam.SetPruning(pruningtypes.NewPruningOptionsFromString(val.GetAppConfig().Pruning)),
bam.SetMinGasPrices(val.GetAppConfig().MinGasPrices),
bam.SetChainID(val.GetViper().GetString(flags.FlagChainID)),
if expSimPass {
require.NoError(t, err)
require.NotNil(t, res)
} else {
require.Error(t, err)
require.Nil(t, res)
}

// Simulate a sending a transaction and committing a block
app.BeginBlock(abci.RequestBeginBlock{Header: header})
gInfo, res, err := app.Deliver(txCfg.TxEncoder(), tx)

if expPass {
require.NoError(t, err)
require.NotNil(t, res)
} else {
require.Error(t, err)
require.Nil(t, res)
}

app.EndBlock(abci.RequestEndBlock{})
app.Commit()

return gInfo, res, err
}

// GenSequenceOfTxs generates a set of signed transactions of messages, such
// that they differ only by having the sequence numbers incremented between
// every transaction.
func GenSequenceOfTxs(txGen client.TxConfig, msgs []sdk.Msg, accNums []uint64, initSeqNums []uint64, numToGenerate int, priv ...cryptotypes.PrivKey) ([]sdk.Tx, error) {
txs := make([]sdk.Tx, numToGenerate)
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)},
helpers.DefaultGenTxGas,
"",
accNums,
initSeqNums,
priv...,
)
}

Expand Down
1 change: 1 addition & 0 deletions x/genutil/gentx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,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)},
Expand Down
2 changes: 1 addition & 1 deletion x/simulation/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func GenAndDeliverTxWithRandFees(txCtx OperationInput) (simtypes.OperationMsg, [
// GenAndDeliverTx generates a transactions and delivers it.
func GenAndDeliverTx(txCtx OperationInput, fees sdk.Coins) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
account := txCtx.AccountKeeper.GetAccount(txCtx.Context, txCtx.SimAccount.Address)
tx, err := simtestutil.GenSignedMockTx(
tx, err := helpers.GenTx(
txCtx.R,
txCtx.TxGen,
[]sdk.Msg{txCtx.Msg},
Expand Down

0 comments on commit c983627

Please sign in to comment.