diff --git a/beacon/engine/gen_ed.go b/beacon/engine/gen_ed.go index c733b3f350..ce9669c826 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,24 +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"` + 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"` + BlockAccessList *bal.BlockAccessList `json:"blockAccessList"` + SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"` } var enc ExecutableData enc.ParentHash = e.ParentHash @@ -59,6 +61,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { enc.Withdrawals = e.Withdrawals enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed) enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas) + enc.BlockAccessList = e.BlockAccessList enc.SlotNumber = (*hexutil.Uint64)(e.SlotNumber) return json.Marshal(&enc) } @@ -66,24 +69,25 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) { // 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"` + 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"` + BlockAccessList *bal.BlockAccessList `json:"blockAccessList"` + SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"` } var dec ExecutableData if err := json.Unmarshal(input, &dec); err != nil { @@ -157,6 +161,9 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error { if dec.ExcessBlobGas != nil { e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) } + if dec.BlockAccessList != nil { + e.BlockAccessList = dec.BlockAccessList + } if dec.SlotNumber != nil { e.SlotNumber = (*uint64)(dec.SlotNumber) } diff --git a/core/genesis.go b/core/genesis.go index 550f2e43c7..ca6e112b3c 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -556,6 +556,9 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block { if head.SlotNumber == nil { head.SlotNumber = new(uint64) } + if head.BlockAccessListHash == nil { + head.BlockAccessListHash = &types.EmptyBlockAccessListHash + } } } return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil)) diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 1b65d0c80f..284fc062fc 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -134,8 +134,8 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types // We require transactions to pay for 110% of intrinsic gas in order to // prevent situations where a change in gas limit invalidates a lot // of transactions in the txpool - if tx.Gas() < (intrGas.RegularGas*10)/9 { - return fmt.Errorf("%w: gas %v, minimum needed %v", core.ErrIntrinsicGas, tx.Gas(), intrGas.RegularGas) + if minGas := (intrGas.RegularGas * 10) / 9; tx.Gas() < minGas { + return fmt.Errorf("%w: gas %v, minimum needed %v", core.ErrIntrinsicGas, tx.Gas(), minGas) } } if tx.Gas() < intrGas.RegularGas { diff --git a/core/types/hashes.go b/core/types/hashes.go index db8912a66f..5800ab68c3 100644 --- a/core/types/hashes.go +++ b/core/types/hashes.go @@ -43,6 +43,10 @@ var ( // EmptyRequestsHash is the known hash of an empty request set, sha256(""). EmptyRequestsHash = common.HexToHash("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + // EmptyBlockAccessListHash is the known hash of an empty block access list, + // keccak256(rlp(empty list)) = keccak256(0xc0). + EmptyBlockAccessListHash = common.HexToHash("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") + // EmptyBinaryHash is the known hash of an empty binary trie. EmptyBinaryHash = common.Hash{} ) diff --git a/miner/miner.go b/miner/miner.go index 0ff0237a08..921200bcaa 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -151,12 +151,24 @@ func (miner *Miner) getPending() *newPayloadResult { return cached } var ( - timestamp = uint64(time.Now().Unix()) - withdrawal types.Withdrawals + timestamp = uint64(time.Now().Unix()) + childNumber = new(big.Int).Add(header.Number, big.NewInt(1)) + withdrawal types.Withdrawals + slotNum *uint64 ) - if miner.chainConfig.IsShanghai(new(big.Int).Add(header.Number, big.NewInt(1)), timestamp) { + if miner.chainConfig.IsShanghai(childNumber, timestamp) { withdrawal = []*types.Withdrawal{} } + // Post-Amsterdam, prepareWork requires a slot number (EIP-7843). The pending + // block is synthetic and has no canonical slot, so derive one from the parent + // when available and fall back to zero otherwise. + if miner.chainConfig.IsAmsterdam(childNumber, timestamp) { + var n uint64 + if header.SlotNumber != nil { + n = *header.SlotNumber + 1 + } + slotNum = &n + } ret := miner.generateWork(context.Background(), &generateParams{ timestamp: timestamp, @@ -166,6 +178,7 @@ func (miner *Miner) getPending() *newPayloadResult { random: common.Hash{}, withdrawals: withdrawal, beaconRoot: nil, + slotNum: slotNum, noTxs: false, }, false) // we will never make a witness for a pending block if ret.err != nil {