a bunch of changes. mostly bal persistence and removing bal from block body object. wip...

This commit is contained in:
Jared Wasinger 2026-01-28 17:57:07 -05:00
parent 7036b1cb39
commit 3435849244
18 changed files with 158 additions and 84 deletions

View file

@ -307,11 +307,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
var blockAccessListHash *common.Hash
body := types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}
if data.BlockAccessList != nil {
body.AccessList = data.BlockAccessList
balHash := data.BlockAccessList.Hash()
blockAccessListHash = &balHash
}
header := &types.Header{
ParentHash: data.ParentHash,
UncleHash: types.EmptyUncleHash,
@ -336,7 +332,16 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
BlockAccessListHash: blockAccessListHash,
SlotNumber: data.SlotNumber,
}
if data.BlockAccessList != nil {
balHash := data.BlockAccessList.Hash()
header.BlockAccessListHash = &balHash
block := types.NewBlockWithHeader(header).WithBody(body).WithAccessList(data.BlockAccessList)
return block, nil
}
return types.NewBlockWithHeader(header).WithBody(body), nil
}
// BlockToExecutableData constructs the ExecutableData structure by filling the
@ -360,6 +365,10 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
Withdrawals: block.Withdrawals(),
BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(),
<<<<<<< HEAD
=======
BlockAccessList: block.AccessList(),
>>>>>>> 959ade7689 (a bunch of changes. mostly bal persistence and removing bal from block body object. wip...)
SlotNumber: block.SlotNumber(),
BlockAccessList: block.Body().AccessList,
}

View file

@ -5,10 +5,10 @@
# https://github.com/ethereum/execution-spec-tests/releases/download/v5.1.0
a3192784375acec7eaec492799d5c5d0c47a2909a3cc40178898e4ecd20cc416 fixtures_develop.tar.gz
# version:spec-tests-bal v3.0.1
# version:spec-tests-bal v5.0.0
# https://github.com/ethereum/execution-spec-tests/releases
# https://github.com/ethereum/execution-spec-tests/releases/download/bal%40v3.0.1
57d0f109f0557ec33d6ecd6cbd77b55415a658aefe583c4035157e1021ae512a fixtures_bal.tar.gz
# https://github.com/ethereum/execution-spec-tests/releases/download/bal%40v5.0.0
17aecf8334da7f5d1025635c763a4be0dfbcdb0e659cc70a36e6a81bd3af06f2 fixtures_bal.tar.gz
# version:golang 1.25.1
# https://go.dev/dl/

View file

@ -19,6 +19,7 @@ package beacon
import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum/core/types/bal"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -357,9 +358,9 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
// FinalizeAndAssemble implements consensus.Engine, setting the final state and
// assembling the block.
func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalization func()) (*types.Block, error) {
func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalizeAccessList func() *bal.BlockAccessList) (*types.Block, error) {
if !beacon.IsPoSHeader(header) {
return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts, onFinalization)
return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts, nil)
}
shanghai := chain.Config().IsShanghai(header.Number, header.Time)
if shanghai {
@ -379,12 +380,15 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
// Assign the final state root to header.
header.Root = state.IntermediateRoot(true)
if onFinalization != nil {
onFinalization()
}
// Assemble the final block.
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
if onFinalizeAccessList != nil {
al := onFinalizeAccessList()
alHash := al.Hash()
header.BlockAccessListHash = &alHash
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)).WithAccessList(al), nil
} else {
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
}
}
// Seal generates a new sealing request for the given input block and pushes

View file

@ -21,6 +21,7 @@ import (
"bytes"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/core/types/bal"
"io"
"math/big"
"math/rand"
@ -581,7 +582,7 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block.
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalize func()) (*types.Block, error) {
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalizeAccessList func() *bal.BlockAccessList) (*types.Block, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("clique does not support withdrawals")
}
@ -591,10 +592,9 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
// Assign the final state root to header.
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
if onFinalize != nil {
onFinalize()
if onFinalizeAccessList != nil {
panic("access list embedding not enabled for clique consensus")
}
// Assemble and return the final block for sealing.
return types.NewBlock(header, &types.Body{Transactions: body.Transactions}, receipts, trie.NewStackTrie(nil)), nil
}

View file

@ -18,6 +18,7 @@
package consensus
import (
"github.com/ethereum/go-ethereum/core/types/bal"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -92,7 +93,7 @@ type Engine interface {
//
// Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards).
FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalization func()) (*types.Block, error)
FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalizeAccessList func() *bal.BlockAccessList) (*types.Block, error)
// Seal generates a new sealing request for the given input block and pushes
// the result into the given channel.

View file

@ -19,6 +19,7 @@ package ethash
import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum/core/types/bal"
"math/big"
"time"
@ -513,7 +514,7 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.
// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
// uncle rewards, setting the final state and assembling the block.
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalize func()) (*types.Block, error) {
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalizeAccessList func() *bal.BlockAccessList) (*types.Block, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("ethash does not support withdrawals")
}
@ -523,8 +524,8 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
// Assign the final state root to header.
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
if onFinalize != nil {
onFinalize()
if onFinalizeAccessList != nil {
panic("access list embedding not supported for ethash consenus")
}
// Header seems complete, assemble into a block and return
return types.NewBlock(header, &types.Body{Transactions: body.Transactions, Uncles: body.Uncles}, receipts, trie.NewStackTrie(nil)), nil

View file

@ -116,10 +116,10 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// TODO: verify that this check isn't also done elsewhere
return fmt.Errorf("block access list hash not set in header")
}
if block.Body().AccessList != nil {
if *block.Header().BlockAccessListHash != block.Body().AccessList.Hash() {
return fmt.Errorf("access list hash mismatch. local: %x. remote: %x\n", block.Body().AccessList.Hash(), *block.Header().BlockAccessListHash)
} else if err := block.Body().AccessList.Validate(len(block.Transactions())); err != nil {
if block.AccessList() != nil {
if *block.Header().BlockAccessListHash != block.AccessList().Hash() {
return fmt.Errorf("access list hash mismatch. local: %x. remote: %x\n", block.AccessList().Hash(), *block.Header().BlockAccessListHash)
} else if err := block.AccessList().Validate(len(block.Transactions())); err != nil {
return fmt.Errorf("invalid block access list: %v", err)
}
}
@ -133,7 +133,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
}
} else {
// if experimental.bal is not enabled, block headers cannot have access list hash and bodies cannot have access lists.
if block.Body().AccessList != nil {
if block.AccessList() != nil {
return fmt.Errorf("access list not allowed in block body if not in amsterdam or experimental.bal is set")
} else if block.Header().BlockAccessListHash != nil {
return fmt.Errorf("access list hash in block header not allowed when experimental.bal is set")

View file

@ -2201,7 +2201,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
}
// TODO: need to check that the block is also postcancun if it contained an access list?
// this should be checked during decoding (?)
blockHasAccessList := block.Body().AccessList != nil
blockHasAccessList := block.AccessList() != nil
// only construct and embed BALs in the block if:
// * it has been enabled for testing purposes (preAmsterdam/postCancun blocks with experimental.bal)
// * we are after Amsterdam and the block was provided with bal omitted
@ -2276,7 +2276,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
// Disable tracing for prefetcher executions.
vmCfg := bc.cfg.VmConfig
vmCfg.Tracer = nil
if block.Body().AccessList == nil {
if block.AccessList() == nil {
// only use the state prefetcher for non-BAL blocks.
bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt)
}
@ -2369,13 +2369,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
return nil, err
}
// very ugly... deepcopy the block body before setting the block access
// list on it to prevent mutating the block instance passed by the caller.
existingBody := block.Body()
block = block.WithBody(*existingBody)
existingBody = block.Body()
existingBody.AccessList = balTracer.AccessList().ToEncodingObj()
block = block.WithBody(*existingBody)
block = block.WithAccessList(balTracer.AccessList().ToEncodingObj())
} else if enableBALFork {
computedAccessList := balTracer.AccessList().ToEncodingObj()
@ -2387,16 +2381,12 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
bc.reportBadBlock(block, res, err)
return nil, err
}
if block.Body().AccessList == nil {
// very ugly... deep copy the block body before setting the block access
// list on it to prevent mutating the block instance passed by the caller.
existingBody := block.Body()
block = block.WithBody(*existingBody)
existingBody = block.Body()
existingBody.AccessList = computedAccessList
block = block.WithBody(*existingBody)
} else if block.Body().AccessList.Hash() != computedAccessListHash {
err := fmt.Errorf("block access list hash mismatch (remote=%x computed=%x)", block.Body().AccessList.Hash(), computedAccessListHash)
if block.AccessList() == nil {
// attach the computed access list to the block so it gets persisted
// when the block is written to disk
block = block.WithAccessList(computedAccessList)
} else if block.AccessList().Hash() != computedAccessListHash {
err := fmt.Errorf("block access list hash mismatch (remote=%x computed=%x)", block.AccessList().Hash(), computedAccessListHash)
bc.reportBadBlock(block, res, err)
return nil, err
}

View file

@ -20,6 +20,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"github.com/ethereum/go-ethereum/core/types/bal"
"math/big"
"slices"
@ -421,6 +422,17 @@ func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp
}
}
func WriteAccessListRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) {
if err := db.Put(accessListKey(number, hash), rlp); err != nil {
log.Crit("failed to store block access list", "err", err)
}
}
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Get(accessListKey(number, hash))
return data
}
// HasBody verifies the existence of a block body corresponding to the hash.
func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool {
if isCanon(db, number, hash) {
@ -455,6 +467,25 @@ func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *t
WriteBodyRLP(db, hash, number, data)
}
func ReadAccessList(db ethdb.Reader, hash common.Hash, number uint64) (al *bal.BlockAccessList) {
data := ReadAccessListRLP(db, hash, number)
if data != nil {
err := rlp.DecodeBytes(data, al)
if err != nil {
log.Crit("failed to RLP decode access list", "err", err)
}
}
return al
}
func WriteAccessList(db ethdb.KeyValueWriter, hash common.Hash, number uint64, al *bal.BlockAccessList) {
data, err := rlp.EncodeToBytes(al)
if err != nil {
log.Crit("failed to RLP encode block access list", "err", err)
}
WriteAccessListRLP(db, hash, number, data)
}
// DeleteBody removes all block body data associated with a hash.
func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
if err := db.Delete(blockBodyKey(number, hash)); err != nil {
@ -659,13 +690,26 @@ 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)
// TODO: only read the access list if the bal hash is set in the header.
// I do it here regardless in order to support --experimental.bal which
// doesn't expect bal hash to be set in header in order to be compatible
// with importing mainnet blocks augmented with BALs
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())
panic("TODO write access list if it exists")
}
// WriteAncientBlocks writes entire block data into ancient store and returns the total written size.

View file

@ -111,6 +111,7 @@ var (
headerNumberPrefix = []byte("H") // headerNumberPrefix + hash -> num (uint64 big endian)
blockBodyPrefix = []byte("b") // blockBodyPrefix + num (uint64 big endian) + hash -> block body
accessListPrefix = []byte("z")
blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
txLookupPrefix = []byte("l") // txLookupPrefix + hash -> transaction/receipt lookup metadata
@ -209,6 +210,11 @@ func blockBodyKey(number uint64, hash common.Hash) []byte {
return append(append(blockBodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
}
// accessListKey = accessListPrefix + num (uint64 big endian) + hash
func accessListKey(number uint64, hash common.Hash) []byte {
return append(append(accessListPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
}
// blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash
func blockReceiptsKey(number uint64, hash common.Hash) []byte {
return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)

View file

@ -126,7 +126,7 @@ type BALReader struct {
// NewBALReader constructs a new reader from an access list. db is expected to have been instantiated with a reader.
func NewBALReader(block *types.Block, reader Reader) *BALReader {
r := &BALReader{accesses: make(map[common.Address]*bal.AccountAccess), block: block}
for _, acctDiff := range *block.Body().AccessList {
for _, acctDiff := range *block.AccessList() {
r.accesses[acctDiff.Address] = &acctDiff
}
r.prestateReader.schedule(reader, r.ModifiedAccounts())

View file

@ -462,6 +462,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil {
t.OnGasChange(st.gasRemaining, st.gasRemaining-gas, tracing.GasChangeTxIntrinsicGas)
}
fmt.Printf("gas used %d\n", gas)
st.gasRemaining -= gas
if rules.IsEIP4762 {
@ -568,8 +569,10 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
}
}
fmt.Printf("2 used gas is %d, %d\n", st.gasUsed(), peakGasUsed)
return &ExecutionResult{
UsedGas: st.gasUsed(),
UsedGas: peakGasUsed,
MaxUsedGas: peakGasUsed,
Err: vmerr,
ReturnData: ret,

View file

@ -93,7 +93,8 @@ func makeTestConstructionBAL() *AccessListBuilder {
// TestBALEncoding tests that a populated access list can be encoded/decoded correctly.
func TestBALEncoding(t *testing.T) {
var buf bytes.Buffer
bal := makeTestConstructionBAL()
balBuilder := makeTestConstructionBAL()
bal := balBuilder.FinalizedAccesses
err := bal.EncodeRLP(&buf)
if err != nil {
t.Fatalf("encoding failed: %v\n", err)
@ -136,7 +137,7 @@ func makeTestAccountAccess(sort bool) AccountAccess {
}
if sort {
slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int {
return bytes.Compare(a.Slot[:], b.Slot[:])
return bytes.Compare(a.Slot.inner.Bytes(), b.Slot.inner.Bytes())
})
}
@ -173,7 +174,7 @@ func makeTestAccountAccess(sort bool) AccountAccess {
})
}
var encodedStorageReads []EncodedStorage
var encodedStorageReads []*EncodedStorage
for _, slot := range storageReads {
encodedStorageReads = append(encodedStorageReads, newEncodedStorageFromHash(slot))
}
@ -220,7 +221,7 @@ func TestBlockAccessListCopy(t *testing.T) {
// Make sure the mutations on copy won't affect the origin
for _, aa := range cpyCpy {
for i := 0; i < len(aa.StorageReads); i++ {
aa.StorageReads[i] = testrand.Bytes(32)
aa.StorageReads[i] = &EncodedStorage{new(uint256.Int).SetBytes(testrand.Bytes(32))}
}
}
if !reflect.DeepEqual(list, cpy) {
@ -230,8 +231,9 @@ func TestBlockAccessListCopy(t *testing.T) {
func TestBlockAccessListValidation(t *testing.T) {
// Validate the block access list after RLP decoding
testBALMaxIndex := 8
enc := makeTestBAL(true)
if err := enc.Validate(); err != nil {
if err := enc.Validate(testBALMaxIndex); err != nil {
t.Fatalf("Unexpected validation error: %v", err)
}
var buf bytes.Buffer
@ -243,14 +245,14 @@ func TestBlockAccessListValidation(t *testing.T) {
if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 0)); err != nil {
t.Fatalf("Unexpected RLP-decode error: %v", err)
}
if err := dec.Validate(); err != nil {
if err := dec.Validate(testBALMaxIndex); err != nil {
t.Fatalf("Unexpected validation error: %v", err)
}
// Validate the derived block access list
cBAL := makeTestConstructionBAL()
cBAL := makeTestConstructionBAL().FinalizedAccesses
listB := cBAL.ToEncodingObj()
if err := listB.Validate(); err != nil {
if err := listB.Validate(testBALMaxIndex); err != nil {
t.Fatalf("Unexpected validation error: %v", err)
}
}

View file

@ -182,8 +182,7 @@ func (h *Header) EmptyReceipts() bool {
type Body struct {
Transactions []*Transaction
Uncles []*Header
Withdrawals []*Withdrawal `rlp:"optional"`
AccessList *bal.BlockAccessList `rlp:"optional,nil"`
Withdrawals []*Withdrawal `rlp:"optional"`
}
// Block represents an Ethereum block.
@ -287,15 +286,17 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher ListHasher
b.withdrawals = slices.Clone(withdrawals)
}
if body.AccessList != nil {
balHash := body.AccessList.Hash()
b.header.BlockAccessListHash = &balHash
b.accessList = body.AccessList
}
return b
}
func NewBlockWithAccessList(header *Header, body *Body, receipts []*Receipt, accessList *bal.BlockAccessList, hasher ListHasher) *Block {
block := NewBlock(header, body, receipts, hasher)
block.accessList = accessList
balHash := accessList.Hash()
block.header.BlockAccessListHash = &balHash
return block
}
// CopyHeader creates a deep copy of a block header.
func CopyHeader(h *Header) *Header {
cpy := *h
@ -367,15 +368,16 @@ func (b *Block) EncodeRLP(w io.Writer) error {
// Body returns the non-header content of the block.
// Note the returned data is not an independent copy.
func (b *Block) Body() *Body {
return &Body{b.transactions, b.uncles, b.withdrawals, b.accessList}
return &Body{b.transactions, b.uncles, b.withdrawals}
}
// 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 {
@ -522,16 +524,30 @@ func (b *Block) WithBody(body Body) *Block {
uncles: make([]*Header, len(body.Uncles)),
withdrawals: slices.Clone(body.Withdrawals),
}
if body.AccessList != nil {
balCopy := body.AccessList.Copy()
block.accessList = &balCopy
}
for i := range body.Uncles {
block.uncles[i] = CopyHeader(body.Uncles[i])
}
return block
}
// WithAccessList returns a copy of the block with the access list embedded.
// It does not set the access list hash in the header of the returned block.
// TODO: ^ when support for --experimental.bal is removed, this function should set the access list hash in the header
func (b *Block) WithAccessList(accessList *bal.BlockAccessList) *Block {
alCopy := accessList.Copy()
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

@ -514,8 +514,8 @@ func (b *EthAPIBackend) BlockAccessListByNumberOrHash(number rpc.BlockNumberOrHa
if block == nil {
return nil, fmt.Errorf("block not found")
}
if block.Body().AccessList == nil {
if block.AccessList() == nil {
return nil, nil
}
return block.Body().AccessList.StringableRepresentation(), nil
return block.AccessList().StringableRepresentation(), nil
}

View file

@ -102,7 +102,6 @@ func (f *fetchResult) body() types.Body {
Transactions: f.Transactions,
Uncles: f.Uncles,
Withdrawals: f.Withdrawals,
AccessList: f.AccessList,
}
}

View file

@ -970,8 +970,8 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *param
if block.Withdrawals() != nil {
fields["withdrawals"] = block.Withdrawals()
}
if block.Body().AccessList != nil {
fields["accessList"] = block.Body().AccessList
if block.AccessList() != nil {
fields["accessList"] = block.AccessList()
}
return fields
}

View file

@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types/bal"
"math/big"
"sync/atomic"
"time"
@ -147,9 +148,6 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
}
}
body := types.Body{Transactions: work.txs, Withdrawals: genParam.withdrawals}
if work.alTracer != nil {
body.AccessList = work.alTracer.AccessList().ToEncodingObj()
}
allLogs := make([]*types.Log, 0)
for _, r := range work.receipts {
@ -184,11 +182,12 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
// I considered trying to instantiate the beacon consensus engine with a tracer.
// however, the BAL tracer instance is used once per block, while the engine object
// lives for the entire time the client is running.
onBlockFinalization := func() {
onBlockFinalization := func() *bal.BlockAccessList {
if miner.chainConfig.IsAmsterdam(work.header.Number, work.header.Time) {
work.alTracer.OnBlockFinalization()
body.AccessList = work.alTracer.AccessList().ToEncodingObj()
return work.alTracer.AccessList().ToEncodingObj()
}
return nil
}
block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts, onBlockFinalization)