core, eth: use Pre-execution func

This commit is contained in:
Gary Rong 2026-04-24 14:17:36 +08:00 committed by Jared Wasinger
parent 2f5090b322
commit e54f7e1a17
7 changed files with 54 additions and 48 deletions

View file

@ -230,17 +230,16 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig) evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig)
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
var ( core.ProcessBeaconBlockRoot(*beaconRoot, evm)
prevNumber uint64 }
prevHash common.Hash if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) {
) var (
if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) { prevNumber = pre.Env.Number - 1
prevNumber = pre.Env.Number - 1 prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)]
prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)] )
core.ProcessParentBlockHash(prevHash, evm)
} }
core.PreExecution(context.Background(), pre.Env.ParentBeaconBlockRoot, prevHash, chainConfig, evm, vmContext.BlockNumber, vmContext.Time)
for i := 0; txIt.Next(); i++ { for i := 0; txIt.Next(); i++ {
tx, err := txIt.Tx() tx, err := txIt.Tx()
if err != nil { if err != nil {

View file

@ -315,15 +315,14 @@ func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) {
// off the statedb before executing the system calls. // off the statedb before executing the system calls.
statedb = statedb.Copy() statedb = statedb.Copy()
} }
// EIP-6110 deposits
var blockLogs []*types.Log var blockLogs []*types.Log
for _, r := range b.receipts { for _, r := range b.receipts {
blockLogs = append(blockLogs, r.Logs...) blockLogs = append(blockLogs, r.Logs...)
} }
// TODO(rjl493456442) the EVM instance should be shared across the entire // TODO use the shared EVM throughout the entire generation cycle
// generation life cycle.
blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase) blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{}) evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{})
requests, err := PostExecution(context.Background(), b.cm.config, b.header.Number, b.header.Time, blockLogs, evm) requests, err := PostExecution(context.Background(), b.cm.config, b.header.Number, b.header.Time, blockLogs, evm)
if err != nil { if err != nil {
panic(fmt.Sprintf("failed to run post-execution: %v", err)) panic(fmt.Sprintf("failed to run post-execution: %v", err))

View file

@ -75,7 +75,6 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated
if hooks := cfg.Tracer; hooks != nil { if hooks := cfg.Tracer; hooks != nil {
tracingStateDB = state.NewHookedState(statedb, hooks) tracingStateDB = state.NewHookedState(statedb, hooks)
} }
// Mutate the block and state according to any hard-fork specs // Mutate the block and state according to any hard-fork specs
if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(block.Number()) == 0 { if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(tracingStateDB) misc.ApplyDAOHardFork(tracingStateDB)
@ -87,8 +86,9 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated
) )
defer evm.Release() defer evm.Release()
// Run the pre-execution system calls // Run the pre-execution system calls
PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), config, evm, block.Number(), block.Time()) if err := PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), config, evm, block.Number(), block.Time()); err != nil {
return nil, err
}
// Iterate over and process the individual transactions // Iterate over and process the individual transactions
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
msg, err := TransactionToMessage(tx, signer, header.BaseFee) msg, err := TransactionToMessage(tx, signer, header.BaseFee)
@ -127,16 +127,20 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated
} }
// PreExecution processes pre-execution system calls. // PreExecution processes pre-execution system calls.
func PreExecution(ctx context.Context, beaconRoot *common.Hash, parent common.Hash, config *params.ChainConfig, evm *vm.EVM, number *big.Int, time uint64) { func PreExecution(ctx context.Context, beaconRoot *common.Hash, parent common.Hash, config *params.ChainConfig, evm *vm.EVM, number *big.Int, time uint64) error {
_, _, spanEnd := telemetry.StartSpan(ctx, "core.preExecution") _, _, spanEnd := telemetry.StartSpan(ctx, "core.preExecution")
defer spanEnd(nil) defer spanEnd(nil)
// EIP-4788
// TODO(rjl) it should be enforced if cancun is enabled
if beaconRoot != nil { if beaconRoot != nil {
ProcessBeaconBlockRoot(*beaconRoot, evm) ProcessBeaconBlockRoot(*beaconRoot, evm)
} }
// EIP-2935
if config.IsPrague(number, time) || config.IsUBT(number, time) { if config.IsPrague(number, time) || config.IsUBT(number, time) {
ProcessParentBlockHash(parent, evm) ProcessParentBlockHash(parent, evm)
} }
return nil
} }
// PostExecution processes post-execution system calls when Prague is enabled. // PostExecution processes post-execution system calls when Prague is enabled.

View file

@ -250,8 +250,10 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
defer evm.Release() defer evm.Release()
// Run pre-execution system calls // Run pre-execution system calls
core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), eth.blockchain.Config(), evm, block.Number(), block.Time()) if err := core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), eth.blockchain.Config(), evm, block.Number(), block.Time()); err != nil {
return nil, vm.BlockContext{}, nil, nil, err
}
if txIndex == 0 && len(block.Transactions()) == 0 { if txIndex == 0 && len(block.Transactions()) == 0 {
return nil, context, statedb, release, nil return nil, context, statedb, release, nil
} }

View file

@ -373,12 +373,9 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil) context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil)
evm := vm.NewEVM(context, statedb, api.backend.ChainConfig(), vm.Config{}) evm := vm.NewEVM(context, statedb, api.backend.ChainConfig(), vm.Config{})
if beaconRoot := next.BeaconRoot(); beaconRoot != nil { if err := core.PreExecution(ctx, next.BeaconRoot(), next.ParentHash(), api.backend.ChainConfig(), evm, next.Number(), next.Time()); err != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm) failed = err
} break
// Insert parent hash in history contract.
if api.backend.ChainConfig().IsPrague(next.Number(), next.Time()) {
core.ProcessParentBlockHash(next.ParentHash(), evm)
} }
evm.Release() evm.Release()
// Clean out any pending release functions of trace state. Note this // Clean out any pending release functions of trace state. Note this
@ -495,8 +492,8 @@ func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash,
return api.standardTraceBlockToFile(ctx, block, config) return api.standardTraceBlockToFile(ctx, block, config)
} }
// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list // IntermediateRoots executes a block, and returns a list of intermediate roots:
// of intermediate roots: the stateroot after each transaction. // the stateroot after each transaction.
func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) { func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
block, _ := api.blockByHash(ctx, hash) block, _ := api.blockByHash(ctx, hash)
if block == nil { if block == nil {
@ -518,20 +515,20 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
return nil, err return nil, err
} }
defer release() defer release()
var ( var (
roots []common.Hash roots []common.Hash
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
chainConfig = api.backend.ChainConfig() chainConfig = api.backend.ChainConfig()
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
deleteEmptyObjects = chainConfig.IsEIP158(block.Number()) deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
evm = vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
logs []*types.Log
) )
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
defer evm.Release() defer evm.Release()
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { // Run pre-execution system calls
core.ProcessBeaconBlockRoot(*beaconRoot, evm) if err := core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), chainConfig, evm, block.Number(), block.Time()); err != nil {
} return nil, err
if chainConfig.IsPrague(block.Number(), block.Time()) {
core.ProcessParentBlockHash(block.ParentHash(), evm)
} }
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
if err := ctx.Err(); err != nil { if err := ctx.Err(); err != nil {
@ -549,10 +546,15 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks. // N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
return roots, nil return roots, nil
} }
// calling IntermediateRoot will internally call Finalize on the state // Calling IntermediateRoot will internally call Finalize on the state
// so any modifications are written to the trie // so any modifications are written to the trie
roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects)) roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects))
logs = append(logs, statedb.GetLogs(tx.Hash(), block.NumberU64(), block.Hash(), block.Time())...)
} }
// TODO(rjl) it's a behavioral change, need to discuss with team
// Run post-execution system calls
// core.PostExecution(ctx, chainConfig, block.Number(), block.Time(), logs, evm)
// roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects))
return roots, nil return roots, nil
} }
@ -588,13 +590,11 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{}) evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{})
defer evm.Release() defer evm.Release()
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
}
if api.backend.ChainConfig().IsPrague(block.Number(), block.Time()) {
core.ProcessParentBlockHash(block.ParentHash(), evm)
}
// Run pre-execution system calls
if err := core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), api.backend.ChainConfig(), evm, block.Number(), block.Time()); err != nil {
return nil, err
}
// JS tracers have high overhead. In this case run a parallel // JS tracers have high overhead. In this case run a parallel
// process that generates states in one thread and traces txes // process that generates states in one thread and traces txes
// in separate worker threads. // in separate worker threads.
@ -761,14 +761,12 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
// Note: This copies the config, to not screw up the main config // Note: This copies the config, to not screw up the main config
chainConfig, canon = overrideConfig(chainConfig, config.Overrides) chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
} }
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{}) evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
defer evm.Release() defer evm.Release()
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm) // Run pre-execution system calls
} if err := core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), chainConfig, evm, block.Number(), block.Time()); err != nil {
if chainConfig.IsPrague(block.Number(), block.Time()) { return nil, err
core.ProcessParentBlockHash(block.ParentHash(), evm)
} }
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
// Prepare the transaction for un-traced execution // Prepare the transaction for un-traced execution
@ -796,6 +794,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
return nil, err return nil, err
} }
dumps = append(dumps, dump.Name()) dumps = append(dumps, dump.Name())
// Set up the tracer and EVM for the transaction. // Set up the tracer and EVM for the transaction.
var ( var (
writer = bufio.NewWriter(dump) writer = bufio.NewWriter(dump)

View file

@ -319,8 +319,9 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
evm.SetPrecompiles(precompiles) evm.SetPrecompiles(precompiles)
} }
// Run pre-execution system calls // Run pre-execution system calls
core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, sim.chainConfig, evm, header.Number, header.Time) if err := core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, sim.chainConfig, evm, header.Number, header.Time); err != nil {
return nil, nil, nil, err
}
var allLogs []*types.Log var allLogs []*types.Log
for i, call := range block.Calls { for i, call := range block.Calls {
// Terminate if the context is cancelled // Terminate if the context is cancelled

View file

@ -318,7 +318,9 @@ func (miner *Miner) prepareWork(ctx context.Context, genParams *generateParams,
return nil, err return nil, err
} }
// Run pre-execution system calls // Run pre-execution system calls
core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, miner.chainConfig, env.evm, header.Number, header.Time) if err := core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, miner.chainConfig, env.evm, header.Number, header.Time); err != nil {
return nil, err
}
return env, nil return env, nil
} }