Skip to content

Commit

Permalink
Merge pull request #472 from XinFinOrg/eip3855
Browse files Browse the repository at this point in the history
core/vm: implement EIP-3855: PUSH0 instruction.
  • Loading branch information
gzliudan authored Mar 7, 2024
2 parents ae10d70 + 863d4f1 commit 6a2f753
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 68 deletions.
1 change: 1 addition & 0 deletions common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions common/constants/constants.go.devnet
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions common/constants/constants.go.testnet
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
80 changes: 32 additions & 48 deletions core/asm/asm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,53 +22,37 @@ import (
"encoding/hex"
)

// Tests disassembling the instructions for valid evm code
func TestInstructionIteratorValid(t *testing.T) {
cnt := 0
script, _ := hex.DecodeString("61000000")

it := NewInstructionIterator(script)
for it.Next() {
cnt++
}

if err := it.Error(); err != nil {
t.Errorf("Expected 2, but encountered error %v instead.", err)
}
if cnt != 2 {
t.Errorf("Expected 2, but got %v instead.", cnt)
}
}

// Tests disassembling the instructions for invalid evm code
func TestInstructionIteratorInvalid(t *testing.T) {
cnt := 0
script, _ := hex.DecodeString("6100")

it := NewInstructionIterator(script)
for it.Next() {
cnt++
}

if it.Error() == nil {
t.Errorf("Expected an error, but got %v instead.", cnt)
}
}

// Tests disassembling the instructions for empty evm code
func TestInstructionIteratorEmpty(t *testing.T) {
cnt := 0
script, _ := hex.DecodeString("")

it := NewInstructionIterator(script)
for it.Next() {
cnt++
}

if err := it.Error(); err != nil {
t.Errorf("Expected 0, but encountered error %v instead.", err)
}
if cnt != 0 {
t.Errorf("Expected 0, but got %v instead.", cnt)
// Tests disassembling instructions
func TestInstructionIterator(t *testing.T) {
for i, tc := range []struct {
want int
code string
wantErr string
}{
{2, "61000000", ""}, // valid code
{0, "6100", "incomplete push instruction at 0"}, // invalid code
{2, "5900", ""}, // push0
{0, "", ""}, // empty

} {
var (
have int
code, _ = hex.DecodeString(tc.code)
it = NewInstructionIterator(code)
)
for it.Next() {
have++
}
var haveErr = ""
if it.Error() != nil {
haveErr = it.Error().Error()
}
if haveErr != tc.wantErr {
t.Errorf("test %d: encountered error: %q want %q", i, haveErr, tc.wantErr)
continue
}
if have != tc.want {
t.Errorf("wrong instruction count, have %d want %d", have, tc.want)
}
}
}
21 changes: 20 additions & 1 deletion core/vm/eips.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ import (
// defined jump tables are not polluted.
func EnableEIP(eipNum int, jt *JumpTable) error {
switch eipNum {
case 3898:
case 3855:
enable3855(jt)
case 3198:
enable3198(jt)
case 2200:
enable2200(jt)
Expand Down Expand Up @@ -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
}
2 changes: 2 additions & 0 deletions core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
7 changes: 7 additions & 0 deletions core/vm/jump_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
33 changes: 16 additions & 17 deletions core/vm/opcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ type OpCode byte

// IsPush specifies if an opcode is a PUSH opcode.
func (op OpCode) IsPush() bool {
switch op {
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
return true
}
return false
return PUSH0 <= op && op <= PUSH32
}

// 0x0 range - arithmetic ops.
Expand Down Expand Up @@ -108,18 +104,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.
Expand Down Expand Up @@ -300,6 +297,7 @@ var opCodeToString = [256]string{
MSIZE: "MSIZE",
GAS: "GAS",
JUMPDEST: "JUMPDEST",
PUSH0: "PUSH0",

// 0x60 range - push.
PUSH1: "PUSH1",
Expand Down Expand Up @@ -462,6 +460,7 @@ var stringToOp = map[string]OpCode{
"MSIZE": MSIZE,
"GAS": GAS,
"JUMPDEST": JUMPDEST,
"PUSH0": PUSH0,
"PUSH1": PUSH1,
"PUSH2": PUSH2,
"PUSH3": PUSH3,
Expand Down
11 changes: 9 additions & 2 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -512,6 +512,7 @@ func (c *ChainConfig) String() string {
common.BerlinBlock,
common.LondonBlock,
common.MergeBlock,
common.ShanghaiBlock,
engine,
)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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),
}
}

0 comments on commit 6a2f753

Please sign in to comment.