Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

imp, ci: address pending issues from EVM simulation #1063

Merged
merged 20 commits into from
May 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,84 @@ jobs:
- name: Test e2e
run: |
make test-integration
if: env.GIT_DIFF

test-sim-nondeterminism:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.17
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/[email protected]
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Test x/evm simulation nondeterminism
run: |
make test-sim-nondeterminism
if: env.GIT_DIFF

test-sim-random-genesis-fast:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.17
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/[email protected]
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Test x/evm 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: 15
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.17
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/[email protected]
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Test x/evm simulation import and export
run: |
make test-sim-import-export
if: env.GIT_DIFF

test-sim-after-import:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.17
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/[email protected]
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Test x/evm simulation after import
run: |
make test-sim-after-import
if: env.GIT_DIFF
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
* Move `rpc/ethereum/backend` -> `rpc/backend`
* Move `rpc/ethereum/namespaces` -> `rpc/namespaces/ethereum`

### Improvements

* (ci, evm) [tharsis#1063](https://github.com/tharsis/ethermint/pull/1063) Run simulations on CI.

### Bug Fixes

* (rpc) [tharsis#1059](https://github.com/tharsis/ethermint/pull/1059) Remove unnecessary event filtering logic on the `eth_baseFee` JSON-RPC endpoint.
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ RUNSIM = $(TOOLS_DESTDIR)/runsim
runsim: $(RUNSIM)
$(RUNSIM):
@echo "Installing runsim..."
@(cd /tmp && ${GO_MOD} go get github.com/cosmos/tools/cmd/runsim@master)
@(cd /tmp && ${GO_MOD} go install github.com/cosmos/tools/cmd/runsim@master)

statik: $(STATIK)
$(STATIK):
Expand Down Expand Up @@ -343,7 +343,7 @@ test-sim-nondeterminism:
-NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h

test-sim-random-genesis-fast:
@echo "Running custom genesis simulation..."
@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

Expand Down
2 changes: 1 addition & 1 deletion app/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func RandomAccounts(r *rand.Rand, n int) []simtypes.Account {

prv := secp256k1.GenPrivKeyFromSecret(privkeySeed)
ethPrv := &ethsecp256k1.PrivKey{}
_ = ethPrv.UnmarshalAmino(prv.Bytes())
_ = 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())
Expand Down
56 changes: 56 additions & 0 deletions app/utils_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package app

import (
"encoding/json"
"math/rand"
"os"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -11,7 +13,10 @@ import (
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/tharsis/ethermint/x/evm/types"

"github.com/tharsis/ethermint/crypto/ethsecp256k1"
ethermint "github.com/tharsis/ethermint/types"

"github.com/cosmos/cosmos-sdk/simapp"
Expand Down Expand Up @@ -53,3 +58,54 @@ func TestRandomGenesisAccounts(t *testing.T) {
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)
}
}
12 changes: 6 additions & 6 deletions x/evm/simulation/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ import (
)

// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's
// Value to the corresponding evm type.
// 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):
storageHashA := common.BytesToHash(kvA.Value).Hex()
storageHashB := common.BytesToHash(kvB.Value).Hex()
storageA := common.BytesToHash(kvA.Value).Hex()
storageB := common.BytesToHash(kvB.Value).Hex()

return fmt.Sprintf("%v\n%v", storageHashA, storageHashB)
return fmt.Sprintf("%v\n%v", storageA, storageB)
case bytes.Equal(kvA.Key[:1], types.KeyPrefixCode):
codeHashA := common.BytesToHash(kvA.Value).Hex()
codeHashB := common.BytesToHash(kvB.Value).Hex()
codeHashA := common.Bytes2Hex(kvA.Value)
codeHashB := common.Bytes2Hex(kvB.Value)

return fmt.Sprintf("%v\n%v", codeHashA, codeHashB)
default:
Expand Down
47 changes: 47 additions & 0 deletions x/evm/simulation/decoder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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/tharsis/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)
}
})
}
}
36 changes: 31 additions & 5 deletions x/evm/simulation/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,44 @@ import (
"github.com/tharsis/ethermint/x/evm/types"
)

// GenExtraEIPs randomly generates specific extra eips or not.
func genExtraEIPs(r *rand.Rand) []int64 {
const (
extraEIPsKey = "extra_eips"
)

// GenExtraEIPs defines a set of extra EIPs with 50% probability
func GenExtraEIPs(r *rand.Rand) []int64 {
var extraEIPs []int64
if r.Uint32()%2 == 0 {
// 50% chance of having extra EIPs
if r.Intn(2) == 0 {
extraEIPs = []int64{1344, 1884, 2200, 2929, 3198, 3529}
}
return extraEIPs
}

// RandomizedGenState generates a random GenesisState for nft
// GenEnableCreate enables the EnableCreate param with 80% probability
func GenEnableCreate(r *rand.Rand) bool {
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
// 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 {
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
// 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) {
extraEIPs := genExtraEIPs(simState.Rand)
// 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{})

Expand Down
50 changes: 50 additions & 0 deletions x/evm/simulation/genesis_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package simulation_test

import (
"encoding/json"
"math/rand"
"testing"

"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/tharsis/ethermint/x/evm/simulation"
"github.com/tharsis/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: 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)
}
Loading