From 0e9c7d564d6000a372cd3df914ec6c969aea29f2 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 7 Jun 2021 14:37:56 +0200 Subject: [PATCH] tests: update for London (#22976) This updates the tests submodule to the London fork tests, and also updates the test runner to support the new EIP-1559 fields in test JSON. --- cmd/evm/internal/t8ntool/execution.go | 15 ++++--- core/gen_genesis.go | 8 ++++ core/gen_genesis_account.go | 2 + core/genesis.go | 7 ++- tests/block_test.go | 1 - tests/block_test_util.go | 20 ++++++--- tests/gen_btheader.go | 6 +++ tests/gen_stenv.go | 6 +++ tests/gen_sttransaction.go | 44 ++++++++++++------- tests/state_test_util.go | 63 ++++++++++++++++++++------- tests/testdata | 2 +- 11 files changed, 130 insertions(+), 44 deletions(-) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index cf6974bc43..ccc90618b4 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -52,7 +52,7 @@ type ExecutionResult struct { LogsHash common.Hash `json:"logsHash"` Bloom types.Bloom `json:"logsBloom" gencodec:"required"` Receipts types.Receipts `json:"receipts"` - Rejected []int `json:"rejected,omitempty"` + Rejected []*rejectedTx `json:"rejected,omitempty"` } type ommer struct { @@ -81,6 +81,11 @@ type stEnvMarshaling struct { BaseFee *math.HexOrDecimal256 } +type rejectedTx struct { + Index int `json:"index"` + Err string `json:"error"` +} + // Apply applies a set of transactions to a pre-state func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, txs types.Transactions, miningReward int64, @@ -105,7 +110,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number)) gaspool = new(core.GasPool) blockHash = common.Hash{0x13, 0x37} - rejectedTxs []int + rejectedTxs []*rejectedTx includedTxs types.Transactions gasUsed = uint64(0) receipts = make(types.Receipts, 0) @@ -137,8 +142,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, for i, tx := range txs { msg, err := tx.AsMessage(signer, pre.Env.BaseFee) if err != nil { - log.Info("rejected tx", "index", i, "hash", tx.Hash(), "error", err) - rejectedTxs = append(rejectedTxs, i) + log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", err) + rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) continue } tracer, err := getTracerFn(txIndex, tx.Hash()) @@ -157,7 +162,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, if err != nil { statedb.RevertToSnapshot(snapshot) log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From(), "error", err) - rejectedTxs = append(rejectedTxs, i) + rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) continue } includedTxs = append(includedTxs, tx) diff --git a/core/gen_genesis.go b/core/gen_genesis.go index bb8ea1d6a2..1dcced1a8c 100644 --- a/core/gen_genesis.go +++ b/core/gen_genesis.go @@ -15,6 +15,7 @@ import ( var _ = (*genesisSpecMarshaling)(nil) +// MarshalJSON marshals as JSON. func (g Genesis) MarshalJSON() ([]byte, error) { type Genesis struct { Config *params.ChainConfig `json:"config"` @@ -29,6 +30,7 @@ func (g Genesis) MarshalJSON() ([]byte, error) { Number math.HexOrDecimal64 `json:"number"` GasUsed math.HexOrDecimal64 `json:"gasUsed"` ParentHash common.Hash `json:"parentHash"` + BaseFee *big.Int `json:"baseFee"` } var enc Genesis enc.Config = g.Config @@ -48,9 +50,11 @@ func (g Genesis) MarshalJSON() ([]byte, error) { enc.Number = math.HexOrDecimal64(g.Number) enc.GasUsed = math.HexOrDecimal64(g.GasUsed) enc.ParentHash = g.ParentHash + enc.BaseFee = g.BaseFee return json.Marshal(&enc) } +// UnmarshalJSON unmarshals from JSON. func (g *Genesis) UnmarshalJSON(input []byte) error { type Genesis struct { Config *params.ChainConfig `json:"config"` @@ -65,6 +69,7 @@ func (g *Genesis) UnmarshalJSON(input []byte) error { Number *math.HexOrDecimal64 `json:"number"` GasUsed *math.HexOrDecimal64 `json:"gasUsed"` ParentHash *common.Hash `json:"parentHash"` + BaseFee *big.Int `json:"baseFee"` } var dec Genesis if err := json.Unmarshal(input, &dec); err != nil { @@ -112,5 +117,8 @@ func (g *Genesis) UnmarshalJSON(input []byte) error { if dec.ParentHash != nil { g.ParentHash = *dec.ParentHash } + if dec.BaseFee != nil { + g.BaseFee = dec.BaseFee + } return nil } diff --git a/core/gen_genesis_account.go b/core/gen_genesis_account.go index 64fb9b9248..a9d47e6ba3 100644 --- a/core/gen_genesis_account.go +++ b/core/gen_genesis_account.go @@ -14,6 +14,7 @@ import ( var _ = (*genesisAccountMarshaling)(nil) +// MarshalJSON marshals as JSON. func (g GenesisAccount) MarshalJSON() ([]byte, error) { type GenesisAccount struct { Code hexutil.Bytes `json:"code,omitempty"` @@ -36,6 +37,7 @@ func (g GenesisAccount) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals from JSON. func (g *GenesisAccount) UnmarshalJSON(input []byte) error { type GenesisAccount struct { Code *hexutil.Bytes `json:"code,omitempty"` diff --git a/core/genesis.go b/core/genesis.go index bcfb849119..d14b75da17 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -62,6 +62,7 @@ type Genesis struct { Number uint64 `json:"number"` GasUsed uint64 `json:"gasUsed"` ParentHash common.Hash `json:"parentHash"` + BaseFee *big.Int `json:"baseFee"` } // GenesisAlloc specifies the initial state that is part of the genesis block. @@ -292,7 +293,11 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { head.Difficulty = params.GenesisDifficulty } if g.Config != nil && g.Config.IsLondon(common.Big0) { - head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) + if g.BaseFee != nil { + head.BaseFee = g.BaseFee + } else { + head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) + } } statedb.Commit(false) statedb.Database().TrieDB().Commit(root, true, nil) diff --git a/tests/block_test.go b/tests/block_test.go index f7fbaea2a4..74c7ed8197 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -43,7 +43,6 @@ func TestBlockchain(t *testing.T) { // 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.*`) diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 745208b5b8..c9c0afb1ba 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -23,6 +23,7 @@ import ( "encoding/json" "fmt" "math/big" + "os" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -59,9 +60,10 @@ type btJSON struct { } type btBlock struct { - BlockHeader *btHeader - Rlp string - UncleHeaders []*btHeader + BlockHeader *btHeader + ExpectException string + Rlp string + UncleHeaders []*btHeader } //go:generate gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go @@ -83,6 +85,7 @@ type btHeader struct { GasLimit uint64 GasUsed uint64 Timestamp uint64 + BaseFee *big.Int } type btHeaderMarshaling struct { @@ -92,6 +95,7 @@ type btHeaderMarshaling struct { GasLimit math.HexOrDecimal64 GasUsed math.HexOrDecimal64 Timestamp math.HexOrDecimal64 + BaseFee *math.HexOrDecimal256 } func (t *BlockTest) Run(snapshotter bool) error { @@ -166,6 +170,7 @@ func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis { Mixhash: t.json.Genesis.MixHash, Coinbase: t.json.Genesis.Coinbase, Alloc: t.json.Pre, + BaseFee: t.json.Genesis.BaseFee, } } @@ -184,7 +189,7 @@ func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis { func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) { validBlocks := make([]btBlock, 0) // insert the test blocks, which will execute all transactions - for _, b := range t.json.Blocks { + for bi, b := range t.json.Blocks { cb, err := b.decode() if err != nil { if b.BlockHeader == nil { @@ -204,7 +209,12 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) } } if b.BlockHeader == nil { - return nil, fmt.Errorf("block insertion should have failed") + 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 diff --git a/tests/gen_btheader.go b/tests/gen_btheader.go index f2e086a7b3..07df1ecb36 100644 --- a/tests/gen_btheader.go +++ b/tests/gen_btheader.go @@ -33,6 +33,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) { GasLimit math.HexOrDecimal64 GasUsed math.HexOrDecimal64 Timestamp math.HexOrDecimal64 + BaseFee *math.HexOrDecimal256 } var enc btHeader enc.Bloom = b.Bloom @@ -51,6 +52,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) { enc.GasLimit = math.HexOrDecimal64(b.GasLimit) enc.GasUsed = math.HexOrDecimal64(b.GasUsed) enc.Timestamp = math.HexOrDecimal64(b.Timestamp) + enc.BaseFee = (*math.HexOrDecimal256)(b.BaseFee) return json.Marshal(&enc) } @@ -73,6 +75,7 @@ func (b *btHeader) UnmarshalJSON(input []byte) error { GasLimit *math.HexOrDecimal64 GasUsed *math.HexOrDecimal64 Timestamp *math.HexOrDecimal64 + BaseFee *math.HexOrDecimal256 } var dec btHeader if err := json.Unmarshal(input, &dec); err != nil { @@ -126,5 +129,8 @@ func (b *btHeader) UnmarshalJSON(input []byte) error { if dec.Timestamp != nil { b.Timestamp = uint64(*dec.Timestamp) } + if dec.BaseFee != nil { + b.BaseFee = (*big.Int)(dec.BaseFee) + } return nil } diff --git a/tests/gen_stenv.go b/tests/gen_stenv.go index bfecc145b4..ecf7af8503 100644 --- a/tests/gen_stenv.go +++ b/tests/gen_stenv.go @@ -21,6 +21,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) { 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"` } var enc stEnv enc.Coinbase = common.UnprefixedAddress(s.Coinbase) @@ -28,6 +29,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) { enc.GasLimit = math.HexOrDecimal64(s.GasLimit) enc.Number = math.HexOrDecimal64(s.Number) enc.Timestamp = math.HexOrDecimal64(s.Timestamp) + enc.BaseFee = (*math.HexOrDecimal256)(s.BaseFee) return json.Marshal(&enc) } @@ -39,6 +41,7 @@ func (s *stEnv) UnmarshalJSON(input []byte) error { 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"` } var dec stEnv if err := json.Unmarshal(input, &dec); err != nil { @@ -64,5 +67,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'currentTimestamp' for stEnv") } s.Timestamp = uint64(*dec.Timestamp) + if dec.BaseFee != nil { + s.BaseFee = (*big.Int)(dec.BaseFee) + } return nil } diff --git a/tests/gen_sttransaction.go b/tests/gen_sttransaction.go index 2670f4f9c8..7693a207a5 100644 --- a/tests/gen_sttransaction.go +++ b/tests/gen_sttransaction.go @@ -16,17 +16,21 @@ var _ = (*stTransactionMarshaling)(nil) // MarshalJSON marshals as JSON. func (s stTransaction) MarshalJSON() ([]byte, error) { type stTransaction struct { - GasPrice *math.HexOrDecimal256 `json:"gasPrice"` - Nonce math.HexOrDecimal64 `json:"nonce"` - To string `json:"to"` - Data []string `json:"data"` - AccessLists []*types.AccessList `json:"accessLists,omitempty"` - GasLimit []math.HexOrDecimal64 `json:"gasLimit"` - Value []string `json:"value"` - PrivateKey hexutil.Bytes `json:"secretKey"` + GasPrice *math.HexOrDecimal256 `json:"gasPrice"` + MaxFeePerGas *math.HexOrDecimal256 `json:"maxFeePerGas"` + MaxPriorityFeePerGas *math.HexOrDecimal256 `json:"maxPriorityFeePerGas"` + Nonce math.HexOrDecimal64 `json:"nonce"` + To string `json:"to"` + Data []string `json:"data"` + AccessLists []*types.AccessList `json:"accessLists,omitempty"` + GasLimit []math.HexOrDecimal64 `json:"gasLimit"` + Value []string `json:"value"` + PrivateKey hexutil.Bytes `json:"secretKey"` } var enc stTransaction enc.GasPrice = (*math.HexOrDecimal256)(s.GasPrice) + enc.MaxFeePerGas = (*math.HexOrDecimal256)(s.MaxFeePerGas) + enc.MaxPriorityFeePerGas = (*math.HexOrDecimal256)(s.MaxPriorityFeePerGas) enc.Nonce = math.HexOrDecimal64(s.Nonce) enc.To = s.To enc.Data = s.Data @@ -45,14 +49,16 @@ func (s stTransaction) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (s *stTransaction) UnmarshalJSON(input []byte) error { type stTransaction struct { - GasPrice *math.HexOrDecimal256 `json:"gasPrice"` - Nonce *math.HexOrDecimal64 `json:"nonce"` - To *string `json:"to"` - Data []string `json:"data"` - AccessLists []*types.AccessList `json:"accessLists,omitempty"` - GasLimit []math.HexOrDecimal64 `json:"gasLimit"` - Value []string `json:"value"` - PrivateKey *hexutil.Bytes `json:"secretKey"` + GasPrice *math.HexOrDecimal256 `json:"gasPrice"` + MaxFeePerGas *math.HexOrDecimal256 `json:"maxFeePerGas"` + MaxPriorityFeePerGas *math.HexOrDecimal256 `json:"maxPriorityFeePerGas"` + Nonce *math.HexOrDecimal64 `json:"nonce"` + To *string `json:"to"` + Data []string `json:"data"` + AccessLists []*types.AccessList `json:"accessLists,omitempty"` + GasLimit []math.HexOrDecimal64 `json:"gasLimit"` + Value []string `json:"value"` + PrivateKey *hexutil.Bytes `json:"secretKey"` } var dec stTransaction if err := json.Unmarshal(input, &dec); err != nil { @@ -61,6 +67,12 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error { if dec.GasPrice != nil { s.GasPrice = (*big.Int)(dec.GasPrice) } + if dec.MaxFeePerGas != nil { + s.MaxFeePerGas = (*big.Int)(dec.MaxFeePerGas) + } + if dec.MaxPriorityFeePerGas != nil { + s.MaxPriorityFeePerGas = (*big.Int)(dec.MaxPriorityFeePerGas) + } if dec.Nonce != nil { s.Nonce = uint64(*dec.Nonce) } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 9778f058fe..227ef77cc4 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -82,6 +82,7 @@ type stEnv struct { 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"` } type stEnvMarshaling struct { @@ -90,26 +91,31 @@ type stEnvMarshaling struct { GasLimit math.HexOrDecimal64 Number math.HexOrDecimal64 Timestamp math.HexOrDecimal64 + BaseFee *math.HexOrDecimal256 } //go:generate gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go type stTransaction struct { - GasPrice *big.Int `json:"gasPrice"` - 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"` + 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"` } type stTransactionMarshaling struct { - GasPrice *math.HexOrDecimal256 - Nonce math.HexOrDecimal64 - GasLimit []math.HexOrDecimal64 - PrivateKey hexutil.Bytes + GasPrice *math.HexOrDecimal256 + MaxFeePerGas *math.HexOrDecimal256 + MaxPriorityFeePerGas *math.HexOrDecimal256 + Nonce math.HexOrDecimal64 + GasLimit []math.HexOrDecimal64 + PrivateKey hexutil.Bytes } // GetChainConfig takes a fork definition and returns a chain config. @@ -177,8 +183,17 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh block := t.genesis(config).ToBlock(nil) snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter) + 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) + msg, err := t.json.Tx.toMessage(post, baseFee) if err != nil { return nil, nil, common.Hash{}, err } @@ -187,6 +202,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh 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) // Execute the message. @@ -248,7 +264,7 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis { } } -func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) { +func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Message, error) { // Derive sender from private key if present. var from common.Address if len(tx.PrivateKey) > 0 { @@ -297,7 +313,24 @@ func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) { if tx.AccessLists != nil && tx.AccessLists[ps.Indexes.Data] != nil { accessList = *tx.AccessLists[ps.Indexes.Data] } - msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, nil, nil, data, accessList, true) + // 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) + } + + msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, gasPrice, + tx.MaxFeePerGas, tx.MaxPriorityFeePerGas, data, accessList, true) return msg, nil } diff --git a/tests/testdata b/tests/testdata index c600d7795a..fa0ab110f3 160000 --- a/tests/testdata +++ b/tests/testdata @@ -1 +1 @@ -Subproject commit c600d7795aa2ea57a9c856fc79f72fc05b542124 +Subproject commit fa0ab110f3f45d1f6786f978ea596a18ecbe8275