From aac9c15b62ddb2d2d6b54a2d538467b3f888f840 Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Thu, 21 May 2026 12:06:43 -0400 Subject: [PATCH] beacon/engine: encode/decode bals as hex for ExecutableData --- beacon/engine/ed_codec.go | 80 +++++++++++++++++++-------------------- beacon/engine/types.go | 41 ++++++++++++++------ 2 files changed, 70 insertions(+), 51 deletions(-) diff --git a/beacon/engine/ed_codec.go b/beacon/engine/ed_codec.go index 02a1fd3805..7a1f8f89c0 100644 --- a/beacon/engine/ed_codec.go +++ b/beacon/engine/ed_codec.go @@ -18,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"` - BlockAccessList *bal.BlockAccessList `json:"blockAccessList,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 *hexBlockAccessList `json:"blockAccessList,omitempty"` } var enc ExecutableData enc.ParentHash = e.ParentHash @@ -62,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.BlockAccessList = e.BlockAccessList + enc.BlockAccessList = (*hexBlockAccessList)(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"` - BlockAccessList *bal.BlockAccessList `json:"blockAccessList,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 *hexBlockAccessList `json:"blockAccessList,omitempty"` } var dec ExecutableData if err := json.Unmarshal(input, &dec); err != nil { @@ -165,7 +165,7 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error { e.SlotNumber = (*uint64)(dec.SlotNumber) } if dec.BlockAccessList != nil { - e.BlockAccessList = dec.BlockAccessList + e.BlockAccessList = (*bal.BlockAccessList)(dec.BlockAccessList) } return nil } diff --git a/beacon/engine/types.go b/beacon/engine/types.go index 60d564b877..a5977c71df 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -17,7 +17,9 @@ package engine import ( + "bytes" "fmt" + "github.com/ethereum/go-ethereum/rlp" "math/big" "slices" @@ -104,19 +106,36 @@ type ExecutableData struct { BlockAccessList *bal.BlockAccessList `json:"blockAccessList,omitempty"` } +type hexBlockAccessList bal.BlockAccessList + +func (h *hexBlockAccessList) MarshalJSON() ([]byte, error) { + return rlp.EncodeToBytes(bal.BlockAccessList(*h)) +} + +func (h *hexBlockAccessList) UnmarshalJSON(inp []byte) error { + if *h == nil { + *h = make(hexBlockAccessList, 0) + } + if err := rlp.Decode(bytes.NewReader(inp), *h); err != nil { + return err + } + return nil +} + // JSON type overrides for executableData. type executableDataMarshaling struct { - Number hexutil.Uint64 - GasLimit hexutil.Uint64 - GasUsed hexutil.Uint64 - Timestamp hexutil.Uint64 - BaseFeePerGas *hexutil.Big - ExtraData hexutil.Bytes - LogsBloom hexutil.Bytes - Transactions []hexutil.Bytes - BlobGasUsed *hexutil.Uint64 - ExcessBlobGas *hexutil.Uint64 - SlotNumber *hexutil.Uint64 + Number hexutil.Uint64 + GasLimit hexutil.Uint64 + GasUsed hexutil.Uint64 + Timestamp hexutil.Uint64 + BaseFeePerGas *hexutil.Big + ExtraData hexutil.Bytes + LogsBloom hexutil.Bytes + Transactions []hexutil.Bytes + BlobGasUsed *hexutil.Uint64 + ExcessBlobGas *hexutil.Uint64 + SlotNumber *hexutil.Uint64 + BlockAccessList *hexBlockAccessList } // StatelessPayloadStatusV1 is the result of a stateless payload execution.