From fa2fb737b4c30bf0c6ec9908fc33f09341419683 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 13 Jul 2023 18:42:01 +0200 Subject: [PATCH 01/15] tests: update for cancun --- tests/state_test.go | 3 +++ tests/testdata | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/state_test.go b/tests/state_test.go index 9d3862e1dc7c2..e2ca0815891a4 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -65,6 +65,9 @@ func TestState(t *testing.T) { // For Istanbul, older tests were moved into LegacyTests for _, dir := range []string{ + filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP1153-transientStorage"), + filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP5656-MCOPY"), + filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP4844-blobtransactions"), stateTestDir, legacyStateTestDir, benchmarksDir, diff --git a/tests/testdata b/tests/testdata index bac70c50a5791..ee3fa4c86d05f 160000 --- a/tests/testdata +++ b/tests/testdata @@ -1 +1 @@ -Subproject commit bac70c50a579197af68af5fc6d8c7b6163b92c52 +Subproject commit ee3fa4c86d05f99f2717f83a6ad08008490ddf07 From 274a8a6e25db4a67e3b276c06ae134969166c623 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 13 Jul 2023 18:56:37 +0200 Subject: [PATCH 02/15] tests: parse blobhashes --- tests/gen_sttransaction.go | 7 +++++++ tests/state_test_util.go | 2 ++ 2 files changed, 9 insertions(+) diff --git a/tests/gen_sttransaction.go b/tests/gen_sttransaction.go index 7693a207a56cb..5fec2587407d0 100644 --- a/tests/gen_sttransaction.go +++ b/tests/gen_sttransaction.go @@ -6,6 +6,7 @@ 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" @@ -26,6 +27,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) { GasLimit []math.HexOrDecimal64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey hexutil.Bytes `json:"secretKey"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes",omitempty` } var enc stTransaction enc.GasPrice = (*math.HexOrDecimal256)(s.GasPrice) @@ -43,6 +45,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) { } enc.Value = s.Value enc.PrivateKey = s.PrivateKey + enc.BlobVersionedHashes = s.BlobVersionedHashes return json.Marshal(&enc) } @@ -59,6 +62,7 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error { GasLimit []math.HexOrDecimal64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey *hexutil.Bytes `json:"secretKey"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes",omitempty` } var dec stTransaction if err := json.Unmarshal(input, &dec); err != nil { @@ -97,5 +101,8 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error { if dec.PrivateKey != nil { s.PrivateKey = *dec.PrivateKey } + if dec.BlobVersionedHashes != nil { + s.BlobVersionedHashes = dec.BlobVersionedHashes + } return nil } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 667e951b66033..c99a2e1aa51a9 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -113,6 +113,7 @@ type stTransaction struct { GasLimit []uint64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey []byte `json:"secretKey"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes",omitempty` } type stTransactionMarshaling struct { @@ -413,6 +414,7 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Mess GasTipCap: tx.MaxPriorityFeePerGas, Data: data, AccessList: accessList, + BlobHashes: tx.BlobVersionedHashes, } return msg, nil } From 87a02cbe089972cbbb5e8d07ba03ea6bec545924 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 13 Jul 2023 21:23:26 +0200 Subject: [PATCH 03/15] cmd/evm: fix --dump option in staterunner --- cmd/evm/staterunner.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go index ed102e6054da9..231830f6d78bf 100644 --- a/cmd/evm/staterunner.go +++ b/cmd/evm/staterunner.go @@ -117,6 +117,7 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error { // Test failed, mark as so and dump any state to aid debugging result.Pass, result.Error = false, err.Error() if dump && s != nil { + s, _ = state.New(*result.Root, s.Database(), nil) dump := s.RawDump(nil) result.State = &dump } From f2f7d20d3973450be092a609dcb5ad283c86c6d8 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 14 Jul 2023 09:51:58 +0200 Subject: [PATCH 04/15] core: validate blob versions + nonempty --- core/block_validator.go | 2 ++ core/state_transition.go | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/core/block_validator.go b/core/block_validator.go index 1bca444451275..a519c80eb7e12 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -88,6 +88,8 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { blobs += len(tx.BlobHashes()) // Validate the data blobs individually too + // These checks are now duplicated in state_transition.go. + // TODO remove them from here? if tx.Type() == types.BlobTxType { if len(tx.BlobHashes()) == 0 { return errors.New("no-blob blob transaction present in block body") diff --git a/core/state_transition.go b/core/state_transition.go index 022238c8d640b..2c2cd80324139 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -17,6 +17,7 @@ package core import ( + "errors" "fmt" "math" "math/big" @@ -297,6 +298,18 @@ func (st *StateTransition) preCheck() error { } } } + // Check the blob version validity + if msg.BlobHashes != nil { + if len(msg.BlobHashes) == 0 { + return errors.New("blob transaction missing blob hashes") + } + for i, hash := range msg.BlobHashes { + if hash[0] != params.BlobTxHashVersion { + return fmt.Errorf("blob %d hash version mismatch (have %d, supported %d)", + i, hash[0], params.BlobTxHashVersion) + } + } + } return st.buyGas() } From 6a24eb9459e26d96facd36ac5f8915440488ea6a Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 14 Jul 2023 13:59:09 +0200 Subject: [PATCH 05/15] core: remove blob-checks from block validator --- core/block_validator.go | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/core/block_validator.go b/core/block_validator.go index a519c80eb7e12..4ea623cf47fc1 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -86,20 +86,8 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { for _, tx := range block.Transactions() { // Count the number of blobs to validate against the header's dataGasUsed blobs += len(tx.BlobHashes()) - - // Validate the data blobs individually too - // These checks are now duplicated in state_transition.go. - // TODO remove them from here? - if tx.Type() == types.BlobTxType { - if len(tx.BlobHashes()) == 0 { - return errors.New("no-blob blob transaction present in block body") - } - for _, hash := range tx.BlobHashes() { - if hash[0] != params.BlobTxHashVersion { - return fmt.Errorf("blob hash version mismatch (have %d, supported %d)", hash[0], params.BlobTxHashVersion) - } - } - } + // The individual checks for blob validity (version-check + not empty) + // happens in the state_transition check. } if header.DataGasUsed != nil { if want := *header.DataGasUsed / params.BlobTxDataGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated From d6b1744286291b890e23491a06166bef4219d416 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 14 Jul 2023 14:52:58 +0200 Subject: [PATCH 06/15] tests: skip blobtests --- tests/state_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/state_test.go b/tests/state_test.go index e2ca0815891a4..fffc2cf3b591a 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -58,16 +58,12 @@ func TestState(t *testing.T) { // Broken tests: // - // The stEOF tests are generated with EOF as part of Shanghai, which - // is erroneous. Therefore, these tests are skipped. - st.skipLoad(`^EIPTests/stEOF/`) // Expected failures: - // For Istanbul, older tests were moved into LegacyTests for _, dir := range []string{ filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP1153-transientStorage"), filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP5656-MCOPY"), - filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP4844-blobtransactions"), + //filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP4844-blobtransactions"), stateTestDir, legacyStateTestDir, benchmarksDir, From 8d9a7747a10dac215ef264196337ca9ea367f75d Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 14 Jul 2023 19:04:12 +0200 Subject: [PATCH 07/15] tests: fix sttransaction json --- tests/gen_sttransaction.go | 4 ++-- tests/state_test_util.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/gen_sttransaction.go b/tests/gen_sttransaction.go index 5fec2587407d0..ba6b697937014 100644 --- a/tests/gen_sttransaction.go +++ b/tests/gen_sttransaction.go @@ -27,7 +27,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) { GasLimit []math.HexOrDecimal64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey hexutil.Bytes `json:"secretKey"` - BlobVersionedHashes []common.Hash `json:"blobVersionedHashes",omitempty` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` } var enc stTransaction enc.GasPrice = (*math.HexOrDecimal256)(s.GasPrice) @@ -62,7 +62,7 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error { GasLimit []math.HexOrDecimal64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey *hexutil.Bytes `json:"secretKey"` - BlobVersionedHashes []common.Hash `json:"blobVersionedHashes",omitempty` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` } var dec stTransaction if err := json.Unmarshal(input, &dec); err != nil { diff --git a/tests/state_test_util.go b/tests/state_test_util.go index c99a2e1aa51a9..bc5a20ec92591 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -113,7 +113,7 @@ type stTransaction struct { GasLimit []uint64 `json:"gasLimit"` Value []string `json:"value"` PrivateKey []byte `json:"secretKey"` - BlobVersionedHashes []common.Hash `json:"blobVersionedHashes",omitempty` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` } type stTransactionMarshaling struct { From 7e264d579693a63e05fc52cbd3db9a1e22f17ac7 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Fri, 14 Jul 2023 19:35:41 +0200 Subject: [PATCH 08/15] core: state processing for blobhash opcode --- core/error.go | 4 +++ core/evm.go | 21 +++++++------- core/gen_genesis.go | 58 +++++++++++++++++++++----------------- core/genesis.go | 24 +++++++++++----- core/state_processor.go | 2 +- core/state_transition.go | 61 +++++++++++++++++++++++++++++++--------- core/vm/evm.go | 15 +++++----- 7 files changed, 121 insertions(+), 64 deletions(-) diff --git a/core/error.go b/core/error.go index 872ba8d365d8c..8967432a40f53 100644 --- a/core/error.go +++ b/core/error.go @@ -100,4 +100,8 @@ var ( // ErrSenderNoEOA is returned if the sender of a transaction is a contract. ErrSenderNoEOA = errors.New("sender not an eoa") + + // ErrBlobFeeCapTooLow is returned if the transaction fee cap is less than the + // data gas fee of the block. + ErrBlobFeeCapTooLow = errors.New("max fee per data gas less than block data gas fee") ) diff --git a/core/evm.go b/core/evm.go index b7ff7790295be..f4e6aa43f4271 100644 --- a/core/evm.go +++ b/core/evm.go @@ -56,16 +56,17 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common random = &header.MixDigest } return vm.BlockContext{ - CanTransfer: CanTransfer, - Transfer: Transfer, - GetHash: GetHashFn(header, chain), - Coinbase: beneficiary, - BlockNumber: new(big.Int).Set(header.Number), - Time: header.Time, - Difficulty: new(big.Int).Set(header.Difficulty), - BaseFee: baseFee, - GasLimit: header.GasLimit, - Random: random, + CanTransfer: CanTransfer, + Transfer: Transfer, + GetHash: GetHashFn(header, chain), + Coinbase: beneficiary, + BlockNumber: new(big.Int).Set(header.Number), + Time: header.Time, + Difficulty: new(big.Int).Set(header.Difficulty), + BaseFee: baseFee, + GasLimit: header.GasLimit, + Random: random, + ExcessDataGas: header.ExcessDataGas, } } diff --git a/core/gen_genesis.go b/core/gen_genesis.go index 4e0844e889ab4..bf5296c9d0643 100644 --- a/core/gen_genesis.go +++ b/core/gen_genesis.go @@ -18,19 +18,20 @@ var _ = (*genesisSpecMarshaling)(nil) // MarshalJSON marshals as JSON. func (g Genesis) MarshalJSON() ([]byte, error) { type Genesis struct { - Config *params.ChainConfig `json:"config"` - Nonce math.HexOrDecimal64 `json:"nonce"` - Timestamp math.HexOrDecimal64 `json:"timestamp"` - ExtraData hexutil.Bytes `json:"extraData"` - GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash common.Hash `json:"mixHash"` - Coinbase common.Address `json:"coinbase"` - Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` - Number math.HexOrDecimal64 `json:"number"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - ParentHash common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + Config *params.ChainConfig `json:"config"` + Nonce math.HexOrDecimal64 `json:"nonce"` + Timestamp math.HexOrDecimal64 `json:"timestamp"` + ExtraData hexutil.Bytes `json:"extraData"` + GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` + Mixhash common.Hash `json:"mixHash"` + Coinbase common.Address `json:"coinbase"` + Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` + Number math.HexOrDecimal64 `json:"number"` + GasUsed math.HexOrDecimal64 `json:"gasUsed"` + ParentHash common.Hash `json:"parentHash"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + ExcessDataGas *uint64 `json:"excessDataGas"` } var enc Genesis enc.Config = g.Config @@ -51,25 +52,27 @@ func (g Genesis) MarshalJSON() ([]byte, error) { enc.GasUsed = math.HexOrDecimal64(g.GasUsed) enc.ParentHash = g.ParentHash enc.BaseFee = (*math.HexOrDecimal256)(g.BaseFee) + enc.ExcessDataGas = g.ExcessDataGas return json.Marshal(&enc) } // UnmarshalJSON unmarshals from JSON. func (g *Genesis) UnmarshalJSON(input []byte) error { type Genesis struct { - Config *params.ChainConfig `json:"config"` - Nonce *math.HexOrDecimal64 `json:"nonce"` - Timestamp *math.HexOrDecimal64 `json:"timestamp"` - ExtraData *hexutil.Bytes `json:"extraData"` - GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash *common.Hash `json:"mixHash"` - Coinbase *common.Address `json:"coinbase"` - Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` - Number *math.HexOrDecimal64 `json:"number"` - GasUsed *math.HexOrDecimal64 `json:"gasUsed"` - ParentHash *common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + Config *params.ChainConfig `json:"config"` + Nonce *math.HexOrDecimal64 `json:"nonce"` + Timestamp *math.HexOrDecimal64 `json:"timestamp"` + ExtraData *hexutil.Bytes `json:"extraData"` + GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` + Mixhash *common.Hash `json:"mixHash"` + Coinbase *common.Address `json:"coinbase"` + Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` + Number *math.HexOrDecimal64 `json:"number"` + GasUsed *math.HexOrDecimal64 `json:"gasUsed"` + ParentHash *common.Hash `json:"parentHash"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + ExcessDataGas *uint64 `json:"excessDataGas"` } var dec Genesis if err := json.Unmarshal(input, &dec); err != nil { @@ -120,5 +123,8 @@ func (g *Genesis) UnmarshalJSON(input []byte) error { if dec.BaseFee != nil { g.BaseFee = (*big.Int)(dec.BaseFee) } + if dec.ExcessDataGas != nil { + g.ExcessDataGas = dec.ExcessDataGas + } return nil } diff --git a/core/genesis.go b/core/genesis.go index 013ef78601fce..e01b56f3011c8 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -59,10 +59,11 @@ type Genesis struct { // These fields are used for consensus tests. Please don't use them // in actual genesis blocks. - Number uint64 `json:"number"` - GasUsed uint64 `json:"gasUsed"` - ParentHash common.Hash `json:"parentHash"` - BaseFee *big.Int `json:"baseFeePerGas"` + Number uint64 `json:"number"` + GasUsed uint64 `json:"gasUsed"` + ParentHash common.Hash `json:"parentHash"` + BaseFee *big.Int `json:"baseFeePerGas"` + ExcessDataGas *uint64 `json:"excessDataGas"` } func ReadGenesis(db ethdb.Database) (*Genesis, error) { @@ -463,9 +464,18 @@ func (g *Genesis) ToBlock() *types.Block { } } var withdrawals []*types.Withdrawal - if g.Config != nil && g.Config.IsShanghai(big.NewInt(int64(g.Number)), g.Timestamp) { - head.WithdrawalsHash = &types.EmptyWithdrawalsHash - withdrawals = make([]*types.Withdrawal, 0) + if conf := g.Config; conf != nil { + num := big.NewInt(int64(g.Number)) + if conf.IsShanghai(num, g.Timestamp) { + head.WithdrawalsHash = &types.EmptyWithdrawalsHash + withdrawals = make([]*types.Withdrawal, 0) + } + if conf.IsCancun(num, g.Timestamp) { + head.ExcessDataGas = g.ExcessDataGas + if head.ExcessDataGas == nil { + head.ExcessDataGas = new(uint64) + } + } } return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals) } diff --git a/core/state_processor.go b/core/state_processor.go index 4837628e66021..fcaf5a8ff3c9b 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -157,6 +157,6 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo } // Create a new context to be used in the EVM environment blockContext := NewEVMBlockContext(header, bc, author) - vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) + vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.BlobHashes()}, statedb, config, cfg) return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) } diff --git a/core/state_transition.go b/core/state_transition.go index 2c2cd80324139..cee83766adc57 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/common" cmath "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" @@ -126,17 +127,18 @@ func toWordSize(size uint64) uint64 { // A Message contains the data derived from a single transaction that is relevant to state // processing. type Message struct { - To *common.Address - From common.Address - Nonce uint64 - Value *big.Int - GasLimit uint64 - GasPrice *big.Int - GasFeeCap *big.Int - GasTipCap *big.Int - Data []byte - AccessList types.AccessList - BlobHashes []common.Hash + To *common.Address + From common.Address + Nonce uint64 + Value *big.Int + GasLimit uint64 + GasPrice *big.Int + GasFeeCap *big.Int + GasTipCap *big.Int + Data []byte + AccessList types.AccessList + BlobGasFeeCap *big.Int + BlobHashes []common.Hash // When SkipAccountChecks is true, the message nonce is not checked against the // account nonce in state. It also disables checking that the sender is an EOA. @@ -158,6 +160,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In AccessList: tx.AccessList(), SkipAccountChecks: false, BlobHashes: tx.BlobHashes(), + BlobGasFeeCap: tx.BlobGasFeeCap(), } // If baseFee provided, set gasPrice to effectiveGasPrice. if baseFee != nil { @@ -231,12 +234,28 @@ func (st *StateTransition) to() common.Address { func (st *StateTransition) buyGas() error { mgval := new(big.Int).SetUint64(st.msg.GasLimit) mgval = mgval.Mul(mgval, st.msg.GasPrice) - balanceCheck := mgval + balanceCheck := new(big.Int).Set(mgval) if st.msg.GasFeeCap != nil { - balanceCheck = new(big.Int).SetUint64(st.msg.GasLimit) + balanceCheck.SetUint64(st.msg.GasLimit) balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap) balanceCheck.Add(balanceCheck, st.msg.Value) } + if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) { + if dataGas := st.dataGasUsed(); dataGas > 0 { + if st.evm.Context.ExcessDataGas == nil { + // programming error + panic("missing field excess data gas") + } + // Check that the user has enough funds to cover dataGasUsed * tx.BlobGasFeeCap + blobBalanceCheck := new(big.Int).SetUint64(dataGas) + blobBalanceCheck.Mul(blobBalanceCheck, st.msg.BlobGasFeeCap) + balanceCheck.Add(balanceCheck, blobBalanceCheck) + // Pay for dataGasUsed * actual blob fee + blobFee := new(big.Int).SetUint64(dataGas) + blobFee.Mul(blobFee, misc.CalcBlobFee(*st.evm.Context.ExcessDataGas)) + mgval.Add(mgval, blobFee) + } + } if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 { return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) } @@ -247,6 +266,7 @@ func (st *StateTransition) buyGas() error { st.initialGas = st.msg.GasLimit st.state.SubBalance(st.msg.From, mgval) + return nil } @@ -310,6 +330,16 @@ func (st *StateTransition) preCheck() error { } } } + + if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) { + if st.dataGasUsed() > 0 { + // Check that the user is paying at least the current blob fee + if have, want := st.msg.BlobGasFeeCap, misc.CalcBlobFee(*st.evm.Context.ExcessDataGas); have.Cmp(want) < 0 { + return fmt.Errorf("%w: address %v have %v want %v", ErrBlobFeeCapTooLow, st.msg.From.Hex(), have, want) + } + } + } + return st.buyGas() } @@ -440,3 +470,8 @@ func (st *StateTransition) refundGas(refundQuotient uint64) { func (st *StateTransition) gasUsed() uint64 { return st.initialGas - st.gasRemaining } + +// dataGasUsed returns the amount of data gas used by the message. +func (st *StateTransition) dataGasUsed() uint64 { + return uint64(len(st.msg.BlobHashes) * params.BlobTxDataGasPerBlob) +} diff --git a/core/vm/evm.go b/core/vm/evm.go index 36336d8cbd4cf..aded5225cd126 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -70,13 +70,14 @@ type BlockContext struct { GetHash GetHashFunc // Block information - Coinbase common.Address // Provides information for COINBASE - GasLimit uint64 // Provides information for GASLIMIT - BlockNumber *big.Int // Provides information for NUMBER - Time uint64 // Provides information for TIME - Difficulty *big.Int // Provides information for DIFFICULTY - BaseFee *big.Int // Provides information for BASEFEE - Random *common.Hash // Provides information for PREVRANDAO + Coinbase common.Address // Provides information for COINBASE + GasLimit uint64 // Provides information for GASLIMIT + BlockNumber *big.Int // Provides information for NUMBER + Time uint64 // Provides information for TIME + Difficulty *big.Int // Provides information for DIFFICULTY + BaseFee *big.Int // Provides information for BASEFEE + Random *common.Hash // Provides information for PREVRANDAO + ExcessDataGas *uint64 // ExcessDataGas field in the header, needed to compute the data } // TxContext provides the EVM with information about a transaction. From bd0b2f4ca422f78fbef9b02491602ac92ff6599f Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 14 Jul 2023 19:37:06 +0200 Subject: [PATCH 09/15] tests: updates --- tests/gen_sttransaction.go | 6 ++++++ tests/state_test.go | 2 +- tests/state_test_util.go | 25 ++++++++++++++----------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/gen_sttransaction.go b/tests/gen_sttransaction.go index ba6b697937014..11278833157d8 100644 --- a/tests/gen_sttransaction.go +++ b/tests/gen_sttransaction.go @@ -28,6 +28,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) { Value []string `json:"value"` PrivateKey hexutil.Bytes `json:"secretKey"` BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + BlobGasFeeCap *math.HexOrDecimal256 `json:"maxFeePerDataGas,omitempty"` } var enc stTransaction enc.GasPrice = (*math.HexOrDecimal256)(s.GasPrice) @@ -46,6 +47,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) { enc.Value = s.Value enc.PrivateKey = s.PrivateKey enc.BlobVersionedHashes = s.BlobVersionedHashes + enc.BlobGasFeeCap = (*math.HexOrDecimal256)(s.BlobGasFeeCap) return json.Marshal(&enc) } @@ -63,6 +65,7 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error { Value []string `json:"value"` PrivateKey *hexutil.Bytes `json:"secretKey"` BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + BlobGasFeeCap *math.HexOrDecimal256 `json:"maxFeePerDataGas,omitempty"` } var dec stTransaction if err := json.Unmarshal(input, &dec); err != nil { @@ -104,5 +107,8 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error { if dec.BlobVersionedHashes != nil { s.BlobVersionedHashes = dec.BlobVersionedHashes } + if dec.BlobGasFeeCap != nil { + s.BlobGasFeeCap = (*big.Int)(dec.BlobGasFeeCap) + } return nil } diff --git a/tests/state_test.go b/tests/state_test.go index fffc2cf3b591a..a618ccfe65216 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -63,7 +63,7 @@ func TestState(t *testing.T) { for _, dir := range []string{ filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP1153-transientStorage"), filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP5656-MCOPY"), - //filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP4844-blobtransactions"), + filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP4844-blobtransactions"), stateTestDir, legacyStateTestDir, benchmarksDir, diff --git a/tests/state_test_util.go b/tests/state_test_util.go index bc5a20ec92591..aab471caf02e6 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -114,6 +114,7 @@ type stTransaction struct { Value []string `json:"value"` PrivateKey []byte `json:"secretKey"` BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + BlobGasFeeCap *big.Int `json:"maxFeePerDataGas,omitempty"` } type stTransactionMarshaling struct { @@ -123,6 +124,7 @@ type stTransactionMarshaling struct { Nonce math.HexOrDecimal64 GasLimit []math.HexOrDecimal64 PrivateKey hexutil.Bytes + BlobGasFeeCap *math.HexOrDecimal256 } // GetChainConfig takes a fork definition and returns a chain config. @@ -404,17 +406,18 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Mess } 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, + 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 } From 9b49d9f1d4374fad7c1b2d0dc29d6f37d20c4ac7 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sat, 15 Jul 2023 09:51:47 +0200 Subject: [PATCH 10/15] tests: comment out erroneous tests --- tests/state_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/state_test.go b/tests/state_test.go index a618ccfe65216..d301c0462dfcd 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -57,13 +57,16 @@ func TestState(t *testing.T) { st.skipLoad(`^stStaticCall/static_Call1MB`) // Broken tests: + // EOF is not part of cancun + st.skipLoad(`^stEOF/`) + // These EIP-4844 tests need to be regenerated + st.skipLoad(`stEIP4844-blobtransactions/opcodeBlobhashOutOfRange.json`) + st.skipLoad(`stEIP4844-blobtransactions/opcodeBlobhBounds.json`) // // Expected failures: // For Istanbul, older tests were moved into LegacyTests for _, dir := range []string{ - filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP1153-transientStorage"), - filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP5656-MCOPY"), - filepath.Join(baseDir, "EIPTests", "StateTests", "stEIP4844-blobtransactions"), + filepath.Join(baseDir, "EIPTests", "StateTests"), stateTestDir, legacyStateTestDir, benchmarksDir, From 3ecac0752595c361cf09225d5024f6a4f288b2e7 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Sat, 15 Jul 2023 12:16:22 +0200 Subject: [PATCH 11/15] tests: mark broken 4844 tests as failing, rather than skipping them --- tests/state_test.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/state_test.go b/tests/state_test.go index d301c0462dfcd..61ce8aab39568 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -48,22 +48,21 @@ func TestState(t *testing.T) { 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/`) - // These EIP-4844 tests need to be regenerated - st.skipLoad(`stEIP4844-blobtransactions/opcodeBlobhashOutOfRange.json`) - st.skipLoad(`stEIP4844-blobtransactions/opcodeBlobhBounds.json`) - // + // 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"), From 19db4e0c9fe131d2c343ae09a9a6283a408bbc03 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Sat, 15 Jul 2023 12:17:23 +0200 Subject: [PATCH 12/15] core: remove blank line --- core/state_transition.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/state_transition.go b/core/state_transition.go index cee83766adc57..9fcdb74458ba3 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -266,7 +266,6 @@ func (st *StateTransition) buyGas() error { st.initialGas = st.msg.GasLimit st.state.SubBalance(st.msg.From, mgval) - return nil } From db101fd1f8bb01ccb8ee8e782a5cc26844b03676 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Sat, 15 Jul 2023 15:06:20 +0200 Subject: [PATCH 13/15] core: add DataGasUsed in Genesis --- core/gen_genesis.go | 14 ++++++++++---- core/genesis.go | 31 ++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/core/gen_genesis.go b/core/gen_genesis.go index bf5296c9d0643..9a8b279d257bf 100644 --- a/core/gen_genesis.go +++ b/core/gen_genesis.go @@ -31,7 +31,8 @@ func (g Genesis) MarshalJSON() ([]byte, error) { GasUsed math.HexOrDecimal64 `json:"gasUsed"` ParentHash common.Hash `json:"parentHash"` BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` - ExcessDataGas *uint64 `json:"excessDataGas"` + ExcessDataGas *math.HexOrDecimal64 `json:"excessDataGas"` + DataGasUsed *math.HexOrDecimal64 `json:"dataGasUsed"` } var enc Genesis enc.Config = g.Config @@ -52,7 +53,8 @@ func (g Genesis) MarshalJSON() ([]byte, error) { enc.GasUsed = math.HexOrDecimal64(g.GasUsed) enc.ParentHash = g.ParentHash enc.BaseFee = (*math.HexOrDecimal256)(g.BaseFee) - enc.ExcessDataGas = g.ExcessDataGas + enc.ExcessDataGas = (*math.HexOrDecimal64)(g.ExcessDataGas) + enc.DataGasUsed = (*math.HexOrDecimal64)(g.DataGasUsed) return json.Marshal(&enc) } @@ -72,7 +74,8 @@ func (g *Genesis) UnmarshalJSON(input []byte) error { GasUsed *math.HexOrDecimal64 `json:"gasUsed"` ParentHash *common.Hash `json:"parentHash"` BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` - ExcessDataGas *uint64 `json:"excessDataGas"` + ExcessDataGas *math.HexOrDecimal64 `json:"excessDataGas"` + DataGasUsed *math.HexOrDecimal64 `json:"dataGasUsed"` } var dec Genesis if err := json.Unmarshal(input, &dec); err != nil { @@ -124,7 +127,10 @@ func (g *Genesis) UnmarshalJSON(input []byte) error { g.BaseFee = (*big.Int)(dec.BaseFee) } if dec.ExcessDataGas != nil { - g.ExcessDataGas = dec.ExcessDataGas + g.ExcessDataGas = (*uint64)(dec.ExcessDataGas) + } + if dec.DataGasUsed != nil { + g.DataGasUsed = (*uint64)(dec.DataGasUsed) } return nil } diff --git a/core/genesis.go b/core/genesis.go index e01b56f3011c8..4082c905e2dee 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -62,8 +62,9 @@ type Genesis struct { Number uint64 `json:"number"` GasUsed uint64 `json:"gasUsed"` ParentHash common.Hash `json:"parentHash"` - BaseFee *big.Int `json:"baseFeePerGas"` - ExcessDataGas *uint64 `json:"excessDataGas"` + BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559 + ExcessDataGas *uint64 `json:"excessDataGas"` // EIP-4844 + DataGasUsed *uint64 `json:"dataGasUsed"` // EIP-4844 } func ReadGenesis(db ethdb.Database) (*Genesis, error) { @@ -97,6 +98,9 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) { genesis.Difficulty = genesisHeader.Difficulty genesis.Mixhash = genesisHeader.MixDigest genesis.Coinbase = genesisHeader.Coinbase + genesis.BaseFee = genesisHeader.BaseFee + genesis.ExcessDataGas = genesisHeader.ExcessDataGas + genesis.DataGasUsed = genesisHeader.DataGasUsed return &genesis, nil } @@ -215,15 +219,17 @@ type GenesisAccount struct { // field type overrides for gencodec type genesisSpecMarshaling struct { - Nonce math.HexOrDecimal64 - Timestamp math.HexOrDecimal64 - ExtraData hexutil.Bytes - GasLimit math.HexOrDecimal64 - GasUsed math.HexOrDecimal64 - Number math.HexOrDecimal64 - Difficulty *math.HexOrDecimal256 - BaseFee *math.HexOrDecimal256 - Alloc map[common.UnprefixedAddress]GenesisAccount + Nonce math.HexOrDecimal64 + Timestamp math.HexOrDecimal64 + ExtraData hexutil.Bytes + GasLimit math.HexOrDecimal64 + GasUsed math.HexOrDecimal64 + Number math.HexOrDecimal64 + Difficulty *math.HexOrDecimal256 + Alloc map[common.UnprefixedAddress]GenesisAccount + BaseFee *math.HexOrDecimal256 + ExcessDataGas *math.HexOrDecimal64 + DataGasUsed *math.HexOrDecimal64 } type genesisAccountMarshaling struct { @@ -475,6 +481,9 @@ func (g *Genesis) ToBlock() *types.Block { if head.ExcessDataGas == nil { head.ExcessDataGas = new(uint64) } + if head.DataGasUsed == nil { + head.DataGasUsed = new(uint64) + } } } return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals) From 92ce33c8433a4fefbcbfb90bb138070c6111266d Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Sat, 15 Jul 2023 15:10:14 +0200 Subject: [PATCH 14/15] core: apply DataGasUsed in genesis --- core/genesis.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/genesis.go b/core/genesis.go index 4082c905e2dee..0b255a8d37371 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -478,6 +478,7 @@ func (g *Genesis) ToBlock() *types.Block { } if conf.IsCancun(num, g.Timestamp) { head.ExcessDataGas = g.ExcessDataGas + head.DataGasUsed = g.DataGasUsed if head.ExcessDataGas == nil { head.ExcessDataGas = new(uint64) } From fd7b28f6bc83dbd71fd18c1b8b6429c6f69c8ba1 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sat, 15 Jul 2023 16:32:24 +0200 Subject: [PATCH 15/15] core: test new state errors --- core/state_processor_test.go | 154 ++++++++++++++++------------------- 1 file changed, 71 insertions(+), 83 deletions(-) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 5dbeed97a00bd..a8858ec7e3f9c 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" + "github.com/holiman/uint256" "golang.org/x/crypto/sha3" ) @@ -45,19 +46,23 @@ func u64(val uint64) *uint64 { return &val } func TestStateProcessorErrors(t *testing.T) { var ( config = ¶ms.ChainConfig{ - 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), - Ethash: new(params.EthashConfig), + 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), + Ethash: new(params.EthashConfig), + TerminalTotalDifficulty: big.NewInt(0), + TerminalTotalDifficultyPassed: true, + ShanghaiTime: new(uint64), + CancunTime: new(uint64), } signer = types.LatestSigner(config) key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") @@ -89,6 +94,22 @@ func TestStateProcessorErrors(t *testing.T) { }), signer, key1) return tx } + var mkBlobTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, hashes []common.Hash) *types.Transaction { + tx, err := types.SignTx(types.NewTx(&types.BlobTx{ + Nonce: nonce, + GasTipCap: uint256.MustFromBig(gasTipCap), + GasFeeCap: uint256.MustFromBig(gasFeeCap), + Gas: gasLimit, + To: to, + BlobHashes: hashes, + Value: new(uint256.Int), + }), signer, key1) + if err != nil { + t.Fatal(err) + } + return tx + } + { // Tests against a 'recent' chain definition var ( db = rawdb.NewMemoryDatabase() @@ -105,8 +126,10 @@ func TestStateProcessorErrors(t *testing.T) { }, }, } - blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil) + tooBigInitCode = [params.MaxInitCodeSize + 1]byte{} ) + defer blockchain.Stop() bigNumber := new(big.Int).SetBytes(common.FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) tooBigNumber := new(big.Int).Set(bigNumber) @@ -209,8 +232,26 @@ func TestStateProcessorErrors(t *testing.T) { }, want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 2431633873983640103894990685182446064918669677978451844828609264166175722438635000", }, + { // ErrMaxInitCodeSizeExceeded + txs: []*types.Transaction{ + mkDynamicCreationTx(0, 500000, common.Big0, big.NewInt(params.InitialBaseFee), tooBigInitCode[:]), + }, + want: "could not apply tx 0 [0xd491405f06c92d118dd3208376fcee18a57c54bc52063ee4a26b1cf296857c25]: max initcode size exceeded: code size 49153 limit 49152", + }, + { // ErrIntrinsicGas: Not enough gas to cover init code + txs: []*types.Transaction{ + mkDynamicCreationTx(0, 54299, common.Big0, big.NewInt(params.InitialBaseFee), make([]byte, 320)), + }, + want: "could not apply tx 0 [0xfd49536a9b323769d8472fcb3ebb3689b707a349379baee3e2ee3fe7baae06a1]: intrinsic gas too low: have 54299, want 54300", + }, + { // ErrBlobFeeCapTooLow + txs: []*types.Transaction{ + mkBlobTx(0, common.Address{}, params.TxGas, big.NewInt(1), big.NewInt(1), []common.Hash{(common.Hash{1})}), + }, + want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1 baseFee: 875000000", + }, } { - block := GenerateBadBlock(gspec.ToBlock(), ethash.NewFaker(), tt.txs, gspec.Config) + block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) _, err := blockchain.InsertChain(types.Blocks{block}) if err == nil { t.Fatal("block imported without errors") @@ -284,7 +325,7 @@ func TestStateProcessorErrors(t *testing.T) { }, }, } - blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil) ) defer blockchain.Stop() for i, tt := range []struct { @@ -298,73 +339,7 @@ func TestStateProcessorErrors(t *testing.T) { want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1", }, } { - block := GenerateBadBlock(gspec.ToBlock(), ethash.NewFaker(), tt.txs, gspec.Config) - _, err := blockchain.InsertChain(types.Blocks{block}) - if err == nil { - t.Fatal("block imported without errors") - } - if have, want := err.Error(), tt.want; have != want { - t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) - } - } - } - - // ErrMaxInitCodeSizeExceeded, for this we need extra Shanghai (EIP-3860) enabled. - { - var ( - db = rawdb.NewMemoryDatabase() - gspec = &Genesis{ - Config: ¶ms.ChainConfig{ - 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(0), - TerminalTotalDifficultyPassed: true, - ShanghaiTime: u64(0), - }, - Alloc: GenesisAlloc{ - common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{ - Balance: big.NewInt(1000000000000000000), // 1 ether - Nonce: 0, - }, - }, - } - genesis = gspec.MustCommit(db) - blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil) - tooBigInitCode = [params.MaxInitCodeSize + 1]byte{} - smallInitCode = [320]byte{} - ) - defer blockchain.Stop() - for i, tt := range []struct { - txs []*types.Transaction - want string - }{ - { // ErrMaxInitCodeSizeExceeded - txs: []*types.Transaction{ - mkDynamicCreationTx(0, 500000, common.Big0, misc.CalcBaseFee(config, genesis.Header()), tooBigInitCode[:]), - }, - want: "could not apply tx 0 [0x832b54a6c3359474a9f504b1003b2cc1b6fcaa18e4ef369eb45b5d40dad6378f]: max initcode size exceeded: code size 49153 limit 49152", - }, - { // ErrIntrinsicGas: Not enough gas to cover init code - txs: []*types.Transaction{ - mkDynamicCreationTx(0, 54299, common.Big0, misc.CalcBaseFee(config, genesis.Header()), smallInitCode[:]), - }, - want: "could not apply tx 0 [0x39b7436cb432d3662a25626474282c5c4c1a213326fd87e4e18a91477bae98b2]: intrinsic gas too low: have 54299, want 54300", - }, - } { - block := GenerateBadBlock(genesis, beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) + block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) _, err := blockchain.InsertChain(types.Blocks{block}) if err == nil { t.Fatal("block imported without errors") @@ -412,6 +387,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr hasher := sha3.NewLegacyKeccak256() hasher.Write(header.Number.Bytes()) var cumulativeGas uint64 + var nBlobs int for _, tx := range txs { txh := tx.Hash() hasher.Write(txh[:]) @@ -420,8 +396,20 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr receipt.GasUsed = tx.Gas() receipts = append(receipts, receipt) cumulativeGas += tx.Gas() + nBlobs += len(tx.BlobHashes()) } header.Root = common.BytesToHash(hasher.Sum(nil)) + if config.IsCancun(header.Number, header.Time) { + var pExcess, pUsed = uint64(0), uint64(0) + if parent.ExcessDataGas() != nil { + pExcess = *parent.ExcessDataGas() + pUsed = *parent.DataGasUsed() + } + excess := misc.CalcExcessDataGas(pExcess, pUsed) + used := uint64(nBlobs * params.BlobTxDataGasPerBlob) + header.ExcessDataGas = &excess + header.DataGasUsed = &used + } // Assemble and return the final block for sealing if config.IsShanghai(header.Number, header.Time) { return types.NewBlockWithWithdrawals(header, txs, nil, receipts, []*types.Withdrawal{}, trie.NewStackTrie(nil))