diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index d01aa75ee4..c4dfd4d36b 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -275,18 +275,22 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa } } + // Verify the existence / non-existence of Amsterdam-specific header fields amsterdam := chain.Config().IsAmsterdam(header.Number, header.Time) - if amsterdam && header.SlotNumber == nil { - return errors.New("header is missing slotNumber") - } - if !amsterdam && header.SlotNumber != nil { - return fmt.Errorf("invalid slotNumber: have %d, expected nil", *header.SlotNumber) - } - if amsterdam && header.BlockAccessListHash == nil { - return errors.New("header is missing block access list hash") - } - if !amsterdam && header.BlockAccessListHash != nil { - return fmt.Errorf("invalid block access list hash: have %x, expected nil", header.BlockAccessListHash) + if amsterdam { + if header.BlockAccessListHash == nil { + return errors.New("header is missing block access list hash") + } + if header.SlotNumber == nil { + return errors.New("header is missing slotNumber") + } + } else { + if header.BlockAccessListHash != nil { + return fmt.Errorf("invalid block access list hash: have %x, expected nil", header.BlockAccessListHash) + } + if header.SlotNumber != nil { + return fmt.Errorf("invalid slotNumber: have %d, expected nil", *header.SlotNumber) + } } return nil } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index c986aa99ac..0582e842c3 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -608,7 +608,8 @@ func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { // HasAccessList verifies the existence of a block access list for a block. func HasAccessList(db ethdb.Reader, hash common.Hash, number uint64) bool { - return len(ReadAccessListRLP(db, hash, number)) > 0 + has, _ := db.Has(accessListKey(number, hash)) + return has } // ReadAccessListRLP retrieves the RLP-encoded block access list for a block from KV. @@ -709,21 +710,23 @@ func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block { return nil } block := types.NewBlockWithHeader(header).WithBody(*body) + + // Best-effort assembly of the block access list from the database. if header.BlockAccessListHash != nil { - accessList := ReadAccessList(db, hash, number) - if accessList != nil { - block = block.WithAccessList(accessList) - } + al := ReadAccessList(db, hash, number) + block = block.WithAccessListUnsafe(al) } return block } // WriteBlock serializes a block into the database, header and body separately. func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { - WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) + hash, number := block.Hash(), block.NumberU64() + WriteBody(db, hash, number, block.Body()) WriteHeader(db, block.Header()) - if block.AccessList() != nil { - WriteAccessList(db, block.Hash(), block.NumberU64(), block.AccessList()) + + if accessList := block.AccessList(); accessList != nil { + WriteAccessList(db, hash, number, accessList) } } diff --git a/core/types/bal/bal_encoding.go b/core/types/bal/bal_encoding.go index 1b1406ea32..6d52c17c83 100644 --- a/core/types/bal/bal_encoding.go +++ b/core/types/bal/bal_encoding.go @@ -350,9 +350,12 @@ func (e *BlockAccessList) PrettyPrint() string { } // Copy returns a deep copy of the access list -func (e *BlockAccessList) Copy() (res BlockAccessList) { - for _, accountAccess := range e.Accesses { - res.Accesses = append(res.Accesses, accountAccess.Copy()) +func (e *BlockAccessList) Copy() *BlockAccessList { + cpy := &BlockAccessList{ + Accesses: make([]AccountAccess, 0, len(e.Accesses)), } - return + for _, accountAccess := range e.Accesses { + cpy.Accesses = append(cpy.Accesses, accountAccess.Copy()) + } + return cpy } diff --git a/core/types/block.go b/core/types/block.go index eacd96902b..2d65adeff3 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -28,10 +28,9 @@ import ( "sync/atomic" "time" - "github.com/ethereum/go-ethereum/core/types/bal" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types/bal" "github.com/ethereum/go-ethereum/rlp" ) @@ -110,18 +109,17 @@ type Header struct { // field type overrides for gencodec type headerMarshaling struct { - Difficulty *hexutil.Big - Number *hexutil.Big - GasLimit hexutil.Uint64 - GasUsed hexutil.Uint64 - Time hexutil.Uint64 - Extra hexutil.Bytes - BaseFee *hexutil.Big - Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON - BlobGasUsed *hexutil.Uint64 - ExcessBlobGas *hexutil.Uint64 - BlockAccessListHash *common.Hash - SlotNumber *hexutil.Uint64 + Difficulty *hexutil.Big + Number *hexutil.Big + GasLimit hexutil.Uint64 + GasUsed hexutil.Uint64 + Time hexutil.Uint64 + Extra hexutil.Bytes + BaseFee *hexutil.Big + Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON + BlobGasUsed *hexutil.Uint64 + ExcessBlobGas *hexutil.Uint64 + SlotNumber *hexutil.Uint64 } // Hash returns the block hash of the header, which is simply the keccak256 hash of its @@ -523,20 +521,20 @@ func (b *Block) WithBody(body Body) *Block { // WithAccessList returns a copy of the block with the given access list embedded. func (b *Block) WithAccessList(accessList *bal.BlockAccessList) *Block { - alCopy := accessList.Copy() - alHash := accessList.Hash() - b.header.BlockAccessListHash = &alHash - block := &Block{ + return b.WithAccessListUnsafe(accessList.Copy()) +} + +// WithAccessListUnsafe returns a copy of the block with the given access list +// embedded. Note that the access list is not deep-copied; use WithAccessList +// if the provided list may be modified by other actors. +func (b *Block) WithAccessListUnsafe(accessList *bal.BlockAccessList) *Block { + return &Block{ header: b.header, - transactions: slices.Clone(b.transactions), - uncles: make([]*Header, len(b.uncles)), - withdrawals: slices.Clone(b.withdrawals), - accessList: &alCopy, + transactions: b.transactions, + uncles: b.uncles, + withdrawals: b.withdrawals, + accessList: accessList, } - for i := range b.uncles { - block.uncles[i] = CopyHeader(b.uncles[i]) - } - return block } // Hash returns the keccak256 hash of b's header.