Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine,
bc.statedb = state.NewDatabase(bc.triedb, nil)
bc.validator = NewBlockValidator(chainConfig, bc)
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
bc.processor = NewStateProcessor(chainConfig, bc.hc)
bc.processor = NewStateProcessor(bc.hc)

genesisHeader := bc.GetHeaderByNumber(0)
if genesisHeader == nil {
Expand Down
9 changes: 2 additions & 7 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,16 @@ import (
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)

// ChainContext supports retrieving headers and consensus parameters from the
// current blockchain to be used during transaction processing.
type ChainContext interface {
consensus.ChainHeaderReader

// Engine retrieves the chain's consensus engine.
Engine() consensus.Engine

// GetHeader returns the header corresponding to the hash/number argument pair.
GetHeader(common.Hash, uint64) *types.Header

// Config returns the chain's configuration.
Config() *params.ChainConfig
}

// NewEVMBlockContext creates a new context for use in the EVM.
Expand Down
27 changes: 15 additions & 12 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,21 @@ import (
//
// StateProcessor implements Processor.
type StateProcessor struct {
config *params.ChainConfig // Chain configuration options
chain *HeaderChain // Canonical header chain
chain ChainContext // Chain context interface
}

// NewStateProcessor initialises a new StateProcessor.
func NewStateProcessor(config *params.ChainConfig, chain *HeaderChain) *StateProcessor {
func NewStateProcessor(chain ChainContext) *StateProcessor {
return &StateProcessor{
config: config,
chain: chain,
chain: chain,
}
}

// chainConfig returns the chain configuration.
func (p *StateProcessor) chainConfig() *params.ChainConfig {
return p.chain.Config()
}

// Process processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb and applying any rewards to both
// the processor (coinbase) and any included uncles.
Expand All @@ -66,12 +69,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
)

// Mutate the block and state according to any hard-fork specs
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
if p.chainConfig().DAOForkSupport && p.chainConfig().DAOForkBlock != nil && p.chainConfig().DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb)
}
var (
context vm.BlockContext
signer = types.MakeSigner(p.config, header.Number, header.Time)
signer = types.MakeSigner(p.chainConfig(), header.Number, header.Time)
)

// Apply pre-execution system calls.
Expand All @@ -80,12 +83,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
tracingStateDB = state.NewHookedState(statedb, hooks)
}
context = NewEVMBlockContext(header, p.chain, nil)
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
evm := vm.NewEVM(context, tracingStateDB, p.chainConfig(), cfg)

if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
ProcessBeaconBlockRoot(*beaconRoot, evm)
}
if p.config.IsPrague(block.Number(), block.Time()) || p.config.IsVerkle(block.Number(), block.Time()) {
if p.chainConfig().IsPrague(block.Number(), block.Time()) || p.chainConfig().IsVerkle(block.Number(), block.Time()) {
ProcessParentBlockHash(block.ParentHash(), evm)
}

Expand All @@ -106,10 +109,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
}
// Read requests if Prague is enabled.
var requests [][]byte
if p.config.IsPrague(block.Number(), block.Time()) {
if p.chainConfig().IsPrague(block.Number(), block.Time()) {
requests = [][]byte{}
// EIP-6110
if err := ParseDepositLogs(&requests, allLogs, p.config); err != nil {
if err := ParseDepositLogs(&requests, allLogs, p.chainConfig()); err != nil {
return nil, fmt.Errorf("failed to parse deposit logs: %w", err)
}
// EIP-7002
Expand All @@ -123,7 +126,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
}

// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.chain.engine.Finalize(p.chain, header, tracingStateDB, block.Body())
p.chain.Engine().Finalize(p.chain, header, tracingStateDB, block.Body())

return &ProcessResult{
Receipts: receipts,
Expand Down
2 changes: 1 addition & 1 deletion core/stateless.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func ExecuteStateless(config *params.ChainConfig, vmconfig vm.Config, block *typ
headerCache: lru.NewCache[common.Hash, *types.Header](256),
engine: beacon.New(ethash.NewFaker()),
}
processor := NewStateProcessor(config, chain)
processor := NewStateProcessor(chain)
validator := NewBlockValidator(config, nil) // No chain, we only validate the state, not the block

// Run the stateless blocks processing and self-validate certain fields
Expand Down
12 changes: 12 additions & 0 deletions core/vm/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,18 @@ func (d *dummyChain) Config() *params.ChainConfig {
return nil
}

func (d *dummyChain) CurrentHeader() *types.Header {
return nil
}

func (d *dummyChain) GetHeaderByNumber(n uint64) *types.Header {
return d.GetHeader(common.Hash{}, n)
}

func (d *dummyChain) GetHeaderByHash(h common.Hash) *types.Header {
return nil
}

// TestBlockhash tests the blockhash operation. It's a bit special, since it internally
// requires access to a chain reader.
func TestBlockhash(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type StateReleaseFunc func()
type Backend interface {
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
CurrentHeader() *types.Header
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64)
Expand Down
4 changes: 4 additions & 0 deletions eth/tracers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ func (b *testBackend) ChainDb() ethdb.Database {
return b.chaindb
}

func (b *testBackend) CurrentHeader() *types.Header {
return b.chain.CurrentHeader()
}

// teardown releases the associated resources.
func (b *testBackend) teardown() {
b.chain.Stop()
Expand Down
16 changes: 16 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,8 @@ func (api *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rp
type ChainContextBackend interface {
Engine() consensus.Engine
HeaderByNumber(context.Context, rpc.BlockNumber) (*types.Header, error)
HeaderByHash(context.Context, common.Hash) (*types.Header, error)
CurrentHeader() *types.Header
ChainConfig() *params.ChainConfig
}

Expand Down Expand Up @@ -669,6 +671,20 @@ func (context *ChainContext) Config() *params.ChainConfig {
return context.b.ChainConfig()
}

func (context *ChainContext) CurrentHeader() *types.Header {
return context.b.CurrentHeader()
}

func (context *ChainContext) GetHeaderByNumber(number uint64) *types.Header {
header, _ := context.b.HeaderByNumber(context.ctx, rpc.BlockNumber(number))
return header
}

func (context *ChainContext) GetHeaderByHash(hash common.Hash) *types.Header {
header, _ := context.b.HeaderByHash(context.ctx, hash)
return header
}

func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *override.StateOverride, blockOverrides *override.BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
if blockOverrides != nil {
Expand Down
20 changes: 20 additions & 0 deletions internal/ethapi/simulate.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,3 +541,23 @@ func (b *simBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber)
func (b *simBackend) ChainConfig() *params.ChainConfig {
return b.b.ChainConfig()
}

func (b *simBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
if b.base.Hash() == hash {
return b.base, nil
}
if header, err := b.b.HeaderByHash(ctx, hash); err == nil {
return header, nil
}
// Check simulated headers
for _, header := range b.headers {
if header.Hash() == hash {
return header, nil
}
}
return nil, errors.New("header not found")
}

func (b *simBackend) CurrentHeader() *types.Header {
return b.b.CurrentHeader()
}
3 changes: 3 additions & 0 deletions tests/state_test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,3 +559,6 @@ type dummyChain struct {
func (d *dummyChain) Engine() consensus.Engine { return nil }
func (d *dummyChain) GetHeader(h common.Hash, n uint64) *types.Header { return nil }
func (d *dummyChain) Config() *params.ChainConfig { return d.config }
func (d *dummyChain) CurrentHeader() *types.Header { return nil }
func (d *dummyChain) GetHeaderByNumber(n uint64) *types.Header { return nil }
func (d *dummyChain) GetHeaderByHash(h common.Hash) *types.Header { return nil }