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 { if !amsterdam && header.SlotNumber != nil {
return fmt.Errorf("invalid slotNumber: have %d, expected nil", *header.SlotNumber) 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 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. // HasAccessList verifies the existence of a block access list for a block.
func HasBAL(db ethdb.Reader, hash common.Hash, number uint64) bool { func HasAccessList(db ethdb.Reader, hash common.Hash, number uint64) bool {
return len(ReadBALRLP(db, hash, number)) > 0 return len(ReadAccessListRLP(db, hash, number)) > 0
} }
// ReadBALRLP retrieves the RLP-encoded block access list for a block. // ReadAccessListRLP retrieves the RLP-encoded block access list for a block.
func ReadBALRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte var data []byte
db.ReadAncients(func(reader ethdb.AncientReaderOp) error { err := db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
if isCanon(reader, number, hash) { if isCanon(reader, number, hash) {
data, _ = reader.Ancient(ChainFreezerBALTable, number) data, _ = reader.Ancient(ChainFreezerBALTable, number)
return nil return nil
@ -622,12 +622,15 @@ func ReadBALRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
data, _ = db.Get(balKey(number, hash)) data, _ = db.Get(balKey(number, hash))
return nil return nil
}) })
if err != nil {
log.Crit("error reading from ancient store", "err", err)
}
return data 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. // 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 var data []byte
db.ReadAncients(func(reader ethdb.AncientReaderOp) error { db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
data, _ = reader.Ancient(ChainFreezerBALTable, number) data, _ = reader.Ancient(ChainFreezerBALTable, number)
@ -646,9 +649,9 @@ func ReadCanonicalBALRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.
return data return data
} }
// ReadBAL retrieves and decodes the block access list for a block. // ReadAccessList retrieves and decodes the block access list for a block.
func ReadBAL(db ethdb.Reader, hash common.Hash, number uint64) *bal.BlockAccessList { func ReadAccessList(db ethdb.Reader, hash common.Hash, number uint64) *bal.BlockAccessList {
data := ReadBALRLP(db, hash, number) data := ReadAccessListRLP(db, hash, number)
if len(data) == 0 { if len(data) == 0 {
return nil return nil
} }
@ -660,26 +663,24 @@ func ReadBAL(db ethdb.Reader, hash common.Hash, number uint64) *bal.BlockAccessL
return b return b
} }
// WriteBAL RLP-encodes and stores a block access list in the active KV store. // WriteAccessList 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) { func WriteAccessList(db ethdb.KeyValueWriter, hash common.Hash, number uint64, b *bal.BlockAccessList) {
bytes, err := rlp.EncodeToBytes(b) bytes, err := rlp.EncodeToBytes(b)
if err != nil { if err != nil {
log.Crit("Failed to encode BAL", "err", err) log.Crit("Failed to encode BAL", "err", err)
} }
if err := db.Put(balKey(number, hash), bytes); err != nil { WriteAccessListRLP(db, hash, number, bytes)
log.Crit("Failed to store BAL", "err", err)
}
} }
// WriteBALRLP stores a pre-encoded block access list in the active KV store. // WriteAccessListRLP 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) { func WriteAccessListRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, encoded rlp.RawValue) {
if err := db.Put(balKey(number, hash), encoded); err != nil { if err := db.Put(balKey(number, hash), encoded); err != nil {
log.Crit("Failed to store BAL", "err", err) log.Crit("Failed to store BAL", "err", err)
} }
} }
// DeleteBAL removes a block access list from the active KV store. // DeleteAccessList removes a block access list from the active KV store.
func DeleteBAL(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { func DeleteAccessList(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
if err := db.Delete(balKey(number, hash)); err != nil { if err := db.Delete(balKey(number, hash)); err != nil {
log.Crit("Failed to delete BAL", "err", err) 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 { if body == nil {
return 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. // WriteBlock serializes a block into the database, header and body separately.
func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
WriteHeader(db, block.Header()) 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. // 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. // DeleteBlock removes all block data associated with a hash.
func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
DeleteReceipts(db, hash, number) DeleteReceipts(db, hash, number)
DeleteBAL(db, hash, number) DeleteAccessList(db, hash, number)
DeleteHeader(db, hash, number) DeleteHeader(db, hash, number)
DeleteBody(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. // the hash to number mapping.
func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
DeleteReceipts(db, hash, number) DeleteReceipts(db, hash, number)
DeleteBAL(db, hash, number) DeleteAccessList(db, hash, number)
deleteHeaderWithoutNumber(db, hash, number) deleteHeaderWithoutNumber(db, hash, number)
DeleteBody(db, hash, number) DeleteBody(db, hash, number)
} }

View file

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

View file

@ -21,6 +21,7 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/core/types/bal"
"io" "io"
"math/big" "math/big"
"reflect" "reflect"
@ -99,23 +100,27 @@ type Header struct {
// RequestsHash was added by EIP-7685 and is ignored in legacy headers. // RequestsHash was added by EIP-7685 and is ignored in legacy headers.
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"` 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 was added by EIP-7843 and is ignored in legacy headers.
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"` SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`
} }
// field type overrides for gencodec // field type overrides for gencodec
type headerMarshaling struct { type headerMarshaling struct {
Difficulty *hexutil.Big Difficulty *hexutil.Big
Number *hexutil.Big Number *hexutil.Big
GasLimit hexutil.Uint64 GasLimit hexutil.Uint64
GasUsed hexutil.Uint64 GasUsed hexutil.Uint64
Time hexutil.Uint64 Time hexutil.Uint64
Extra hexutil.Bytes Extra hexutil.Bytes
BaseFee *hexutil.Big BaseFee *hexutil.Big
Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
BlobGasUsed *hexutil.Uint64 BlobGasUsed *hexutil.Uint64
ExcessBlobGas *hexutil.Uint64 ExcessBlobGas *hexutil.Uint64
SlotNumber *hexutil.Uint64 BlockAccessListHash *common.Hash
SlotNumber *hexutil.Uint64
} }
// Hash returns the block hash of the header, which is simply the keccak256 hash of its // 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 uncles []*Header
transactions Transactions transactions Transactions
withdrawals Withdrawals withdrawals Withdrawals
accessList *bal.BlockAccessList
// caches // caches
hash atomic.Pointer[common.Hash] 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 // 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. // of the body slices does not affect the cached hash/size in block.
func (b *Block) Uncles() []*Header { return b.uncles } func (b *Block) Uncles() []*Header { return b.uncles }
func (b *Block) Transactions() Transactions { return b.transactions } func (b *Block) Transactions() Transactions { return b.transactions }
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals } 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 { func (b *Block) Transaction(hash common.Hash) *Transaction {
for _, transaction := range b.transactions { for _, transaction := range b.transactions {
@ -513,6 +520,24 @@ func (b *Block) WithBody(body Body) *Block {
return 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. // Hash returns the keccak256 hash of b's header.
// The hash is computed on the first call and cached thereafter. // The hash is computed on the first call and cached thereafter.
func (b *Block) Hash() common.Hash { func (b *Block) Hash() common.Hash {

View file

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

View file

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