diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eb9bf2f7fa..4510e5e5e2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -127,84 +127,4 @@ jobs: name: ethermint signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" - name: 'instantiate integration test env' - run: nix-store -r $(nix-instantiate tests/integration_tests/shell.nix) - - test-sim-nondeterminism: - runs-on: ubuntu-latest - timeout-minutes: 25 - steps: - - uses: actions/setup-go@v3 - with: - go-version: 1.19 - check-latest: true - - uses: actions/checkout@v3 - - uses: technote-space/get-diff-action@v6.1.1 - with: - PATTERNS: | - **/**.go - go.mod - go.sum - - name: Test simulation nondeterminism - run: | - make test-sim-nondeterminism - if: env.GIT_DIFF - - test-sim-random-genesis-fast: - runs-on: ubuntu-latest - timeout-minutes: 25 - steps: - - uses: actions/setup-go@v3 - with: - go-version: 1.19 - check-latest: true - - uses: actions/checkout@v3 - - uses: technote-space/get-diff-action@v6.1.1 - with: - PATTERNS: | - **/**.go - go.mod - go.sum - - name: Test simulation with random genesis - run: | - make test-sim-random-genesis-fast - if: env.GIT_DIFF - - test-sim-import-export: - runs-on: ubuntu-latest - timeout-minutes: 25 - steps: - - uses: actions/setup-go@v3 - with: - go-version: 1.19 - check-latest: true - - uses: actions/checkout@v3 - - uses: technote-space/get-diff-action@v6.1.1 - with: - PATTERNS: | - **/**.go - go.mod - go.sum - - name: Simulation of import and export genesis - run: | - make test-sim-import-export - if: env.GIT_DIFF - - test-sim-after-import: - runs-on: ubuntu-latest - timeout-minutes: 25 - steps: - - uses: actions/setup-go@v3 - with: - go-version: 1.19 - check-latest: true - - uses: actions/checkout@v3 - - uses: technote-space/get-diff-action@v6.1.1 - with: - PATTERNS: | - **/**.go - go.mod - go.sum - - name: Test simulation after import - run: | - make test-sim-after-import - if: env.GIT_DIFF + run: nix-store -r "$(nix-instantiate tests/integration_tests/shell.nix)" diff --git a/CHANGELOG.md b/CHANGELOG.md index c1d14b738a..438301dd8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (tests) [#1507](https://github.com/evmos/ethermint/pull/1507) Remove legacy sim tests * (feemarket) [#1508](https://github.com/evmos/ethermint/pull/1508) Remove old x/params migration logic * (evm) [#1499](https://github.com/evmos/ethermint/pull/1499) Add Shanghai and Cancun block * (ante) [#1455](https://github.com/evmos/ethermint/pull/1455) Refactor `AnteHandler` logic diff --git a/Makefile b/Makefile index 765d8cc452..2d698c74bc 100644 --- a/Makefile +++ b/Makefile @@ -343,51 +343,6 @@ test-solidity: .PHONY: run-tests test test-all test-import test-rpc test-contract test-solidity $(TEST_TARGETS) -test-sim-nondeterminism: - @echo "Running non-determinism test..." - @go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \ - -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h - -test-sim-random-genesis-fast: - @echo "Running random genesis simulation..." - @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation \ - -Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h - -test-sim-import-export: runsim - @echo "Running application import/export simulation. This may take several minutes..." - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppImportExport - -test-sim-after-import: runsim - @echo "Running application simulation-after-import. This may take several minutes..." - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppSimulationAfterImport - -test-sim-random-genesis-multi-seed: runsim - @echo "Running multi-seed custom genesis simulation..." - @$(BINDIR)/runsim -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation - -test-sim-multi-seed-long: runsim - @echo "Running long multi-seed application simulation. This may take awhile!" - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation - -test-sim-multi-seed-short: runsim - @echo "Running short multi-seed application simulation. This may take awhile!" - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation - -test-sim-benchmark-invariants: - @echo "Running simulation invariant benchmarks..." - @go test -mod=readonly $(SIMAPP) -benchmem -bench=BenchmarkInvariants -run=^$ \ - -Enabled=true -NumBlocks=1000 -BlockSize=200 \ - -Period=1 -Commit=true -Seed=57 -v -timeout 24h - -.PHONY: \ -test-sim-nondeterminism \ -test-sim-custom-genesis-fast \ -test-sim-import-export \ -test-sim-after-import \ -test-sim-custom-genesis-multi-seed \ -test-sim-multi-seed-short \ -test-sim-multi-seed-long \ -test-sim-benchmark-invariants benchmark: @go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION) diff --git a/app/ante/signverify_test.go b/app/ante/signverify_test.go index 526c2867b3..6dd8b2dd2b 100644 --- a/app/ante/signverify_test.go +++ b/app/ante/signverify_test.go @@ -10,7 +10,6 @@ import ( evmtypes "github.com/evmos/ethermint/x/evm/types" ) - func (suite AnteTestSuite) TestEthSigVerificationDecorator() { addr, privKey := tests.NewAddrKey() diff --git a/app/app.go b/app/app.go index 2f32266ae2..2e0e265c82 100644 --- a/app/app.go +++ b/app/app.go @@ -182,8 +182,6 @@ var ( } ) -var _ simapp.App = (*EthermintApp)(nil) - // var _ server.Application (*EthermintApp)(nil) // EthermintApp implements an extended ABCI application. It is an application @@ -233,9 +231,6 @@ type EthermintApp struct { // the module manager mm *module.Manager - // simulation manager - sm *module.SimulationManager - // the configurator configurator module.Configurator } @@ -600,17 +595,6 @@ func NewEthermintApp( // add test gRPC service for testing gRPC queries in isolation // testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{}) - // create the simulation manager and define the order of the modules for deterministic simulations - // - // NOTE: this is not required apps that don't use the simulator for fuzz testing - // transactions - overrideModules := map[string]module.AppModuleSimulation{ - authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), - } - app.sm = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules) - - app.sm.RegisterStoreDecoders() - // initialize stores app.MountKVStores(keys) app.MountTransientStores(tkeys) @@ -780,11 +764,6 @@ func (app *EthermintApp) GetSubspace(moduleName string) paramstypes.Subspace { return subspace } -// SimulationManager implements the SimulationApp interface -func (app *EthermintApp) SimulationManager() *module.SimulationManager { - return app.sm -} - // RegisterAPIRoutes registers all application module routes with the provided // API server. func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { diff --git a/app/simulation_test.go b/app/simulation_test.go deleted file mode 100644 index 2f1d1b2231..0000000000 --- a/app/simulation_test.go +++ /dev/null @@ -1,403 +0,0 @@ -package app - -// TODO: COsmos SDK fix for the simulator issue for custom keys -import ( - "encoding/json" - "fmt" - "math/rand" - "os" - "runtime/debug" - "strings" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/simapp/params" - "github.com/cosmos/cosmos-sdk/store" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" - 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" - slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - ibctransfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" - ibchost "github.com/cosmos/ibc-go/v5/modules/core/24-host" - "github.com/evmos/ethermint/app/ante" - evmenc "github.com/evmos/ethermint/encoding" - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/log" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - dbm "github.com/tendermint/tm-db" -) - -// MakeEncodingConfig creates the EncodingConfig -func MakeEncodingConfig() params.EncodingConfig { - return evmenc.MakeConfig(ModuleBasics) -} - -func init() { - simapp.GetSimulatorFlags() -} - -const SimAppChainID = "simulation_777-1" - -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() -} - -// NewSimApp disable feemarket on native tx, otherwise the cosmos-sdk simulation tests will fail. -func NewSimApp(logger log.Logger, db dbm.DB) (*EthermintApp, error) { - encodingConfig := MakeEncodingConfig() - app := NewEthermintApp(logger, db, nil, false, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, encodingConfig, simapp.EmptyAppOptions{}, fauxMerkleModeOpt) - // disable feemarket on native tx - anteHandler, err := ante.NewAnteHandler(ante.HandlerOptions{ - AccountKeeper: app.AccountKeeper, - BankKeeper: app.BankKeeper, - SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), - FeegrantKeeper: app.FeeGrantKeeper, - SigGasConsumer: ante.DefaultSigVerificationGasConsumer, - IBCKeeper: app.IBCKeeper, - EvmKeeper: app.EvmKeeper, - FeeMarketKeeper: app.FeeMarketKeeper, - MaxTxGasWanted: 0, - }) - if err != nil { - return nil, err - } - app.SetAnteHandler(anteHandler) - if err := app.LoadLatestVersion(); err != nil { - return nil, err - } - return app, nil -} - -// 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, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation") - if skip { - t.Skip("skipping application simulation") - } - require.NoError(t, err, "simulation setup failed") - - config.ChainID = SimAppChainID - - defer func() { - require.NoError(t, db.Close()) - require.NoError(t, os.RemoveAll(dir)) - }() - - app, err := NewSimApp(logger, db) - require.Equal(t, appName, app.Name()) - require.NoError(t, err) - - // run randomized simulation - _, simParams, simErr := simulation.SimulateFromSeed( - t, - os.Stdout, - app.BaseApp, - StateFn(app.AppCodec(), app.SimulationManager()), - RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simapp.SimulationOperations(app, app.AppCodec(), config), - app.ModuleAccountAddrs(), - config, - app.AppCodec(), - ) - - // export state and simParams before the simulation error is checked - err = simapp.CheckExportSimulation(app, config, simParams) - require.NoError(t, err) - require.NoError(t, simErr) - - if config.Commit { - simapp.PrintStats(db) - } -} - -func TestAppImportExport(t *testing.T) { - config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation") - if skip { - t.Skip("skipping application import/export simulation") - } - require.NoError(t, err, "simulation setup failed") - - config.ChainID = SimAppChainID - - defer func() { - require.NoError(t, db.Close()) - require.NoError(t, os.RemoveAll(dir)) - }() - app, err := NewSimApp(logger, db) - require.NoError(t, err) - require.Equal(t, appName, app.Name()) - - // Run randomized simulation - _, simParams, simErr := simulation.SimulateFromSeed( - t, - os.Stdout, - app.BaseApp, - StateFn(app.AppCodec(), app.SimulationManager()), - RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simapp.SimulationOperations(app, app.AppCodec(), config), - app.ModuleAccountAddrs(), - config, - app.AppCodec(), - ) - - // export state and simParams before the simulation error is checked - err = simapp.CheckExportSimulation(app, config, simParams) - require.NoError(t, err) - require.NoError(t, simErr) - - if config.Commit { - simapp.PrintStats(db) - } - - fmt.Printf("exporting genesis...\n") - - exported, err := app.ExportAppStateAndValidators(false, []string{}) - require.NoError(t, err) - - fmt.Printf("importing genesis...\n") - - //nolint: dogsled - _, newDB, newDir, _, _, err := simapp.SetupSimulation("leveldb-app-sim-2", "Simulation-2") - require.NoError(t, err, "simulation setup failed") - - defer func() { - require.NoError(t, newDB.Close()) - require.NoError(t, os.RemoveAll(newDir)) - }() - - newApp, err := NewSimApp(log.NewNopLogger(), newDB) - require.Equal(t, appName, newApp.Name()) - require.NoError(t, err) - - 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(), ChainID: SimAppChainID}) - ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight(), ChainID: SimAppChainID}) - newApp.mm.InitGenesis(ctxB, app.AppCodec(), genesisState) - newApp.StoreConsensusParams(ctxB, exported.ConsensusParams) - - fmt.Printf("comparing stores...\n") - - storeKeysPrefixes := []storeKeysPrefixes{ - {app.keys[authtypes.StoreKey], newApp.keys[authtypes.StoreKey], [][]byte{}}, - { - app.keys[stakingtypes.StoreKey], newApp.keys[stakingtypes.StoreKey], - [][]byte{ - stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey, - stakingtypes.HistoricalInfoKey, - }, - }, // ordering may change but it doesn't matter - {app.keys[slashingtypes.StoreKey], newApp.keys[slashingtypes.StoreKey], [][]byte{}}, - {app.keys[minttypes.StoreKey], newApp.keys[minttypes.StoreKey], [][]byte{}}, - {app.keys[distrtypes.StoreKey], newApp.keys[distrtypes.StoreKey], [][]byte{}}, - {app.keys[banktypes.StoreKey], newApp.keys[banktypes.StoreKey], [][]byte{banktypes.BalancesPrefix}}, - {app.keys[paramtypes.StoreKey], newApp.keys[paramtypes.StoreKey], [][]byte{}}, - {app.keys[govtypes.StoreKey], newApp.keys[govtypes.StoreKey], [][]byte{}}, - {app.keys[evidencetypes.StoreKey], newApp.keys[evidencetypes.StoreKey], [][]byte{}}, - {app.keys[capabilitytypes.StoreKey], newApp.keys[capabilitytypes.StoreKey], [][]byte{}}, - {app.keys[authzkeeper.StoreKey], newApp.keys[authzkeeper.StoreKey], [][]byte{authzkeeper.GrantKey, authzkeeper.GrantQueuePrefix}}, - {app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}}, - {app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.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) - require.Equal(t, len(failedKVAs), 0, simapp.GetSimulationLog(skp.A.Name(), app.SimulationManager().StoreDecoders, failedKVAs, failedKVBs)) - } -} - -func TestAppSimulationAfterImport(t *testing.T) { - config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation") - if skip { - t.Skip("skipping application simulation after import") - } - require.NoError(t, err, "simulation setup failed") - - config.ChainID = SimAppChainID - - defer func() { - require.NoError(t, db.Close()) - require.NoError(t, os.RemoveAll(dir)) - }() - - app, err := NewSimApp(logger, db) - require.Equal(t, appName, app.Name()) - require.NoError(t, err) - - // Run randomized simulation - stopEarly, simParams, simErr := simulation.SimulateFromSeed( - t, - os.Stdout, - app.BaseApp, - StateFn(app.AppCodec(), app.SimulationManager()), - RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simapp.SimulationOperations(app, app.AppCodec(), config), - app.ModuleAccountAddrs(), - config, - app.AppCodec(), - ) - - // export state and simParams before the simulation error is checked - err = simapp.CheckExportSimulation(app, config, simParams) - require.NoError(t, err) - require.NoError(t, simErr) - - if config.Commit { - simapp.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{}) - require.NoError(t, err) - - fmt.Printf("importing genesis...\n") - - _, newDB, newDir, _, _, err := simapp.SetupSimulation("leveldb-app-sim-2", "Simulation-2") - require.NoError(t, err, "simulation setup failed") - - defer func() { - require.NoError(t, newDB.Close()) - require.NoError(t, os.RemoveAll(newDir)) - }() - - newApp, err := NewSimApp(log.NewNopLogger(), newDB) - require.Equal(t, appName, newApp.Name()) - require.NoError(t, err) - - newApp.InitChain(abci.RequestInitChain{ - ChainId: SimAppChainID, - AppStateBytes: exported.AppState, - }) - - _, _, err = simulation.SimulateFromSeed( - t, - os.Stdout, - newApp.BaseApp, - StateFn(app.AppCodec(), app.SimulationManager()), - RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simapp.SimulationOperations(newApp, newApp.AppCodec(), config), - app.ModuleAccountAddrs(), - 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 !simapp.FlagEnabledValue { - t.Skip("skipping application simulation") - } - - config := simapp.NewConfigFromFlags() - config.InitialBlockHeight = 1 - config.ExportParamsPath = "" - config.OnOperation = false - config.AllInvariants = false - config.ChainID = SimAppChainID - - numSeeds := 3 - numTimesToRunPerSeed := 5 - appHashList := make([]json.RawMessage, numTimesToRunPerSeed) - - for i := 0; i < numSeeds; i++ { - config.Seed = rand.Int63() - - for j := 0; j < numTimesToRunPerSeed; j++ { - var logger log.Logger - if simapp.FlagVerboseValue { - logger = log.TestingLogger() - } else { - logger = log.NewNopLogger() - } - - db := dbm.NewMemDB() - app, err := NewSimApp(logger, db) - require.NoError(t, err) - - 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, - StateFn(app.AppCodec(), app.SimulationManager()), - RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simapp.SimulationOperations(app, app.AppCodec(), config), - app.ModuleAccountAddrs(), - config, - app.AppCodec(), - ) - require.NoError(t, err) - - if config.Commit { - simapp.PrintStats(db) - } - - appHash := app.LastCommitID().Hash - appHashList[j] = appHash - - if j != 0 { - require.Equal( - t, string(appHashList[0]), string(appHashList[j]), - "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, - ) - } - } - } -} diff --git a/app/utils.go b/app/utils.go index 03fefdbe0f..38e8dcc0a5 100644 --- a/app/utils.go +++ b/app/utils.go @@ -2,7 +2,6 @@ package app import ( "encoding/json" - "math/rand" "time" "github.com/cosmos/cosmos-sdk/codec" @@ -11,21 +10,12 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/mock" - "github.com/cosmos/cosmos-sdk/types/module" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/evmos/ethermint/encoding" - ethermint "github.com/evmos/ethermint/types" - evmtypes "github.com/evmos/ethermint/x/evm/types" - - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/evmos/ethermint/crypto/ethsecp256k1" + "github.com/evmos/ethermint/encoding" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -94,96 +84,6 @@ func SetupWithDB(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.Genesis return app } -// RandomGenesisAccounts is used by the auth module to create random genesis accounts in simulation when a genesis.json is not specified. -// In contrast, the default auth module's RandomGenesisAccounts implementation creates only base accounts and vestings accounts. -func RandomGenesisAccounts(simState *module.SimulationState) authtypes.GenesisAccounts { - emptyCodeHash := crypto.Keccak256(nil) - genesisAccs := make(authtypes.GenesisAccounts, len(simState.Accounts)) - for i, acc := range simState.Accounts { - bacc := authtypes.NewBaseAccountWithAddress(acc.Address) - - ethacc := ðermint.EthAccount{ - BaseAccount: bacc, - CodeHash: common.BytesToHash(emptyCodeHash).String(), - } - genesisAccs[i] = ethacc - } - - return genesisAccs -} - -// RandomAccounts creates random accounts with an ethsecp256k1 private key -// TODO: replace secp256k1.GenPrivKeyFromSecret() with similar function in go-ethereum -func RandomAccounts(r *rand.Rand, n int) []simtypes.Account { - accs := make([]simtypes.Account, n) - - for i := 0; i < n; i++ { - // don't need that much entropy for simulation - privkeySeed := make([]byte, 15) - _, _ = r.Read(privkeySeed) - - prv := secp256k1.GenPrivKeyFromSecret(privkeySeed) - ethPrv := ðsecp256k1.PrivKey{} - _ = ethPrv.UnmarshalAmino(prv.Bytes()) // UnmarshalAmino simply copies the bytes and assigns them to ethPrv.Key - accs[i].PrivKey = ethPrv - accs[i].PubKey = accs[i].PrivKey.PubKey() - accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address()) - - accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(privkeySeed) - } - - return accs -} - -// StateFn returns the initial application state using a genesis or the simulation parameters. -// It is a wrapper of simapp.AppStateFn to replace evm param EvmDenom with staking param BondDenom. -func StateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn { - return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, - ) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) { - appStateFn := simapp.AppStateFn(cdc, simManager) - appState, simAccs, chainID, genesisTimestamp = appStateFn(r, accs, config) - - rawState := make(map[string]json.RawMessage) - err := json.Unmarshal(appState, &rawState) - if err != nil { - panic(err) - } - - stakingStateBz, ok := rawState[stakingtypes.ModuleName] - if !ok { - panic("staking genesis state is missing") - } - - stakingState := new(stakingtypes.GenesisState) - cdc.MustUnmarshalJSON(stakingStateBz, stakingState) - - // we should get the BondDenom and make it the evmdenom. - // thus simulation accounts could have positive amount of gas token. - bondDenom := stakingState.Params.BondDenom - - evmStateBz, ok := rawState[evmtypes.ModuleName] - if !ok { - panic("evm genesis state is missing") - } - - evmState := new(evmtypes.GenesisState) - cdc.MustUnmarshalJSON(evmStateBz, evmState) - - // we should replace the EvmDenom with BondDenom - evmState.Params.EvmDenom = bondDenom - - // change appState back - rawState[evmtypes.ModuleName] = cdc.MustMarshalJSON(evmState) - - // replace appstate - appState, err = json.Marshal(rawState) - if err != nil { - panic(err) - } - return appState, simAccs, chainID, genesisTimestamp - } -} - // NewTestGenesisState generate genesis state with single validator func NewTestGenesisState(codec codec.Codec) simapp.GenesisState { privVal := mock.NewPV() diff --git a/app/utils_test.go b/app/utils_test.go deleted file mode 100644 index ff233ea263..0000000000 --- a/app/utils_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package app - -import ( - "encoding/json" - "math/rand" - "os" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/types/module" - "github.com/cosmos/cosmos-sdk/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - evmtypes "github.com/evmos/ethermint/x/evm/types" - - "github.com/evmos/ethermint/crypto/ethsecp256k1" - ethermint "github.com/evmos/ethermint/types" - - "github.com/cosmos/cosmos-sdk/simapp" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -var ( - maxTestingAccounts = 100 - seed = int64(233) -) - -func TestRandomGenesisAccounts(t *testing.T) { - r := rand.New(rand.NewSource(seed)) - accs := RandomAccounts(r, rand.Intn(maxTestingAccounts)) - - encodingConfig := MakeEncodingConfig() - appCodec := encodingConfig.Codec - cdc := encodingConfig.Amino - - paramsKeeper := initParamsKeeper(appCodec, cdc, sdk.NewKVStoreKey(paramstypes.StoreKey), sdk.NewTransientStoreKey(paramstypes.StoreKey)) - subSpace, find := paramsKeeper.GetSubspace(authtypes.ModuleName) - require.True(t, find) - accountKeeper := authkeeper.NewAccountKeeper( - appCodec, sdk.NewKVStoreKey(authtypes.StoreKey), subSpace, ethermint.ProtoAccount, maccPerms, sdk.GetConfig().GetBech32AccountAddrPrefix(), - ) - authModule := auth.NewAppModule(appCodec, accountKeeper, RandomGenesisAccounts) - - genesisState := simapp.NewDefaultGenesisState(appCodec) - simState := &module.SimulationState{Accounts: accs, Cdc: appCodec, Rand: r, GenState: genesisState} - authModule.GenerateGenesisState(simState) - - authStateBz, find := genesisState[authtypes.ModuleName] - require.True(t, find) - - authState := new(authtypes.GenesisState) - appCodec.MustUnmarshalJSON(authStateBz, authState) - accounts, err := authtypes.UnpackAccounts(authState.Accounts) - require.NoError(t, err) - for _, acc := range accounts { - _, ok := acc.(ethermint.EthAccountI) - require.True(t, ok) - } -} - -func TestStateFn(t *testing.T) { - config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation") - if skip { - t.Skip("skipping AppStateFn testing") - } - require.NoError(t, err, "simulation setup failed") - - config.ChainID = SimAppChainID - config.Commit = true - - defer func() { - db.Close() - require.NoError(t, os.RemoveAll(dir)) - }() - - app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt) - require.Equal(t, appName, app.Name()) - - appStateFn := StateFn(app.AppCodec(), app.SimulationManager()) - r := rand.New(rand.NewSource(seed)) - accounts := RandomAccounts(r, rand.Intn(maxTestingAccounts)) - appState, _, _, _ := appStateFn(r, accounts, config) - - rawState := make(map[string]json.RawMessage) - err = json.Unmarshal(appState, &rawState) - require.NoError(t, err) - - stakingStateBz, ok := rawState[stakingtypes.ModuleName] - require.True(t, ok) - - stakingState := new(stakingtypes.GenesisState) - app.AppCodec().MustUnmarshalJSON(stakingStateBz, stakingState) - bondDenom := stakingState.Params.BondDenom - - evmStateBz, ok := rawState[evmtypes.ModuleName] - require.True(t, ok) - - evmState := new(evmtypes.GenesisState) - app.AppCodec().MustUnmarshalJSON(evmStateBz, evmState) - require.Equal(t, bondDenom, evmState.Params.EvmDenom) -} - -func TestRandomAccounts(t *testing.T) { - r := rand.New(rand.NewSource(seed)) - accounts := RandomAccounts(r, rand.Intn(maxTestingAccounts)) - for _, acc := range accounts { - _, ok := acc.PrivKey.(*ethsecp256k1.PrivKey) - require.True(t, ok) - } -} diff --git a/x/evm/module.go b/x/evm/module.go index 17aac6cf1f..43161fab9b 100644 --- a/x/evm/module.go +++ b/x/evm/module.go @@ -21,7 +21,6 @@ import ( "github.com/evmos/ethermint/x/evm/client/cli" "github.com/evmos/ethermint/x/evm/keeper" - "github.com/evmos/ethermint/x/evm/simulation" "github.com/evmos/ethermint/x/evm/types" ) @@ -65,7 +64,7 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingCo // RegisterRESTRoutes performs a no-op as the EVM module doesn't expose REST // endpoints -func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { +func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) { } func (b AppModuleBasic) RegisterGRPCGatewayRoutes(c client.Context, serveMux *runtime.ServeMux) { @@ -114,7 +113,7 @@ func (AppModule) Name() string { // RegisterInvariants interface for registering invariants. Performs a no-op // as the evm module doesn't expose invariants. -func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) { } // RegisterServices registers a GRPC query service to respond to the @@ -134,7 +133,7 @@ func (AppModule) QuerierRoute() string { return types.RouterKey } // LegacyQuerierHandler returns nil as the evm module doesn't expose a legacy // Querier. -func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { +func (am AppModule) LegacyQuerierHandler(_ *codec.LegacyAmino) sdk.Querier { return nil } @@ -167,28 +166,24 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // RandomizedParams creates randomized evm param changes for the simulator. -func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { - return simulation.ParamChanges(r) +func (AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { + return nil } // RegisterStoreDecoder registers a decoder for evm module's types -func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { - sdr[types.StoreKey] = simulation.NewDecodeStore() +func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) { } // ProposalContents doesn't return any content functions for governance proposals. -func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { +func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { return nil } // GenerateGenesisState creates a randomized GenState of the evm module. -func (AppModule) GenerateGenesisState(simState *module.SimulationState) { - simulation.RandomizedGenState(simState) +func (AppModule) GenerateGenesisState(_ *module.SimulationState) { } // WeightedOperations returns the all the evm module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, am.ak, am.keeper, - ) +func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { + return nil } diff --git a/x/evm/simulation/decoder.go b/x/evm/simulation/decoder.go deleted file mode 100644 index ec2cdf4230..0000000000 --- a/x/evm/simulation/decoder.go +++ /dev/null @@ -1,31 +0,0 @@ -package simulation - -import ( - "bytes" - "fmt" - - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/ethereum/go-ethereum/common" - "github.com/evmos/ethermint/x/evm/types" -) - -// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's -// value to the corresponding EVM type. -func NewDecodeStore() func(kvA, kvB kv.Pair) string { - return func(kvA, kvB kv.Pair) string { - switch { - case bytes.Equal(kvA.Key[:1], types.KeyPrefixStorage): - storageA := common.BytesToHash(kvA.Value).Hex() - storageB := common.BytesToHash(kvB.Value).Hex() - - return fmt.Sprintf("%v\n%v", storageA, storageB) - case bytes.Equal(kvA.Key[:1], types.KeyPrefixCode): - codeHashA := common.Bytes2Hex(kvA.Value) - codeHashB := common.Bytes2Hex(kvB.Value) - - return fmt.Sprintf("%v\n%v", codeHashA, codeHashB) - default: - panic(fmt.Sprintf("invalid evm key prefix %X", kvA.Key[:1])) - } - } -} diff --git a/x/evm/simulation/decoder_test.go b/x/evm/simulation/decoder_test.go deleted file mode 100644 index f4e5372b12..0000000000 --- a/x/evm/simulation/decoder_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package simulation - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/ethereum/go-ethereum/common" - "github.com/evmos/ethermint/x/evm/types" -) - -// TestDecodeStore tests that evm simulation decoder decodes the key value pairs as expected. -func TestDecodeStore(t *testing.T) { - dec := NewDecodeStore() - - hash := common.BytesToHash([]byte("hash")) - code := common.Bytes2Hex([]byte{1, 2, 3}) - - kvPairs := kv.Pairs{ - Pairs: []kv.Pair{ - {Key: types.KeyPrefixCode, Value: common.FromHex(code)}, - {Key: types.KeyPrefixStorage, Value: hash.Bytes()}, - }, - } - - tests := []struct { - name string - expectedLog string - }{ - {"Code", fmt.Sprintf("%v\n%v", code, code)}, - {"Storage", fmt.Sprintf("%v\n%v", hash, hash)}, - {"other", ""}, - } - for i, tt := range tests { - i, tt := i, tt - t.Run(tt.name, func(t *testing.T) { - switch i { - case len(tests) - 1: - require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) - default: - require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) - } - }) - } -} diff --git a/x/evm/simulation/genesis.go b/x/evm/simulation/genesis.go deleted file mode 100644 index 00132925c9..0000000000 --- a/x/evm/simulation/genesis.go +++ /dev/null @@ -1,61 +0,0 @@ -package simulation - -import ( - "encoding/json" - "fmt" - "math/rand" - - "github.com/cosmos/cosmos-sdk/types/module" - - "github.com/evmos/ethermint/x/evm/types" -) - -const ( - extraEIPsKey = "extra_eips" -) - -// GenExtraEIPs defines a set of extra EIPs with 50% probability -func GenExtraEIPs(r *rand.Rand) []int64 { - var extraEIPs []int64 - // 50% chance of having extra EIPs - if r.Intn(2) == 0 { - extraEIPs = []int64{1344, 1884, 2200, 2929, 3198, 3529} - } - return extraEIPs -} - -// GenEnableCreate enables the EnableCreate param with 80% probability -func GenEnableCreate(r *rand.Rand) bool { - // 80% chance of enabling create contract - enableCreate := r.Intn(100) < 80 - return enableCreate -} - -// GenEnableCall enables the EnableCall param with 80% probability -func GenEnableCall(r *rand.Rand) bool { - // 80% chance of enabling evm account transfer and calling contract - enableCall := r.Intn(100) < 80 - return enableCall -} - -// RandomizedGenState generates a random GenesisState for the EVM module -func RandomizedGenState(simState *module.SimulationState) { - // evm params - var extraEIPs []int64 - - simState.AppParams.GetOrGenerate( - simState.Cdc, extraEIPsKey, &extraEIPs, simState.Rand, - func(r *rand.Rand) { extraEIPs = GenExtraEIPs(r) }, - ) - - params := types.NewParams(types.DefaultEVMDenom, true, true, types.DefaultChainConfig(), extraEIPs...) - evmGenesis := types.NewGenesisState(params, []types.GenesisAccount{}) - - bz, err := json.MarshalIndent(evmGenesis, "", " ") - 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(evmGenesis) -} diff --git a/x/evm/simulation/genesis_test.go b/x/evm/simulation/genesis_test.go deleted file mode 100644 index 9fb4dd5c81..0000000000 --- a/x/evm/simulation/genesis_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package simulation_test - -import ( - "encoding/json" - "math/rand" - "testing" - - sdkmath "cosmossdk.io/math" - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/types/module" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/evmos/ethermint/x/evm/simulation" - "github.com/evmos/ethermint/x/evm/types" -) - -// TestRandomizedGenState tests the normal scenario of applying RandomizedGenState. -// Abonormal scenarios are not tested here. -func TestRandomizedGenState(t *testing.T) { - registry := codectypes.NewInterfaceRegistry() - types.RegisterInterfaces(registry) - cdc := codec.NewProtoCodec(registry) - - s := rand.NewSource(1) - r := rand.New(s) - - simState := module.SimulationState{ - AppParams: make(simtypes.AppParams), - Cdc: cdc, - Rand: r, - NumBonded: 3, - Accounts: simtypes.RandomAccounts(r, 3), - InitialStake: sdkmath.NewInt(1000), - GenState: make(map[string]json.RawMessage), - } - - simulation.RandomizedGenState(&simState) - - var evmGenesis types.GenesisState - simState.Cdc.MustUnmarshalJSON(simState.GenState[types.ModuleName], &evmGenesis) - - require.Equal(t, true, evmGenesis.Params.GetEnableCreate()) - require.Equal(t, true, evmGenesis.Params.GetEnableCall()) - require.Equal(t, types.DefaultEVMDenom, evmGenesis.Params.GetEvmDenom()) - require.Equal(t, simulation.GenExtraEIPs(r), evmGenesis.Params.GetExtraEIPs()) - require.Equal(t, types.DefaultChainConfig(), evmGenesis.Params.GetChainConfig()) - - require.Equal(t, len(evmGenesis.Accounts), 0) -} diff --git a/x/evm/simulation/operations.go b/x/evm/simulation/operations.go deleted file mode 100644 index cd5800adc4..0000000000 --- a/x/evm/simulation/operations.go +++ /dev/null @@ -1,313 +0,0 @@ -package simulation - -import ( - "encoding/json" - "fmt" - "math/big" - "math/rand" - "time" - - sdkmath "cosmossdk.io/math" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - sdktx "github.com/cosmos/cosmos-sdk/types/tx" - "github.com/cosmos/cosmos-sdk/x/auth/tx" - "github.com/cosmos/cosmos-sdk/x/simulation" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - ethtypes "github.com/ethereum/go-ethereum/core/types" - - "github.com/cosmos/cosmos-sdk/client" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/ethereum/go-ethereum/crypto" - "github.com/evmos/ethermint/encoding" - "github.com/evmos/ethermint/tests" - "github.com/evmos/ethermint/x/evm/keeper" - "github.com/evmos/ethermint/x/evm/types" -) - -const ( - /* #nosec */ - OpWeightMsgEthSimpleTransfer = "op_weight_msg_eth_simple_transfer" - /* #nosec */ - OpWeightMsgEthCreateContract = "op_weight_msg_eth_create_contract" - /* #nosec */ - OpWeightMsgEthCallContract = "op_weight_msg_eth_call_contract" -) - -const ( - WeightMsgEthSimpleTransfer = 50 - WeightMsgEthCreateContract = 50 -) - -var ErrNoEnoughBalance = fmt.Errorf("no enough balance") - -var maxWaitSeconds = 10 - -type simulateContext struct { - context sdk.Context - bapp *baseapp.BaseApp - rand *rand.Rand - keeper *keeper.Keeper -} - -// WeightedOperations generate Two kinds of operations: SimulateEthSimpleTransfer, SimulateEthCreateContract. -// Contract call operations work as the future operations of SimulateEthCreateContract. -func WeightedOperations( - appParams simtypes.AppParams, cdc codec.JSONCodec, ak types.AccountKeeper, k *keeper.Keeper, -) simulation.WeightedOperations { - var ( - weightMsgEthSimpleTransfer int - weightMsgEthCreateContract int - ) - - appParams.GetOrGenerate(cdc, OpWeightMsgEthSimpleTransfer, &weightMsgEthSimpleTransfer, nil, - func(_ *rand.Rand) { - weightMsgEthSimpleTransfer = WeightMsgEthSimpleTransfer - }, - ) - - appParams.GetOrGenerate(cdc, OpWeightMsgEthCreateContract, &weightMsgEthCreateContract, nil, - func(_ *rand.Rand) { - weightMsgEthCreateContract = WeightMsgEthCreateContract - }, - ) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgEthSimpleTransfer, - SimulateEthSimpleTransfer(ak, k), - ), - simulation.NewWeightedOperation( - weightMsgEthCreateContract, - SimulateEthCreateContract(ak, k), - ), - } -} - -// SimulateEthSimpleTransfer simulate simple eth account transferring gas token. -// It randomly choose sender, recipient and transferable amount. -// Other tx details like nonce, gasprice, gaslimit are calculated to get valid value. -func SimulateEthSimpleTransfer(ak types.AccountKeeper, k *keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, bapp *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - var recipient simtypes.Account - if r.Intn(2) == 1 { - recipient, _ = simtypes.RandomAcc(r, accs) - } else { - recipient = simtypes.RandomAccounts(r, 1)[0] - } - from := common.BytesToAddress(simAccount.Address) - to := common.BytesToAddress(recipient.Address) - - simulateContext := &simulateContext{ctx, bapp, r, k} - - return SimulateEthTx(simulateContext, &from, &to, nil, (*hexutil.Bytes)(&[]byte{}), simAccount.PrivKey, nil) - } -} - -// SimulateEthCreateContract simulate create an ERC20 contract. -// It makes operationSimulateEthCallContract the future operations of SimulateEthCreateContract -// to ensure valid contract call. -func SimulateEthCreateContract(ak types.AccountKeeper, k *keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, bapp *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - - from := common.BytesToAddress(simAccount.Address) - nonce := k.GetNonce(ctx, from) - - ctorArgs, err := types.ERC20Contract.ABI.Pack("", from, sdkmath.NewIntWithDecimal(1000, 18).BigInt()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "can not pack owner and supply"), nil, err - } - data := types.ERC20Contract.Bin - data = append(data, ctorArgs...) - - simulateContext := &simulateContext{ctx, bapp, r, k} - - fops := make([]simtypes.FutureOperation, 1) - whenCall := ctx.BlockHeader().Time.Add(time.Duration(r.Intn(maxWaitSeconds)+1) * time.Second) - contractAddr := crypto.CreateAddress(from, nonce) - var tokenReceipient simtypes.Account - if r.Intn(2) == 1 { - tokenReceipient, _ = simtypes.RandomAcc(r, accs) - } else { - tokenReceipient = simtypes.RandomAccounts(r, 1)[0] - } - receipientAddr := common.BytesToAddress(tokenReceipient.Address) - fops[0] = simtypes.FutureOperation{ - BlockTime: whenCall, - Op: operationSimulateEthCallContract(k, &contractAddr, &receipientAddr, nil), - } - return SimulateEthTx(simulateContext, &from, nil, nil, (*hexutil.Bytes)(&data), simAccount.PrivKey, fops) - } -} - -// operationSimulateEthCallContract simulate calling an contract. -// It is always calling an ERC20 contract. -func operationSimulateEthCallContract(k *keeper.Keeper, contractAddr, to *common.Address, amount *big.Int) simtypes.Operation { - return func( - r *rand.Rand, bapp *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - - from := common.BytesToAddress(simAccount.Address) - - ctorArgs, err := types.ERC20Contract.ABI.Pack("transfer", to, amount) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "can not pack method and args"), nil, err - } - data := types.ERC20Contract.Bin - data = append(data, ctorArgs...) - - simulateContext := &simulateContext{ctx, bapp, r, k} - - return SimulateEthTx(simulateContext, &from, contractAddr, nil, (*hexutil.Bytes)(&data), simAccount.PrivKey, nil) - } -} - -// SimulateEthTx creates valid ethereum tx and pack it as cosmos tx, and deliver it. -func SimulateEthTx( - ctx *simulateContext, from, to *common.Address, amount *big.Int, data *hexutil.Bytes, prv cryptotypes.PrivKey, fops []simtypes.FutureOperation, -) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - ethTx, err := CreateRandomValidEthTx(ctx, from, nil, nil, data) - if err == ErrNoEnoughBalance { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "no enough balance"), nil, nil - } - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "can not create valid eth tx"), nil, err - } - - txConfig := encoding.MakeConfig(module.NewBasicManager()).TxConfig - txBuilder := txConfig.NewTxBuilder() - signedTx, err := GetSignedTx(ctx, txBuilder, ethTx, prv) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "can not sign ethereum tx"), nil, err - } - - _, _, err = ctx.bapp.SimDeliver(txConfig.TxEncoder(), signedTx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "failed to deliver tx"), nil, err - } - - return simtypes.OperationMsg{}, fops, nil -} - -// CreateRandomValidEthTx create the ethereum tx with valid random values -func CreateRandomValidEthTx(ctx *simulateContext, - from, - to *common.Address, - amount *big.Int, - data *hexutil.Bytes, -) (ethTx *types.MsgEthereumTx, err error) { - gasCap := ctx.rand.Uint64() - estimateGas, err := EstimateGas(ctx, from, to, data, gasCap) - if err != nil { - return nil, err - } - // we suppose that gasLimit should be larger than estimateGas to ensure tx validity - gasLimit := estimateGas + uint64(ctx.rand.Intn(int(sdktx.MaxGasWanted-estimateGas))) - ethChainID := ctx.keeper.ChainID() - chainConfig := ctx.keeper.GetParams(ctx.context).ChainConfig.EthereumConfig(ethChainID) - gasPrice := ctx.keeper.GetBaseFee(ctx.context, chainConfig) - gasFeeCap := new(big.Int).Add(gasPrice, big.NewInt(int64(ctx.rand.Int()))) - gasTipCap := big.NewInt(int64(ctx.rand.Int())) - nonce := ctx.keeper.GetNonce(ctx.context, *from) - - if amount == nil { - amount, err = RandomTransferableAmount(ctx, *from, estimateGas, gasFeeCap) - if err != nil { - return nil, err - } - } - - ethTx = types.NewTx(ethChainID, nonce, to, amount, gasLimit, gasPrice, gasFeeCap, gasTipCap, *data, nil) - ethTx.From = from.String() - return ethTx, nil -} - -// EstimateGas estimates the gas used by quering the keeper. -func EstimateGas(ctx *simulateContext, from, to *common.Address, data *hexutil.Bytes, gasCap uint64) (gas uint64, err error) { - args, err := json.Marshal(&types.TransactionArgs{To: to, From: from, Data: data}) - if err != nil { - return 0, err - } - - res, err := ctx.keeper.EstimateGas(sdk.WrapSDKContext(ctx.context), &types.EthCallRequest{ - Args: args, - GasCap: gasCap, - }) - if err != nil { - return 0, err - } - return res.Gas, nil -} - -// RandomTransferableAmount generates a random valid transferable amount. -// Transferable amount is between the range [0, spendable), spendable = balance - gasFeeCap * GasLimit. -func RandomTransferableAmount(ctx *simulateContext, address common.Address, estimateGas uint64, gasFeeCap *big.Int) (amount *big.Int, err error) { - balance := ctx.keeper.GetBalance(ctx.context, address) - feeLimit := new(big.Int).Mul(gasFeeCap, big.NewInt(int64(estimateGas))) - if (feeLimit.Cmp(balance)) > 0 { - return nil, ErrNoEnoughBalance - } - spendable := new(big.Int).Sub(balance, feeLimit) - if spendable.Cmp(big.NewInt(0)) == 0 { - amount = new(big.Int).Set(spendable) - return amount, nil - } - simAmount, err := simtypes.RandPositiveInt(ctx.rand, sdkmath.NewIntFromBigInt(spendable)) - if err != nil { - return nil, err - } - amount = simAmount.BigInt() - return amount, nil -} - -// GetSignedTx sign the ethereum tx and packs it as a signing.Tx . -func GetSignedTx( - ctx *simulateContext, - txBuilder client.TxBuilder, - msg *types.MsgEthereumTx, - prv cryptotypes.PrivKey, -) (signedTx signing.Tx, err error) { - builder, ok := txBuilder.(tx.ExtensionOptionsTxBuilder) - if !ok { - return nil, fmt.Errorf("can not initiate ExtensionOptionsTxBuilder") - } - option, err := codectypes.NewAnyWithValue(&types.ExtensionOptionsEthereumTx{}) - if err != nil { - return nil, err - } - builder.SetExtensionOptions(option) - - if err := msg.Sign(ethtypes.LatestSignerForChainID(ctx.keeper.ChainID()), tests.NewSigner(prv)); err != nil { - return nil, err - } - - if err = builder.SetMsgs(msg); err != nil { - return nil, err - } - - txData, err := types.UnpackTxData(msg.Data) - if err != nil { - return nil, err - } - - fees := sdk.NewCoins(sdk.NewCoin(ctx.keeper.GetParams(ctx.context).EvmDenom, sdkmath.NewIntFromBigInt(txData.Fee()))) - builder.SetFeeAmount(fees) - builder.SetGasLimit(msg.GetGas()) - - signedTx = builder.GetTx() - return signedTx, nil -} diff --git a/x/evm/simulation/params.go b/x/evm/simulation/params.go deleted file mode 100644 index 1ebc811e69..0000000000 --- a/x/evm/simulation/params.go +++ /dev/null @@ -1,41 +0,0 @@ -package simulation - -// DONTCOVER - -import ( - "fmt" - "math/rand" - - amino "github.com/cosmos/cosmos-sdk/codec" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" - "github.com/evmos/ethermint/x/evm/types" -) - -// ParamChanges defines the parameters that can be modified by param change proposals -// on the simulation. -func ParamChanges(r *rand.Rand) []simtypes.ParamChange { - return []simtypes.ParamChange{ - simulation.NewSimParamChange(types.ModuleName, string(types.ParamStoreKeyExtraEIPs), - func(r *rand.Rand) string { - extraEIPs := GenExtraEIPs(r) - amino := amino.NewLegacyAmino() - bz, err := amino.MarshalJSON(extraEIPs) - if err != nil { - panic(err) - } - return string(bz) - }, - ), - simulation.NewSimParamChange(types.ModuleName, string(types.ParamStoreKeyEnableCreate), - func(r *rand.Rand) string { - return fmt.Sprintf("%v", GenEnableCreate(r)) - }, - ), - simulation.NewSimParamChange(types.ModuleName, string(types.ParamStoreKeyEnableCall), - func(r *rand.Rand) string { - return fmt.Sprintf("%v", GenEnableCall(r)) - }, - ), - } -} diff --git a/x/evm/simulation/params_test.go b/x/evm/simulation/params_test.go deleted file mode 100644 index 9c6ad371ad..0000000000 --- a/x/evm/simulation/params_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package simulation_test - -import ( - "encoding/json" - "fmt" - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/evmos/ethermint/x/evm/simulation" -) - -// TestParamChanges tests the paramChanges are generated as expected. -func TestParamChanges(t *testing.T) { - s := rand.NewSource(1) - r := rand.New(s) - - extraEIPs := simulation.GenExtraEIPs(r) - bz, err := json.Marshal(extraEIPs) - require.NoError(t, err) - - expected := []struct { - composedKey string - key string - simValue string - subspace string - }{ - {"evm/EnableExtraEIPs", "EnableExtraEIPs", string(bz), "evm"}, - {"evm/EnableCreate", "EnableCreate", fmt.Sprintf("%v", simulation.GenEnableCreate(r)), "evm"}, - {"evm/EnableCall", "EnableCall", fmt.Sprintf("%v", simulation.GenEnableCall(r)), "evm"}, - } - - paramChanges := simulation.ParamChanges(r) - - require.Len(t, paramChanges, 3) - - for i, p := range paramChanges { - require.Equal(t, expected[i].composedKey, p.ComposedKey()) - require.Equal(t, expected[i].key, p.Key()) - require.Equal(t, expected[i].simValue, p.SimValue()(r)) - require.Equal(t, expected[i].subspace, p.Subspace()) - } -} diff --git a/x/feemarket/module.go b/x/feemarket/module.go index a93e8fba42..226584b9e2 100644 --- a/x/feemarket/module.go +++ b/x/feemarket/module.go @@ -21,7 +21,6 @@ import ( "github.com/evmos/ethermint/x/feemarket/client/cli" "github.com/evmos/ethermint/x/feemarket/keeper" - "github.com/evmos/ethermint/x/feemarket/simulation" "github.com/evmos/ethermint/x/feemarket/types" ) @@ -65,7 +64,7 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingCo // RegisterRESTRoutes performs a no-op as the EVM module doesn't expose REST // endpoints -func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { +func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) { } func (b AppModuleBasic) RegisterGRPCGatewayRoutes(c client.Context, serveMux *runtime.ServeMux) { @@ -110,7 +109,7 @@ func (AppModule) Name() string { // RegisterInvariants interface for registering invariants. Performs a no-op // as the fee market module doesn't expose invariants. -func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} // RegisterServices registers the GRPC query service and migrator service to respond to the // module-specific GRPC queries and handle the upgrade store migration for the module. @@ -128,7 +127,7 @@ func (AppModule) QuerierRoute() string { return types.RouterKey } // LegacyQuerierHandler returns nil as the fee market module doesn't expose a legacy // Querier. -func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { +func (am AppModule) LegacyQuerierHandler(_ *codec.LegacyAmino) sdk.Querier { return nil } @@ -162,24 +161,23 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // RandomizedParams creates randomized fee market param changes for the simulator. -func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { +func (AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { return nil } // RegisterStoreDecoder registers a decoder for fee market module's types -func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {} +func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {} // ProposalContents doesn't return any content functions for governance proposals. -func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { +func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { return nil } // GenerateGenesisState creates a randomized GenState of the fee market module. -func (AppModule) GenerateGenesisState(simState *module.SimulationState) { - simulation.RandomizedGenState(simState) +func (AppModule) GenerateGenesisState(_ *module.SimulationState) { } // WeightedOperations returns the all the fee market module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { +func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { return nil } diff --git a/x/feemarket/simulation/genesis.go b/x/feemarket/simulation/genesis.go deleted file mode 100644 index 987e4c1ba7..0000000000 --- a/x/feemarket/simulation/genesis.go +++ /dev/null @@ -1,33 +0,0 @@ -package simulation - -import ( - "encoding/json" - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" - - "github.com/evmos/ethermint/x/feemarket/types" -) - -// RandomizedGenState generates a random GenesisState for nft -func RandomizedGenState(simState *module.SimulationState) { - params := types.NewParams(simState.Rand.Uint32()%2 == 0, - simState.Rand.Uint32(), - simState.Rand.Uint32(), - simState.Rand.Uint64(), - simState.Rand.Int63(), - sdk.ZeroDec(), - types.DefaultMinGasMultiplier) - - blockGas := simState.Rand.Uint64() - feemarketGenesis := types.NewGenesisState(params, blockGas) - - bz, err := json.MarshalIndent(feemarketGenesis, "", " ") - 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(feemarketGenesis) -}