core,consensus: introduce AccessList as a field on the block struct. introduce AccessListHash field on block header. rename block access list retrieval methods on rawdb 'BAL'->'AccessList'

This commit is contained in:
Jared Wasinger 2026-03-23 08:53:03 -04:00 committed by jonny rhea
parent b49a15c5b2
commit 4d7532abab
7 changed files with 177 additions and 121 deletions

View file

@ -282,6 +282,12 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
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)
}
return nil
}

View file

@ -606,15 +606,15 @@ func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
}
}
// HasBAL verifies the existence of a block access list for a block.
func HasBAL(db ethdb.Reader, hash common.Hash, number uint64) bool {
return len(ReadBALRLP(db, hash, number)) > 0
// 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
}
// ReadBALRLP retrieves the RLP-encoded block access list for a block.
func ReadBALRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
// ReadAccessListRLP retrieves the RLP-encoded block access list for a block.
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
err := db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
if isCanon(reader, number, hash) {
data, _ = reader.Ancient(ChainFreezerBALTable, number)
return nil
@ -622,12 +622,15 @@ func ReadBALRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
data, _ = db.Get(balKey(number, hash))
return nil
})
if err != nil {
log.Crit("error reading from ancient store", "err", err)
}
return data
}
// ReadCanonicalBALRLP retrieves the BAL RLP for the canonical block at number.
// ReadCanonicalAccessListRLP retrieves the BAL RLP for the canonical block at number.
// Optionally takes the block hash to avoid looking it up.
func ReadCanonicalBALRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.RawValue {
func ReadCanonicalAccessListRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
data, _ = reader.Ancient(ChainFreezerBALTable, number)
@ -646,9 +649,9 @@ func ReadCanonicalBALRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.
return data
}
// ReadBAL retrieves and decodes the block access list for a block.
func ReadBAL(db ethdb.Reader, hash common.Hash, number uint64) *bal.BlockAccessList {
data := ReadBALRLP(db, hash, number)
// ReadAccessList retrieves and decodes the block access list for a block.
func ReadAccessList(db ethdb.Reader, hash common.Hash, number uint64) *bal.BlockAccessList {
data := ReadAccessListRLP(db, hash, number)
if len(data) == 0 {
return nil
}
@ -660,26 +663,24 @@ func ReadBAL(db ethdb.Reader, hash common.Hash, number uint64) *bal.BlockAccessL
return b
}
// WriteBAL RLP-encodes and stores a block access list in the active KV store.
func WriteBAL(db ethdb.KeyValueWriter, hash common.Hash, number uint64, b *bal.BlockAccessList) {
// WriteAccessList RLP-encodes and stores a block access list in the active KV store.
func WriteAccessList(db ethdb.KeyValueWriter, hash common.Hash, number uint64, b *bal.BlockAccessList) {
bytes, err := rlp.EncodeToBytes(b)
if err != nil {
log.Crit("Failed to encode BAL", "err", err)
}
if err := db.Put(balKey(number, hash), bytes); err != nil {
log.Crit("Failed to store BAL", "err", err)
}
WriteAccessListRLP(db, hash, number, bytes)
}
// WriteBALRLP stores a pre-encoded block access list in the active KV store.
func WriteBALRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, encoded rlp.RawValue) {
// WriteAccessListRLP stores a pre-encoded block access list in the active KV store.
func WriteAccessListRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, encoded rlp.RawValue) {
if err := db.Put(balKey(number, hash), encoded); err != nil {
log.Crit("Failed to store BAL", "err", err)
}
}
// DeleteBAL removes a block access list from the active KV store.
func DeleteBAL(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
// DeleteAccessList removes a block access list from the active KV store.
func DeleteAccessList(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
if err := db.Delete(balKey(number, hash)); err != nil {
log.Crit("Failed to delete BAL", "err", err)
}
@ -739,13 +740,23 @@ func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block {
if body == nil {
return nil
}
return types.NewBlockWithHeader(header).WithBody(*body)
block := types.NewBlockWithHeader(header).WithBody(*body)
if header.BlockAccessListHash != nil {
accessList := ReadAccessList(db, hash, number)
if accessList != nil {
block = block.WithAccessList(accessList)
}
}
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())
WriteHeader(db, block.Header())
if block.AccessList() != nil {
WriteAccessList(db, block.Hash(), block.NumberU64(), block.AccessList())
}
}
// WriteAncientBlocks writes entire block data into ancient store and returns the total written size.
@ -815,7 +826,7 @@ func WriteAncientHeaderChain(db ethdb.AncientWriter, headers []*types.Header) (i
// DeleteBlock removes all block data associated with a hash.
func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
DeleteReceipts(db, hash, number)
DeleteBAL(db, hash, number)
DeleteAccessList(db, hash, number)
DeleteHeader(db, hash, number)
DeleteBody(db, hash, number)
}
@ -824,7 +835,7 @@ func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
// the hash to number mapping.
func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
DeleteReceipts(db, hash, number)
DeleteBAL(db, hash, number)
DeleteAccessList(db, hash, number)
deleteHeaderWithoutNumber(db, hash, number)
DeleteBody(db, hash, number)
}

View file

@ -934,45 +934,45 @@ func TestBALStorage(t *testing.T) {
number := uint64(42)
// Check that no BAL exists in a new database.
if HasBAL(db, hash, number) {
if HasAccessList(db, hash, number) {
t.Fatal("BAL found in new database")
}
if b := ReadBAL(db, hash, number); b != nil {
if b := ReadAccessList(db, hash, number); b != nil {
t.Fatalf("non existent BAL returned: %v", b)
}
// Write a BAL and verify it can be read back.
encoded, testBAL := makeTestBAL(t)
WriteBAL(db, hash, number, testBAL)
WriteAccessList(db, hash, number, testBAL)
if !HasBAL(db, hash, number) {
t.Fatal("HasBAL returned false after write")
if !HasAccessList(db, hash, number) {
t.Fatal("HasAccessList returned false after write")
}
if blob := ReadBALRLP(db, hash, number); len(blob) == 0 {
t.Fatal("ReadBALRLP returned empty after write")
if blob := ReadAccessListRLP(db, hash, number); len(blob) == 0 {
t.Fatal("ReadAccessListRLP returned empty after write")
}
if b := ReadBAL(db, hash, number); b == nil {
t.Fatal("ReadBAL returned nil after write")
if b := ReadAccessList(db, hash, number); b == nil {
t.Fatal("ReadAccessList returned nil after write")
} else if b.Hash() != testBAL.Hash() {
t.Fatalf("BAL hash mismatch: got %x, want %x", b.Hash(), testBAL.Hash())
}
// Also test WriteBALRLP with pre-encoded data.
// Also test WriteAccessListRLP with pre-encoded data.
hash2 := common.BytesToHash([]byte{0x03, 0x15})
WriteBALRLP(db, hash2, number, encoded)
if b := ReadBAL(db, hash2, number); b == nil {
t.Fatal("ReadBAL returned nil after WriteBALRLP")
WriteAccessListRLP(db, hash2, number, encoded)
if b := ReadAccessList(db, hash2, number); b == nil {
t.Fatal("ReadAccessList returned nil after WriteAccessListRLP")
} else if b.Hash() != testBAL.Hash() {
t.Fatalf("BAL hash mismatch after WriteBALRLP: got %x, want %x", b.Hash(), testBAL.Hash())
t.Fatalf("BAL hash mismatch after WriteAccessListRLP: got %x, want %x", b.Hash(), testBAL.Hash())
}
// Delete the BAL and verify it's gone.
DeleteBAL(db, hash, number)
DeleteAccessList(db, hash, number)
if HasBAL(db, hash, number) {
t.Fatal("HasBAL returned true after delete")
if HasAccessList(db, hash, number) {
t.Fatal("HasAccessList returned true after delete")
}
if b := ReadBAL(db, hash, number); b != nil {
if b := ReadAccessList(db, hash, number); b != nil {
t.Fatalf("deleted BAL returned: %v", b)
}
}
@ -998,7 +998,7 @@ func TestBALFreezer(t *testing.T) {
hash, number := block.Hash(), block.NumberU64()
// Verify no BAL exists before writing.
if blob := ReadBALRLP(db, hash, number); len(blob) > 0 {
if blob := ReadAccessListRLP(db, hash, number); len(blob) > 0 {
t.Fatalf("non existent BAL returned")
}
@ -1009,18 +1009,18 @@ func TestBALFreezer(t *testing.T) {
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}), []rlp.RawValue{balRLP})
// Verify the BAL can be read from the freezer.
if blob := ReadBALRLP(db, hash, number); len(blob) == 0 {
if blob := ReadAccessListRLP(db, hash, number); len(blob) == 0 {
t.Fatal("no BAL returned from freezer")
}
if b := ReadBAL(db, hash, number); b == nil {
t.Fatal("ReadBAL returned nil from freezer")
if b := ReadAccessList(db, hash, number); b == nil {
t.Fatal("ReadAccessList returned nil from freezer")
} else if b.Hash() != testBAL.Hash() {
t.Fatalf("frozen BAL hash mismatch: got %x, want %x", b.Hash(), testBAL.Hash())
}
// Verify ReadCanonicalBALRLP works.
if blob := ReadCanonicalBALRLP(db, number, &hash); len(blob) == 0 {
t.Fatal("ReadCanonicalBALRLP returned empty for frozen block")
// Verify ReadCanonicalAccessListRLP works.
if blob := ReadCanonicalAccessListRLP(db, number, &hash); len(blob) == 0 {
t.Fatal("ReadCanonicalAccessListRLP returned empty for frozen block")
}
}
@ -1046,11 +1046,11 @@ func TestBALEmptyFreezer(t *testing.T) {
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}), nil)
// HasBAL should return false for a block with an empty freezer entry.
if HasBAL(db, hash, number) {
t.Fatal("HasBAL returned true for block with no BAL")
// HasAccessList should return false for a block with an empty freezer entry.
if HasAccessList(db, hash, number) {
t.Fatal("HasAccessList returned true for block with no BAL")
}
if b := ReadBAL(db, hash, number); b != nil {
t.Fatalf("ReadBAL returned non-nil for block with no BAL: %v", b)
if b := ReadAccessList(db, hash, number); b != nil {
t.Fatalf("ReadAccessList returned non-nil for block with no BAL: %v", b)
}
}

View file

@ -327,7 +327,7 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
if len(receipts) == 0 {
return fmt.Errorf("block receipts missing, can't freeze block %d", number)
}
bal := ReadBALRLP(nfdb, hash, number)
bal := ReadAccessListRLP(nfdb, hash, number)
// Write to the batch.
if err := op.AppendRaw(ChainFreezerHashTable, number, hash[:]); err != nil {
return fmt.Errorf("can't write hash to Freezer: %v", err)

View file

@ -21,6 +21,7 @@ import (
"crypto/sha256"
"encoding/binary"
"fmt"
"github.com/ethereum/go-ethereum/core/types/bal"
"io"
"math/big"
"reflect"
@ -99,23 +100,27 @@ type Header struct {
// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
// BlockAccessListHash was added by EIP-7928 and is ignored in legacy headers.
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"`
// SlotNumber was added by EIP-7843 and is ignored in legacy headers.
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`
}
// 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
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
BlockAccessListHash *common.Hash
SlotNumber *hexutil.Uint64
}
// Hash returns the block hash of the header, which is simply the keccak256 hash of its
@ -204,6 +209,7 @@ type Block struct {
uncles []*Header
transactions Transactions
withdrawals Withdrawals
accessList *bal.BlockAccessList
// caches
hash atomic.Pointer[common.Hash]
@ -358,9 +364,10 @@ func (b *Block) Body() *Body {
// Accessors for body data. These do not return a copy because the content
// of the body slices does not affect the cached hash/size in block.
func (b *Block) Uncles() []*Header { return b.uncles }
func (b *Block) Transactions() Transactions { return b.transactions }
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
func (b *Block) Uncles() []*Header { return b.uncles }
func (b *Block) Transactions() Transactions { return b.transactions }
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
func (b *Block) AccessList() *bal.BlockAccessList { return b.accessList }
func (b *Block) Transaction(hash common.Hash) *Transaction {
for _, transaction := range b.transactions {
@ -513,6 +520,24 @@ func (b *Block) WithBody(body Body) *Block {
return 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{
header: b.header,
transactions: slices.Clone(b.transactions),
uncles: make([]*Header, len(b.uncles)),
withdrawals: slices.Clone(b.withdrawals),
accessList: &alCopy,
}
for i := range b.uncles {
block.uncles[i] = CopyHeader(b.uncles[i])
}
return block
}
// Hash returns the keccak256 hash of b's header.
// The hash is computed on the first call and cached thereafter.
func (b *Block) Hash() common.Hash {

View file

@ -16,29 +16,30 @@ var _ = (*headerMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (h Header) MarshalJSON() ([]byte, error) {
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
Hash common.Hash `json:"hash"`
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"`
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
Hash common.Hash `json:"hash"`
}
var enc Header
enc.ParentHash = h.ParentHash
@ -62,6 +63,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
enc.ParentBeaconRoot = h.ParentBeaconRoot
enc.RequestsHash = h.RequestsHash
enc.BlockAccessListHash = h.BlockAccessListHash
enc.SlotNumber = (*hexutil.Uint64)(h.SlotNumber)
enc.Hash = h.Hash()
return json.Marshal(&enc)
@ -70,28 +72,29 @@ func (h Header) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON.
func (h *Header) UnmarshalJSON(input []byte) error {
type Header struct {
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase *common.Address `json:"miner"`
Root *common.Hash `json:"stateRoot" gencodec:"required"`
TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash"`
Nonce *BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase *common.Address `json:"miner"`
Root *common.Hash `json:"stateRoot" gencodec:"required"`
TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash"`
Nonce *BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"`
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
}
var dec Header
if err := json.Unmarshal(input, &dec); err != nil {
@ -172,6 +175,9 @@ func (h *Header) UnmarshalJSON(input []byte) error {
if dec.RequestsHash != nil {
h.RequestsHash = dec.RequestsHash
}
if dec.BlockAccessListHash != nil {
h.BlockAccessListHash = dec.BlockAccessListHash
}
if dec.SlotNumber != nil {
h.SlotNumber = (*uint64)(dec.SlotNumber)
}

View file

@ -43,8 +43,9 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
_tmp4 := obj.ExcessBlobGas != nil
_tmp5 := obj.ParentBeaconRoot != nil
_tmp6 := obj.RequestsHash != nil
_tmp7 := obj.SlotNumber != nil
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
_tmp7 := obj.BlockAccessListHash != nil
_tmp8 := obj.SlotNumber != nil
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.BaseFee == nil {
w.Write(rlp.EmptyString)
} else {
@ -54,42 +55,49 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
w.WriteBigInt(obj.BaseFee)
}
}
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.WithdrawalsHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.WithdrawalsHash[:])
}
}
if _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.BlobGasUsed == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.BlobGasUsed))
}
}
if _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.ExcessBlobGas == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.ExcessBlobGas))
}
}
if _tmp5 || _tmp6 || _tmp7 {
if _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.ParentBeaconRoot == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.ParentBeaconRoot[:])
}
}
if _tmp6 || _tmp7 {
if _tmp6 || _tmp7 || _tmp8 {
if obj.RequestsHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.RequestsHash[:])
}
}
if _tmp7 {
if _tmp7 || _tmp8 {
if obj.BlockAccessListHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.BlockAccessListHash[:])
}
}
if _tmp8 {
if obj.SlotNumber == nil {
w.Write([]byte{0x80})
} else {