forked from cerc-io/laconicd-deprecated
Remove simulation checks (#1507)
* Add cli rollback command it's useful in app-hash mismatch situation. * Update CHANGELOG.md * (refactor): removed old sim tests logic * (fix): removed tests from CI * (fix): fix test.yml * (fix): format and lint * (fix): fix linter issue * (fix): fix linter issues v2 * (fix): linter * (fix): removed sim-test references * Applied changes from code review Co-authored-by: HuangYi <huang@crypto.com>
This commit is contained in:
parent
831588c72c
commit
a5c927bf5b
82
.github/workflows/test.yml
vendored
82
.github/workflows/test.yml
vendored
@ -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)"
|
||||
|
@ -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
|
||||
|
45
Makefile
45
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)
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
|
||||
func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
||||
addr, privKey := tests.NewAddrKey()
|
||||
|
||||
|
21
app/app.go
21
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) {
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
102
app/utils.go
102
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()
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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]))
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
@ -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))
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
@ -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())
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user