core/vm: implement EIP-3855: PUSH0 instruction.

This commit is contained in:
geruiwang 2024-03-07 21:44:37 +08:00
parent 0e36b5be42
commit 968440ce3d
8 changed files with 55 additions and 14 deletions

View file

@ -49,6 +49,7 @@ var TIPXDCXDISABLE = big.NewInt(99999999900)
var BerlinBlock = big.NewInt(9999999999)
var LondonBlock = big.NewInt(9999999999)
var MergeBlock = big.NewInt(9999999999)
var ShanghaiBlock = big.NewInt(9999999999)
var TIPXDCXTestnet = big.NewInt(38383838)
var IsTestnet bool = false

View file

@ -49,6 +49,7 @@ var TIPXDCXDISABLE = big.NewInt(15894900)
var BerlinBlock = big.NewInt(9999999999)
var LondonBlock = big.NewInt(9999999999)
var MergeBlock = big.NewInt(9999999999)
var ShanghaiBlock = big.NewInt(9999999999)
var TIPXDCXTestnet = big.NewInt(0)
var IsTestnet bool = false

View file

@ -49,6 +49,7 @@ var TIPXDCXDISABLE = big.NewInt(99999999900)
var BerlinBlock = big.NewInt(9999999999)
var LondonBlock = big.NewInt(9999999999)
var MergeBlock = big.NewInt(9999999999)
var ShanghaiBlock = big.NewInt(9999999999)
var TIPXDCXTestnet = big.NewInt(23779191)
var IsTestnet bool = false

View file

@ -29,6 +29,8 @@ import (
// defined jump tables are not polluted.
func EnableEIP(eipNum int, jt *JumpTable) error {
switch eipNum {
case 3855:
enable3855(jt)
case 3198:
enable3198(jt)
case 2200:
@ -112,3 +114,20 @@ func opBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([
callContext.stack.push(baseFee)
return nil, nil
}
// enable3855 applies EIP-3855 (PUSH0 opcode)
func enable3855(jt *JumpTable) {
// New opcode
jt[PUSH0] = &operation{
execute: opPush0,
constantGas: GasQuickStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
}
}
// opPush0 implements the PUSH0 opcode
func opPush0(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
callContext.stack.push(new(uint256.Int))
return nil, nil
}

View file

@ -93,6 +93,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
// If jump table was not initialised we set the default one.
if cfg.JumpTable == nil {
switch {
case evm.chainRules.IsShanghai:
cfg.JumpTable = &shanghaiInstructionSet
case evm.chainRules.IsMerge:
cfg.JumpTable = &mergeInstructionSet
case evm.chainRules.IsLondon:

View file

@ -53,11 +53,18 @@ var (
berlinInstructionSet = newBerlinInstructionSet()
londonInstructionSet = newLondonInstructionSet()
mergeInstructionSet = newMergeInstructionSet()
shanghaiInstructionSet = newShanghaiInstructionSet()
)
// JumpTable contains the EVM opcodes supported at a given fork.
type JumpTable [256]*operation
func newShanghaiInstructionSet() JumpTable {
instructionSet := newMergeInstructionSet()
enable3855(&instructionSet) // PUSH0 instruction
return instructionSet
}
func newMergeInstructionSet() JumpTable {
instructionSet := newLondonInstructionSet()
instructionSet[PREVRANDAO] = &operation{

View file

@ -108,18 +108,19 @@ const (
// 0x50 range - 'storage' and execution.
const (
POP OpCode = 0x50 + iota
MLOAD
MSTORE
MSTORE8
SLOAD
SSTORE
JUMP
JUMPI
PC
MSIZE
GAS
JUMPDEST
POP OpCode = 0x50
MLOAD OpCode = 0x51
MSTORE OpCode = 0x52
MSTORE8 OpCode = 0x53
SLOAD OpCode = 0x54
SSTORE OpCode = 0x55
JUMP OpCode = 0x56
JUMPI OpCode = 0x57
PC OpCode = 0x58
MSIZE OpCode = 0x59
GAS OpCode = 0x5a
JUMPDEST OpCode = 0x5b
PUSH0 OpCode = 0x5f
)
// 0x60 range - pushes.
@ -300,6 +301,7 @@ var opCodeToString = [256]string{
MSIZE: "MSIZE",
GAS: "GAS",
JUMPDEST: "JUMPDEST",
PUSH0: "PUSH0",
// 0x60 range - push.
PUSH1: "PUSH1",
@ -462,6 +464,7 @@ var stringToOp = map[string]OpCode{
"MSIZE": MSIZE,
"GAS": GAS,
"JUMPDEST": JUMPDEST,
"PUSH0": PUSH0,
"PUSH1": PUSH1,
"PUSH2": PUSH2,
"PUSH3": PUSH3,

View file

@ -498,7 +498,7 @@ func (c *ChainConfig) String() string {
default:
engine = "unknown"
}
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Istanbul: %v BerlinBlock: %v LondonBlock: %v MergeBlock: %v Engine: %v}",
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Istanbul: %v BerlinBlock: %v LondonBlock: %v MergeBlock: %v ShanghaiBlock: %v Engine: %v}",
c.ChainId,
c.HomesteadBlock,
c.DAOForkBlock,
@ -512,6 +512,7 @@ func (c *ChainConfig) String() string {
common.BerlinBlock,
common.LondonBlock,
common.MergeBlock,
common.ShanghaiBlock,
engine,
)
}
@ -574,6 +575,11 @@ func (c *ChainConfig) IsMerge(num *big.Int) bool {
return isForked(common.MergeBlock, num)
}
// IsShanghai returns whether num is either equal to the Shanghai fork block or greater.
func (c *ChainConfig) IsShanghai(num *big.Int) bool {
return isForked(common.ShanghaiBlock, num)
}
func (c *ChainConfig) IsTIP2019(num *big.Int) bool {
return isForked(common.TIP2019Block, num)
}
@ -742,7 +748,7 @@ type Rules struct {
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
IsBerlin, IsLondon bool
IsMerge bool
IsMerge, IsShanghai bool
}
func (c *ChainConfig) Rules(num *big.Int) Rules {
@ -763,5 +769,6 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
IsBerlin: c.IsBerlin(num),
IsLondon: c.IsLondon(num),
IsMerge: c.IsMerge(num),
IsShanghai: c.IsShanghai(num),
}
}