diff --git a/.github/workflows/sims.yaml b/.github/workflows/sims.yaml new file mode 100644 index 000000000..f1028a2be --- /dev/null +++ b/.github/workflows/sims.yaml @@ -0,0 +1,37 @@ +name: Simulation Test +on: [pull_request] + +jobs: + test-sim-nondeterminism-fast: + name: Test AppStateDeterminism + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v3 + - name: Setup go + uses: actions/setup-go@v3 + with: + go-version: '^1.19' # The Go version to download (if necessary) and use. + - run: make test-sim-nondeterminism-fast + # test-sim-import-export: + # name: Test AppImportExport + # runs-on: ubuntu-latest + # steps: + # - name: Checkout source code + # uses: actions/checkout@v3 + # - name: Setup go + # uses: actions/setup-go@v3 + # with: + # go-version: '^1.19' # The Go version to download (if necessary) and use. + # - run: make test-sim-import-export + # test-sim-after-import: + # name: Test AppSimulationAfterImport + # runs-on: ubuntu-latest + # steps: + # - name: Checkout source code + # uses: actions/checkout@v3 + # - name: Setup go + # uses: actions/setup-go@v3 + # with: + # go-version: '^1.19' # The Go version to download (if necessary) and use. + # - run: make test-sim-after-import \ No newline at end of file diff --git a/Makefile b/Makefile index e3b90142f..5fec4ebbd 100644 --- a/Makefile +++ b/Makefile @@ -5,4 +5,5 @@ include scripts/build/godoc.mk include scripts/build/contract.mk include scripts/build/protobuf.mk include scripts/build/testing.mk +include scripts/build/simulations.mk include scripts/build/linting.mk \ No newline at end of file diff --git a/e2e/go.mod b/e2e/go.mod index 5d712e129..67cfcf07d 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -6,6 +6,7 @@ require ( cosmossdk.io/api v0.3.1 cosmossdk.io/core v0.5.1 github.com/cometbft/cometbft v0.37.4 + github.com/cometbft/cometbft-db v0.7.0 github.com/cosmos/cosmos-sdk v0.47.9 github.com/cosmos/gogoproto v1.4.10 github.com/stretchr/testify v1.8.4 @@ -57,7 +58,6 @@ require ( github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect - github.com/cometbft/cometbft-db v0.7.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.4 // indirect diff --git a/e2e/sim_test.go b/e2e/sim_test.go new file mode 100644 index 000000000..390ae4df6 --- /dev/null +++ b/e2e/sim_test.go @@ -0,0 +1,534 @@ +package e2e + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "math/rand" + "os" + "path/filepath" + "runtime/debug" + "strings" + "testing" + + dbm "github.com/cometbft/cometbft-db" + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/libs/log" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/server" + "github.com/cosmos/cosmos-sdk/store" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/cosmos/cosmos-sdk/x/simulation" + simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + coinswaptypes "mods.irisnet.org/modules/coinswap/types" + htlctypes "mods.irisnet.org/modules/htlc/types" + mttypes "mods.irisnet.org/modules/mt/types" + nfttypes "mods.irisnet.org/modules/nft/types" + oracletypes "mods.irisnet.org/modules/oracle/types" + randomtypes "mods.irisnet.org/modules/random/types" + servicetypes "mods.irisnet.org/modules/service/types" + tokentypes "mods.irisnet.org/modules/token/types" + "mods.irisnet.org/simapp" + "mods.irisnet.org/simapp/helpers" +) + +// SimAppChainID hardcoded chainID for simulation +const SimAppChainID = "simulation-app" + +var DefaultNodeHome string + +// Get flags every time the simulator is run +func init() { + simcli.GetSimulatorFlags() + + userHomeDir, err := os.UserHomeDir() + if err != nil { + panic(err) + } + + DefaultNodeHome = filepath.Join(userHomeDir, ".e2e") +} + +type StoreKeysPrefixes struct { + A storetypes.StoreKey + B storetypes.StoreKey + Prefixes [][]byte +} + +// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of +// an IAVLStore for faster simulation speed. +func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { + bapp.SetFauxMerkleMode() +} + +// interBlockCacheOpt returns a BaseApp option function that sets the persistent +// inter-block write-through cache. +func interBlockCacheOpt() func(*baseapp.BaseApp) { + return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) +} + +func TestFullAppSimulation(t *testing.T) { + config := simcli.NewConfigFromFlags() + config.ChainID = SimAppChainID + + db, dir, logger, skip, err := simtestutil.SetupSimulation( + config, + "leveldb-app-sim", + "Simulation", + simcli.FlagVerboseValue, + simcli.FlagEnabledValue, + ) + if skip { + t.Skip("skipping application simulation") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) + }() + + appOptions := make(simtestutil.AppOptionsMap, 0) + appOptions[flags.FlagHome] = DefaultNodeHome + appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue + + app := simapp.NewSimApp( + logger, + db, + nil, + true, + defaultDepinjectOptions(), + appOptions, + fauxMerkleModeOpt, + baseapp.SetChainID(config.ChainID), + ) + require.Equal(t, "SimApp", app.Name()) + + // run randomized simulation + _, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + simapp.AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(app, app.AppCodec(), config), + app.BankKeeper.GetBlockedAddresses(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = simtestutil.CheckExportSimulation(app, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + simtestutil.PrintStats(db) + } +} + +func TestAppImportExport(t *testing.T) { + // simcli.FlagEnabledValue = true + // simcli.FlagBlockSizeValue = 50 + // simcli.FlagPeriodValue = 5 + // simcli.FlagCommitValue = true + + config := simcli.NewConfigFromFlags() + config.ChainID = SimAppChainID + config.Commit = true + + + + db, dir, logger, skip, err := simtestutil.SetupSimulation( + config, + "leveldb-app-sim", + "Simulation", + simcli.FlagVerboseValue, + simcli.FlagEnabledValue, + ) + if skip { + t.Skip("skipping application simulation") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) + }() + + appOptions := make(simtestutil.AppOptionsMap, 0) + appOptions[flags.FlagHome] = DefaultNodeHome + appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue + + app := simapp.NewSimApp( + logger, + db, + nil, + true, + defaultDepinjectOptions(), + appOptions, + fauxMerkleModeOpt, + baseapp.SetChainID(config.ChainID), + ) + require.Equal(t, "SimApp", app.Name()) + + // Run randomized simulation + _, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + simapp.AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(app, app.AppCodec(), config), + app.BankKeeper.GetBlockedAddresses(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = simtestutil.CheckExportSimulation(app, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + simtestutil.PrintStats(db) + } + + fmt.Printf("exporting genesis...\n") + + exported, err := app.ExportAppStateAndValidators(false, []string{}, []string{}) + require.NoError(t, err) + + fmt.Printf("importing genesis...\n") + + newDB, newDir, _, _, err := simtestutil.SetupSimulation( + config, + "leveldb-app-sim-2", + "Simulation-2", + simcli.FlagVerboseValue, + simcli.FlagEnabledValue, + ) + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, newDB.Close()) + require.NoError(t, os.RemoveAll(newDir)) + }() + + newApp := simapp.NewSimApp( + log.NewNopLogger(), + newDB, + nil, + true, + defaultDepinjectOptions(), + appOptions, + fauxMerkleModeOpt, + baseapp.SetChainID(config.ChainID), + ) + require.Equal(t, "SimApp", newApp.Name()) + + var genesisState simapp.GenesisState + err = json.Unmarshal(exported.AppState, &genesisState) + require.NoError(t, err) + + defer func() { + if r := recover(); r != nil { + err := fmt.Sprintf("%v", r) + if !strings.Contains(err, "validator set is empty after InitGenesis") { + panic(r) + } + logger.Info("Skipping simulation as all validators have been unbonded") + logger.Info("err", err, "stacktrace", string(debug.Stack())) + } + }() + + ctxA := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) + ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) + newApp.ModuleManager.InitGenesis(ctxB, app.AppCodec(), genesisState) + newApp.StoreConsensusParams(ctxB, exported.ConsensusParams) + + fmt.Printf("comparing stores...\n") + + storeKeysPrefixes := []StoreKeysPrefixes{ + {app.GetKey(authtypes.StoreKey), newApp.GetKey(authtypes.StoreKey), [][]byte{}}, + {app.GetKey(stakingtypes.StoreKey), newApp.GetKey(stakingtypes.StoreKey), + [][]byte{ + stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, + stakingtypes.ValidatorQueueKey, stakingtypes.HistoricalInfoKey, + }}, // ordering may change but it doesn't matter + {app.GetKey(slashingtypes.StoreKey), newApp.GetKey(slashingtypes.StoreKey), [][]byte{}}, + {app.GetKey(minttypes.StoreKey), newApp.GetKey(minttypes.StoreKey), [][]byte{}}, + {app.GetKey(distrtypes.StoreKey), newApp.GetKey(distrtypes.StoreKey), [][]byte{}}, + { + app.GetKey(banktypes.StoreKey), + newApp.GetKey(banktypes.StoreKey), + [][]byte{banktypes.BalancesPrefix}, + }, + {app.GetKey(paramtypes.StoreKey), newApp.GetKey(paramtypes.StoreKey), [][]byte{}}, + {app.GetKey(govtypes.StoreKey), newApp.GetKey(govtypes.StoreKey), [][]byte{}}, + {app.GetKey(evidencetypes.StoreKey), newApp.GetKey(evidencetypes.StoreKey), [][]byte{}}, + {app.GetKey(capabilitytypes.StoreKey), newApp.GetKey(capabilitytypes.StoreKey), [][]byte{}}, + + // check irismod module + {app.GetKey(tokentypes.StoreKey), newApp.GetKey(tokentypes.StoreKey), [][]byte{}}, + {app.GetKey(oracletypes.StoreKey), newApp.GetKey(oracletypes.StoreKey), [][]byte{}}, + //mt.Supply is InitSupply, can be not equal to TotalSupply + {app.GetKey(mttypes.StoreKey), newApp.GetKey(mttypes.StoreKey), [][]byte{mttypes.PrefixMT}}, + {app.GetKey(nfttypes.StoreKey), newApp.GetKey(nfttypes.StoreKey), [][]byte{{0x05}}}, + { + app.GetKey(servicetypes.StoreKey), + newApp.GetKey(servicetypes.StoreKey), + [][]byte{servicetypes.InternalCounterKey}, + }, + { + app.GetKey(randomtypes.StoreKey), + newApp.GetKey(randomtypes.StoreKey), + [][]byte{randomtypes.RandomKey}, + }, + //{app.keys[recordtypes.StoreKey), newApp.keys[recordtypes.StoreKey), [][]byte{recordtypes.IntraTxCounterKey}}, + {app.GetKey(htlctypes.StoreKey), newApp.GetKey(htlctypes.StoreKey), [][]byte{}}, + {app.GetKey(coinswaptypes.StoreKey), newApp.GetKey(coinswaptypes.StoreKey), [][]byte{}}, + } + + for _, skp := range storeKeysPrefixes { + storeA := ctxA.KVStore(skp.A) + storeB := ctxB.KVStore(skp.B) + + failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, skp.Prefixes) + require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare") + + fmt.Printf( + "compared %d different key/value pairs between %s and %s\n", + len(failedKVAs), + skp.A, + skp.B, + ) + for _, kv := range failedKVAs { + fmt.Printf("storeKey: %s,\n failedKVBs: %v,\n ", skp.A.Name(), kv.Key) + } + require.Equal( + t, + 0, + len(failedKVAs), + simtestutil.GetSimulationLog( + skp.A.Name(), + app.SimulationManager().StoreDecoders, + failedKVAs, + failedKVBs, + ), + ) + } +} + +func TestAppSimulationAfterImport(t *testing.T) { + config := simcli.NewConfigFromFlags() + config.ChainID = SimAppChainID + + db, dir, logger, skip, err := simtestutil.SetupSimulation( + config, + "leveldb-app-sim", + "Simulation", + simcli.FlagVerboseValue, + simcli.FlagEnabledValue, + ) + if skip { + t.Skip("skipping application simulation") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) + }() + + appOptions := make(simtestutil.AppOptionsMap, 0) + appOptions[flags.FlagHome] = DefaultNodeHome + appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue + + app := simapp.NewSimApp( + logger, + db, + nil, + true, + defaultDepinjectOptions(), + appOptions, + fauxMerkleModeOpt, + baseapp.SetChainID(config.ChainID), + ) + require.Equal(t, "SimApp", app.Name()) + + // Run randomized simulation + stopEarly, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + simapp.AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(app, app.AppCodec(), config), + app.BankKeeper.GetBlockedAddresses(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = simtestutil.CheckExportSimulation(app, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + simtestutil.PrintStats(db) + } + + if stopEarly { + fmt.Println("can't export or import a zero-validator genesis, exiting test...") + return + } + + fmt.Printf("exporting genesis...\n") + + exported, err := app.ExportAppStateAndValidators(true, []string{}, []string{}) + require.NoError(t, err) + + fmt.Printf("importing genesis...\n") + + newDB, newDir, _, _, err := simtestutil.SetupSimulation( + config, + "leveldb-app-sim-2", + "Simulation-2", + simcli.FlagVerboseValue, + simcli.FlagEnabledValue, + ) + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, newDB.Close()) + require.NoError(t, os.RemoveAll(newDir)) + }() + + newApp := simapp.NewSimApp( + log.NewNopLogger(), + newDB, + nil, + true, + defaultDepinjectOptions(), + appOptions, + fauxMerkleModeOpt, + baseapp.SetChainID(config.ChainID), + ) + require.Equal(t, "SimApp", newApp.Name()) + + newApp.InitChain(abci.RequestInitChain{ + AppStateBytes: exported.AppState, + }) + _, _, err = simulation.SimulateFromSeed( + t, + os.Stdout, + newApp.BaseApp, + simapp.AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config), + app.BankKeeper.GetBlockedAddresses(), + config, + app.AppCodec(), + ) + require.NoError(t, err) +} + +// TODO: Make another test for the fuzzer itself, which just has noOp txs +// and doesn't depend on the application. +func TestAppStateDeterminism(t *testing.T) { + if !simcli.FlagEnabledValue { + t.Skip("skipping application simulation") + } + + config := simcli.NewConfigFromFlags() + config.InitialBlockHeight = 1 + config.ExportParamsPath = "" + config.OnOperation = false + config.AllInvariants = false + config.ChainID = helpers.SimAppChainID + + numSeeds := 3 + numTimesToRunPerSeed := 5 + appHashList := make([]json.RawMessage, numTimesToRunPerSeed) + + appOptions := make(simtestutil.AppOptionsMap, 0) + appOptions[flags.FlagHome] = DefaultNodeHome + appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue + + for i := 0; i < numSeeds; i++ { + config.Seed = rand.Int63() + + for j := 0; j < numTimesToRunPerSeed; j++ { + var logger log.Logger + if simcli.FlagVerboseValue { + logger = log.TestingLogger() + } else { + logger = log.NewNopLogger() + } + + db := dbm.NewMemDB() + app := simapp.NewSimApp( + logger, + db, + nil, + true, + defaultDepinjectOptions(), + appOptions, + interBlockCacheOpt(), + baseapp.SetChainID(config.ChainID), + ) + + fmt.Printf( + "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", + config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + ) + + _, _, err := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + simapp.AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(app, app.AppCodec(), config), + app.BankKeeper.GetBlockedAddresses(), + config, + app.AppCodec(), + ) + require.NoError(t, err) + + if config.Commit { + simtestutil.PrintStats(db) + } + + appHash := app.LastCommitID().Hash + appHashList[j] = appHash + + if j != 0 { + require.Equal( + t, hex.EncodeToString(appHashList[0]), hex.EncodeToString(appHashList[j]), + "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", + config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + ) + } + } + } +} \ No newline at end of file diff --git a/e2e/suite.go b/e2e/suite.go index df47efaf4..5446a1e4a 100644 --- a/e2e/suite.go +++ b/e2e/suite.go @@ -48,6 +48,10 @@ func (s *TestSuite) TearDownSuite() { // DepinjectOptions returns the depinject options for the test suite func (s *TestSuite) DepinjectOptions() simapp.DepinjectOptions { + return defaultDepinjectOptions() +} + +func defaultDepinjectOptions() simapp.DepinjectOptions { return simapp.DepinjectOptions{ Config: AppConfig, Providers: []interface{}{ diff --git a/modules/coinswap/simulation/genesis.go b/modules/coinswap/simulation/genesis.go index 98b3a6505..94b4c63b8 100644 --- a/modules/coinswap/simulation/genesis.go +++ b/modules/coinswap/simulation/genesis.go @@ -1,8 +1,74 @@ package simulation import ( + "encoding/json" + "fmt" + "math/rand" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/types/simulation" + "mods.irisnet.org/modules/coinswap/types" +) + +const ( + keyFee = "swap_fee" + keyPoolCreationFee = "pool_creation_fee" + keyTaxRate = "tax_rate" + keyUnilateralLiquidityFee = "unilateral_liquidity_fee" ) // RandomizedGenState generates a random GenesisState for coinswap -func RandomizedGenState(simState *module.SimulationState) {} +func RandomizedGenState(simState *module.SimulationState) { + var ( + fee sdk.Dec + poolCreationFee sdk.Coin + taxRate sdk.Dec + unilateralLiquidityFee sdk.Dec + ) + + simState.AppParams.GetOrGenerate( + simState.Cdc, keyFee, &fee, simState.Rand, + func(r *rand.Rand) { + num := simulation.RandIntBetween(simState.Rand, 1, 9) + fee = sdk.NewDecWithPrec(int64(num), 3) + }, + ) + + simState.AppParams.GetOrGenerate( + simState.Cdc, keyPoolCreationFee, &poolCreationFee, simState.Rand, + func(r *rand.Rand) { poolCreationFee = sdk.NewInt64Coin(sdk.DefaultBondDenom, r.Int63n(100)) }, + ) + + simState.AppParams.GetOrGenerate( + simState.Cdc, keyTaxRate, &taxRate, simState.Rand, + func(r *rand.Rand) { + num := simulation.RandIntBetween(simState.Rand, 1, 5) + taxRate = sdk.NewDecWithPrec(int64(num), 1) + }, + ) + + simState.AppParams.GetOrGenerate( + simState.Cdc, keyUnilateralLiquidityFee, &unilateralLiquidityFee, simState.Rand, + func(r *rand.Rand) { + num := simulation.RandIntBetween(simState.Rand, 1, 3) + unilateralLiquidityFee = sdk.NewDecWithPrec(int64(num), 3) + }, + ) + + params := types.NewParams(fee, taxRate, unilateralLiquidityFee, poolCreationFee) + genesis := &types.GenesisState{ + Params: params, + StandardDenom: sdk.DefaultBondDenom, + Sequence: 1, + } + + bz, err := json.MarshalIndent(&genesis, "", " ") + if err != nil { + panic(err) + } + fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, bz) + + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(genesis) +} diff --git a/modules/coinswap/simulation/operations.go b/modules/coinswap/simulation/operations.go index 119f3f0a0..1ed7977f7 100644 --- a/modules/coinswap/simulation/operations.go +++ b/modules/coinswap/simulation/operations.go @@ -941,7 +941,7 @@ func randToken(r *rand.Rand, spendableCoin sdk.Coins) (sdk.Coin, error) { return sdk.Coin{}, errors.New("insufficient funds") } token := spendableCoin[r.Intn(len(spendableCoin))] - randAmt, err := simtypes.RandPositiveInt(r, token.Amount.QuoRaw(2)) + randAmt, err := simtypes.RandPositiveInt(r, token.Amount.QuoRaw(4)) if err != nil { return sdk.Coin{}, errors.New("insufficient funds") } @@ -1001,6 +1001,18 @@ func doubleSwapBill( outputReserve2, param.Fee, ) + + if soldTokenAmt.IsNegative() { + return sdk.Coin{}, sdk.Coin{}, errorsmod.Wrap( + types.ErrConstraintNotMet, + fmt.Sprintf( + "insufficient amount of %s, user expected: %s, actual: %s", + outputCoin.Denom, + outputCoin.Amount, + outputReserve, + ), + ) + } inputCoin = sdk.NewCoin(inputCoin.Denom, soldTokenAmt) return inputCoin, outputCoin, nil diff --git a/modules/farm/keeper/keeper_test.go b/modules/farm/keeper/keeper_test.go index ab31ab2ed..cec47b42e 100644 --- a/modules/farm/keeper/keeper_test.go +++ b/modules/farm/keeper/keeper_test.go @@ -441,7 +441,10 @@ func (suite *KeeperTestSuite) TestHarvest() { tc.expectReward, tc.debt, tc.rewardPerShare) + err,broken := keeper.RewardInvariant(suite.keeper)(ctx) + suite.Require().False(broken, err) } + } func (suite *KeeperTestSuite) AssertStake( diff --git a/modules/farm/simulation/operations.go b/modules/farm/simulation/operations.go index 686692654..0814bd8b9 100644 --- a/modules/farm/simulation/operations.go +++ b/modules/farm/simulation/operations.go @@ -104,6 +104,7 @@ func WeightedOperations( } } +// SimulateMsgCreatePool randomized CreatePool func SimulateMsgCreatePool( k keeper.Keeper, ak types.AccountKeeper, @@ -232,11 +233,11 @@ func SimulateMsgCreatePool( if _, _, err = app.SimDeliver(txGen.TxEncoder(), tx); err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, nil } - keeper.RewardInvariant(k) return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } +// SimulateMsgAdjustPool simulates MsgAdjustPool func SimulateMsgAdjustPool( k keeper.Keeper, ak types.AccountKeeper, @@ -384,11 +385,11 @@ func SimulateMsgAdjustPool( if err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - keeper.RewardInvariant(k) return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } +// SimulateMsgStake simulates MsgStake func SimulateMsgStake( k keeper.Keeper, ak types.AccountKeeper, @@ -491,11 +492,11 @@ func SimulateMsgStake( return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - keeper.RewardInvariant(k) return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } +// SimulateMsgUnStake simulates MsgUnStake func SimulateMsgUnStake( k keeper.Keeper, ak types.AccountKeeper, @@ -596,11 +597,11 @@ func SimulateMsgUnStake( if err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - keeper.RewardInvariant(k) return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } +// SimulateMsgHarvest simulates MsgHarvest func SimulateMsgHarvest( k keeper.Keeper, ak types.AccountKeeper, @@ -675,11 +676,11 @@ func SimulateMsgHarvest( if err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - keeper.RewardInvariant(k) return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } +// SimulateMsgDestroyPool simulates MsgDestroyPool func SimulateMsgDestroyPool( k keeper.Keeper, ak types.AccountKeeper, @@ -782,7 +783,6 @@ func SimulateMsgDestroyPool( if err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - keeper.RewardInvariant(k) return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/scripts/build/build.mk b/scripts/build/build.mk index 8f2cdca13..d83781118 100644 --- a/scripts/build/build.mk +++ b/scripts/build/build.mk @@ -1 +1,3 @@ -DOCKER := $(shell which docker) \ No newline at end of file +DOCKER := $(shell which docker) +BINDIR ?= $(GOPATH)/bin +CURRENT_DIR = $(shell pwd) \ No newline at end of file diff --git a/scripts/build/simulations.mk b/scripts/build/simulations.mk new file mode 100644 index 000000000..5ea3936c4 --- /dev/null +++ b/scripts/build/simulations.mk @@ -0,0 +1,19 @@ +test-sim-nondeterminism: + @echo "Running non-determinism test..." + @cd ${CURRENT_DIR}/e2e && go test -mod=readonly -run TestAppStateDeterminism -Enabled=true \ + -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + +test-sim-nondeterminism-fast: + @echo "Running non-determinism test..." + @cd ${CURRENT_DIR}/e2e && go test -mod=readonly -run TestAppStateDeterminism -Enabled=true \ + -NumBlocks=10 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + +test-sim-import-export: + @echo "Running application import/export simulation. This may take several minutes..." + @cd ${CURRENT_DIR}/e2e && go test -mod=readonly -run TestAppImportExport -Enabled=true \ + -NumBlocks=10 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + +test-sim-after-import: + @echo "Running application simulation-after-import. This may take several minutes..." + @cd ${CURRENT_DIR}/e2e && go test -mod=readonly -run TestAppSimulationAfterImport -Enabled=true \ + -NumBlocks=10 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h \ No newline at end of file diff --git a/simapp/sim_bench_test.go b/simapp/sim_bench_test.go deleted file mode 100644 index 6d3a23aed..000000000 --- a/simapp/sim_bench_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package simapp - -// import ( -// "fmt" -// "os" -// "testing" - -// tmproto "github.com/cometbft/cometbft/proto/tendermint/types" -// "github.com/stretchr/testify/require" - -// "github.com/cosmos/cosmos-sdk/baseapp" -// "github.com/cosmos/cosmos-sdk/client/flags" -// "github.com/cosmos/cosmos-sdk/server" -// simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" -// simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -// "github.com/cosmos/cosmos-sdk/x/simulation" -// simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" -// ) - -// // Profile with: -// func BenchmarkFullAppSimulation(b *testing.B) { -// b.ReportAllocs() - -// config := simcli.NewConfigFromFlags() -// config.ChainID = SimAppChainID - -// db, dir, logger, skip, err := simtestutil.SetupSimulation( -// config, -// "leveldb-app-sim", -// "Simulation", -// simcli.FlagVerboseValue, -// simcli.FlagEnabledValue, -// ) -// if err != nil { -// b.Fatalf("simulation setup failed: %s", err.Error()) -// } - -// if skip { -// b.Skip("skipping benchmark application simulation") -// } - -// defer func() { -// require.NoError(b, db.Close()) -// require.NoError(b, os.RemoveAll(dir)) -// }() - -// appOptions := make(simtestutil.AppOptionsMap, 0) -// appOptions[flags.FlagHome] = DefaultNodeHome -// appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue - -// app := NewSimApp( -// logger, -// db, -// nil, -// true, -// appOptions, -// interBlockCacheOpt(), -// baseapp.SetChainID(config.ChainID), -// ) - -// // run randomized simulation -// _, simParams, simErr := simulation.SimulateFromSeed( -// b, -// os.Stdout, -// app.BaseApp, -// AppStateFn(app.AppCodec(), app.SimulationManager()), -// simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 -// simtestutil.SimulationOperations(app, app.AppCodec(), config), -// BlockedAddresses(), -// config, -// app.AppCodec(), -// ) - -// // export state and simParams before the simulation error is checked -// if err = simtestutil.CheckExportSimulation(app, config, simParams); err != nil { -// b.Fatal(err) -// } - -// if simErr != nil { -// b.Fatal(simErr) -// } - -// if config.Commit { -// simtestutil.PrintStats(db) -// } -// } - -// func BenchmarkInvariants(b *testing.B) { -// b.ReportAllocs() -// config := simcli.NewConfigFromFlags() -// config.ChainID = SimAppChainID - -// db, dir, logger, skip, err := simtestutil.SetupSimulation( -// config, -// "leveldb-app-sim", -// "Simulation", -// simcli.FlagVerboseValue, -// simcli.FlagEnabledValue, -// ) -// if err != nil { -// b.Fatalf("simulation setup failed: %s", err.Error()) -// } - -// if skip { -// b.Skip("skipping benchmark application simulation") -// } - -// config.AllInvariants = false - -// defer func() { -// require.NoError(b, db.Close()) -// require.NoError(b, os.RemoveAll(dir)) -// }() - -// appOptions := make(simtestutil.AppOptionsMap, 0) -// appOptions[flags.FlagHome] = DefaultNodeHome -// appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue - -// app := NewSimApp( -// logger, -// db, -// nil, -// true, -// appOptions, -// interBlockCacheOpt(), -// baseapp.SetChainID(config.ChainID), -// ) - -// // run randomized simulation -// _, simParams, simErr := simulation.SimulateFromSeed( -// b, -// os.Stdout, -// app.BaseApp, -// AppStateFn(app.AppCodec(), app.SimulationManager()), -// simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 -// simtestutil.SimulationOperations(app, app.AppCodec(), config), -// BlockedAddresses(), -// config, -// app.AppCodec(), -// ) - -// // export state and simParams before the simulation error is checked -// if err = simtestutil.CheckExportSimulation(app, config, simParams); err != nil { -// b.Fatal(err) -// } - -// if simErr != nil { -// b.Fatal(simErr) -// } - -// if config.Commit { -// simtestutil.PrintStats(db) -// } - -// ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight() + 1}) - -// // 3. Benchmark each invariant separately -// // -// // NOTE: We use the crisis keeper as it has all the invariants registered with -// // their respective metadata which makes it useful for testing/benchmarking. -// for _, cr := range app.CrisisKeeper.Routes() { -// cr := cr -// b.Run(fmt.Sprintf("%s/%s", cr.ModuleName, cr.Route), func(b *testing.B) { -// if res, stop := cr.Invar(ctx); stop { -// b.Fatalf( -// "broken invariant at block %d of %d\n%s", -// ctx.BlockHeight()-1, config.NumBlocks, res, -// ) -// } -// }) -// } -// } diff --git a/simapp/sim_test.go b/simapp/sim_test.go deleted file mode 100644 index c6b415aa3..000000000 --- a/simapp/sim_test.go +++ /dev/null @@ -1,509 +0,0 @@ -package simapp - -// import ( -// "encoding/hex" -// "encoding/json" -// "fmt" -// "math/rand" -// "os" -// "runtime/debug" -// "strings" -// "testing" - -// dbm "github.com/cometbft/cometbft-db" -// abci "github.com/cometbft/cometbft/abci/types" -// "github.com/cometbft/cometbft/libs/log" -// tmproto "github.com/cometbft/cometbft/proto/tendermint/types" -// "github.com/stretchr/testify/require" - -// "github.com/cosmos/cosmos-sdk/baseapp" -// "github.com/cosmos/cosmos-sdk/client/flags" -// "github.com/cosmos/cosmos-sdk/server" -// "github.com/cosmos/cosmos-sdk/store" -// storetypes "github.com/cosmos/cosmos-sdk/store/types" -// simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" -// sdk "github.com/cosmos/cosmos-sdk/types" -// simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -// authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -// banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -// capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" -// distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" -// evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" -// govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" -// minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" -// paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" -// "github.com/cosmos/cosmos-sdk/x/simulation" -// simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" -// slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" -// stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - -// coinswaptypes "github.com/irisnet/irismod/modules/coinswap/types" -// htlctypes "github.com/irisnet/irismod/modules/htlc/types" -// mttypes "github.com/irisnet/irismod/modules/mt/types" -// nfttypes "github.com/irisnet/irismod/modules/nft/types" -// oracletypes "github.com/irisnet/irismod/modules/oracle/types" -// randomtypes "github.com/irisnet/irismod/modules/random/types" -// servicetypes "github.com/irisnet/irismod/modules/service/types" -// tokentypes "github.com/irisnet/irismod/modules/token/types" -// "github.com/irisnet/irismod/simapp/helpers" -// ) - -// // SimAppChainID hardcoded chainID for simulation -// const SimAppChainID = "simulation-app" - -// // Get flags every time the simulator is run -// func init() { -// simcli.GetSimulatorFlags() -// } - -// type StoreKeysPrefixes struct { -// A storetypes.StoreKey -// B storetypes.StoreKey -// Prefixes [][]byte -// } - -// // fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of -// // an IAVLStore for faster simulation speed. -// func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { -// bapp.SetFauxMerkleMode() -// } - -// // interBlockCacheOpt returns a BaseApp option function that sets the persistent -// // inter-block write-through cache. -// func interBlockCacheOpt() func(*baseapp.BaseApp) { -// return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) -// } - -// func TestFullAppSimulation(t *testing.T) { -// config := simcli.NewConfigFromFlags() -// config.ChainID = SimAppChainID - -// db, dir, logger, skip, err := simtestutil.SetupSimulation( -// config, -// "leveldb-app-sim", -// "Simulation", -// simcli.FlagVerboseValue, -// simcli.FlagEnabledValue, -// ) -// if skip { -// t.Skip("skipping application simulation") -// } -// require.NoError(t, err, "simulation setup failed") - -// defer func() { -// require.NoError(t, db.Close()) -// require.NoError(t, os.RemoveAll(dir)) -// }() - -// appOptions := make(simtestutil.AppOptionsMap, 0) -// appOptions[flags.FlagHome] = DefaultNodeHome -// appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue - -// app := NewSimApp( -// logger, -// db, -// nil, -// true, -// appOptions, -// fauxMerkleModeOpt, -// baseapp.SetChainID(config.ChainID), -// ) -// require.Equal(t, "SimApp", app.Name()) - -// // run randomized simulation -// _, simParams, simErr := simulation.SimulateFromSeed( -// t, -// os.Stdout, -// app.BaseApp, -// AppStateFn(app.AppCodec(), app.SimulationManager()), -// simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 -// simtestutil.SimulationOperations(app, app.AppCodec(), config), -// BlockedAddresses(), -// config, -// app.AppCodec(), -// ) - -// // export state and simParams before the simulation error is checked -// err = simtestutil.CheckExportSimulation(app, config, simParams) -// require.NoError(t, err) -// require.NoError(t, simErr) - -// if config.Commit { -// simtestutil.PrintStats(db) -// } -// } - -// func TestAppImportExport(t *testing.T) { -// config := simcli.NewConfigFromFlags() -// config.ChainID = SimAppChainID - -// db, dir, logger, skip, err := simtestutil.SetupSimulation( -// config, -// "leveldb-app-sim", -// "Simulation", -// simcli.FlagVerboseValue, -// simcli.FlagEnabledValue, -// ) -// if skip { -// t.Skip("skipping application simulation") -// } -// require.NoError(t, err, "simulation setup failed") - -// defer func() { -// require.NoError(t, db.Close()) -// require.NoError(t, os.RemoveAll(dir)) -// }() - -// appOptions := make(simtestutil.AppOptionsMap, 0) -// appOptions[flags.FlagHome] = DefaultNodeHome -// appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue - -// app := NewSimApp( -// logger, -// db, -// nil, -// true, -// appOptions, -// fauxMerkleModeOpt, -// baseapp.SetChainID(config.ChainID), -// ) -// require.Equal(t, "SimApp", app.Name()) - -// // Run randomized simulation -// _, simParams, simErr := simulation.SimulateFromSeed( -// t, -// os.Stdout, -// app.BaseApp, -// AppStateFn(app.AppCodec(), app.SimulationManager()), -// simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 -// simtestutil.SimulationOperations(app, app.AppCodec(), config), -// BlockedAddresses(), -// config, -// app.AppCodec(), -// ) - -// // export state and simParams before the simulation error is checked -// err = simtestutil.CheckExportSimulation(app, config, simParams) -// require.NoError(t, err) -// require.NoError(t, simErr) - -// if config.Commit { -// simtestutil.PrintStats(db) -// } - -// fmt.Printf("exporting genesis...\n") - -// exported, err := app.ExportAppStateAndValidators(false, []string{}, []string{}) -// require.NoError(t, err) - -// fmt.Printf("importing genesis...\n") - -// newDB, newDir, _, _, err := simtestutil.SetupSimulation( -// config, -// "leveldb-app-sim-2", -// "Simulation-2", -// simcli.FlagVerboseValue, -// simcli.FlagEnabledValue, -// ) -// require.NoError(t, err, "simulation setup failed") - -// defer func() { -// require.NoError(t, newDB.Close()) -// require.NoError(t, os.RemoveAll(newDir)) -// }() - -// newApp := NewSimApp( -// log.NewNopLogger(), -// newDB, -// nil, -// true, -// appOptions, -// fauxMerkleModeOpt, -// baseapp.SetChainID(config.ChainID), -// ) -// require.Equal(t, "SimApp", newApp.Name()) - -// var genesisState GenesisState -// err = json.Unmarshal(exported.AppState, &genesisState) -// require.NoError(t, err) - -// defer func() { -// if r := recover(); r != nil { -// err := fmt.Sprintf("%v", r) -// if !strings.Contains(err, "validator set is empty after InitGenesis") { -// panic(r) -// } -// logger.Info("Skipping simulation as all validators have been unbonded") -// logger.Info("err", err, "stacktrace", string(debug.Stack())) -// } -// }() - -// ctxA := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) -// ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) -// newApp.ModuleManager.InitGenesis(ctxB, app.AppCodec(), genesisState) -// newApp.StoreConsensusParams(ctxB, exported.ConsensusParams) - -// fmt.Printf("comparing stores...\n") - -// storeKeysPrefixes := []StoreKeysPrefixes{ -// {app.GetKey(authtypes.StoreKey), newApp.GetKey(authtypes.StoreKey), [][]byte{}}, -// {app.GetKey(stakingtypes.StoreKey), newApp.GetKey(stakingtypes.StoreKey), -// [][]byte{ -// stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, -// stakingtypes.ValidatorQueueKey, stakingtypes.HistoricalInfoKey, -// }}, // ordering may change but it doesn't matter -// {app.GetKey(slashingtypes.StoreKey), newApp.GetKey(slashingtypes.StoreKey), [][]byte{}}, -// {app.GetKey(minttypes.StoreKey), newApp.GetKey(minttypes.StoreKey), [][]byte{}}, -// {app.GetKey(distrtypes.StoreKey), newApp.GetKey(distrtypes.StoreKey), [][]byte{}}, -// { -// app.GetKey(banktypes.StoreKey), -// newApp.GetKey(banktypes.StoreKey), -// [][]byte{banktypes.BalancesPrefix}, -// }, -// {app.GetKey(paramtypes.StoreKey), newApp.GetKey(paramtypes.StoreKey), [][]byte{}}, -// {app.GetKey(govtypes.StoreKey), newApp.GetKey(govtypes.StoreKey), [][]byte{}}, -// {app.GetKey(evidencetypes.StoreKey), newApp.GetKey(evidencetypes.StoreKey), [][]byte{}}, -// {app.GetKey(capabilitytypes.StoreKey), newApp.GetKey(capabilitytypes.StoreKey), [][]byte{}}, - -// // check irismod module -// {app.GetKey(tokentypes.StoreKey), newApp.GetKey(tokentypes.StoreKey), [][]byte{}}, -// {app.GetKey(oracletypes.StoreKey), newApp.GetKey(oracletypes.StoreKey), [][]byte{}}, -// //mt.Supply is InitSupply, can be not equal to TotalSupply -// {app.GetKey(mttypes.StoreKey), newApp.GetKey(mttypes.StoreKey), [][]byte{mttypes.PrefixMT}}, -// {app.GetKey(nfttypes.StoreKey), newApp.GetKey(nfttypes.StoreKey), [][]byte{{0x05}}}, -// { -// app.GetKey(servicetypes.StoreKey), -// newApp.GetKey(servicetypes.StoreKey), -// [][]byte{servicetypes.InternalCounterKey}, -// }, -// { -// app.GetKey(randomtypes.StoreKey), -// newApp.GetKey(randomtypes.StoreKey), -// [][]byte{randomtypes.RandomKey}, -// }, -// //{app.keys[recordtypes.StoreKey), newApp.keys[recordtypes.StoreKey), [][]byte{recordtypes.IntraTxCounterKey}}, -// {app.GetKey(htlctypes.StoreKey), newApp.GetKey(htlctypes.StoreKey), [][]byte{}}, -// {app.GetKey(coinswaptypes.StoreKey), newApp.GetKey(coinswaptypes.StoreKey), [][]byte{}}, -// } - -// for _, skp := range storeKeysPrefixes { -// storeA := ctxA.KVStore(skp.A) -// storeB := ctxB.KVStore(skp.B) - -// failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, skp.Prefixes) -// require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare") - -// fmt.Printf( -// "compared %d different key/value pairs between %s and %s\n", -// len(failedKVAs), -// skp.A, -// skp.B, -// ) -// for _, kv := range failedKVAs { -// fmt.Printf("storeKey: %s,\n failedKVBs: %v,\n ", skp.A.Name(), kv.Key) -// } -// require.Equal( -// t, -// 0, -// len(failedKVAs), -// simtestutil.GetSimulationLog( -// skp.A.Name(), -// app.SimulationManager().StoreDecoders, -// failedKVAs, -// failedKVBs, -// ), -// ) -// } -// } - -// func TestAppSimulationAfterImport(t *testing.T) { -// config := simcli.NewConfigFromFlags() -// config.ChainID = SimAppChainID - -// db, dir, logger, skip, err := simtestutil.SetupSimulation( -// config, -// "leveldb-app-sim", -// "Simulation", -// simcli.FlagVerboseValue, -// simcli.FlagEnabledValue, -// ) -// if skip { -// t.Skip("skipping application simulation") -// } -// require.NoError(t, err, "simulation setup failed") - -// defer func() { -// require.NoError(t, db.Close()) -// require.NoError(t, os.RemoveAll(dir)) -// }() - -// appOptions := make(simtestutil.AppOptionsMap, 0) -// appOptions[flags.FlagHome] = DefaultNodeHome -// appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue - -// app := NewSimApp( -// logger, -// db, -// nil, -// true, -// appOptions, -// fauxMerkleModeOpt, -// baseapp.SetChainID(config.ChainID), -// ) -// require.Equal(t, "SimApp", app.Name()) - -// // Run randomized simulation -// stopEarly, simParams, simErr := simulation.SimulateFromSeed( -// t, -// os.Stdout, -// app.BaseApp, -// AppStateFn(app.AppCodec(), app.SimulationManager()), -// simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 -// simtestutil.SimulationOperations(app, app.AppCodec(), config), -// BlockedAddresses(), -// config, -// app.AppCodec(), -// ) - -// // export state and simParams before the simulation error is checked -// err = simtestutil.CheckExportSimulation(app, config, simParams) -// require.NoError(t, err) -// require.NoError(t, simErr) - -// if config.Commit { -// simtestutil.PrintStats(db) -// } - -// if stopEarly { -// fmt.Println("can't export or import a zero-validator genesis, exiting test...") -// return -// } - -// fmt.Printf("exporting genesis...\n") - -// exported, err := app.ExportAppStateAndValidators(true, []string{}, []string{}) -// require.NoError(t, err) - -// fmt.Printf("importing genesis...\n") - -// newDB, newDir, _, _, err := simtestutil.SetupSimulation( -// config, -// "leveldb-app-sim-2", -// "Simulation-2", -// simcli.FlagVerboseValue, -// simcli.FlagEnabledValue, -// ) -// require.NoError(t, err, "simulation setup failed") - -// defer func() { -// require.NoError(t, newDB.Close()) -// require.NoError(t, os.RemoveAll(newDir)) -// }() - -// newApp := NewSimApp( -// log.NewNopLogger(), -// newDB, -// nil, -// true, -// appOptions, -// fauxMerkleModeOpt, -// baseapp.SetChainID(config.ChainID), -// ) -// require.Equal(t, "SimApp", newApp.Name()) - -// newApp.InitChain(abci.RequestInitChain{ -// AppStateBytes: exported.AppState, -// }) -// _, _, err = simulation.SimulateFromSeed( -// t, -// os.Stdout, -// newApp.BaseApp, -// AppStateFn(app.AppCodec(), app.SimulationManager()), -// simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 -// simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config), -// BlockedAddresses(), -// config, -// app.AppCodec(), -// ) -// require.NoError(t, err) -// } - -// // TODO: Make another test for the fuzzer itself, which just has noOp txs -// // and doesn't depend on the application. -// func TestAppStateDeterminism(t *testing.T) { -// if !simcli.FlagEnabledValue { -// t.Skip("skipping application simulation") -// } - -// config := simcli.NewConfigFromFlags() -// config.InitialBlockHeight = 1 -// config.ExportParamsPath = "" -// config.OnOperation = false -// config.AllInvariants = false -// config.ChainID = helpers.SimAppChainID - -// numSeeds := 3 -// numTimesToRunPerSeed := 5 -// appHashList := make([]json.RawMessage, numTimesToRunPerSeed) - -// appOptions := make(simtestutil.AppOptionsMap, 0) -// appOptions[flags.FlagHome] = DefaultNodeHome -// appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue - -// for i := 0; i < numSeeds; i++ { -// config.Seed = rand.Int63() - -// for j := 0; j < numTimesToRunPerSeed; j++ { -// var logger log.Logger -// if simcli.FlagVerboseValue { -// logger = log.TestingLogger() -// } else { -// logger = log.NewNopLogger() -// } - -// db := dbm.NewMemDB() -// app := NewSimApp( -// logger, -// db, -// nil, -// true, -// appOptions, -// interBlockCacheOpt(), -// baseapp.SetChainID(config.ChainID), -// ) - -// fmt.Printf( -// "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", -// config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, -// ) - -// _, _, err := simulation.SimulateFromSeed( -// t, -// os.Stdout, -// app.BaseApp, -// AppStateFn(app.AppCodec(), app.SimulationManager()), -// simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 -// simtestutil.SimulationOperations(app, app.AppCodec(), config), -// BlockedAddresses(), -// config, -// app.AppCodec(), -// ) -// require.NoError(t, err) - -// if config.Commit { -// simtestutil.PrintStats(db) -// } - -// appHash := app.LastCommitID().Hash -// appHashList[j] = appHash - -// if j != 0 { -// require.Equal( -// t, hex.EncodeToString(appHashList[0]), hex.EncodeToString(appHashList[j]), -// "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", -// config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, -// ) -// } -// } -// } -// }