forked from cerc-io/plugeth
Merge tag 'v1.10.16' into re-merge/v1.10.16
This commit is contained in:
Submodule
+1
Submodule tests/evm-benchmarks added at 849b3e239a
+10
-5
@@ -17,7 +17,8 @@ var _ = (*stEnvMarshaling)(nil)
|
||||
func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||
type stEnv struct {
|
||||
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
|
||||
Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
|
||||
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||
@@ -26,6 +27,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||
var enc stEnv
|
||||
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
||||
enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty)
|
||||
enc.Random = (*math.HexOrDecimal256)(s.Random)
|
||||
enc.GasLimit = math.HexOrDecimal64(s.GasLimit)
|
||||
enc.Number = math.HexOrDecimal64(s.Number)
|
||||
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
|
||||
@@ -37,7 +39,8 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||
func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||
type stEnv struct {
|
||||
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
|
||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
|
||||
Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
|
||||
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
|
||||
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
|
||||
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
|
||||
@@ -51,10 +54,12 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||
return errors.New("missing required field 'currentCoinbase' for stEnv")
|
||||
}
|
||||
s.Coinbase = common.Address(*dec.Coinbase)
|
||||
if dec.Difficulty == nil {
|
||||
return errors.New("missing required field 'currentDifficulty' for stEnv")
|
||||
if dec.Difficulty != nil {
|
||||
s.Difficulty = (*big.Int)(dec.Difficulty)
|
||||
}
|
||||
if dec.Random != nil {
|
||||
s.Random = (*big.Int)(dec.Random)
|
||||
}
|
||||
s.Difficulty = (*big.Int)(dec.Difficulty)
|
||||
if dec.GasLimit == nil {
|
||||
return errors.New("missing required field 'currentGasLimit' for stEnv")
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ var (
|
||||
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
|
||||
rlpTestDir = filepath.Join(baseDir, "RLPTests")
|
||||
difficultyTestDir = filepath.Join(baseDir, "BasicTests")
|
||||
benchmarksDir = filepath.Join(".", "evm-benchmarks", "benchmarks")
|
||||
)
|
||||
|
||||
func readJSON(reader io.Reader, value interface{}) error {
|
||||
|
||||
@@ -20,9 +20,16 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||
)
|
||||
@@ -61,6 +68,7 @@ func TestState(t *testing.T) {
|
||||
for _, dir := range []string{
|
||||
stateTestDir,
|
||||
legacyStateTestDir,
|
||||
benchmarksDir,
|
||||
} {
|
||||
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
|
||||
for _, subtest := range test.Subtests() {
|
||||
@@ -131,3 +139,116 @@ func withTrace(t *testing.T, gasLimit uint64, test func(vm.Config) error) {
|
||||
// t.Logf("EVM output: 0x%x", tracer.Output())
|
||||
// t.Logf("EVM error: %v", tracer.Error())
|
||||
}
|
||||
|
||||
func BenchmarkEVM(b *testing.B) {
|
||||
// Walk the directory.
|
||||
dir := benchmarksDir
|
||||
dirinfo, err := os.Stat(dir)
|
||||
if os.IsNotExist(err) || !dirinfo.IsDir() {
|
||||
fmt.Fprintf(os.Stderr, "can't find test files in %s, did you clone the evm-benchmarks submodule?\n", dir)
|
||||
b.Skip("missing test files")
|
||||
}
|
||||
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if ext := filepath.Ext(path); ext == ".json" {
|
||||
name := filepath.ToSlash(strings.TrimPrefix(strings.TrimSuffix(path, ext), dir+string(filepath.Separator)))
|
||||
b.Run(name, func(b *testing.B) { runBenchmarkFile(b, path) })
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func runBenchmarkFile(b *testing.B, path string) {
|
||||
m := make(map[string]StateTest)
|
||||
if err := readJSONFile(path, &m); err != nil {
|
||||
b.Fatal(err)
|
||||
return
|
||||
}
|
||||
if len(m) != 1 {
|
||||
b.Fatal("expected single benchmark in a file")
|
||||
return
|
||||
}
|
||||
for _, t := range m {
|
||||
runBenchmark(b, &t)
|
||||
}
|
||||
}
|
||||
|
||||
func runBenchmark(b *testing.B, t *StateTest) {
|
||||
for _, subtest := range t.Subtests() {
|
||||
subtest := subtest
|
||||
key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index)
|
||||
|
||||
b.Run(key, func(b *testing.B) {
|
||||
vmconfig := vm.Config{}
|
||||
|
||||
config, eips, err := GetChainConfig(subtest.Fork)
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
return
|
||||
}
|
||||
vmconfig.ExtraEips = eips
|
||||
block := t.genesis(config).ToBlock(nil)
|
||||
_, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false)
|
||||
|
||||
var baseFee *big.Int
|
||||
if config.IsLondon(new(big.Int)) {
|
||||
baseFee = t.json.Env.BaseFee
|
||||
if baseFee == nil {
|
||||
// Retesteth uses `0x10` for genesis baseFee. Therefore, it defaults to
|
||||
// parent - 2 : 0xa as the basefee for 'this' context.
|
||||
baseFee = big.NewInt(0x0a)
|
||||
}
|
||||
}
|
||||
post := t.json.Post[subtest.Fork][subtest.Index]
|
||||
msg, err := t.json.Tx.toMessage(post, baseFee)
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Try to recover tx with current signer
|
||||
if len(post.TxBytes) != 0 {
|
||||
var ttx types.Transaction
|
||||
err := ttx.UnmarshalBinary(post.TxBytes)
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
|
||||
b.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the EVM.
|
||||
txContext := core.NewEVMTxContext(msg)
|
||||
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
||||
context.GetHash = vmTestBlockHash
|
||||
context.BaseFee = baseFee
|
||||
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
|
||||
|
||||
// Create "contract" for sender to cache code analysis.
|
||||
sender := vm.NewContract(vm.AccountRef(msg.From()), vm.AccountRef(msg.From()),
|
||||
nil, 0)
|
||||
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
// Execute the message.
|
||||
snapshot := statedb.Snapshot()
|
||||
_, _, err = evm.Call(sender, *msg.To(), msg.Data(), msg.Gas(), msg.Value())
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
return
|
||||
}
|
||||
statedb.RevertToSnapshot(snapshot)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,16 +80,18 @@ type stPostState struct {
|
||||
|
||||
type stEnv struct {
|
||||
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
|
||||
Difficulty *big.Int `json:"currentDifficulty" gencodec:"required"`
|
||||
Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
|
||||
Random *big.Int `json:"currentRandom" gencodec:"optional"`
|
||||
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
|
||||
Number uint64 `json:"currentNumber" gencodec:"required"`
|
||||
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
|
||||
BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
|
||||
BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
|
||||
}
|
||||
|
||||
type stEnvMarshaling struct {
|
||||
Coinbase common.UnprefixedAddress
|
||||
Difficulty *math.HexOrDecimal256
|
||||
Random *math.HexOrDecimal256
|
||||
GasLimit math.HexOrDecimal64
|
||||
Number math.HexOrDecimal64
|
||||
Timestamp math.HexOrDecimal64
|
||||
@@ -218,8 +220,12 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
||||
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
||||
context.GetHash = vmTestBlockHash
|
||||
context.BaseFee = baseFee
|
||||
if t.json.Env.Random != nil {
|
||||
rnd := common.BigToHash(t.json.Env.Random)
|
||||
context.Random = &rnd
|
||||
context.Difficulty = big.NewInt(0)
|
||||
}
|
||||
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
|
||||
|
||||
// Execute the message.
|
||||
snapshot := statedb.Snapshot()
|
||||
gaspool := new(core.GasPool)
|
||||
@@ -268,7 +274,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter boo
|
||||
}
|
||||
|
||||
func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
|
||||
return &core.Genesis{
|
||||
genesis := &core.Genesis{
|
||||
Config: config,
|
||||
Coinbase: t.json.Env.Coinbase,
|
||||
Difficulty: t.json.Env.Difficulty,
|
||||
@@ -277,6 +283,12 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
|
||||
Timestamp: t.json.Env.Timestamp,
|
||||
Alloc: t.json.Pre,
|
||||
}
|
||||
if t.json.Env.Random != nil {
|
||||
// Post-Merge
|
||||
genesis.Mixhash = common.BigToHash(t.json.Env.Random)
|
||||
genesis.Difficulty = big.NewInt(0)
|
||||
}
|
||||
return genesis
|
||||
}
|
||||
|
||||
func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Message, error) {
|
||||
|
||||
Reference in New Issue
Block a user