core: apply fixes for BAL (claude)

This commit is contained in:
Marius van der Wijden 2026-04-23 10:30:49 +02:00 committed by MariusVanDerWijden
parent 0cb107dfd6
commit 6ded1620db
4 changed files with 72 additions and 16 deletions

View file

@ -465,8 +465,10 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
body.Withdrawals = make([]*types.Withdrawal, 0)
}
}
// Assemble the block for delivery.
block := AssembleBlock(b.engine, cm, b.header, statedb, &body, b.receipts)
// Assemble the block for delivery. When Amsterdam is active,
// pass the accumulated BAL so engine.Finalize's accesses and
// mutations are folded in and the BAL is attached to the block.
block := AssembleBlock(b.engine, cm, b.header, statedb, &body, b.receipts, b.accessList)
// Write state changes to db
root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number), config.IsCancun(b.header.Number, b.header.Time))

View file

@ -408,9 +408,26 @@ func onSystemCallStart(tracer *tracing.Hooks, ctx *tracing.VMContext) {
}
// AssembleBlock finalizes the state and assembles the block with provided
// body and receipts.
func AssembleBlock(engine consensus.Engine, chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) *types.Block {
engine.Finalize(chain, header, state, body)
// body and receipts. When accessList is non-nil (EIP-7928 / Amsterdam), the
// accesses and mutations produced by engine.Finalize (e.g. withdrawal balance
// changes) are accumulated into it as block-finalize entries, the computed
// BAL hash is written into the header, and the finalized BAL is attached to
// the returned block.
func AssembleBlock(engine consensus.Engine, chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, accessList *bal.ConstructionBlockAccessList) *types.Block {
finalizeAccesses, finalizeMutations := engine.Finalize(chain, header, state, body)
if accessList != nil {
if finalizeMutations != nil {
accessList.AddBlockFinalizeMutations(finalizeMutations)
}
if finalizeAccesses != nil {
accessList.AddAccesses(finalizeAccesses)
}
encoded := accessList.ToEncodingObj()
balHash := encoded.Hash()
header.BlockAccessListHash = &balHash
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)).WithAccessListUnsafe(encoded)
}
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
}

View file

@ -423,8 +423,8 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
}
chainHeadReader := &simChainHeadReader{ctx, sim.b}
// Assemble the block
b := core.AssembleBlock(sim.b.Engine(), chainHeadReader, header, sim.state, blockBody, receipts)
// Assemble the block. Simulated blocks don't carry a BAL.
b := core.AssembleBlock(sim.b.Engine(), chainHeadReader, header, sim.state, blockBody, receipts, nil)
repairLogs(callResults, b.Hash())
return b, callResults, senders, nil

View file

@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types/bal"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/internal/telemetry"
"github.com/ethereum/go-ethereum/log"
@ -73,6 +74,14 @@ type environment struct {
blobs int
witness *stateless.Witness
// accessList accumulates the block's BAL (EIP-7928). Non-nil only when
// Amsterdam is active. Populated from pre-tx system calls
// (ProcessBeaconBlockRoot, ProcessParentBlockHash) in prepareWork, each
// transaction in applyTransaction, post-tx system calls
// (ProcessWithdrawalQueue, ProcessConsolidationQueue) in generateWork,
// and finally engine.Finalize inside AssembleBlock.
accessList *bal.ConstructionBlockAccessList
}
// txFitsSize reports whether the transaction fits into the block size limit.
@ -213,21 +222,33 @@ func (miner *Miner) generateWork(ctx context.Context, genParam *generateParams,
return &newPayloadResult{err: err}
}
// EIP-7002
if _, _, err := core.ProcessWithdrawalQueue(&requests, work.evm); err != nil {
wqAccesses, wqMutations, err := core.ProcessWithdrawalQueue(&requests, work.evm)
if err != nil {
return &newPayloadResult{err: err}
}
// EIP-7251 consolidations
if _, _, err := core.ProcessConsolidationQueue(&requests, work.evm); err != nil {
cqAccesses, cqMutations, err := core.ProcessConsolidationQueue(&requests, work.evm)
if err != nil {
return &newPayloadResult{err: err}
}
if work.accessList != nil {
postMut := bal.NewStateMutations()
postMut.Merge(wqMutations)
postMut.Merge(cqMutations)
work.accessList.AddBlockFinalizeMutations(postMut)
work.accessList.AddAccesses(wqAccesses)
work.accessList.AddAccesses(cqAccesses)
}
}
if requests != nil {
reqHash := types.CalcRequestsHash(requests)
work.header.RequestsHash = &reqHash
}
// Assemble the block for delivery.
// Assemble the block for delivery. AssembleBlock calls engine.Finalize
// and, when a BAL is supplied, folds its accesses/mutations into the BAL,
// sets header.BlockAccessListHash, and attaches the BAL to the block.
_, _, assembleSpanEnd := telemetry.StartSpan(ctx, "miner.AssembleBlock")
block := core.AssembleBlock(miner.engine, miner.chain, work.header, work.state, &body, work.receipts)
block := core.AssembleBlock(miner.engine, miner.chain, work.header, work.state, &body, work.receipts, work.accessList)
assembleSpanEnd(nil)
return &newPayloadResult{
@ -327,10 +348,18 @@ func (miner *Miner) prepareWork(ctx context.Context, genParams *generateParams,
return nil, err
}
if header.ParentBeaconRoot != nil {
core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, env.evm)
accesses, mutations := core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, env.evm)
if env.accessList != nil {
env.accessList.AddBlockInitMutations(mutations)
env.accessList.AddAccesses(accesses)
}
}
if miner.chainConfig.IsPrague(header.Number, header.Time) {
core.ProcessParentBlockHash(header.ParentHash, env.evm)
accesses, mutations := core.ProcessParentBlockHash(header.ParentHash, env.evm)
if env.accessList != nil {
env.accessList.AddBlockInitMutations(mutations)
env.accessList.AddAccesses(accesses)
}
}
return env, nil
}
@ -351,7 +380,7 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
}
state.StartPrefetcher("miner", bundle)
// Note the passed coinbase may be different with header.Coinbase.
return &environment{
env := &environment{
signer: types.MakeSigner(miner.chainConfig, header.Number, header.Time),
state: state,
size: uint64(header.Size()),
@ -360,7 +389,11 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
header: header,
witness: state.Witness(),
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, &coinbase), state, miner.chainConfig, vm.Config{}),
}, nil
}
if miner.chainConfig.IsAmsterdam(header.Number, header.Time) {
env.accessList = bal.NewConstructionBlockAccessList()
}
return env, nil
}
func (miner *Miner) commitTransaction(ctx context.Context, env *environment, tx *types.Transaction) (err error) {
@ -414,12 +447,16 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*
snap = env.state.Snapshot()
gp = env.gasPool.Snapshot()
)
_, _, receipt, err := core.ApplyTransaction(env.evm, env.gasPool, env.state, env.header, tx)
txAccesses, txMutations, receipt, err := core.ApplyTransaction(env.evm, env.gasPool, env.state, env.header, tx)
if err != nil {
env.state.RevertToSnapshot(snap)
env.gasPool.Set(gp)
return nil, err
}
if env.accessList != nil {
env.accessList.AddTransactionMutations(txMutations, env.tcount)
env.accessList.AddAccesses(txAccesses)
}
env.header.GasUsed = env.gasPool.Used()
return receipt, nil
}