Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 }