Delete tests directory

This commit is contained in:
Isabel Schöps Thiel 2024-01-01 00:43:26 +01:00 committed by GitHub
parent 52e2ded002
commit 9d267b279d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 0 additions and 2760 deletions

View file

@ -1,93 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"math/rand"
"runtime"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
)
func TestBlockchain(t *testing.T) {
bt := new(testMatcher)
// General state tests are 'exported' as blockchain tests, but we can run them natively.
// For speedier CI-runs, the line below can be uncommented, so those are skipped.
// For now, in hardfork-times (Berlin), we run the tests both as StateTests and
// as blockchain tests, since the latter also covers things like receipt root
bt.skipLoad(`^GeneralStateTests/`)
// Skip random failures due to selfish mining test
bt.skipLoad(`.*bcForgedTest/bcForkUncle\.json`)
// Slow tests
bt.slow(`.*bcExploitTest/DelegateCallSpam.json`)
bt.slow(`.*bcExploitTest/ShanghaiLove.json`)
bt.slow(`.*bcExploitTest/SuicideIssue.json`)
bt.slow(`.*/bcForkStressTest/`)
bt.slow(`.*/bcGasPricerTest/RPC_API_Test.json`)
bt.slow(`.*/bcWalletTest/`)
// Very slow test
bt.skipLoad(`.*/stTimeConsuming/.*`)
// test takes a lot for time and goes easily OOM because of sha3 calculation on a huge range,
// using 4.6 TGas
bt.skipLoad(`.*randomStatetest94.json.*`)
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
if runtime.GOARCH == "386" && runtime.GOOS == "windows" && rand.Int63()%2 == 0 {
t.Skip("test (randomly) skipped on 32-bit windows")
}
execBlockTest(t, bt, test)
})
// There is also a LegacyTests folder, containing blockchain tests generated
// prior to Istanbul. However, they are all derived from GeneralStateTests,
// which run natively, so there's no reason to run them here.
}
// TestExecutionSpec runs the test fixtures from execution-spec-tests.
func TestExecutionSpec(t *testing.T) {
if !common.FileExist(executionSpecDir) {
t.Skipf("directory %s does not exist", executionSpecDir)
}
bt := new(testMatcher)
bt.walk(t, executionSpecDir, func(t *testing.T, name string, test *BlockTest) {
execBlockTest(t, bt, test)
})
}
func execBlockTest(t *testing.T, bt *testMatcher, test *BlockTest) {
if err := bt.checkFailure(t, test.Run(false, rawdb.HashScheme, nil, nil)); err != nil {
t.Errorf("test in hash mode without snapshotter failed: %v", err)
return
}
if err := bt.checkFailure(t, test.Run(true, rawdb.HashScheme, nil, nil)); err != nil {
t.Errorf("test in hash mode with snapshotter failed: %v", err)
return
}
if err := bt.checkFailure(t, test.Run(false, rawdb.PathScheme, nil, nil)); err != nil {
t.Errorf("test in path mode without snapshotter failed: %v", err)
return
}
if err := bt.checkFailure(t, test.Run(true, rawdb.PathScheme, nil, nil)); err != nil {
t.Errorf("test in path mode with snapshotter failed: %v", err)
return
}
}

View file

@ -1,377 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package tests implements execution of Ethereum JSON tests.
package tests
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"os"
"reflect"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
)
// A BlockTest checks handling of entire blocks.
type BlockTest struct {
json btJSON
}
// UnmarshalJSON implements json.Unmarshaler interface.
func (t *BlockTest) UnmarshalJSON(in []byte) error {
return json.Unmarshal(in, &t.json)
}
type btJSON struct {
Blocks []btBlock `json:"blocks"`
Genesis btHeader `json:"genesisBlockHeader"`
Pre core.GenesisAlloc `json:"pre"`
Post core.GenesisAlloc `json:"postState"`
BestBlock common.UnprefixedHash `json:"lastblockhash"`
Network string `json:"network"`
SealEngine string `json:"sealEngine"`
}
type btBlock struct {
BlockHeader *btHeader
ExpectException string
Rlp string
UncleHeaders []*btHeader
}
//go:generate go run github.com/fjl/gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go
type btHeader struct {
Bloom types.Bloom
Coinbase common.Address
MixHash common.Hash
Nonce types.BlockNonce
Number *big.Int
Hash common.Hash
ParentHash common.Hash
ReceiptTrie common.Hash
StateRoot common.Hash
TransactionsTrie common.Hash
UncleHash common.Hash
ExtraData []byte
Difficulty *big.Int
GasLimit uint64
GasUsed uint64
Timestamp uint64
BaseFeePerGas *big.Int
WithdrawalsRoot *common.Hash
BlobGasUsed *uint64
ExcessBlobGas *uint64
ParentBeaconBlockRoot *common.Hash
}
type btHeaderMarshaling struct {
ExtraData hexutil.Bytes
Number *math.HexOrDecimal256
Difficulty *math.HexOrDecimal256
GasLimit math.HexOrDecimal64
GasUsed math.HexOrDecimal64
Timestamp math.HexOrDecimal64
BaseFeePerGas *math.HexOrDecimal256
BlobGasUsed *math.HexOrDecimal64
ExcessBlobGas *math.HexOrDecimal64
}
func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, postCheck func(error, *core.BlockChain)) (result error) {
config, ok := Forks[t.json.Network]
if !ok {
return UnsupportedForkError{t.json.Network}
}
// import pre accounts & construct test genesis block & state root
var (
db = rawdb.NewMemoryDatabase()
tconf = &trie.Config{
Preimages: true,
}
)
if scheme == rawdb.PathScheme {
tconf.PathDB = pathdb.Defaults
} else {
tconf.HashDB = hashdb.Defaults
}
// Commit genesis state
gspec := t.genesis(config)
triedb := trie.NewDatabase(db, tconf)
gblock, err := gspec.Commit(db, triedb)
if err != nil {
return err
}
triedb.Close() // close the db to prevent memory leak
if gblock.Hash() != t.json.Genesis.Hash {
return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
}
if gblock.Root() != t.json.Genesis.StateRoot {
return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
}
// Wrap the original engine within the beacon-engine
engine := beacon.New(ethash.NewFaker())
cache := &core.CacheConfig{TrieCleanLimit: 0, StateScheme: scheme, Preimages: true}
if snapshotter {
cache.SnapshotLimit = 1
cache.SnapshotWait = true
}
chain, err := core.NewBlockChain(db, cache, gspec, nil, engine, vm.Config{
Tracer: tracer,
}, nil, nil)
if err != nil {
return err
}
defer chain.Stop()
validBlocks, err := t.insertBlocks(chain)
if err != nil {
return err
}
// Import succeeded: regardless of whether the _test_ succeeds or not, schedule
// the post-check to run
if postCheck != nil {
defer postCheck(result, chain)
}
cmlast := chain.CurrentBlock().Hash()
if common.Hash(t.json.BestBlock) != cmlast {
return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast)
}
newDB, err := chain.State()
if err != nil {
return err
}
if err = t.validatePostState(newDB); err != nil {
return fmt.Errorf("post state validation failed: %v", err)
}
// Cross-check the snapshot-to-hash against the trie hash
if snapshotter {
if err := chain.Snapshots().Verify(chain.CurrentBlock().Root); err != nil {
return err
}
}
return t.validateImportedHeaders(chain, validBlocks)
}
func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
return &core.Genesis{
Config: config,
Nonce: t.json.Genesis.Nonce.Uint64(),
Timestamp: t.json.Genesis.Timestamp,
ParentHash: t.json.Genesis.ParentHash,
ExtraData: t.json.Genesis.ExtraData,
GasLimit: t.json.Genesis.GasLimit,
GasUsed: t.json.Genesis.GasUsed,
Difficulty: t.json.Genesis.Difficulty,
Mixhash: t.json.Genesis.MixHash,
Coinbase: t.json.Genesis.Coinbase,
Alloc: t.json.Pre,
BaseFee: t.json.Genesis.BaseFeePerGas,
BlobGasUsed: t.json.Genesis.BlobGasUsed,
ExcessBlobGas: t.json.Genesis.ExcessBlobGas,
}
}
/*
See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
Whether a block is valid or not is a bit subtle, it's defined by presence of
blockHeader, transactions and uncleHeaders fields. If they are missing, the block is
invalid and we must verify that we do not accept it.
Since some tests mix valid and invalid blocks we need to check this for every block.
If a block is invalid it does not necessarily fail the test, if it's invalidness is
expected we are expected to ignore it and continue processing and then validate the
post state.
*/
func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) {
validBlocks := make([]btBlock, 0)
// insert the test blocks, which will execute all transactions
for bi, b := range t.json.Blocks {
cb, err := b.decode()
if err != nil {
if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block
} else {
return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err)
}
}
// RLP decoding worked, try to insert into chain:
blocks := types.Blocks{cb}
i, err := blockchain.InsertChain(blocks)
if err != nil {
if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block
} else {
return nil, fmt.Errorf("block #%v insertion into chain failed: %v", blocks[i].Number(), err)
}
}
if b.BlockHeader == nil {
if data, err := json.MarshalIndent(cb.Header(), "", " "); err == nil {
fmt.Fprintf(os.Stderr, "block (index %d) insertion should have failed due to: %v:\n%v\n",
bi, b.ExpectException, string(data))
}
return nil, fmt.Errorf("block (index %d) insertion should have failed due to: %v",
bi, b.ExpectException)
}
// validate RLP decoding by checking all values against test file JSON
if err = validateHeader(b.BlockHeader, cb.Header()); err != nil {
return nil, fmt.Errorf("deserialised block header validation failed: %v", err)
}
validBlocks = append(validBlocks, b)
}
return validBlocks, nil
}
func validateHeader(h *btHeader, h2 *types.Header) error {
if h.Bloom != h2.Bloom {
return fmt.Errorf("bloom: want: %x have: %x", h.Bloom, h2.Bloom)
}
if h.Coinbase != h2.Coinbase {
return fmt.Errorf("coinbase: want: %x have: %x", h.Coinbase, h2.Coinbase)
}
if h.MixHash != h2.MixDigest {
return fmt.Errorf("MixHash: want: %x have: %x", h.MixHash, h2.MixDigest)
}
if h.Nonce != h2.Nonce {
return fmt.Errorf("nonce: want: %x have: %x", h.Nonce, h2.Nonce)
}
if h.Number.Cmp(h2.Number) != 0 {
return fmt.Errorf("number: want: %v have: %v", h.Number, h2.Number)
}
if h.ParentHash != h2.ParentHash {
return fmt.Errorf("parent hash: want: %x have: %x", h.ParentHash, h2.ParentHash)
}
if h.ReceiptTrie != h2.ReceiptHash {
return fmt.Errorf("receipt hash: want: %x have: %x", h.ReceiptTrie, h2.ReceiptHash)
}
if h.TransactionsTrie != h2.TxHash {
return fmt.Errorf("tx hash: want: %x have: %x", h.TransactionsTrie, h2.TxHash)
}
if h.StateRoot != h2.Root {
return fmt.Errorf("state hash: want: %x have: %x", h.StateRoot, h2.Root)
}
if h.UncleHash != h2.UncleHash {
return fmt.Errorf("uncle hash: want: %x have: %x", h.UncleHash, h2.UncleHash)
}
if !bytes.Equal(h.ExtraData, h2.Extra) {
return fmt.Errorf("extra data: want: %x have: %x", h.ExtraData, h2.Extra)
}
if h.Difficulty.Cmp(h2.Difficulty) != 0 {
return fmt.Errorf("difficulty: want: %v have: %v", h.Difficulty, h2.Difficulty)
}
if h.GasLimit != h2.GasLimit {
return fmt.Errorf("gasLimit: want: %d have: %d", h.GasLimit, h2.GasLimit)
}
if h.GasUsed != h2.GasUsed {
return fmt.Errorf("gasUsed: want: %d have: %d", h.GasUsed, h2.GasUsed)
}
if h.Timestamp != h2.Time {
return fmt.Errorf("timestamp: want: %v have: %v", h.Timestamp, h2.Time)
}
if !reflect.DeepEqual(h.BaseFeePerGas, h2.BaseFee) {
return fmt.Errorf("baseFeePerGas: want: %v have: %v", h.BaseFeePerGas, h2.BaseFee)
}
if !reflect.DeepEqual(h.WithdrawalsRoot, h2.WithdrawalsHash) {
return fmt.Errorf("withdrawalsRoot: want: %v have: %v", h.WithdrawalsRoot, h2.WithdrawalsHash)
}
if !reflect.DeepEqual(h.BlobGasUsed, h2.BlobGasUsed) {
return fmt.Errorf("blobGasUsed: want: %v have: %v", h.BlobGasUsed, h2.BlobGasUsed)
}
if !reflect.DeepEqual(h.ExcessBlobGas, h2.ExcessBlobGas) {
return fmt.Errorf("excessBlobGas: want: %v have: %v", h.ExcessBlobGas, h2.ExcessBlobGas)
}
if !reflect.DeepEqual(h.ParentBeaconBlockRoot, h2.ParentBeaconRoot) {
return fmt.Errorf("parentBeaconBlockRoot: want: %v have: %v", h.ParentBeaconBlockRoot, h2.ParentBeaconRoot)
}
return nil
}
func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
// validate post state accounts in test file against what we have in state db
for addr, acct := range t.json.Post {
// address is indirectly verified by the other fields, as it's the db key
code2 := statedb.GetCode(addr)
balance2 := statedb.GetBalance(addr)
nonce2 := statedb.GetNonce(addr)
if !bytes.Equal(code2, acct.Code) {
return fmt.Errorf("account code mismatch for addr: %s want: %v have: %s", addr, acct.Code, hex.EncodeToString(code2))
}
if balance2.Cmp(acct.Balance) != 0 {
return fmt.Errorf("account balance mismatch for addr: %s, want: %d, have: %d", addr, acct.Balance, balance2)
}
if nonce2 != acct.Nonce {
return fmt.Errorf("account nonce mismatch for addr: %s want: %d have: %d", addr, acct.Nonce, nonce2)
}
for k, v := range acct.Storage {
v2 := statedb.GetState(addr, k)
if v2 != v {
return fmt.Errorf("account storage mismatch for addr: %s, slot: %x, want: %x, have: %x", addr, k, v, v2)
}
}
}
return nil
}
func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []btBlock) error {
// to get constant lookup when verifying block headers by hash (some tests have many blocks)
bmap := make(map[common.Hash]btBlock, len(t.json.Blocks))
for _, b := range validBlocks {
bmap[b.BlockHeader.Hash] = b
}
// iterate over blocks backwards from HEAD and validate imported
// headers vs test file. some tests have reorgs, and we import
// block-by-block, so we can only validate imported headers after
// all blocks have been processed by BlockChain, as they may not
// be part of the longest chain until last block is imported.
for b := cm.CurrentBlock(); b != nil && b.Number.Uint64() != 0; b = cm.GetBlockByHash(b.ParentHash).Header() {
if err := validateHeader(bmap[b.Hash()].BlockHeader, b); err != nil {
return fmt.Errorf("imported block header validation failed: %v", err)
}
}
return nil
}
func (bb *btBlock) decode() (*types.Block, error) {
data, err := hexutil.Decode(bb.Rlp)
if err != nil {
return nil, err
}
var b types.Block
err = rlp.DecodeBytes(data, &b)
return &b, err
}

View file

@ -1,111 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/params"
)
var (
mainnetChainConfig = params.ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(1150000),
DAOForkBlock: big.NewInt(1920000),
DAOForkSupport: true,
EIP150Block: big.NewInt(2463000),
EIP155Block: big.NewInt(2675000),
EIP158Block: big.NewInt(2675000),
ByzantiumBlock: big.NewInt(4370000),
}
ropstenChainConfig = params.ChainConfig{
ChainID: big.NewInt(3),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: true,
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(10),
EIP158Block: big.NewInt(10),
ByzantiumBlock: big.NewInt(1_700_000),
ConstantinopleBlock: big.NewInt(4_230_000),
PetersburgBlock: big.NewInt(4_939_394),
IstanbulBlock: big.NewInt(6_485_846),
MuirGlacierBlock: big.NewInt(7_117_117),
BerlinBlock: big.NewInt(9_812_189),
LondonBlock: big.NewInt(10_499_401),
TerminalTotalDifficulty: new(big.Int).SetUint64(50_000_000_000_000_000),
TerminalTotalDifficultyPassed: true,
}
)
func TestDifficulty(t *testing.T) {
t.Parallel()
dt := new(testMatcher)
// Not difficulty-tests
dt.skipLoad("hexencodetest.*")
dt.skipLoad("crypto.*")
dt.skipLoad("blockgenesistest\\.json")
dt.skipLoad("genesishashestest\\.json")
dt.skipLoad("keyaddrtest\\.json")
dt.skipLoad("txtest\\.json")
// files are 2 years old, contains strange values
dt.skipLoad("difficultyCustomHomestead\\.json")
dt.config("Ropsten", ropstenChainConfig)
dt.config("Frontier", params.ChainConfig{})
dt.config("Homestead", params.ChainConfig{
HomesteadBlock: big.NewInt(0),
})
dt.config("Byzantium", params.ChainConfig{
ByzantiumBlock: big.NewInt(0),
})
dt.config("Frontier", ropstenChainConfig)
dt.config("MainNetwork", mainnetChainConfig)
dt.config("CustomMainNetwork", mainnetChainConfig)
dt.config("Constantinople", params.ChainConfig{
ConstantinopleBlock: big.NewInt(0),
})
dt.config("EIP2384", params.ChainConfig{
MuirGlacierBlock: big.NewInt(0),
})
dt.config("EIP4345", params.ChainConfig{
ArrowGlacierBlock: big.NewInt(0),
})
dt.config("EIP5133", params.ChainConfig{
GrayGlacierBlock: big.NewInt(0),
})
dt.config("difficulty.json", mainnetChainConfig)
dt.walk(t, difficultyTestDir, func(t *testing.T, name string, test *DifficultyTest) {
cfg := dt.findConfig(t)
if test.ParentDifficulty.Cmp(params.MinimumDifficulty) < 0 {
t.Skip("difficulty below minimum")
return
}
if err := dt.checkFailure(t, test.Run(cfg)); err != nil {
t.Error(err)
}
})
}

View file

@ -1,68 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
//go:generate go run github.com/fjl/gencodec -type DifficultyTest -field-override difficultyTestMarshaling -out gen_difficultytest.go
type DifficultyTest struct {
ParentTimestamp uint64 `json:"parentTimestamp"`
ParentDifficulty *big.Int `json:"parentDifficulty"`
UncleHash common.Hash `json:"parentUncles"`
CurrentTimestamp uint64 `json:"currentTimestamp"`
CurrentBlockNumber uint64 `json:"currentBlockNumber"`
CurrentDifficulty *big.Int `json:"currentDifficulty"`
}
type difficultyTestMarshaling struct {
ParentTimestamp math.HexOrDecimal64
ParentDifficulty *math.HexOrDecimal256
CurrentTimestamp math.HexOrDecimal64
CurrentDifficulty *math.HexOrDecimal256
UncleHash common.Hash
CurrentBlockNumber math.HexOrDecimal64
}
func (test *DifficultyTest) Run(config *params.ChainConfig) error {
parentNumber := big.NewInt(int64(test.CurrentBlockNumber - 1))
parent := &types.Header{
Difficulty: test.ParentDifficulty,
Time: test.ParentTimestamp,
Number: parentNumber,
UncleHash: test.UncleHash,
}
actual := ethash.CalcDifficulty(config, test.CurrentTimestamp, parent)
exp := test.CurrentDifficulty
if actual.Cmp(exp) != 0 {
return fmt.Errorf("parent[time %v diff %v unclehash:%x] child[time %v number %v] diff %v != expected %v",
test.ParentTimestamp, test.ParentDifficulty, test.UncleHash,
test.CurrentTimestamp, test.CurrentBlockNumber, actual, exp)
}
return nil
}

@ -1 +0,0 @@
Subproject commit d8b88f4046a87d6b902378cef752591f95427b43

View file

@ -1,160 +0,0 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package tests
import (
"encoding/json"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
)
var _ = (*btHeaderMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (b btHeader) MarshalJSON() ([]byte, error) {
type btHeader struct {
Bloom types.Bloom
Coinbase common.Address
MixHash common.Hash
Nonce types.BlockNonce
Number *math.HexOrDecimal256
Hash common.Hash
ParentHash common.Hash
ReceiptTrie common.Hash
StateRoot common.Hash
TransactionsTrie common.Hash
UncleHash common.Hash
ExtraData hexutil.Bytes
Difficulty *math.HexOrDecimal256
GasLimit math.HexOrDecimal64
GasUsed math.HexOrDecimal64
Timestamp math.HexOrDecimal64
BaseFeePerGas *math.HexOrDecimal256
WithdrawalsRoot *common.Hash
BlobGasUsed *math.HexOrDecimal64
ExcessBlobGas *math.HexOrDecimal64
ParentBeaconBlockRoot *common.Hash
}
var enc btHeader
enc.Bloom = b.Bloom
enc.Coinbase = b.Coinbase
enc.MixHash = b.MixHash
enc.Nonce = b.Nonce
enc.Number = (*math.HexOrDecimal256)(b.Number)
enc.Hash = b.Hash
enc.ParentHash = b.ParentHash
enc.ReceiptTrie = b.ReceiptTrie
enc.StateRoot = b.StateRoot
enc.TransactionsTrie = b.TransactionsTrie
enc.UncleHash = b.UncleHash
enc.ExtraData = b.ExtraData
enc.Difficulty = (*math.HexOrDecimal256)(b.Difficulty)
enc.GasLimit = math.HexOrDecimal64(b.GasLimit)
enc.GasUsed = math.HexOrDecimal64(b.GasUsed)
enc.Timestamp = math.HexOrDecimal64(b.Timestamp)
enc.BaseFeePerGas = (*math.HexOrDecimal256)(b.BaseFeePerGas)
enc.WithdrawalsRoot = b.WithdrawalsRoot
enc.BlobGasUsed = (*math.HexOrDecimal64)(b.BlobGasUsed)
enc.ExcessBlobGas = (*math.HexOrDecimal64)(b.ExcessBlobGas)
enc.ParentBeaconBlockRoot = b.ParentBeaconBlockRoot
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (b *btHeader) UnmarshalJSON(input []byte) error {
type btHeader struct {
Bloom *types.Bloom
Coinbase *common.Address
MixHash *common.Hash
Nonce *types.BlockNonce
Number *math.HexOrDecimal256
Hash *common.Hash
ParentHash *common.Hash
ReceiptTrie *common.Hash
StateRoot *common.Hash
TransactionsTrie *common.Hash
UncleHash *common.Hash
ExtraData *hexutil.Bytes
Difficulty *math.HexOrDecimal256
GasLimit *math.HexOrDecimal64
GasUsed *math.HexOrDecimal64
Timestamp *math.HexOrDecimal64
BaseFeePerGas *math.HexOrDecimal256
WithdrawalsRoot *common.Hash
BlobGasUsed *math.HexOrDecimal64
ExcessBlobGas *math.HexOrDecimal64
ParentBeaconBlockRoot *common.Hash
}
var dec btHeader
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Bloom != nil {
b.Bloom = *dec.Bloom
}
if dec.Coinbase != nil {
b.Coinbase = *dec.Coinbase
}
if dec.MixHash != nil {
b.MixHash = *dec.MixHash
}
if dec.Nonce != nil {
b.Nonce = *dec.Nonce
}
if dec.Number != nil {
b.Number = (*big.Int)(dec.Number)
}
if dec.Hash != nil {
b.Hash = *dec.Hash
}
if dec.ParentHash != nil {
b.ParentHash = *dec.ParentHash
}
if dec.ReceiptTrie != nil {
b.ReceiptTrie = *dec.ReceiptTrie
}
if dec.StateRoot != nil {
b.StateRoot = *dec.StateRoot
}
if dec.TransactionsTrie != nil {
b.TransactionsTrie = *dec.TransactionsTrie
}
if dec.UncleHash != nil {
b.UncleHash = *dec.UncleHash
}
if dec.ExtraData != nil {
b.ExtraData = *dec.ExtraData
}
if dec.Difficulty != nil {
b.Difficulty = (*big.Int)(dec.Difficulty)
}
if dec.GasLimit != nil {
b.GasLimit = uint64(*dec.GasLimit)
}
if dec.GasUsed != nil {
b.GasUsed = uint64(*dec.GasUsed)
}
if dec.Timestamp != nil {
b.Timestamp = uint64(*dec.Timestamp)
}
if dec.BaseFeePerGas != nil {
b.BaseFeePerGas = (*big.Int)(dec.BaseFeePerGas)
}
if dec.WithdrawalsRoot != nil {
b.WithdrawalsRoot = dec.WithdrawalsRoot
}
if dec.BlobGasUsed != nil {
b.BlobGasUsed = (*uint64)(dec.BlobGasUsed)
}
if dec.ExcessBlobGas != nil {
b.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
}
if dec.ParentBeaconBlockRoot != nil {
b.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
}
return nil
}

View file

@ -1,68 +0,0 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package tests
import (
"encoding/json"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
)
var _ = (*difficultyTestMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (d DifficultyTest) MarshalJSON() ([]byte, error) {
type DifficultyTest struct {
ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp"`
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
UncleHash common.Hash `json:"parentUncles"`
CurrentTimestamp math.HexOrDecimal64 `json:"currentTimestamp"`
CurrentBlockNumber math.HexOrDecimal64 `json:"currentBlockNumber"`
CurrentDifficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
}
var enc DifficultyTest
enc.ParentTimestamp = math.HexOrDecimal64(d.ParentTimestamp)
enc.ParentDifficulty = (*math.HexOrDecimal256)(d.ParentDifficulty)
enc.UncleHash = d.UncleHash
enc.CurrentTimestamp = math.HexOrDecimal64(d.CurrentTimestamp)
enc.CurrentBlockNumber = math.HexOrDecimal64(d.CurrentBlockNumber)
enc.CurrentDifficulty = (*math.HexOrDecimal256)(d.CurrentDifficulty)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (d *DifficultyTest) UnmarshalJSON(input []byte) error {
type DifficultyTest struct {
ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp"`
ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
UncleHash *common.Hash `json:"parentUncles"`
CurrentTimestamp *math.HexOrDecimal64 `json:"currentTimestamp"`
CurrentBlockNumber *math.HexOrDecimal64 `json:"currentBlockNumber"`
CurrentDifficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
}
var dec DifficultyTest
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.ParentTimestamp != nil {
d.ParentTimestamp = uint64(*dec.ParentTimestamp)
}
if dec.ParentDifficulty != nil {
d.ParentDifficulty = (*big.Int)(dec.ParentDifficulty)
}
if dec.UncleHash != nil {
d.UncleHash = *dec.UncleHash
}
if dec.CurrentTimestamp != nil {
d.CurrentTimestamp = uint64(*dec.CurrentTimestamp)
}
if dec.CurrentBlockNumber != nil {
d.CurrentBlockNumber = uint64(*dec.CurrentBlockNumber)
}
if dec.CurrentDifficulty != nil {
d.CurrentDifficulty = (*big.Int)(dec.CurrentDifficulty)
}
return nil
}

View file

@ -1,85 +0,0 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package tests
import (
"encoding/json"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
)
var _ = (*stEnvMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (s stEnv) MarshalJSON() ([]byte, error) {
type stEnv struct {
Coinbase common.UnprefixedAddress `json:"currentCoinbase" 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"`
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
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)
enc.BaseFee = (*math.HexOrDecimal256)(s.BaseFee)
enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (s *stEnv) UnmarshalJSON(input []byte) error {
type stEnv struct {
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" 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"`
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
var dec stEnv
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Coinbase == nil {
return errors.New("missing required field 'currentCoinbase' for stEnv")
}
s.Coinbase = common.Address(*dec.Coinbase)
if dec.Difficulty != nil {
s.Difficulty = (*big.Int)(dec.Difficulty)
}
if dec.Random != nil {
s.Random = (*big.Int)(dec.Random)
}
if dec.GasLimit == nil {
return errors.New("missing required field 'currentGasLimit' for stEnv")
}
s.GasLimit = uint64(*dec.GasLimit)
if dec.Number == nil {
return errors.New("missing required field 'currentNumber' for stEnv")
}
s.Number = uint64(*dec.Number)
if dec.Timestamp == nil {
return errors.New("missing required field 'currentTimestamp' for stEnv")
}
s.Timestamp = uint64(*dec.Timestamp)
if dec.BaseFee != nil {
s.BaseFee = (*big.Int)(dec.BaseFee)
}
if dec.ExcessBlobGas != nil {
s.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
}
return nil
}

View file

@ -1,359 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"fmt"
"math/big"
"sort"
"github.com/ethereum/go-ethereum/params"
)
func u64(val uint64) *uint64 { return &val }
// Forks table defines supported forks and their chain config.
var Forks = map[string]*params.ChainConfig{
"Frontier": {
ChainID: big.NewInt(1),
},
"Homestead": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
},
"EIP150": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
},
"EIP158": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
},
"Byzantium": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
DAOForkBlock: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
},
"Constantinople": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
DAOForkBlock: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(10000000),
},
"ConstantinopleFix": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
DAOForkBlock: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
},
"Istanbul": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
DAOForkBlock: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
},
"MuirGlacier": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
DAOForkBlock: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
},
"FrontierToHomesteadAt5": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(5),
},
"HomesteadToEIP150At5": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(5),
},
"HomesteadToDaoAt5": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: big.NewInt(5),
DAOForkSupport: true,
},
"EIP158ToByzantiumAt5": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(5),
},
"ByzantiumToConstantinopleAt5": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(5),
},
"ByzantiumToConstantinopleFixAt5": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(5),
PetersburgBlock: big.NewInt(5),
},
"ConstantinopleFixToIstanbulAt5": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(5),
},
"Berlin": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
},
"BerlinToLondonAt5": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(5),
},
"London": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
},
"ArrowGlacier": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
},
"ArrowGlacierToMergeAtDiffC0000": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0xC0000),
},
"GrayGlacier": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
},
"Merge": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
},
"Shanghai": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
ShanghaiTime: u64(0),
},
"MergeToShanghaiAtTime15k": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
ShanghaiTime: u64(15_000),
},
"Cancun": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
ShanghaiTime: u64(0),
CancunTime: u64(0),
},
"ShanghaiToCancunAtTime15k": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
ShanghaiTime: u64(0),
CancunTime: u64(15_000),
},
}
// AvailableForks returns the set of defined fork names
func AvailableForks() []string {
var availableForks []string
for k := range Forks {
availableForks = append(availableForks, k)
}
sort.Strings(availableForks)
return availableForks
}
// UnsupportedForkError is returned when a test requests a fork that isn't implemented.
type UnsupportedForkError struct {
Name string
}
func (e UnsupportedForkError) Error() string {
return fmt.Sprintf("unsupported fork %q", e.Name)
}

View file

@ -1,291 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"reflect"
"regexp"
"runtime"
"sort"
"strings"
"testing"
"github.com/ethereum/go-ethereum/params"
)
var (
baseDir = filepath.Join(".", "testdata")
blockTestDir = filepath.Join(baseDir, "BlockchainTests")
stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
rlpTestDir = filepath.Join(baseDir, "RLPTests")
difficultyTestDir = filepath.Join(baseDir, "BasicTests")
executionSpecDir = filepath.Join(".", "spec-tests", "fixtures")
benchmarksDir = filepath.Join(".", "evm-benchmarks", "benchmarks")
)
func readJSON(reader io.Reader, value interface{}) error {
data, err := io.ReadAll(reader)
if err != nil {
return fmt.Errorf("error reading JSON file: %v", err)
}
if err = json.Unmarshal(data, &value); err != nil {
if syntaxerr, ok := err.(*json.SyntaxError); ok {
line := findLine(data, syntaxerr.Offset)
return fmt.Errorf("JSON syntax error at line %v: %v", line, err)
}
return err
}
return nil
}
func readJSONFile(fn string, value interface{}) error {
file, err := os.Open(fn)
if err != nil {
return err
}
defer file.Close()
err = readJSON(file, value)
if err != nil {
return fmt.Errorf("%s in file %s", err.Error(), fn)
}
return nil
}
// findLine returns the line number for the given offset into data.
func findLine(data []byte, offset int64) (line int) {
line = 1
for i, r := range string(data) {
if int64(i) >= offset {
return
}
if r == '\n' {
line++
}
}
return
}
// testMatcher controls skipping and chain config assignment to tests.
type testMatcher struct {
configpat []testConfig
failpat []testFailure
skiploadpat []*regexp.Regexp
slowpat []*regexp.Regexp
runonlylistpat *regexp.Regexp
}
type testConfig struct {
p *regexp.Regexp
config params.ChainConfig
}
type testFailure struct {
p *regexp.Regexp
reason string
}
// skipShortMode skips tests matching when the -short flag is used.
func (tm *testMatcher) slow(pattern string) {
tm.slowpat = append(tm.slowpat, regexp.MustCompile(pattern))
}
// skipLoad skips JSON loading of tests matching the pattern.
func (tm *testMatcher) skipLoad(pattern string) {
tm.skiploadpat = append(tm.skiploadpat, regexp.MustCompile(pattern))
}
// fails adds an expected failure for tests matching the pattern.
//
//nolint:unused
func (tm *testMatcher) fails(pattern string, reason string) {
if reason == "" {
panic("empty fail reason")
}
tm.failpat = append(tm.failpat, testFailure{regexp.MustCompile(pattern), reason})
}
func (tm *testMatcher) runonly(pattern string) {
tm.runonlylistpat = regexp.MustCompile(pattern)
}
// config defines chain config for tests matching the pattern.
func (tm *testMatcher) config(pattern string, cfg params.ChainConfig) {
tm.configpat = append(tm.configpat, testConfig{regexp.MustCompile(pattern), cfg})
}
// findSkip matches name against test skip patterns.
func (tm *testMatcher) findSkip(name string) (reason string, skipload bool) {
isWin32 := runtime.GOARCH == "386" && runtime.GOOS == "windows"
for _, re := range tm.slowpat {
if re.MatchString(name) {
if testing.Short() {
return "skipped in -short mode", false
}
if isWin32 {
return "skipped on 32bit windows", false
}
}
}
for _, re := range tm.skiploadpat {
if re.MatchString(name) {
return "skipped by skipLoad", true
}
}
return "", false
}
// findConfig returns the chain config matching defined patterns.
func (tm *testMatcher) findConfig(t *testing.T) *params.ChainConfig {
for _, m := range tm.configpat {
if m.p.MatchString(t.Name()) {
return &m.config
}
}
return new(params.ChainConfig)
}
// checkFailure checks whether a failure is expected.
func (tm *testMatcher) checkFailure(t *testing.T, err error) error {
failReason := ""
for _, m := range tm.failpat {
if m.p.MatchString(t.Name()) {
failReason = m.reason
break
}
}
if failReason != "" {
t.Logf("expected failure: %s", failReason)
if err != nil {
t.Logf("error: %v", err)
return nil
}
return errors.New("test succeeded unexpectedly")
}
return err
}
// walk invokes its runTest argument for all subtests in the given directory.
//
// runTest should be a function of type func(t *testing.T, name string, x <TestType>),
// where TestType is the type of the test contained in test files.
func (tm *testMatcher) walk(t *testing.T, dir string, runTest interface{}) {
// Walk the directory.
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 tests submodule?\n", dir)
t.Skip("missing test files")
}
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
name := filepath.ToSlash(strings.TrimPrefix(path, dir+string(filepath.Separator)))
if info.IsDir() {
if _, skipload := tm.findSkip(name + "/"); skipload {
return filepath.SkipDir
}
return nil
}
if filepath.Ext(path) == ".json" {
t.Run(name, func(t *testing.T) { tm.runTestFile(t, path, name, runTest) })
}
return nil
})
if err != nil {
t.Fatal(err)
}
}
func (tm *testMatcher) runTestFile(t *testing.T, path, name string, runTest interface{}) {
if r, _ := tm.findSkip(name); r != "" {
t.Skip(r)
}
if tm.runonlylistpat != nil {
if !tm.runonlylistpat.MatchString(name) {
t.Skip("Skipped by runonly")
}
}
t.Parallel()
// Load the file as map[string]<testType>.
m := makeMapFromTestFunc(runTest)
if err := readJSONFile(path, m.Addr().Interface()); err != nil {
t.Fatal(err)
}
// Run all tests from the map. Don't wrap in a subtest if there is only one test in the file.
keys := sortedMapKeys(m)
if len(keys) == 1 {
runTestFunc(runTest, t, name, m, keys[0])
} else {
for _, key := range keys {
name := name + "/" + key
t.Run(key, func(t *testing.T) {
if r, _ := tm.findSkip(name); r != "" {
t.Skip(r)
}
runTestFunc(runTest, t, name, m, key)
})
}
}
}
func makeMapFromTestFunc(f interface{}) reflect.Value {
stringT := reflect.TypeOf("")
testingT := reflect.TypeOf((*testing.T)(nil))
ftyp := reflect.TypeOf(f)
if ftyp.Kind() != reflect.Func || ftyp.NumIn() != 3 || ftyp.NumOut() != 0 || ftyp.In(0) != testingT || ftyp.In(1) != stringT {
panic(fmt.Sprintf("bad test function type: want func(*testing.T, string, <TestType>), have %s", ftyp))
}
testType := ftyp.In(2)
mp := reflect.New(reflect.MapOf(stringT, testType))
return mp.Elem()
}
func sortedMapKeys(m reflect.Value) []string {
keys := make([]string, m.Len())
for i, k := range m.MapKeys() {
keys[i] = k.String()
}
sort.Strings(keys)
return keys
}
func runTestFunc(runTest interface{}, t *testing.T, name string, m reflect.Value, key string) {
reflect.ValueOf(runTest).Call([]reflect.Value{
reflect.ValueOf(t),
reflect.ValueOf(name),
m.MapIndex(reflect.ValueOf(key)),
})
}
func TestMatcherRunonlylist(t *testing.T) {
t.Parallel()
tm := new(testMatcher)
tm.runonly("invalid*")
tm.walk(t, rlpTestDir, func(t *testing.T, name string, test *RLPTest) {
if name[:len("invalidRLPTest.json")] != "invalidRLPTest.json" {
t.Fatalf("invalid test found: %s != invalidRLPTest.json", name)
}
})
}

View file

@ -1,31 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"testing"
)
func TestRLP(t *testing.T) {
t.Parallel()
tm := new(testMatcher)
tm.walk(t, rlpTestDir, func(t *testing.T, name string, test *RLPTest) {
if err := tm.checkFailure(t, test.Run()); err != nil {
t.Error(err)
}
})
}

View file

@ -1,172 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/rlp"
)
// RLPTest is the JSON structure of a single RLP test.
type RLPTest struct {
// If the value of In is "INVALID" or "VALID", the test
// checks whether Out can be decoded into a value of
// type interface{}.
//
// For other JSON values, In is treated as a driver for
// calls to rlp.Stream. The test also verifies that encoding
// In produces the bytes in Out.
In interface{}
// Out is a hex-encoded RLP value.
Out string
}
// FromHex returns the bytes represented by the hexadecimal string s.
// s may be prefixed with "0x".
// This is copy-pasted from bytes.go, which does not return the error
func FromHex(s string) ([]byte, error) {
if len(s) > 1 && (s[0:2] == "0x" || s[0:2] == "0X") {
s = s[2:]
}
if len(s)%2 == 1 {
s = "0" + s
}
return hex.DecodeString(s)
}
// Run executes the test.
func (t *RLPTest) Run() error {
outb, err := FromHex(t.Out)
if err != nil {
return errors.New("invalid hex in Out")
}
// Handle simple decoding tests with no actual In value.
if t.In == "VALID" || t.In == "INVALID" {
return checkDecodeInterface(outb, t.In == "VALID")
}
// Check whether encoding the value produces the same bytes.
in := translateJSON(t.In)
b, err := rlp.EncodeToBytes(in)
if err != nil {
return fmt.Errorf("encode failed: %v", err)
}
if !bytes.Equal(b, outb) {
return fmt.Errorf("encode produced %x, want %x", b, outb)
}
// Test stream decoding.
s := rlp.NewStream(bytes.NewReader(outb), 0)
return checkDecodeFromJSON(s, in)
}
func checkDecodeInterface(b []byte, isValid bool) error {
err := rlp.DecodeBytes(b, new(interface{}))
switch {
case isValid && err != nil:
return fmt.Errorf("decoding failed: %v", err)
case !isValid && err == nil:
return errors.New("decoding of invalid value succeeded")
}
return nil
}
// translateJSON makes test json values encodable with RLP.
func translateJSON(v interface{}) interface{} {
switch v := v.(type) {
case float64:
return uint64(v)
case string:
if len(v) > 0 && v[0] == '#' { // # starts a faux big int.
big, ok := new(big.Int).SetString(v[1:], 10)
if !ok {
panic(fmt.Errorf("bad test: bad big int: %q", v))
}
return big
}
return []byte(v)
case []interface{}:
new := make([]interface{}, len(v))
for i := range v {
new[i] = translateJSON(v[i])
}
return new
default:
panic(fmt.Errorf("can't handle %T", v))
}
}
// checkDecodeFromJSON decodes from s guided by exp. exp drives the
// Stream by invoking decoding operations (Uint, Big, List, ...) based
// on the type of each value. The value decoded from the RLP stream
// must match the JSON value.
func checkDecodeFromJSON(s *rlp.Stream, exp interface{}) error {
switch exp := exp.(type) {
case uint64:
i, err := s.Uint64()
if err != nil {
return addStack("Uint", exp, err)
}
if i != exp {
return addStack("Uint", exp, fmt.Errorf("result mismatch: got %d", i))
}
case *big.Int:
big := new(big.Int)
if err := s.Decode(&big); err != nil {
return addStack("Big", exp, err)
}
if big.Cmp(exp) != 0 {
return addStack("Big", exp, fmt.Errorf("result mismatch: got %d", big))
}
case []byte:
b, err := s.Bytes()
if err != nil {
return addStack("Bytes", exp, err)
}
if !bytes.Equal(b, exp) {
return addStack("Bytes", exp, fmt.Errorf("result mismatch: got %x", b))
}
case []interface{}:
if _, err := s.List(); err != nil {
return addStack("List", exp, err)
}
for i, v := range exp {
if err := checkDecodeFromJSON(s, v); err != nil {
return addStack(fmt.Sprintf("[%d]", i), exp, err)
}
}
if err := s.ListEnd(); err != nil {
return addStack("ListEnd", exp, err)
}
default:
panic(fmt.Errorf("unhandled type: %T", exp))
}
return nil
}
func addStack(op string, val interface{}, err error) error {
lines := strings.Split(err.Error(), "\n")
lines = append(lines, fmt.Sprintf("\t%s: %v", op, val))
return errors.New(strings.Join(lines, "\n"))
}

View file

@ -1,311 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"bufio"
"bytes"
"fmt"
"math/big"
"math/rand"
"os"
"path/filepath"
"reflect"
"runtime"
"strings"
"testing"
"time"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
)
func TestState(t *testing.T) {
t.Parallel()
st := new(testMatcher)
// Long tests:
st.slow(`^stAttackTest/ContractCreationSpam`)
st.slow(`^stBadOpcode/badOpcodes`)
st.slow(`^stPreCompiledContracts/modexp`)
st.slow(`^stQuadraticComplexityTest/`)
st.slow(`^stStaticCall/static_Call50000`)
st.slow(`^stStaticCall/static_Return50000`)
st.slow(`^stSystemOperationsTest/CallRecursiveBomb`)
st.slow(`^stTransactionTest/Opcodes_TransactionInit`)
// Very time consuming
st.skipLoad(`^stTimeConsuming/`)
st.skipLoad(`.*vmPerformance/loop.*`)
// Uses 1GB RAM per tested fork
st.skipLoad(`^stStaticCall/static_Call1MB`)
// Broken tests:
// EOF is not part of cancun
st.skipLoad(`^stEOF/`)
// EIP-4844 tests need to be regenerated due to the data-to-blob rename
st.skipLoad(`^stEIP4844-blobtransactions/`)
// Expected failures:
// These EIP-4844 tests need to be regenerated.
st.fails(`stEIP4844-blobtransactions/opcodeBlobhashOutOfRange.json`, "test has incorrect state root")
st.fails(`stEIP4844-blobtransactions/opcodeBlobhBounds.json`, "test has incorrect state root")
// For Istanbul, older tests were moved into LegacyTests
for _, dir := range []string{
filepath.Join(baseDir, "EIPTests", "StateTests"),
stateTestDir,
legacyStateTestDir,
benchmarksDir,
} {
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
if runtime.GOARCH == "386" && runtime.GOOS == "windows" && rand.Int63()%2 == 0 {
t.Skip("test (randomly) skipped on 32-bit windows")
return
}
for _, subtest := range test.Subtests() {
subtest := subtest
key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index)
t.Run(key+"/hash/trie", func(t *testing.T) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error
test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
result = st.checkFailure(t, err)
})
return result
})
})
t.Run(key+"/hash/snap", func(t *testing.T) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error
test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
if snaps != nil && state != nil {
if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
result = err
return
}
}
result = st.checkFailure(t, err)
})
return result
})
})
t.Run(key+"/path/trie", func(t *testing.T) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error
test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
result = st.checkFailure(t, err)
})
return result
})
})
t.Run(key+"/path/snap", func(t *testing.T) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error
test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
if snaps != nil && state != nil {
if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
result = err
return
}
}
result = st.checkFailure(t, err)
})
return result
})
})
}
})
}
}
// Transactions with gasLimit above this value will not get a VM trace on failure.
const traceErrorLimit = 400000
func withTrace(t *testing.T, gasLimit uint64, test func(vm.Config) error) {
// Use config from command line arguments.
config := vm.Config{}
err := test(config)
if err == nil {
return
}
// Test failed, re-run with tracing enabled.
t.Error(err)
if gasLimit > traceErrorLimit {
t.Log("gas limit too high for EVM trace")
return
}
buf := new(bytes.Buffer)
w := bufio.NewWriter(buf)
config.Tracer = logger.NewJSONLogger(&logger.Config{}, w)
err2 := test(config)
if !reflect.DeepEqual(err, err2) {
t.Errorf("different error for second run: %v", err2)
}
w.Flush()
if buf.Len() == 0 {
t.Log("no EVM operation logs generated")
} else {
t.Log("EVM operation log:\n" + buf.String())
}
// 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 {
t := t
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
}
var rules = config.Rules(new(big.Int), false, 0)
vmconfig.ExtraEips = eips
block := t.genesis(config).ToBlock()
triedb, _, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false, rawdb.HashScheme)
defer triedb.Close()
var baseFee *big.Int
if rules.IsLondon {
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)
var (
gasUsed uint64
elapsed uint64
refund uint64
)
b.ResetTimer()
for n := 0; n < b.N; n++ {
snapshot := statedb.Snapshot()
statedb.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)
b.StartTimer()
start := time.Now()
// Execute the message.
_, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, msg.Value)
if err != nil {
b.Error(err)
return
}
b.StopTimer()
elapsed += uint64(time.Since(start))
refund += statedb.GetRefund()
gasUsed += msg.GasLimit - leftOverGas
statedb.RevertToSnapshot(snapshot)
}
if elapsed < 1 {
elapsed = 1
}
// Keep it as uint64, multiply 100 to get two digit float later
mgasps := (100 * 1000 * (gasUsed - refund)) / elapsed
b.ReportMetric(float64(mgasps)/100, "mgas/s")
})
}
}

View file

@ -1,468 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"math/big"
"strconv"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"golang.org/x/crypto/sha3"
)
// StateTest checks transaction processing without block context.
// See https://github.com/ethereum/EIPs/issues/176 for the test format specification.
type StateTest struct {
json stJSON
}
// StateSubtest selects a specific configuration of a General State Test.
type StateSubtest struct {
Fork string
Index int
}
func (t *StateTest) UnmarshalJSON(in []byte) error {
return json.Unmarshal(in, &t.json)
}
type stJSON struct {
Env stEnv `json:"env"`
Pre core.GenesisAlloc `json:"pre"`
Tx stTransaction `json:"transaction"`
Out hexutil.Bytes `json:"out"`
Post map[string][]stPostState `json:"post"`
}
type stPostState struct {
Root common.UnprefixedHash `json:"hash"`
Logs common.UnprefixedHash `json:"logs"`
TxBytes hexutil.Bytes `json:"txbytes"`
ExpectException string `json:"expectException"`
Indexes struct {
Data int `json:"data"`
Gas int `json:"gas"`
Value int `json:"value"`
}
}
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
type stEnv struct {
Coinbase common.Address `json:"currentCoinbase" 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"`
ExcessBlobGas *uint64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
type stEnvMarshaling struct {
Coinbase common.UnprefixedAddress
Difficulty *math.HexOrDecimal256
Random *math.HexOrDecimal256
GasLimit math.HexOrDecimal64
Number math.HexOrDecimal64
Timestamp math.HexOrDecimal64
BaseFee *math.HexOrDecimal256
ExcessBlobGas *math.HexOrDecimal64
}
//go:generate go run github.com/fjl/gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go
type stTransaction struct {
GasPrice *big.Int `json:"gasPrice"`
MaxFeePerGas *big.Int `json:"maxFeePerGas"`
MaxPriorityFeePerGas *big.Int `json:"maxPriorityFeePerGas"`
Nonce uint64 `json:"nonce"`
To string `json:"to"`
Data []string `json:"data"`
AccessLists []*types.AccessList `json:"accessLists,omitempty"`
GasLimit []uint64 `json:"gasLimit"`
Value []string `json:"value"`
PrivateKey []byte `json:"secretKey"`
Sender *common.Address `json:"sender"`
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
BlobGasFeeCap *big.Int `json:"maxFeePerBlobGas,omitempty"`
}
type stTransactionMarshaling struct {
GasPrice *math.HexOrDecimal256
MaxFeePerGas *math.HexOrDecimal256
MaxPriorityFeePerGas *math.HexOrDecimal256
Nonce math.HexOrDecimal64
GasLimit []math.HexOrDecimal64
PrivateKey hexutil.Bytes
BlobGasFeeCap *math.HexOrDecimal256
}
// GetChainConfig takes a fork definition and returns a chain config.
// The fork definition can be
// - a plain forkname, e.g. `Byzantium`,
// - a fork basename, and a list of EIPs to enable; e.g. `Byzantium+1884+1283`.
func GetChainConfig(forkString string) (baseConfig *params.ChainConfig, eips []int, err error) {
var (
splitForks = strings.Split(forkString, "+")
ok bool
baseName, eipsStrings = splitForks[0], splitForks[1:]
)
if baseConfig, ok = Forks[baseName]; !ok {
return nil, nil, UnsupportedForkError{baseName}
}
for _, eip := range eipsStrings {
if eipNum, err := strconv.Atoi(eip); err != nil {
return nil, nil, fmt.Errorf("syntax error, invalid eip number %v", eipNum)
} else {
if !vm.ValidEip(eipNum) {
return nil, nil, fmt.Errorf("syntax error, invalid eip number %v", eipNum)
}
eips = append(eips, eipNum)
}
}
return baseConfig, eips, nil
}
// Subtests returns all valid subtests of the test.
func (t *StateTest) Subtests() []StateSubtest {
var sub []StateSubtest
for fork, pss := range t.json.Post {
for i := range pss {
sub = append(sub, StateSubtest{fork, i})
}
}
return sub
}
// checkError checks if the error returned by the state transition matches any expected error.
// A failing expectation returns a wrapped version of the original error, if any,
// or a new error detailing the failing expectation.
// This function does not return or modify the original error, it only evaluates and returns expectations for the error.
func (t *StateTest) checkError(subtest StateSubtest, err error) error {
expectedError := t.json.Post[subtest.Fork][subtest.Index].ExpectException
if err == nil && expectedError == "" {
return nil
}
if err == nil && expectedError != "" {
return fmt.Errorf("expected error %q, got no error", expectedError)
}
if err != nil && expectedError == "" {
return fmt.Errorf("unexpected error: %w", err)
}
if err != nil && expectedError != "" {
// Ignore expected errors (TODO MariusVanDerWijden check error string)
return nil
}
return nil
}
// Run executes a specific subtest and verifies the post-state and logs
func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, snaps *snapshot.Tree, state *state.StateDB)) (result error) {
triedb, snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
// Invoke the callback at the end of function for further analysis.
defer func() {
postCheck(result, snaps, statedb)
if triedb != nil {
triedb.Close()
}
if snaps != nil {
snaps.Release()
}
}()
checkedErr := t.checkError(subtest, err)
if checkedErr != nil {
return checkedErr
}
// The error has been checked; if it was unexpected, it's already returned.
if err != nil {
// Here, an error exists but it was expected.
// We do not check the post state or logs.
return nil
}
post := t.json.Post[subtest.Fork][subtest.Index]
// N.B: We need to do this in a two-step process, because the first Commit takes care
// of self-destructs, and we need to touch the coinbase _after_ it has potentially self-destructed.
if root != common.Hash(post.Root) {
return fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
}
if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
}
statedb, _ = state.New(root, statedb.Database(), snaps)
return nil
}
// RunNoVerify runs a specific subtest and returns the statedb and post-state root
func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB, common.Hash, error) {
config, eips, err := GetChainConfig(subtest.Fork)
if err != nil {
return nil, nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork}
}
vmconfig.ExtraEips = eips
block := t.genesis(config).ToBlock()
triedb, snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
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 {
triedb.Close()
return nil, nil, nil, common.Hash{}, err
}
// Try to recover tx with current signer
if len(post.TxBytes) != 0 {
var ttx types.Transaction
err := ttx.UnmarshalBinary(post.TxBytes)
if err != nil {
triedb.Close()
return nil, nil, nil, common.Hash{}, err
}
if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
triedb.Close()
return nil, nil, nil, common.Hash{}, err
}
}
// Prepare the EVM.
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
context.GetHash = vmTestBlockHash
context.BaseFee = baseFee
context.Random = nil
if t.json.Env.Difficulty != nil {
context.Difficulty = new(big.Int).Set(t.json.Env.Difficulty)
}
if config.IsLondon(new(big.Int)) && t.json.Env.Random != nil {
rnd := common.BigToHash(t.json.Env.Random)
context.Random = &rnd
context.Difficulty = big.NewInt(0)
}
if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
context.BlobBaseFee = eip4844.CalcBlobFee(*t.json.Env.ExcessBlobGas)
}
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
// Execute the message.
snapshot := statedb.Snapshot()
gaspool := new(core.GasPool)
gaspool.AddGas(block.GasLimit())
_, err = core.ApplyMessage(evm, msg, gaspool)
if err != nil {
statedb.RevertToSnapshot(snapshot)
}
// Add 0-value mining reward. This only makes a difference in the cases
// where
// - the coinbase self-destructed, or
// - there are only 'bad' transactions, which aren't executed. In those cases,
// the coinbase gets no txfee, so isn't created, and thus needs to be touched
statedb.AddBalance(block.Coinbase(), new(big.Int))
// Commit state mutations into database.
root, _ := statedb.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
return triedb, snaps, statedb, root, err
}
func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
}
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB) {
tconf := &trie.Config{Preimages: true}
if scheme == rawdb.HashScheme {
tconf.HashDB = hashdb.Defaults
} else {
tconf.PathDB = pathdb.Defaults
}
triedb := trie.NewDatabase(db, tconf)
sdb := state.NewDatabaseWithNodeDB(db, triedb)
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
for addr, a := range accounts {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce)
statedb.SetBalance(addr, a.Balance)
for k, v := range a.Storage {
statedb.SetState(addr, k, v)
}
}
// Commit and re-open to start with a clean state.
root, _ := statedb.Commit(0, false)
var snaps *snapshot.Tree
if snapshotter {
snapconfig := snapshot.Config{
CacheSize: 1,
Recovery: false,
NoBuild: false,
AsyncBuild: false,
}
snaps, _ = snapshot.New(snapconfig, db, triedb, root)
}
statedb, _ = state.New(root, sdb, snaps)
return triedb, snaps, statedb
}
func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
genesis := &core.Genesis{
Config: config,
Coinbase: t.json.Env.Coinbase,
Difficulty: t.json.Env.Difficulty,
GasLimit: t.json.Env.GasLimit,
Number: t.json.Env.Number,
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) {
var from common.Address
// If 'sender' field is present, use that
if tx.Sender != nil {
from = *tx.Sender
} else if len(tx.PrivateKey) > 0 {
// Derive sender from private key if needed.
key, err := crypto.ToECDSA(tx.PrivateKey)
if err != nil {
return nil, fmt.Errorf("invalid private key: %v", err)
}
from = crypto.PubkeyToAddress(key.PublicKey)
}
// Parse recipient if present.
var to *common.Address
if tx.To != "" {
to = new(common.Address)
if err := to.UnmarshalText([]byte(tx.To)); err != nil {
return nil, fmt.Errorf("invalid to address: %v", err)
}
}
// Get values specific to this post state.
if ps.Indexes.Data > len(tx.Data) {
return nil, fmt.Errorf("tx data index %d out of bounds", ps.Indexes.Data)
}
if ps.Indexes.Value > len(tx.Value) {
return nil, fmt.Errorf("tx value index %d out of bounds", ps.Indexes.Value)
}
if ps.Indexes.Gas > len(tx.GasLimit) {
return nil, fmt.Errorf("tx gas limit index %d out of bounds", ps.Indexes.Gas)
}
dataHex := tx.Data[ps.Indexes.Data]
valueHex := tx.Value[ps.Indexes.Value]
gasLimit := tx.GasLimit[ps.Indexes.Gas]
// Value, Data hex encoding is messy: https://github.com/ethereum/tests/issues/203
value := new(big.Int)
if valueHex != "0x" {
v, ok := math.ParseBig256(valueHex)
if !ok {
return nil, fmt.Errorf("invalid tx value %q", valueHex)
}
value = v
}
data, err := hex.DecodeString(strings.TrimPrefix(dataHex, "0x"))
if err != nil {
return nil, fmt.Errorf("invalid tx data %q", dataHex)
}
var accessList types.AccessList
if tx.AccessLists != nil && tx.AccessLists[ps.Indexes.Data] != nil {
accessList = *tx.AccessLists[ps.Indexes.Data]
}
// If baseFee provided, set gasPrice to effectiveGasPrice.
gasPrice := tx.GasPrice
if baseFee != nil {
if tx.MaxFeePerGas == nil {
tx.MaxFeePerGas = gasPrice
}
if tx.MaxFeePerGas == nil {
tx.MaxFeePerGas = new(big.Int)
}
if tx.MaxPriorityFeePerGas == nil {
tx.MaxPriorityFeePerGas = tx.MaxFeePerGas
}
gasPrice = math.BigMin(new(big.Int).Add(tx.MaxPriorityFeePerGas, baseFee),
tx.MaxFeePerGas)
}
if gasPrice == nil {
return nil, errors.New("no gas price provided")
}
msg := &core.Message{
From: from,
To: to,
Nonce: tx.Nonce,
Value: value,
GasLimit: gasLimit,
GasPrice: gasPrice,
GasFeeCap: tx.MaxFeePerGas,
GasTipCap: tx.MaxPriorityFeePerGas,
Data: data,
AccessList: accessList,
BlobHashes: tx.BlobVersionedHashes,
BlobGasFeeCap: tx.BlobGasFeeCap,
}
return msg, nil
}
func rlpHash(x interface{}) (h common.Hash) {
hw := sha3.NewLegacyKeccak256()
rlp.Encode(hw, x)
hw.Sum(h[:0])
return h
}
func vmTestBlockHash(n uint64) common.Hash {
return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
}

@ -1 +0,0 @@
Subproject commit ee3fa4c86d05f99f2717f83a6ad08008490ddf07

View file

@ -1,54 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"testing"
"github.com/ethereum/go-ethereum/params"
)
func TestTransaction(t *testing.T) {
t.Parallel()
txt := new(testMatcher)
// These can't be parsed, invalid hex in RLP
txt.skipLoad("^ttWrongRLP/.*")
// We don't allow more than uint64 in gas amount
// This is a pseudo-consensus vulnerability, but not in practice
// because of the gas limit
txt.skipLoad("^ttGasLimit/TransactionWithGasLimitxPriceOverflow.json")
// We _do_ allow more than uint64 in gas price, as opposed to the tests
// This is also not a concern, as long as tx.Cost() uses big.Int for
// calculating the final cozt
txt.skipLoad(".*TransactionWithGasPriceOverflow.*")
// The nonce is too large for uint64. Not a concern, it means geth won't
// accept transactions at a certain point in the distant future
txt.skipLoad("^ttNonce/TransactionWithHighNonce256.json")
// The value is larger than uint64, which according to the test is invalid.
// Geth accepts it, which is not a consensus issue since we use big.Int's
// internally to calculate the cost
txt.skipLoad("^ttValue/TransactionWithHighValueOverflow.json")
txt.walk(t, transactionTestDir, func(t *testing.T, name string, test *TransactionTest) {
cfg := params.MainnetChainConfig
if err := txt.checkFailure(t, test.Run(cfg)); err != nil {
t.Error(err)
}
})
}

View file

@ -1,110 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package tests
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
// TransactionTest checks RLP decoding and sender derivation of transactions.
type TransactionTest struct {
RLP hexutil.Bytes `json:"rlp"`
Byzantium ttFork
Constantinople ttFork
Istanbul ttFork
EIP150 ttFork
EIP158 ttFork
Frontier ttFork
Homestead ttFork
}
type ttFork struct {
Sender common.UnprefixedAddress `json:"sender"`
Hash common.UnprefixedHash `json:"hash"`
}
func (tt *TransactionTest) Run(config *params.ChainConfig) error {
validateTx := func(rlpData hexutil.Bytes, signer types.Signer, isHomestead bool, isIstanbul bool) (*common.Address, *common.Hash, error) {
tx := new(types.Transaction)
if err := rlp.DecodeBytes(rlpData, tx); err != nil {
return nil, nil, err
}
sender, err := types.Sender(signer, tx)
if err != nil {
return nil, nil, err
}
// Intrinsic gas
requiredGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, isHomestead, isIstanbul, false)
if err != nil {
return nil, nil, err
}
if requiredGas > tx.Gas() {
return nil, nil, fmt.Errorf("insufficient gas ( %d < %d )", tx.Gas(), requiredGas)
}
h := tx.Hash()
return &sender, &h, nil
}
for _, testcase := range []struct {
name string
signer types.Signer
fork ttFork
isHomestead bool
isIstanbul bool
}{
{"Frontier", types.FrontierSigner{}, tt.Frontier, false, false},
{"Homestead", types.HomesteadSigner{}, tt.Homestead, true, false},
{"EIP150", types.HomesteadSigner{}, tt.EIP150, true, false},
{"EIP158", types.NewEIP155Signer(config.ChainID), tt.EIP158, true, false},
{"Byzantium", types.NewEIP155Signer(config.ChainID), tt.Byzantium, true, false},
{"Constantinople", types.NewEIP155Signer(config.ChainID), tt.Constantinople, true, false},
{"Istanbul", types.NewEIP155Signer(config.ChainID), tt.Istanbul, true, true},
} {
sender, txhash, err := validateTx(tt.RLP, testcase.signer, testcase.isHomestead, testcase.isIstanbul)
if testcase.fork.Sender == (common.UnprefixedAddress{}) {
if err == nil {
return fmt.Errorf("expected error, got none (address %v)[%v]", sender.String(), testcase.name)
}
continue
}
// Should resolve the right address
if err != nil {
return fmt.Errorf("got error, expected none: %v", err)
}
if sender == nil {
return fmt.Errorf("sender was nil, should be %x", common.Address(testcase.fork.Sender))
}
if *sender != common.Address(testcase.fork.Sender) {
return fmt.Errorf("sender mismatch: got %x, want %x", sender, testcase.fork.Sender)
}
if txhash == nil {
return fmt.Errorf("txhash was nil, should be %x", common.Hash(testcase.fork.Hash))
}
if *txhash != common.Hash(testcase.fork.Hash) {
return fmt.Errorf("hash mismatch: got %x, want %x", *txhash, testcase.fork.Hash)
}
}
return nil
}