mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 02:10:46 +00:00
Merge pull request #472 from XinFinOrg/eip3855
core/vm: implement EIP-3855: PUSH0 instruction.
This commit is contained in:
commit
6a2f753cee
9 changed files with 88 additions and 67 deletions
|
|
@ -49,6 +49,7 @@ var TIPXDCXDISABLE = big.NewInt(99999999900)
|
||||||
var BerlinBlock = big.NewInt(9999999999)
|
var BerlinBlock = big.NewInt(9999999999)
|
||||||
var LondonBlock = big.NewInt(9999999999)
|
var LondonBlock = big.NewInt(9999999999)
|
||||||
var MergeBlock = big.NewInt(9999999999)
|
var MergeBlock = big.NewInt(9999999999)
|
||||||
|
var ShanghaiBlock = big.NewInt(9999999999)
|
||||||
|
|
||||||
var TIPXDCXTestnet = big.NewInt(38383838)
|
var TIPXDCXTestnet = big.NewInt(38383838)
|
||||||
var IsTestnet bool = false
|
var IsTestnet bool = false
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ var TIPXDCXDISABLE = big.NewInt(15894900)
|
||||||
var BerlinBlock = big.NewInt(9999999999)
|
var BerlinBlock = big.NewInt(9999999999)
|
||||||
var LondonBlock = big.NewInt(9999999999)
|
var LondonBlock = big.NewInt(9999999999)
|
||||||
var MergeBlock = big.NewInt(9999999999)
|
var MergeBlock = big.NewInt(9999999999)
|
||||||
|
var ShanghaiBlock = big.NewInt(9999999999)
|
||||||
|
|
||||||
var TIPXDCXTestnet = big.NewInt(0)
|
var TIPXDCXTestnet = big.NewInt(0)
|
||||||
var IsTestnet bool = false
|
var IsTestnet bool = false
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ var TIPXDCXDISABLE = big.NewInt(99999999900)
|
||||||
var BerlinBlock = big.NewInt(9999999999)
|
var BerlinBlock = big.NewInt(9999999999)
|
||||||
var LondonBlock = big.NewInt(9999999999)
|
var LondonBlock = big.NewInt(9999999999)
|
||||||
var MergeBlock = big.NewInt(9999999999)
|
var MergeBlock = big.NewInt(9999999999)
|
||||||
|
var ShanghaiBlock = big.NewInt(9999999999)
|
||||||
|
|
||||||
var TIPXDCXTestnet = big.NewInt(23779191)
|
var TIPXDCXTestnet = big.NewInt(23779191)
|
||||||
var IsTestnet bool = false
|
var IsTestnet bool = false
|
||||||
|
|
|
||||||
|
|
@ -22,53 +22,37 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tests disassembling the instructions for valid evm code
|
// Tests disassembling instructions
|
||||||
func TestInstructionIteratorValid(t *testing.T) {
|
func TestInstructionIterator(t *testing.T) {
|
||||||
cnt := 0
|
for i, tc := range []struct {
|
||||||
script, _ := hex.DecodeString("61000000")
|
want int
|
||||||
|
code string
|
||||||
|
wantErr string
|
||||||
|
}{
|
||||||
|
{2, "61000000", ""}, // valid code
|
||||||
|
{0, "6100", "incomplete push instruction at 0"}, // invalid code
|
||||||
|
{2, "5900", ""}, // push0
|
||||||
|
{0, "", ""}, // empty
|
||||||
|
|
||||||
it := NewInstructionIterator(script)
|
} {
|
||||||
for it.Next() {
|
var (
|
||||||
cnt++
|
have int
|
||||||
}
|
code, _ = hex.DecodeString(tc.code)
|
||||||
|
it = NewInstructionIterator(code)
|
||||||
if err := it.Error(); err != nil {
|
)
|
||||||
t.Errorf("Expected 2, but encountered error %v instead.", err)
|
for it.Next() {
|
||||||
}
|
have++
|
||||||
if cnt != 2 {
|
}
|
||||||
t.Errorf("Expected 2, but got %v instead.", cnt)
|
var haveErr = ""
|
||||||
}
|
if it.Error() != nil {
|
||||||
}
|
haveErr = it.Error().Error()
|
||||||
|
}
|
||||||
// Tests disassembling the instructions for invalid evm code
|
if haveErr != tc.wantErr {
|
||||||
func TestInstructionIteratorInvalid(t *testing.T) {
|
t.Errorf("test %d: encountered error: %q want %q", i, haveErr, tc.wantErr)
|
||||||
cnt := 0
|
continue
|
||||||
script, _ := hex.DecodeString("6100")
|
}
|
||||||
|
if have != tc.want {
|
||||||
it := NewInstructionIterator(script)
|
t.Errorf("wrong instruction count, have %d want %d", have, tc.want)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,9 @@ import (
|
||||||
// defined jump tables are not polluted.
|
// defined jump tables are not polluted.
|
||||||
func EnableEIP(eipNum int, jt *JumpTable) error {
|
func EnableEIP(eipNum int, jt *JumpTable) error {
|
||||||
switch eipNum {
|
switch eipNum {
|
||||||
case 3898:
|
case 3855:
|
||||||
|
enable3855(jt)
|
||||||
|
case 3198:
|
||||||
enable3198(jt)
|
enable3198(jt)
|
||||||
case 2200:
|
case 2200:
|
||||||
enable2200(jt)
|
enable2200(jt)
|
||||||
|
|
@ -112,3 +114,20 @@ func opBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([
|
||||||
callContext.stack.push(baseFee)
|
callContext.stack.push(baseFee)
|
||||||
return nil, nil
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
|
||||||
// If jump table was not initialised we set the default one.
|
// If jump table was not initialised we set the default one.
|
||||||
if cfg.JumpTable == nil {
|
if cfg.JumpTable == nil {
|
||||||
switch {
|
switch {
|
||||||
|
case evm.chainRules.IsShanghai:
|
||||||
|
cfg.JumpTable = &shanghaiInstructionSet
|
||||||
case evm.chainRules.IsMerge:
|
case evm.chainRules.IsMerge:
|
||||||
cfg.JumpTable = &mergeInstructionSet
|
cfg.JumpTable = &mergeInstructionSet
|
||||||
case evm.chainRules.IsLondon:
|
case evm.chainRules.IsLondon:
|
||||||
|
|
|
||||||
|
|
@ -53,11 +53,18 @@ var (
|
||||||
berlinInstructionSet = newBerlinInstructionSet()
|
berlinInstructionSet = newBerlinInstructionSet()
|
||||||
londonInstructionSet = newLondonInstructionSet()
|
londonInstructionSet = newLondonInstructionSet()
|
||||||
mergeInstructionSet = newMergeInstructionSet()
|
mergeInstructionSet = newMergeInstructionSet()
|
||||||
|
shanghaiInstructionSet = newShanghaiInstructionSet()
|
||||||
)
|
)
|
||||||
|
|
||||||
// JumpTable contains the EVM opcodes supported at a given fork.
|
// JumpTable contains the EVM opcodes supported at a given fork.
|
||||||
type JumpTable [256]*operation
|
type JumpTable [256]*operation
|
||||||
|
|
||||||
|
func newShanghaiInstructionSet() JumpTable {
|
||||||
|
instructionSet := newMergeInstructionSet()
|
||||||
|
enable3855(&instructionSet) // PUSH0 instruction
|
||||||
|
return instructionSet
|
||||||
|
}
|
||||||
|
|
||||||
func newMergeInstructionSet() JumpTable {
|
func newMergeInstructionSet() JumpTable {
|
||||||
instructionSet := newLondonInstructionSet()
|
instructionSet := newLondonInstructionSet()
|
||||||
instructionSet[PREVRANDAO] = &operation{
|
instructionSet[PREVRANDAO] = &operation{
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,7 @@ type OpCode byte
|
||||||
|
|
||||||
// IsPush specifies if an opcode is a PUSH opcode.
|
// IsPush specifies if an opcode is a PUSH opcode.
|
||||||
func (op OpCode) IsPush() bool {
|
func (op OpCode) IsPush() bool {
|
||||||
switch op {
|
return PUSH0 <= op && op <= PUSH32
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x0 range - arithmetic ops.
|
// 0x0 range - arithmetic ops.
|
||||||
|
|
@ -108,18 +104,19 @@ const (
|
||||||
|
|
||||||
// 0x50 range - 'storage' and execution.
|
// 0x50 range - 'storage' and execution.
|
||||||
const (
|
const (
|
||||||
POP OpCode = 0x50 + iota
|
POP OpCode = 0x50
|
||||||
MLOAD
|
MLOAD OpCode = 0x51
|
||||||
MSTORE
|
MSTORE OpCode = 0x52
|
||||||
MSTORE8
|
MSTORE8 OpCode = 0x53
|
||||||
SLOAD
|
SLOAD OpCode = 0x54
|
||||||
SSTORE
|
SSTORE OpCode = 0x55
|
||||||
JUMP
|
JUMP OpCode = 0x56
|
||||||
JUMPI
|
JUMPI OpCode = 0x57
|
||||||
PC
|
PC OpCode = 0x58
|
||||||
MSIZE
|
MSIZE OpCode = 0x59
|
||||||
GAS
|
GAS OpCode = 0x5a
|
||||||
JUMPDEST
|
JUMPDEST OpCode = 0x5b
|
||||||
|
PUSH0 OpCode = 0x5f
|
||||||
)
|
)
|
||||||
|
|
||||||
// 0x60 range - pushes.
|
// 0x60 range - pushes.
|
||||||
|
|
@ -300,6 +297,7 @@ var opCodeToString = [256]string{
|
||||||
MSIZE: "MSIZE",
|
MSIZE: "MSIZE",
|
||||||
GAS: "GAS",
|
GAS: "GAS",
|
||||||
JUMPDEST: "JUMPDEST",
|
JUMPDEST: "JUMPDEST",
|
||||||
|
PUSH0: "PUSH0",
|
||||||
|
|
||||||
// 0x60 range - push.
|
// 0x60 range - push.
|
||||||
PUSH1: "PUSH1",
|
PUSH1: "PUSH1",
|
||||||
|
|
@ -462,6 +460,7 @@ var stringToOp = map[string]OpCode{
|
||||||
"MSIZE": MSIZE,
|
"MSIZE": MSIZE,
|
||||||
"GAS": GAS,
|
"GAS": GAS,
|
||||||
"JUMPDEST": JUMPDEST,
|
"JUMPDEST": JUMPDEST,
|
||||||
|
"PUSH0": PUSH0,
|
||||||
"PUSH1": PUSH1,
|
"PUSH1": PUSH1,
|
||||||
"PUSH2": PUSH2,
|
"PUSH2": PUSH2,
|
||||||
"PUSH3": PUSH3,
|
"PUSH3": PUSH3,
|
||||||
|
|
|
||||||
|
|
@ -498,7 +498,7 @@ func (c *ChainConfig) String() string {
|
||||||
default:
|
default:
|
||||||
engine = "unknown"
|
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.ChainId,
|
||||||
c.HomesteadBlock,
|
c.HomesteadBlock,
|
||||||
c.DAOForkBlock,
|
c.DAOForkBlock,
|
||||||
|
|
@ -512,6 +512,7 @@ func (c *ChainConfig) String() string {
|
||||||
common.BerlinBlock,
|
common.BerlinBlock,
|
||||||
common.LondonBlock,
|
common.LondonBlock,
|
||||||
common.MergeBlock,
|
common.MergeBlock,
|
||||||
|
common.ShanghaiBlock,
|
||||||
engine,
|
engine,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -574,6 +575,11 @@ func (c *ChainConfig) IsMerge(num *big.Int) bool {
|
||||||
return isForked(common.MergeBlock, num)
|
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 {
|
func (c *ChainConfig) IsTIP2019(num *big.Int) bool {
|
||||||
return isForked(common.TIP2019Block, num)
|
return isForked(common.TIP2019Block, num)
|
||||||
}
|
}
|
||||||
|
|
@ -742,7 +748,7 @@ type Rules struct {
|
||||||
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
|
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
|
||||||
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
|
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
|
||||||
IsBerlin, IsLondon bool
|
IsBerlin, IsLondon bool
|
||||||
IsMerge bool
|
IsMerge, IsShanghai bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChainConfig) Rules(num *big.Int) Rules {
|
func (c *ChainConfig) Rules(num *big.Int) Rules {
|
||||||
|
|
@ -763,5 +769,6 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
|
||||||
IsBerlin: c.IsBerlin(num),
|
IsBerlin: c.IsBerlin(num),
|
||||||
IsLondon: c.IsLondon(num),
|
IsLondon: c.IsLondon(num),
|
||||||
IsMerge: c.IsMerge(num),
|
IsMerge: c.IsMerge(num),
|
||||||
|
IsShanghai: c.IsShanghai(num),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue