diff --git a/beacon/engine/gen_ed.go b/beacon/engine/gen_ed.go index 5af133d02f..02a1fd3805 100644 --- a/beacon/engine/gen_ed.go +++ b/beacon/engine/gen_ed.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/types/bal" ) var _ = (*executableDataMarshaling)(nil) @@ -17,25 +18,25 @@ var _ = (*executableDataMarshaling)(nil) // MarshalJSON marshals as JSON. func (e ExecutableData) MarshalJSON() ([]byte, error) { type ExecutableData struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` - SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"` - BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` + StateRoot common.Hash `json:"stateRoot" gencodec:"required"` + ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` + LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"` + Random common.Hash `json:"prevRandao" gencodec:"required"` + Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"` + GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` + ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"` + BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` + BlockHash common.Hash `json:"blockHash" gencodec:"required"` + Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"` + BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"` } var enc ExecutableData enc.ParentHash = e.ParentHash @@ -61,32 +62,32 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed) enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas) enc.SlotNumber = (*hexutil.Uint64)(e.SlotNumber) - enc.BlockAccessListHash = e.BlockAccessListHash + enc.BlockAccessList = e.BlockAccessList return json.Marshal(&enc) } // UnmarshalJSON unmarshals from JSON. func (e *ExecutableData) UnmarshalJSON(input []byte) error { type ExecutableData struct { - ParentHash *common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot *common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"` - Random *common.Hash `json:"prevRandao" gencodec:"required"` - Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash *common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` - SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"` - BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` + ParentHash *common.Hash `json:"parentHash" gencodec:"required"` + FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"` + StateRoot *common.Hash `json:"stateRoot" gencodec:"required"` + ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"` + LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"` + Random *common.Hash `json:"prevRandao" gencodec:"required"` + Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"` + GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` + ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"` + BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` + BlockHash *common.Hash `json:"blockHash" gencodec:"required"` + Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` + SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"` + BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"` } var dec ExecutableData if err := json.Unmarshal(input, &dec); err != nil { @@ -163,8 +164,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error { if dec.SlotNumber != nil { e.SlotNumber = (*uint64)(dec.SlotNumber) } - if dec.BlockAccessListHash != nil { - e.BlockAccessListHash = dec.BlockAccessListHash + if dec.BlockAccessList != nil { + e.BlockAccessList = dec.BlockAccessList } return nil } diff --git a/beacon/engine/types.go b/beacon/engine/types.go index ebd4d5192e..5c31ee4e98 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/types/bal" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" ) @@ -82,25 +83,25 @@ type payloadAttributesMarshaling struct { // ExecutableData is the data necessary to execute an EL payload. type ExecutableData struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom []byte `json:"logsBloom" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - Number uint64 `json:"blockNumber" gencodec:"required"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - GasUsed uint64 `json:"gasUsed" gencodec:"required"` - Timestamp uint64 `json:"timestamp" gencodec:"required"` - ExtraData []byte `json:"extraData" gencodec:"required"` - BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` - BlockHash common.Hash `json:"blockHash" gencodec:"required"` - Transactions [][]byte `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *uint64 `json:"blobGasUsed"` - ExcessBlobGas *uint64 `json:"excessBlobGas"` - SlotNumber *uint64 `json:"slotNumber,omitempty"` - BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` + StateRoot common.Hash `json:"stateRoot" gencodec:"required"` + ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` + LogsBloom []byte `json:"logsBloom" gencodec:"required"` + Random common.Hash `json:"prevRandao" gencodec:"required"` + Number uint64 `json:"blockNumber" gencodec:"required"` + GasLimit uint64 `json:"gasLimit" gencodec:"required"` + GasUsed uint64 `json:"gasUsed" gencodec:"required"` + Timestamp uint64 `json:"timestamp" gencodec:"required"` + ExtraData []byte `json:"extraData" gencodec:"required"` + BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` + BlockHash common.Hash `json:"blockHash" gencodec:"required"` + Transactions [][]byte `json:"transactions" gencodec:"required"` + Withdrawals []*types.Withdrawal `json:"withdrawals"` + BlobGasUsed *uint64 `json:"blobGasUsed"` + ExcessBlobGas *uint64 `json:"excessBlobGas"` + SlotNumber *uint64 `json:"slotNumber,omitempty"` + BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"` } // JSON type overrides for executableData. @@ -304,6 +305,16 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H requestsHash = &h } + // If Amsterdam is enabled, data.BlockAccessList is always non-nil, + // even for empty blocks with no state transitions. + // + // If Amsterdam is not enabled yet, blockAccessListHash is expected + // to be nil. + var blockAccessListHash *common.Hash + if data.BlockAccessList != nil { + hash := data.BlockAccessList.Hash() + blockAccessListHash = &hash + } header := &types.Header{ ParentHash: data.ParentHash, UncleHash: types.EmptyUncleHash, @@ -326,36 +337,34 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H ParentBeaconRoot: beaconRoot, RequestsHash: requestsHash, SlotNumber: data.SlotNumber, - BlockAccessListHash: data.BlockAccessListHash, + BlockAccessListHash: blockAccessListHash, } - return types.NewBlockWithHeader(header). - WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}), - nil + return types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}), nil } // BlockToExecutableData constructs the ExecutableData structure by filling the // fields from the given block. It assumes the given block is post-merge block. func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar, requests [][]byte) *ExecutionPayloadEnvelope { data := &ExecutableData{ - BlockHash: block.Hash(), - ParentHash: block.ParentHash(), - FeeRecipient: block.Coinbase(), - StateRoot: block.Root(), - Number: block.NumberU64(), - GasLimit: block.GasLimit(), - GasUsed: block.GasUsed(), - BaseFeePerGas: block.BaseFee(), - Timestamp: block.Time(), - ReceiptsRoot: block.ReceiptHash(), - LogsBloom: block.Bloom().Bytes(), - Transactions: encodeTransactions(block.Transactions()), - Random: block.MixDigest(), - ExtraData: block.Extra(), - Withdrawals: block.Withdrawals(), - BlobGasUsed: block.BlobGasUsed(), - ExcessBlobGas: block.ExcessBlobGas(), - SlotNumber: block.SlotNumber(), - BlockAccessListHash: block.BlockAccessListHash(), + BlockHash: block.Hash(), + ParentHash: block.ParentHash(), + FeeRecipient: block.Coinbase(), + StateRoot: block.Root(), + Number: block.NumberU64(), + GasLimit: block.GasLimit(), + GasUsed: block.GasUsed(), + BaseFeePerGas: block.BaseFee(), + Timestamp: block.Time(), + ReceiptsRoot: block.ReceiptHash(), + LogsBloom: block.Bloom().Bytes(), + Transactions: encodeTransactions(block.Transactions()), + Random: block.MixDigest(), + ExtraData: block.Extra(), + Withdrawals: block.Withdrawals(), + BlobGasUsed: block.BlobGasUsed(), + ExcessBlobGas: block.ExcessBlobGas(), + SlotNumber: block.SlotNumber(), + BlockAccessList: block.AccessList(), } // Add blobs. diff --git a/core/types/bal/bal_encoding.go b/core/types/bal/bal_encoding.go index 5d7c2856f1..d53ccdc1b0 100644 --- a/core/types/bal/bal_encoding.go +++ b/core/types/bal/bal_encoding.go @@ -92,11 +92,11 @@ func (e *BlockAccessList) Validate() error { return nil } -// ItemCount returns the number of items in the BAL for EIP-7928 size-constraint +// itemCount returns the number of items in the BAL for EIP-7928 size-constraint // purposes: the count of distinct addresses plus every storage key (writes + // reads) carried by those accounts. A storage slot is counted once regardless // of how many transactions wrote to it. -func (e *BlockAccessList) ItemCount() uint64 { +func (e *BlockAccessList) itemCount() uint64 { count := uint64(len(*e)) // distinct addresses for i := range *e { count += uint64(len((*e)[i].StorageWrites)) + uint64(len((*e)[i].StorageReads)) @@ -107,9 +107,9 @@ func (e *BlockAccessList) ItemCount() uint64 { // ValidateSize returns an error if the BAL violates the EIP-7928 size // constraint for the given block gas limit: // -// ItemCount() <= blockGasLimit / params.BALItemCost +// itemCount() <= blockGasLimit / params.BALItemCost func (e *BlockAccessList) ValidateSize(blockGasLimit uint64) error { - items := e.ItemCount() + items := e.itemCount() limit := blockGasLimit / params.BALItemCost if items > limit { return fmt.Errorf("block access list exceeds size constraint: items=%d, limit=%d (block gas limit %d / %d)", diff --git a/core/types/bal/bal_test.go b/core/types/bal/bal_test.go index ca97b92cb5..e65ac6edee 100644 --- a/core/types/bal/bal_test.go +++ b/core/types/bal/bal_test.go @@ -284,7 +284,7 @@ func TestBlockAccessListCopy(t *testing.T) { func TestBlockAccessListItemCount(t *testing.T) { empty := &BlockAccessList{} - if got := empty.ItemCount(); got != 0 { + if got := empty.itemCount(); got != 0 { t.Fatalf("empty BAL item count: got %d, want 0", got) } @@ -304,7 +304,7 @@ func TestBlockAccessListItemCount(t *testing.T) { } // 2 addresses + 2 write-slots + 1 read-slot = 5 items. // (Multiple TxIdx writes to the same slot count as ONE item.) - if got := bal.ItemCount(); got != 5 { + if got := bal.itemCount(); got != 5 { t.Fatalf("item count: got %d, want 5", got) } } @@ -325,7 +325,7 @@ func TestBlockAccessListValidateSize(t *testing.T) { bal[i].StorageReads = append(bal[i].StorageReads, one()) } } - if got := bal.ItemCount(); got != 30 { + if got := bal.itemCount(); got != 30 { t.Fatalf("setup: item count = %d, want 30", got) }