mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 02:10:46 +00:00
cmd, core, eth, miner: apply 7997 in block building (#35285)
This PR applies the 7997 irregular state transition in t8n, block building, simulation and tracing.
This commit is contained in:
parent
cf35a1b6f6
commit
4d2181aa41
7 changed files with 82 additions and 28 deletions
|
|
@ -242,6 +242,13 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
|
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
}
|
}
|
||||||
|
// EIP-7997: insert the deterministic deployment factory at the Amsterdam
|
||||||
|
// activation block via an irregular state transition.
|
||||||
|
if pre.Env.Number > 0 &&
|
||||||
|
chainConfig.IsAmsterdam(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) &&
|
||||||
|
!chainConfig.IsAmsterdam(new(big.Int).SetUint64(pre.Env.Number-1), pre.Env.ParentTimestamp) {
|
||||||
|
misc.ApplyEIP7997(statedb)
|
||||||
|
}
|
||||||
evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig)
|
evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig)
|
||||||
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
|
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm, blockAccessList)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, blockAccessList)
|
||||||
|
|
|
||||||
|
|
@ -81,10 +81,9 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated
|
||||||
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)
|
||||||
}
|
}
|
||||||
// EIP-7997: insert the deterministic deployment factory at the Amsterdam
|
parent := p.chain.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
||||||
// activation block via an irregular state transition.
|
if parent == nil {
|
||||||
if isEIP7997Transition(config, p.chain, header) {
|
return nil, fmt.Errorf("missing parent %#x", block.ParentHash())
|
||||||
misc.ApplyEIP7997(tracingStateDB)
|
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
context = NewEVMBlockContext(header, p.chain, nil)
|
context = NewEVMBlockContext(header, p.chain, nil)
|
||||||
|
|
@ -98,7 +97,7 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated
|
||||||
evm.SetJumpDestCache(jumpDestCache)
|
evm.SetJumpDestCache(jumpDestCache)
|
||||||
}
|
}
|
||||||
// Run the pre-execution system calls
|
// Run the pre-execution system calls
|
||||||
blockAccessList.Merge(PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), config, evm, block.Number(), block.Time()))
|
blockAccessList.Merge(PreExecution(ctx, block.BeaconRoot(), parent, config, evm, block.Number(), block.Time()))
|
||||||
|
|
||||||
// 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() {
|
||||||
|
|
@ -142,27 +141,20 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isEIP7997Transition reports whether the given header belongs to the first block
|
// PreExecution processes pre-execution state changes and system calls.
|
||||||
// on which the Amsterdam fork is active.
|
func PreExecution(ctx context.Context, beaconRoot *common.Hash, parent *types.Header, config *params.ChainConfig, evm *vm.EVM, number *big.Int, time uint64) *bal.ConstructionBlockAccessList {
|
||||||
func isEIP7997Transition(config *params.ChainConfig, chain ChainContext, header *types.Header) bool {
|
|
||||||
if header.Number.Sign() == 0 || !config.IsAmsterdam(header.Number, header.Time) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
|
|
||||||
if parent == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return !config.IsAmsterdam(parent.Number, parent.Time)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) *bal.ConstructionBlockAccessList {
|
|
||||||
_, _, spanEnd := telemetry.StartSpan(ctx, "core.preExecution")
|
_, _, spanEnd := telemetry.StartSpan(ctx, "core.preExecution")
|
||||||
defer spanEnd(nil)
|
defer spanEnd(nil)
|
||||||
|
|
||||||
var blockAccessList *bal.ConstructionBlockAccessList
|
var blockAccessList *bal.ConstructionBlockAccessList
|
||||||
if config.IsAmsterdam(number, time) {
|
if config.IsAmsterdam(number, time) {
|
||||||
blockAccessList = bal.NewConstructionBlockAccessList()
|
blockAccessList = bal.NewConstructionBlockAccessList()
|
||||||
|
|
||||||
|
// EIP-7997: insert the deterministic deployment factory at the Amsterdam
|
||||||
|
// activation block via an irregular state transition.
|
||||||
|
if !config.IsAmsterdam(parent.Number, parent.Time) {
|
||||||
|
misc.ApplyEIP7997(evm.StateDB)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// EIP-4788
|
// EIP-4788
|
||||||
if beaconRoot != nil {
|
if beaconRoot != nil {
|
||||||
|
|
@ -170,7 +162,7 @@ func PreExecution(ctx context.Context, beaconRoot *common.Hash, parent common.Ha
|
||||||
}
|
}
|
||||||
// EIP-2935
|
// EIP-2935
|
||||||
if config.IsPrague(number, time) || config.IsUBT(number, time) {
|
if config.IsPrague(number, time) || config.IsUBT(number, time) {
|
||||||
ProcessParentBlockHash(parent, evm, blockAccessList)
|
ProcessParentBlockHash(parent.Hash(), evm, blockAccessList)
|
||||||
}
|
}
|
||||||
return blockAccessList
|
return blockAccessList
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ 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())
|
core.PreExecution(ctx, block.BeaconRoot(), parent.Header(), eth.blockchain.Config(), evm, block.Number(), block.Time())
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -373,7 +373,7 @@ 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{})
|
||||||
|
|
||||||
core.PreExecution(ctx, next.BeaconRoot(), next.ParentHash(), api.backend.ChainConfig(), evm, next.Number(), next.Time())
|
core.PreExecution(ctx, next.BeaconRoot(), block.Header(), api.backend.ChainConfig(), evm, next.Number(), next.Time())
|
||||||
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
|
||||||
// step must be done after constructing tracing state, because the
|
// step must be done after constructing tracing state, because the
|
||||||
|
|
@ -523,7 +523,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
)
|
)
|
||||||
defer evm.Release()
|
defer evm.Release()
|
||||||
// Run pre-execution system calls
|
// Run pre-execution system calls
|
||||||
core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), chainConfig, evm, block.Number(), block.Time())
|
core.PreExecution(ctx, block.BeaconRoot(), parent.Header(), chainConfig, evm, block.Number(), block.Time())
|
||||||
|
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
|
|
@ -582,7 +582,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
defer evm.Release()
|
defer evm.Release()
|
||||||
|
|
||||||
// Run pre-execution system calls
|
// Run pre-execution system calls
|
||||||
core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), api.backend.ChainConfig(), evm, block.Number(), block.Time())
|
core.PreExecution(ctx, block.BeaconRoot(), parent.Header(), api.backend.ChainConfig(), evm, block.Number(), block.Time())
|
||||||
|
|
||||||
// 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
|
||||||
|
|
@ -754,7 +754,7 @@ func (api *API) standardTraceBlockToFile(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(), chainConfig, evm, block.Number(), block.Time())
|
core.PreExecution(ctx, block.BeaconRoot(), parent.Header(), chainConfig, evm, block.Number(), block.Time())
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -322,7 +322,7 @@ 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
|
||||||
blockAccessList.Merge(core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, sim.chainConfig, evm, header.Number, header.Time))
|
blockAccessList.Merge(core.PreExecution(ctx, header.ParentBeaconRoot, parent, sim.chainConfig, evm, header.Number, header.Time))
|
||||||
|
|
||||||
var allLogs []*types.Log
|
var allLogs []*types.Log
|
||||||
for i, call := range block.Calls {
|
for i, call := range block.Calls {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package miner
|
package miner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
@ -26,6 +27,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/beacon/engine"
|
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||||
"github.com/ethereum/go-ethereum/consensus/clique"
|
"github.com/ethereum/go-ethereum/consensus/clique"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
|
@ -115,6 +117,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
|
||||||
copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes())
|
copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes())
|
||||||
e.Authorize(testBankAddress)
|
e.Authorize(testBankAddress)
|
||||||
case *ethash.Ethash:
|
case *ethash.Ethash:
|
||||||
|
case *beacon.Beacon:
|
||||||
default:
|
default:
|
||||||
t.Fatalf("unexpected consensus engine type: %T", engine)
|
t.Fatalf("unexpected consensus engine type: %T", engine)
|
||||||
}
|
}
|
||||||
|
|
@ -194,6 +197,58 @@ func TestBuildPayload(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestBuildPayloadAmsterdamTransition verifies that a locally built payload for
|
||||||
|
// the first Amsterdam block contains the EIP-7997 deterministic deployment
|
||||||
|
// factory, i.e. the block-building path applies the same irregular state
|
||||||
|
// transition as block processing and the resulting block is importable.
|
||||||
|
func TestBuildPayloadAmsterdamTransition(t *testing.T) {
|
||||||
|
var (
|
||||||
|
db = rawdb.NewMemoryDatabase()
|
||||||
|
recipient = common.HexToAddress("0xdeadbeef")
|
||||||
|
)
|
||||||
|
config := new(params.ChainConfig)
|
||||||
|
*config = *params.MergedTestChainConfig
|
||||||
|
config.AmsterdamTime = new(uint64)
|
||||||
|
*config.AmsterdamTime = 1 // genesis (t=0) is pre-Amsterdam, the first block crosses the fork
|
||||||
|
|
||||||
|
w, b := newTestWorker(t, config, beacon.New(ethash.NewFaker()), db, 0)
|
||||||
|
|
||||||
|
var (
|
||||||
|
beaconRoot = common.Hash{0x01}
|
||||||
|
slotNum = uint64(1)
|
||||||
|
)
|
||||||
|
payload, err := w.buildPayload(context.Background(), &BuildPayloadArgs{
|
||||||
|
Parent: b.chain.CurrentBlock().Hash(),
|
||||||
|
Timestamp: 1,
|
||||||
|
FeeRecipient: recipient,
|
||||||
|
Withdrawals: types.Withdrawals{},
|
||||||
|
BeaconRoot: &beaconRoot,
|
||||||
|
SlotNum: &slotNum,
|
||||||
|
}, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to build payload %v", err)
|
||||||
|
}
|
||||||
|
block := payload.empty
|
||||||
|
if !config.IsAmsterdam(block.Number(), block.Time()) {
|
||||||
|
t.Fatal("transition block is not an Amsterdam block")
|
||||||
|
}
|
||||||
|
// The block must be importable: Process applies EIP-7997 independently, so
|
||||||
|
// a payload built without the factory would fail the state root check here.
|
||||||
|
if _, err := b.chain.InsertChain(types.Blocks{block}); err != nil {
|
||||||
|
t.Fatalf("failed to insert transition block: %v", err)
|
||||||
|
}
|
||||||
|
statedb, err := b.chain.StateAt(block.Header())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to open state at transition block: %v", err)
|
||||||
|
}
|
||||||
|
if code := statedb.GetCode(params.DeterministicFactoryAddress); !bytes.Equal(code, params.DeterministicFactoryCode) {
|
||||||
|
t.Fatalf("factory code missing from built payload state:\n got %x\nwant %x", code, params.DeterministicFactoryCode)
|
||||||
|
}
|
||||||
|
if nonce := statedb.GetNonce(params.DeterministicFactoryAddress); nonce != 1 {
|
||||||
|
t.Fatalf("factory nonce = %d, want 1", nonce)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPayloadId(t *testing.T) {
|
func TestPayloadId(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
ids := make(map[string]int)
|
ids := make(map[string]int)
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,7 @@ 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
|
||||||
env.bal.Merge(core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, miner.chainConfig, env.evm, header.Number, header.Time))
|
env.bal.Merge(core.PreExecution(ctx, header.ParentBeaconRoot, parent, miner.chainConfig, env.evm, header.Number, header.Time))
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue