mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-07 15:38:37 +00:00
core, beacon: add blockAccessList into executionData
This commit is contained in:
parent
2169065ba6
commit
285a13c43d
4 changed files with 100 additions and 90 deletions
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = (*executableDataMarshaling)(nil)
|
var _ = (*executableDataMarshaling)(nil)
|
||||||
|
|
@ -17,25 +18,25 @@ var _ = (*executableDataMarshaling)(nil)
|
||||||
// MarshalJSON marshals as JSON.
|
// MarshalJSON marshals as JSON.
|
||||||
func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||||
type ExecutableData struct {
|
type ExecutableData struct {
|
||||||
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
|
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
|
||||||
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
|
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
|
||||||
StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
|
StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
|
ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||||
LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"`
|
LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"`
|
||||||
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
||||||
Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
|
Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
|
||||||
GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
|
GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
|
||||||
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||||
Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
|
Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
|
||||||
ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"`
|
ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"`
|
||||||
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
|
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
|
||||||
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
|
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
|
||||||
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
|
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"`
|
SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"`
|
||||||
BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"`
|
BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"`
|
||||||
}
|
}
|
||||||
var enc ExecutableData
|
var enc ExecutableData
|
||||||
enc.ParentHash = e.ParentHash
|
enc.ParentHash = e.ParentHash
|
||||||
|
|
@ -61,32 +62,32 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||||
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
||||||
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
||||||
enc.SlotNumber = (*hexutil.Uint64)(e.SlotNumber)
|
enc.SlotNumber = (*hexutil.Uint64)(e.SlotNumber)
|
||||||
enc.BlockAccessListHash = e.BlockAccessListHash
|
enc.BlockAccessList = e.BlockAccessList
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||||
type ExecutableData struct {
|
type ExecutableData struct {
|
||||||
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
|
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
|
||||||
FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"`
|
FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"`
|
||||||
StateRoot *common.Hash `json:"stateRoot" gencodec:"required"`
|
StateRoot *common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"`
|
ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||||
LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"`
|
LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"`
|
||||||
Random *common.Hash `json:"prevRandao" gencodec:"required"`
|
Random *common.Hash `json:"prevRandao" gencodec:"required"`
|
||||||
Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
|
Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
|
||||||
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
|
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
|
||||||
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||||
Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
|
Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
|
||||||
ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"`
|
ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"`
|
||||||
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
|
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
|
||||||
BlockHash *common.Hash `json:"blockHash" gencodec:"required"`
|
BlockHash *common.Hash `json:"blockHash" gencodec:"required"`
|
||||||
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
|
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"`
|
SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"`
|
||||||
BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"`
|
BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"`
|
||||||
}
|
}
|
||||||
var dec ExecutableData
|
var dec ExecutableData
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -163,8 +164,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||||
if dec.SlotNumber != nil {
|
if dec.SlotNumber != nil {
|
||||||
e.SlotNumber = (*uint64)(dec.SlotNumber)
|
e.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||||
}
|
}
|
||||||
if dec.BlockAccessListHash != nil {
|
if dec.BlockAccessList != nil {
|
||||||
e.BlockAccessListHash = dec.BlockAccessListHash
|
e.BlockAccessList = dec.BlockAccessList
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
)
|
)
|
||||||
|
|
@ -82,25 +83,25 @@ type payloadAttributesMarshaling struct {
|
||||||
|
|
||||||
// ExecutableData is the data necessary to execute an EL payload.
|
// ExecutableData is the data necessary to execute an EL payload.
|
||||||
type ExecutableData struct {
|
type ExecutableData struct {
|
||||||
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
|
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
|
||||||
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
|
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
|
||||||
StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
|
StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
|
ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||||
LogsBloom []byte `json:"logsBloom" gencodec:"required"`
|
LogsBloom []byte `json:"logsBloom" gencodec:"required"`
|
||||||
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
||||||
Number uint64 `json:"blockNumber" gencodec:"required"`
|
Number uint64 `json:"blockNumber" gencodec:"required"`
|
||||||
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
|
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
|
||||||
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
||||||
Timestamp uint64 `json:"timestamp" gencodec:"required"`
|
Timestamp uint64 `json:"timestamp" gencodec:"required"`
|
||||||
ExtraData []byte `json:"extraData" gencodec:"required"`
|
ExtraData []byte `json:"extraData" gencodec:"required"`
|
||||||
BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"`
|
BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"`
|
||||||
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
|
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
|
||||||
Transactions [][]byte `json:"transactions" gencodec:"required"`
|
Transactions [][]byte `json:"transactions" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||||
SlotNumber *uint64 `json:"slotNumber,omitempty"`
|
SlotNumber *uint64 `json:"slotNumber,omitempty"`
|
||||||
BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"`
|
BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON type overrides for executableData.
|
// JSON type overrides for executableData.
|
||||||
|
|
@ -304,6 +305,16 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
||||||
requestsHash = &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{
|
header := &types.Header{
|
||||||
ParentHash: data.ParentHash,
|
ParentHash: data.ParentHash,
|
||||||
UncleHash: types.EmptyUncleHash,
|
UncleHash: types.EmptyUncleHash,
|
||||||
|
|
@ -326,36 +337,34 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
||||||
ParentBeaconRoot: beaconRoot,
|
ParentBeaconRoot: beaconRoot,
|
||||||
RequestsHash: requestsHash,
|
RequestsHash: requestsHash,
|
||||||
SlotNumber: data.SlotNumber,
|
SlotNumber: data.SlotNumber,
|
||||||
BlockAccessListHash: data.BlockAccessListHash,
|
BlockAccessListHash: blockAccessListHash,
|
||||||
}
|
}
|
||||||
return types.NewBlockWithHeader(header).
|
return types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}), nil
|
||||||
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}),
|
|
||||||
nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
||||||
// fields from the given block. It assumes the given block is post-merge block.
|
// 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 {
|
func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar, requests [][]byte) *ExecutionPayloadEnvelope {
|
||||||
data := &ExecutableData{
|
data := &ExecutableData{
|
||||||
BlockHash: block.Hash(),
|
BlockHash: block.Hash(),
|
||||||
ParentHash: block.ParentHash(),
|
ParentHash: block.ParentHash(),
|
||||||
FeeRecipient: block.Coinbase(),
|
FeeRecipient: block.Coinbase(),
|
||||||
StateRoot: block.Root(),
|
StateRoot: block.Root(),
|
||||||
Number: block.NumberU64(),
|
Number: block.NumberU64(),
|
||||||
GasLimit: block.GasLimit(),
|
GasLimit: block.GasLimit(),
|
||||||
GasUsed: block.GasUsed(),
|
GasUsed: block.GasUsed(),
|
||||||
BaseFeePerGas: block.BaseFee(),
|
BaseFeePerGas: block.BaseFee(),
|
||||||
Timestamp: block.Time(),
|
Timestamp: block.Time(),
|
||||||
ReceiptsRoot: block.ReceiptHash(),
|
ReceiptsRoot: block.ReceiptHash(),
|
||||||
LogsBloom: block.Bloom().Bytes(),
|
LogsBloom: block.Bloom().Bytes(),
|
||||||
Transactions: encodeTransactions(block.Transactions()),
|
Transactions: encodeTransactions(block.Transactions()),
|
||||||
Random: block.MixDigest(),
|
Random: block.MixDigest(),
|
||||||
ExtraData: block.Extra(),
|
ExtraData: block.Extra(),
|
||||||
Withdrawals: block.Withdrawals(),
|
Withdrawals: block.Withdrawals(),
|
||||||
BlobGasUsed: block.BlobGasUsed(),
|
BlobGasUsed: block.BlobGasUsed(),
|
||||||
ExcessBlobGas: block.ExcessBlobGas(),
|
ExcessBlobGas: block.ExcessBlobGas(),
|
||||||
SlotNumber: block.SlotNumber(),
|
SlotNumber: block.SlotNumber(),
|
||||||
BlockAccessListHash: block.BlockAccessListHash(),
|
BlockAccessList: block.AccessList(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add blobs.
|
// Add blobs.
|
||||||
|
|
|
||||||
|
|
@ -92,11 +92,11 @@ func (e *BlockAccessList) Validate() error {
|
||||||
return nil
|
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 +
|
// purposes: the count of distinct addresses plus every storage key (writes +
|
||||||
// reads) carried by those accounts. A storage slot is counted once regardless
|
// reads) carried by those accounts. A storage slot is counted once regardless
|
||||||
// of how many transactions wrote to it.
|
// of how many transactions wrote to it.
|
||||||
func (e *BlockAccessList) ItemCount() uint64 {
|
func (e *BlockAccessList) itemCount() uint64 {
|
||||||
count := uint64(len(*e)) // distinct addresses
|
count := uint64(len(*e)) // distinct addresses
|
||||||
for i := range *e {
|
for i := range *e {
|
||||||
count += uint64(len((*e)[i].StorageWrites)) + uint64(len((*e)[i].StorageReads))
|
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
|
// ValidateSize returns an error if the BAL violates the EIP-7928 size
|
||||||
// constraint for the given block gas limit:
|
// constraint for the given block gas limit:
|
||||||
//
|
//
|
||||||
// ItemCount() <= blockGasLimit / params.BALItemCost
|
// itemCount() <= blockGasLimit / params.BALItemCost
|
||||||
func (e *BlockAccessList) ValidateSize(blockGasLimit uint64) error {
|
func (e *BlockAccessList) ValidateSize(blockGasLimit uint64) error {
|
||||||
items := e.ItemCount()
|
items := e.itemCount()
|
||||||
limit := blockGasLimit / params.BALItemCost
|
limit := blockGasLimit / params.BALItemCost
|
||||||
if items > limit {
|
if items > limit {
|
||||||
return fmt.Errorf("block access list exceeds size constraint: items=%d, limit=%d (block gas limit %d / %d)",
|
return fmt.Errorf("block access list exceeds size constraint: items=%d, limit=%d (block gas limit %d / %d)",
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,7 @@ func TestBlockAccessListCopy(t *testing.T) {
|
||||||
|
|
||||||
func TestBlockAccessListItemCount(t *testing.T) {
|
func TestBlockAccessListItemCount(t *testing.T) {
|
||||||
empty := &BlockAccessList{}
|
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)
|
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.
|
// 2 addresses + 2 write-slots + 1 read-slot = 5 items.
|
||||||
// (Multiple TxIdx writes to the same slot count as ONE item.)
|
// (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)
|
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())
|
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)
|
t.Fatalf("setup: item count = %d, want 30", got)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue