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 16 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/get-diff-action@v6.0.1
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/get-diff-action@v6.0.1
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/get-diff-action@v6.0.1
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/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Test x/evm simulation after import
run: |
make test-sim-after-import
if: env.GIT_DIFF
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

* (deps) [tharsis#1046](https://github.com/tharsis/ethermint/pull/1046) Bump Cosmos SDK version to [`v0.45.3`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.3)
* (rpc) [tharsis#1056](https://github.com/tharsis/ethermint/pull/1056) Make json-rpc namespaces extensible
* (app) [https://github.com/tharsis/ethermint/pull/1063] Update github actions to run evm simulation, add more tests for evm simulation, use random gascap in simulation.

### Bug Fixes

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)
}
}
10 changes: 5 additions & 5 deletions x/evm/simulation/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ 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)
}
})
}
}
32 changes: 29 additions & 3 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"
)

const (
extraEIPsKey = "extra_eips"
)

// GenExtraEIPs randomly generates specific extra eips or not.
func genExtraEIPs(r *rand.Rand) []int64 {
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
}

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
}

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 nft
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
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