mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-05 03:23:46 +00:00
cmd, consensus, core, miner: update 7997 (#35458)
https://eips.ethereum.org/EIPS/eip-7997
This commit is contained in:
parent
92a3bed7f2
commit
5131c031dd
7 changed files with 0 additions and 234 deletions
|
|
@ -242,13 +242,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
|
||||
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)
|
||||
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
|
||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm, blockAccessList)
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright 2026 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package misc
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// ApplyEIP7997 inserts the deterministic deployment factory into the state as an
|
||||
// irregular state transition, as specified by EIP-7997. The factory is a keyless
|
||||
// CREATE2 factory that, once present at the canonical address on every EVM chain,
|
||||
// allows contracts to be deployed at identical addresses across chains.
|
||||
func ApplyEIP7997(statedb vm.StateDB) {
|
||||
// The account must hold the canonical factory runtime code. If its code hash
|
||||
// already matches, the chain satisfies EIP-7997 and nothing needs to change.
|
||||
wantHash := crypto.Keccak256Hash(params.DeterministicFactoryCode)
|
||||
if statedb.GetCodeHash(params.DeterministicFactoryAddress) == wantHash {
|
||||
return
|
||||
}
|
||||
if !statedb.Exist(params.DeterministicFactoryAddress) {
|
||||
statedb.CreateAccount(params.DeterministicFactoryAddress)
|
||||
}
|
||||
statedb.CreateContract(params.DeterministicFactoryAddress)
|
||||
statedb.SetCode(params.DeterministicFactoryAddress, params.DeterministicFactoryCode, tracing.CodeChangeUnspecified)
|
||||
|
||||
// Preserve a pre-existing nonce; only bump the default zero nonce to 1.
|
||||
if statedb.GetNonce(params.DeterministicFactoryAddress) == 0 {
|
||||
statedb.SetNonce(params.DeterministicFactoryAddress, 1, tracing.NonceChangeNewContract)
|
||||
}
|
||||
}
|
||||
|
|
@ -384,12 +384,6 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
|||
if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 {
|
||||
misc.ApplyDAOHardFork(statedb)
|
||||
}
|
||||
// EIP-7997: insert the deterministic deployment factory at the Amsterdam
|
||||
// activation block via an irregular state transition.
|
||||
if config.IsAmsterdam(b.header.Number, b.header.Time) && !config.IsAmsterdam(parent.Number(), parent.Time()) {
|
||||
misc.ApplyEIP7997(statedb)
|
||||
}
|
||||
|
||||
if config.IsPrague(b.header.Number, b.header.Time) || config.IsUBT(b.header.Number, b.header.Time) {
|
||||
// EIP-2935
|
||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
||||
|
|
|
|||
|
|
@ -1,113 +0,0 @@
|
|||
// Copyright 2026 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Tests for EIP-7997: the deterministic deployment factory inserted as an
|
||||
// irregular state transition at the Amsterdam activation block.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// TestApplyEIP7997 verifies the irregular state transition seeds the factory
|
||||
// account with the canonical code and nonce.
|
||||
func TestApplyEIP7997(t *testing.T) {
|
||||
sdb := mkState(nil)
|
||||
misc.ApplyEIP7997(sdb)
|
||||
|
||||
if got := sdb.GetCode(params.DeterministicFactoryAddress); !bytes.Equal(got, params.DeterministicFactoryCode) {
|
||||
t.Fatalf("factory code mismatch:\n got %x\nwant %x", got, params.DeterministicFactoryCode)
|
||||
}
|
||||
if got := sdb.GetNonce(params.DeterministicFactoryAddress); got != 1 {
|
||||
t.Fatalf("factory nonce = %d, want %d", got, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// TestApplyEIP7997Existing checks that a chain which already hosts the factory
|
||||
// (for example via its keyless creation transaction) is left untouched, so the
|
||||
// transition never rewrites an existing nonce.
|
||||
func TestApplyEIP7997Existing(t *testing.T) {
|
||||
sdb := mkState(types.GenesisAlloc{
|
||||
params.DeterministicFactoryAddress: {Code: params.DeterministicFactoryCode, Nonce: 5},
|
||||
})
|
||||
misc.ApplyEIP7997(sdb)
|
||||
|
||||
if got := sdb.GetNonce(params.DeterministicFactoryAddress); got != 5 {
|
||||
t.Fatalf("existing factory nonce overwritten: got %d, want 5", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestApplyEIP7997WrongCode checks that an account occupying the factory address
|
||||
// with the wrong code is force-overwritten with the canonical runtime code, while
|
||||
// a pre-existing non-zero nonce is preserved.
|
||||
func TestApplyEIP7997WrongCode(t *testing.T) {
|
||||
sdb := mkState(types.GenesisAlloc{
|
||||
params.DeterministicFactoryAddress: {Code: []byte{0x60, 0x00}, Nonce: 7},
|
||||
})
|
||||
misc.ApplyEIP7997(sdb)
|
||||
|
||||
if got := sdb.GetCode(params.DeterministicFactoryAddress); !bytes.Equal(got, params.DeterministicFactoryCode) {
|
||||
t.Fatalf("factory code not overwritten:\n got %x\nwant %x", got, params.DeterministicFactoryCode)
|
||||
}
|
||||
if got := sdb.GetNonce(params.DeterministicFactoryAddress); got != 7 {
|
||||
t.Fatalf("factory nonce = %d, want %d (existing nonce must be preserved)", got, 7)
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP7997FactoryDeploys exercises the inserted factory bytecode: calling it
|
||||
// with a salt followed by init code must CREATE2-deploy the contract at the
|
||||
// canonical deterministic address and return that address (20 bytes, unpadded).
|
||||
func TestEIP7997FactoryDeploys(t *testing.T) {
|
||||
sdb := mkState(nil)
|
||||
misc.ApplyEIP7997(sdb)
|
||||
|
||||
var (
|
||||
caller = common.Address{0xca}
|
||||
salt [32]byte
|
||||
// initcode returning the single-byte runtime 0xfe:
|
||||
// PUSH1 0xfe PUSH1 0x00 MSTORE8 PUSH1 0x01 PUSH1 0x00 RETURN
|
||||
initcode = common.FromHex("60fe60005360016000f3")
|
||||
)
|
||||
salt[31] = 0x42
|
||||
|
||||
input := append(append([]byte{}, salt[:]...), initcode...)
|
||||
|
||||
ret, _, err := amsterdamCoreEVM(sdb).Call(caller, params.DeterministicFactoryAddress, input, vm.NewGasBudget(10_000_000, 0), new(uint256.Int))
|
||||
if err != nil {
|
||||
t.Fatalf("factory call failed: %v", err)
|
||||
}
|
||||
|
||||
want := crypto.CreateAddress2(params.DeterministicFactoryAddress, salt, crypto.Keccak256(initcode))
|
||||
if len(ret) != 20 {
|
||||
t.Fatalf("factory returned %d bytes, want 20", len(ret))
|
||||
}
|
||||
if got := common.BytesToAddress(ret); got != want {
|
||||
t.Fatalf("factory returned address %x, want %x", got, want)
|
||||
}
|
||||
if code := sdb.GetCode(want); !bytes.Equal(code, []byte{0xfe}) {
|
||||
t.Fatalf("deployed runtime code = %x, want fe", code)
|
||||
}
|
||||
}
|
||||
|
|
@ -160,12 +160,6 @@ func PreExecution(ctx context.Context, beaconRoot *common.Hash, parent *types.He
|
|||
var blockAccessList *bal.ConstructionBlockAccessList
|
||||
if config.IsAmsterdam(number, time) {
|
||||
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
|
||||
if beaconRoot != nil {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package miner
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"math/big"
|
||||
"reflect"
|
||||
|
|
@ -197,58 +196,6 @@ 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) {
|
||||
t.Parallel()
|
||||
ids := make(map[string]int)
|
||||
|
|
|
|||
|
|
@ -276,6 +276,4 @@ var (
|
|||
var (
|
||||
// EIP-7708 - System logs emitted for ETH transfer and burn
|
||||
EthTransferLogEvent = common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") // keccak256('Transfer(address,address,uint256)')
|
||||
EthBurnLogEvent = common.HexToHash("0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5") // keccak256('Burn(address,uint256)')
|
||||
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue