Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Normalcy hardfork #676

Merged
merged 2 commits into from
Jul 1, 2024
Merged
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
19 changes: 13 additions & 6 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,20 @@ func init() {

// ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules *chain.Rules) []libcommon.Address {
if !rules.IsNormalcy {
switch {
case rules.IsForkID8Elderberry:
return PrecompiledAddressesForkID88Elderberry
case rules.IsForkID7Etrog:
return PrecompiledAddressesEtrog
case rules.IsForkID5Dragonfruit:
return PrecompiledAddressesDragonfruit
default:
return PrecompiledAddressesHomestead
}
}

switch {
case rules.IsForkID8Elderberry:
return PrecompiledAddressesForkID88Elderberry
case rules.IsForkID7Etrog:
return PrecompiledAddressesEtrog
case rules.IsForkID5Dragonfruit:
return PrecompiledAddressesDragonfruit
case rules.IsPrague:
return PrecompiledAddressesPrague
case rules.IsNapoli:
Expand Down
23 changes: 13 additions & 10 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
// deployed contract addresses (relevant after the account abstraction).
var emptyCodeHash = crypto.Keccak256Hash(nil)

func (evm *EVM) precompile_disabled(addr libcommon.Address) (PrecompiledContract, bool) {
func (evm *EVM) precompile(addr libcommon.Address) (PrecompiledContract, bool) {
var precompiles map[libcommon.Address]PrecompiledContract
switch {
case evm.chainRules.IsPrague:
Expand Down Expand Up @@ -117,7 +117,11 @@ func NewEVM(blockCtx evmtypes.BlockContext, txCtx evmtypes.TxContext, state evmt
}

// [zkevm] change
evm.interpreter = NewZKEVMInterpreter(evm, NewZkConfig(vmConfig, nil))
if evm.ChainRules().IsNormalcy {
evm.interpreter = NewEVMInterpreter(evm, vmConfig)
} else {
evm.interpreter = NewZKEVMInterpreter(evm, NewZkConfig(vmConfig, nil))
}

return evm
}
Expand Down Expand Up @@ -190,7 +194,7 @@ func (evm *EVM) call(typ OpCode, caller ContractRef, addr libcommon.Address, inp
}
}
}
p, isPrecompile := evm.precompile(addr, 0)
p, isPrecompile := evm.precompile(addr)
var code []byte
if !isPrecompile {
code = evm.intraBlockState.GetCode(addr)
Expand Down Expand Up @@ -349,25 +353,24 @@ func (c *codeAndHash) Hash() libcommon.Hash {
return c.hash
}

func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address libcommon.Address, typ OpCode, incrementNonce bool, intrinsicGas uint64) ([]byte, libcommon.Address, uint64, error) {
// hack to support zkeVM
return evm.createZkEvm(caller, codeAndHash, gas, value, address, typ, incrementNonce, intrinsicGas, false)
}

func (evm *EVM) OverlayCreate(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address libcommon.Address, typ OpCode, incrementNonce bool) ([]byte, libcommon.Address, uint64, error) {
return evm.create(caller, codeAndHash, gas, value, address, typ, incrementNonce, 0)
}

// create creates a new contract using code as deployment code.
func (evm *EVM) create_disabled(caller ContractRef, codeAndHash *codeAndHash, gasRemaining uint64, value *uint256.Int, address libcommon.Address, typ OpCode, incrementNonce bool) ([]byte, libcommon.Address, uint64, error) {
func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gasRemaining uint64, value *uint256.Int, address libcommon.Address, typ OpCode, incrementNonce bool, intrinsicGas uint64) ([]byte, libcommon.Address, uint64, error) {
if !evm.ChainRules().IsNormalcy {
return evm.createZkEvm(caller, codeAndHash, gasRemaining, value, address, typ, incrementNonce, intrinsicGas, false)
}

var ret []byte
var err error
var gasConsumption uint64
depth := evm.interpreter.Depth()

if evm.config.Debug {
if depth == 0 {
evm.config.Tracer.CaptureStart(evm, caller.Address(), address, false /* precompile */, true /* create */, codeAndHash.code, gasRemaining, value, nil)
evm.config.Tracer.CaptureStart(evm, caller.Address(), address, false /* precompile */, true /* create */, codeAndHash.code, gasRemaining+intrinsicGas, value, nil)
defer func() {
evm.config.Tracer.CaptureEnd(ret, gasConsumption, err)
}()
Expand Down
16 changes: 14 additions & 2 deletions core/vm/evm_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
)

// [zkevm] contains the list of zkevm precompiles
func (evm *EVM) precompile(addr libcommon.Address, retSize int) (PrecompiledContract_zkEvm, bool) {
func (evm *EVM) precompile_zkevm(addr libcommon.Address, retSize int) (PrecompiledContract_zkEvm, bool) {
var precompiles map[libcommon.Address]PrecompiledContract_zkEvm
switch {
case evm.chainRules.IsForkID8Elderberry:
Expand All @@ -50,6 +50,10 @@ func (evm *EVM) precompile(addr libcommon.Address, retSize int) (PrecompiledCont
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewZkEVM(blockCtx evmtypes.BlockContext, txCtx evmtypes.TxContext, state evmtypes.IntraBlockState, chainConfig *chain.Config, zkVmConfig ZkConfig) *EVM {
if chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Time).IsNormalcy {
return NewEVM(blockCtx, txCtx, state, chainConfig, zkVmConfig.Config)
}

evm :=
&EVM{
Context: blockCtx,
Expand All @@ -68,6 +72,10 @@ func NewZkEVM(blockCtx evmtypes.BlockContext, txCtx evmtypes.TxContext, state ev
}

func (evm *EVM) Deploy(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, intrinsicGas uint64) (ret []byte, contractAddr libcommon.Address, leftOverGas uint64, err error) {
if evm.ChainRules().IsNormalcy {
return evm.Create(caller, code, gas, endowment, intrinsicGas)
}

contractAddr = crypto.CreateAddress(caller.Address(), evm.intraBlockState.GetNonce(caller.Address()))
return evm.createZkEvm(caller, &codeAndHash{code: code}, gas, endowment, contractAddr, CREATE, true /* incrementNonce */, intrinsicGas, true)
}
Expand Down Expand Up @@ -226,6 +234,10 @@ func (evm *EVM) StaticCall_zkEvm(caller ContractRef, addr libcommon.Address, inp
}

func (evm *EVM) call_zkevm(typ OpCode, caller ContractRef, addr libcommon.Address, input []byte, gas uint64, value *uint256.Int, bailout bool, intrinsicGas uint64, retSize int) (ret []byte, leftOverGas uint64, err error) {
if evm.ChainRules().IsNormalcy {
return evm.call(typ, caller, addr, input, gas, value, bailout, intrinsicGas)
}

depth := evm.interpreter.Depth()

if evm.config.NoRecursion && depth > 0 {
Expand All @@ -243,7 +255,7 @@ func (evm *EVM) call_zkevm(typ OpCode, caller ContractRef, addr libcommon.Addres
}
}
}
p, isPrecompile := evm.precompile(addr, retSize)
p, isPrecompile := evm.precompile_zkevm(addr, retSize)
var code []byte
if !isPrecompile {
code = evm.intraBlockState.GetCode(addr)
Expand Down
13 changes: 12 additions & 1 deletion erigon-lib/chain/chain_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ type Config struct {
ForkID7EtrogBlock *big.Int `json:"forkID7EtrogBlock,omitempty"`
ForkID88ElderberryBlock *big.Int `json:"forkID88ElderberryBlock,omitempty"`
ForkID9Elderberry2Block *big.Int `json:"forkID9FeijoaBlock,omitempty"`
NormalcyBlock *big.Int `json:"normalcyBlock,omitempty"`

SupportGasless bool `json:"supportGasless,omitempty"`
}
Expand All @@ -124,7 +125,7 @@ type BorConfig interface {
func (c *Config) String() string {
engine := c.getEngine()

return fmt.Sprintf("{ChainID: %v, Homestead: %v, DAO: %v, Tangerine Whistle: %v, Spurious Dragon: %v, Byzantium: %v, Constantinople: %v, Petersburg: %v, Istanbul: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Gray Glacier: %v, Terminal Total Difficulty: %v, Merge Netsplit: %v, Shanghai: %v, Cancun: %v, Prague: %v, Osaka: %v, Engine: %v, NoPruneContracts: %v}",
return fmt.Sprintf("{ChainID: %v, Homestead: %v, DAO: %v, Tangerine Whistle: %v, Spurious Dragon: %v, Byzantium: %v, Constantinople: %v, Petersburg: %v, Istanbul: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Gray Glacier: %v, Terminal Total Difficulty: %v, Merge Netsplit: %v, Shanghai: %v, Cancun: %v, Prague: %v, Osaka: %v, Normalcy: %v, Engine: %v, NoPruneContracts: %v}",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional nitpick: consider using %t to format all the boolean values in the string.

c.ChainID,
c.HomesteadBlock,
c.DAOForkBlock,
Expand All @@ -145,6 +146,7 @@ func (c *Config) String() string {
c.CancunTime,
c.PragueTime,
c.OsakaTime,
c.NormalcyBlock,
engine,
c.NoPruneContracts,
)
Expand Down Expand Up @@ -326,6 +328,10 @@ func (c *Config) GetMaxBlobsPerBlock() uint64 {
return c.GetMaxBlobGasPerBlock() / fixedgas.BlobGasPerBlob
}

func (c *Config) IsNormalcy(num uint64) bool {
return isForked(c.NormalcyBlock, num)
}

func (c *Config) IsForkID4(num uint64) bool {
return isForked(c.ForkID4Block, num)
}
Expand Down Expand Up @@ -493,6 +499,9 @@ func (c *Config) checkCompatible(newcfg *Config, head uint64) *ConfigCompatError
if incompatible(c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock, head) {
return newCompatError("Merge netsplit block", c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock)
}
if incompatible(c.NormalcyBlock, newcfg.NormalcyBlock, head) {
return newCompatError("London fork block", c.NormalcyBlock, newcfg.NormalcyBlock)
}

return nil
}
Expand Down Expand Up @@ -591,6 +600,7 @@ type Rules struct {
IsCancun, IsNapoli bool
IsPrague, isOsaka bool
IsAura bool
IsNormalcy bool
IsForkID4, IsForkID5Dragonfruit, IsForkID6IncaBerry, IsForkID7Etrog, IsForkID8Elderberry bool
}

Expand All @@ -617,6 +627,7 @@ func (c *Config) Rules(num uint64, time uint64) *Rules {
IsNapoli: c.IsNapoli(num),
IsPrague: c.IsPrague(time),
isOsaka: c.IsOsaka(time),
IsNormalcy: c.IsNormalcy(num),
IsAura: c.Aura != nil,
IsForkID4: c.IsForkID4(num),
IsForkID5Dragonfruit: c.IsForkID5Dragonfruit(num),
Expand Down
Loading