mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-24 09:25:21 +00:00
Merge pull request #963 from nspcc-dev/fix/tests
vm: restore JSON tests for NEO3
This commit is contained in:
commit
5ea51312e6
14 changed files with 436 additions and 335 deletions
|
@ -26,7 +26,7 @@ var binaryExprTestCases = []testCase{
|
|||
return x
|
||||
}
|
||||
`,
|
||||
[]byte{},
|
||||
big.NewInt(0),
|
||||
},
|
||||
{
|
||||
"simple div",
|
||||
|
@ -97,7 +97,7 @@ var binaryExprTestCases = []testCase{
|
|||
return 0
|
||||
}
|
||||
`,
|
||||
[]byte{},
|
||||
big.NewInt(0),
|
||||
},
|
||||
{
|
||||
"compare equal strings with eql",
|
||||
|
@ -139,7 +139,7 @@ var binaryExprTestCases = []testCase{
|
|||
return 0
|
||||
}
|
||||
`,
|
||||
[]byte{},
|
||||
big.NewInt(0),
|
||||
},
|
||||
{
|
||||
"compare equal ints with eql",
|
||||
|
@ -167,7 +167,7 @@ var binaryExprTestCases = []testCase{
|
|||
return 0
|
||||
}
|
||||
`,
|
||||
[]byte{},
|
||||
big.NewInt(0),
|
||||
},
|
||||
{
|
||||
"compare not equal ints with eql",
|
||||
|
@ -181,7 +181,7 @@ var binaryExprTestCases = []testCase{
|
|||
return 0
|
||||
}
|
||||
`,
|
||||
[]byte{},
|
||||
big.NewInt(0),
|
||||
},
|
||||
{
|
||||
"compare not equal ints with neq",
|
||||
|
|
|
@ -276,7 +276,7 @@ func TestIfUnaryInvert(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, []byte{})
|
||||
eval(t, src, big.NewInt(0))
|
||||
}
|
||||
|
||||
func TestAppendByte(t *testing.T) {
|
||||
|
|
|
@ -39,7 +39,7 @@ func TestNotAssignedFunctionCall(t *testing.T) {
|
|||
// disable stack checks because it is hard right now
|
||||
// to distinguish between simple function call traversal
|
||||
// and the same traversal inside an assignment.
|
||||
evalWithoutStackChecks(t, src, []byte{})
|
||||
evalWithoutStackChecks(t, src, big.NewInt(0))
|
||||
}
|
||||
|
||||
func TestMultipleFunctionCalls(t *testing.T) {
|
||||
|
|
|
@ -30,7 +30,7 @@ func TestGT(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, []byte{})
|
||||
eval(t, src, big.NewInt(0))
|
||||
}
|
||||
|
||||
func TestGTE(t *testing.T) {
|
||||
|
@ -44,7 +44,7 @@ func TestGTE(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, []byte{})
|
||||
eval(t, src, big.NewInt(0))
|
||||
}
|
||||
|
||||
func TestLAND(t *testing.T) {
|
||||
|
@ -89,5 +89,5 @@ func TestNestedIF(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, []byte{})
|
||||
eval(t, src, big.NewInt(0))
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestImportStruct(t *testing.T) {
|
|||
return b.Y
|
||||
}
|
||||
`
|
||||
eval(t, src, []byte{})
|
||||
eval(t, src, big.NewInt(0))
|
||||
}
|
||||
|
||||
func TestMultipleDirFileImport(t *testing.T) {
|
||||
|
|
|
@ -255,7 +255,7 @@ var structTestCases = []testCase{
|
|||
return t.y
|
||||
}
|
||||
`,
|
||||
[]byte{},
|
||||
big.NewInt(0),
|
||||
},
|
||||
{
|
||||
"test return struct from func",
|
||||
|
|
|
@ -11,6 +11,8 @@ import (
|
|||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -37,12 +39,12 @@ type (
|
|||
vmUTExecutionContextState struct {
|
||||
Instruction string `json:"nextInstruction"`
|
||||
InstructionPointer int `json:"instructionPointer"`
|
||||
AStack []vmUTStackItem `json:"altStack"`
|
||||
EStack []vmUTStackItem `json:"evaluationStack"`
|
||||
StaticFields []vmUTStackItem `json:"staticFields"`
|
||||
}
|
||||
|
||||
vmUTExecutionEngineState struct {
|
||||
State vmUTState `json:"state"`
|
||||
State State `json:"state"`
|
||||
ResultStack []vmUTStackItem `json:"resultStack"`
|
||||
InvocationStack []vmUTExecutionContextState `json:"invocationStack"`
|
||||
}
|
||||
|
@ -59,8 +61,6 @@ type (
|
|||
Result vmUTExecutionEngineState `json:"result"`
|
||||
}
|
||||
|
||||
vmUTState State
|
||||
|
||||
vmUTStackItemType string
|
||||
)
|
||||
|
||||
|
@ -73,25 +73,27 @@ type stackItemAUX struct {
|
|||
}
|
||||
|
||||
const (
|
||||
vmExecute vmUTActionType = "Execute"
|
||||
vmStepInto vmUTActionType = "StepInto"
|
||||
vmStepOut vmUTActionType = "StepOut"
|
||||
vmStepOver vmUTActionType = "StepOver"
|
||||
vmExecute vmUTActionType = "execute"
|
||||
vmStepInto vmUTActionType = "stepinto"
|
||||
vmStepOut vmUTActionType = "stepout"
|
||||
vmStepOver vmUTActionType = "stepover"
|
||||
|
||||
typeArray vmUTStackItemType = "Array"
|
||||
typeBoolean vmUTStackItemType = "Boolean"
|
||||
typeByteArray vmUTStackItemType = "ByteArray"
|
||||
typeInteger vmUTStackItemType = "Integer"
|
||||
typeInterop vmUTStackItemType = "Interop"
|
||||
typeMap vmUTStackItemType = "Map"
|
||||
typeString vmUTStackItemType = "String"
|
||||
typeStruct vmUTStackItemType = "Struct"
|
||||
typeArray vmUTStackItemType = "array"
|
||||
typeBoolean vmUTStackItemType = "boolean"
|
||||
typeBuffer vmUTStackItemType = "buffer"
|
||||
typeByteString vmUTStackItemType = "bytestring"
|
||||
typeInteger vmUTStackItemType = "integer"
|
||||
typeInterop vmUTStackItemType = "interop"
|
||||
typeMap vmUTStackItemType = "map"
|
||||
typeNull vmUTStackItemType = "null"
|
||||
typePointer vmUTStackItemType = "pointer"
|
||||
typeString vmUTStackItemType = "string"
|
||||
typeStruct vmUTStackItemType = "struct"
|
||||
|
||||
testsDir = "testdata/neo-vm/tests/neo-vm.Tests/Tests/"
|
||||
)
|
||||
|
||||
func TestUT(t *testing.T) {
|
||||
t.Skip()
|
||||
testsRan := false
|
||||
err := filepath.Walk(testsDir, func(path string, info os.FileInfo, err error) error {
|
||||
if !strings.HasSuffix(path, ".json") {
|
||||
|
@ -110,7 +112,7 @@ func TestUT(t *testing.T) {
|
|||
func getTestingInterop(id uint32) *InteropFuncPrice {
|
||||
if id == binary.LittleEndian.Uint32([]byte{0x77, 0x77, 0x77, 0x77}) {
|
||||
return &InteropFuncPrice{InteropFunc(func(v *VM) error {
|
||||
v.estack.Push(&Element{value: (*InteropItem)(nil)})
|
||||
v.estack.PushVal(&InteropItem{new(int)})
|
||||
return nil
|
||||
}), 0}
|
||||
}
|
||||
|
@ -121,12 +123,24 @@ func testFile(t *testing.T, filename string) {
|
|||
data, err := ioutil.ReadFile(filename)
|
||||
require.NoError(t, err)
|
||||
|
||||
// get rid of possible BOM
|
||||
if len(data) > 2 && data[0] == 0xef && data[1] == 0xbb && data[2] == 0xbf {
|
||||
data = data[3:]
|
||||
}
|
||||
if strings.HasSuffix(filename, "MEMCPY.json") {
|
||||
return // FIXME not a valid JSON https://github.com/neo-project/neo-vm/issues/322
|
||||
}
|
||||
|
||||
ut := new(vmUT)
|
||||
require.NoError(t, json.Unmarshal(data, ut))
|
||||
require.NoErrorf(t, json.Unmarshal(data, ut), "file: %s", filename)
|
||||
|
||||
t.Run(ut.Category+":"+ut.Name, func(t *testing.T) {
|
||||
isRot := strings.HasSuffix(filename, "ROT.json")
|
||||
for i := range ut.Tests {
|
||||
test := ut.Tests[i]
|
||||
if isRot && test.Name == "Without push" {
|
||||
return // FIXME #927 single ROT is interpreted as PUSH1
|
||||
}
|
||||
t.Run(ut.Tests[i].Name, func(t *testing.T) {
|
||||
prog := []byte(test.Script)
|
||||
vm := load(prog)
|
||||
|
@ -136,8 +150,8 @@ func testFile(t *testing.T, filename string) {
|
|||
for i := range test.Steps {
|
||||
execStep(t, vm, test.Steps[i])
|
||||
result := test.Steps[i].Result
|
||||
require.Equal(t, State(result.State), vm.state)
|
||||
if result.State == vmUTState(faultState) { // do not compare stacks on fault
|
||||
require.Equal(t, result.State, vm.state)
|
||||
if result.State == faultState { // do not compare stacks on fault
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -146,10 +160,12 @@ func testFile(t *testing.T, filename string) {
|
|||
ctx := vm.istack.Peek(i).Value().(*Context)
|
||||
if ctx.nextip < len(ctx.prog) {
|
||||
require.Equal(t, s.InstructionPointer, ctx.nextip)
|
||||
require.Equal(t, s.Instruction, opcode.Opcode(ctx.prog[ctx.nextip]).String())
|
||||
op, err := opcode.FromString(s.Instruction)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, op, opcode.Opcode(ctx.prog[ctx.nextip]))
|
||||
}
|
||||
compareStacks(t, s.EStack, vm.estack)
|
||||
compareStacks(t, s.AStack, vm.astack)
|
||||
compareSlots(t, s.StaticFields, vm.static)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,31 +196,47 @@ func compareItems(t *testing.T, a, b StackItem) {
|
|||
default:
|
||||
require.Fail(t, "wrong type")
|
||||
}
|
||||
case *PointerItem:
|
||||
p, ok := b.(*PointerItem)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, si.pos, p.pos) // there no script in test files
|
||||
default:
|
||||
require.Equal(t, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
func compareStacks(t *testing.T, expected []vmUTStackItem, actual *Stack) {
|
||||
compareItemArrays(t, expected, actual.Len(), func(i int) StackItem { return actual.Peek(i).Item() })
|
||||
}
|
||||
|
||||
func compareSlots(t *testing.T, expected []vmUTStackItem, actual *Slot) {
|
||||
if actual == nil && len(expected) == 0 {
|
||||
return
|
||||
}
|
||||
require.NotNil(t, actual)
|
||||
compareItemArrays(t, expected, actual.Size(), actual.Get)
|
||||
}
|
||||
|
||||
func compareItemArrays(t *testing.T, expected []vmUTStackItem, n int, getItem func(i int) StackItem) {
|
||||
if expected == nil {
|
||||
return
|
||||
}
|
||||
|
||||
require.Equal(t, len(expected), actual.Len())
|
||||
require.Equal(t, len(expected), n)
|
||||
for i, item := range expected {
|
||||
e := actual.Peek(i)
|
||||
require.NotNil(t, e)
|
||||
it := getItem(i)
|
||||
require.NotNil(t, it)
|
||||
|
||||
if item.Type == typeInterop {
|
||||
require.IsType(t, (*InteropItem)(nil), e.value)
|
||||
require.IsType(t, (*InteropItem)(nil), it)
|
||||
continue
|
||||
}
|
||||
compareItems(t, item.toStackItem(), e.value)
|
||||
compareItems(t, item.toStackItem(), it)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *vmUTStackItem) toStackItem() StackItem {
|
||||
switch v.Type {
|
||||
switch v.Type.toLower() {
|
||||
case typeArray:
|
||||
items := v.Value.([]vmUTStackItem)
|
||||
result := make([]StackItem, len(items))
|
||||
|
@ -217,20 +249,19 @@ func (v *vmUTStackItem) toStackItem() StackItem {
|
|||
case typeString:
|
||||
panic("not implemented")
|
||||
case typeMap:
|
||||
items := v.Value.(map[string]vmUTStackItem)
|
||||
result := NewMapItem()
|
||||
for k, v := range items {
|
||||
var item vmUTStackItem
|
||||
_ = json.Unmarshal([]byte(`"`+k+`"`), &item)
|
||||
result.Add(item.toStackItem(), v.toStackItem())
|
||||
}
|
||||
return result
|
||||
return v.Value.(*MapItem)
|
||||
case typeInterop:
|
||||
panic("not implemented")
|
||||
case typeByteArray:
|
||||
case typeByteString:
|
||||
return &ByteArrayItem{
|
||||
v.Value.([]byte),
|
||||
}
|
||||
case typeBuffer:
|
||||
return &BufferItem{v.Value.([]byte)}
|
||||
case typePointer:
|
||||
return NewPointerItem(v.Value.(int), nil)
|
||||
case typeNull:
|
||||
return NullItem{}
|
||||
case typeBoolean:
|
||||
return &BoolItem{
|
||||
v.Value.(bool),
|
||||
|
@ -249,14 +280,14 @@ func (v *vmUTStackItem) toStackItem() StackItem {
|
|||
value: result,
|
||||
}
|
||||
default:
|
||||
panic("invalid type")
|
||||
panic(fmt.Sprintf("invalid type: %s", v.Type))
|
||||
}
|
||||
}
|
||||
|
||||
func execStep(t *testing.T, v *VM, step vmUTStep) {
|
||||
for i, a := range step.Actions {
|
||||
var err error
|
||||
switch a {
|
||||
switch a.toLower() {
|
||||
case vmExecute:
|
||||
err = v.Run()
|
||||
case vmStepInto:
|
||||
|
@ -276,30 +307,65 @@ func execStep(t *testing.T, v *VM, step vmUTStep) {
|
|||
}
|
||||
}
|
||||
|
||||
func (v *vmUTState) UnmarshalJSON(data []byte) error {
|
||||
switch s := string(data); s {
|
||||
case `"Break"`:
|
||||
*v = vmUTState(breakState)
|
||||
case `"Fault"`:
|
||||
*v = vmUTState(faultState)
|
||||
case `"Halt"`:
|
||||
*v = vmUTState(haltState)
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid state: %s", s))
|
||||
func jsonStringToInteger(s string) StackItem {
|
||||
b, err := decodeHex(s)
|
||||
if err == nil {
|
||||
return NewBigIntegerItem(new(big.Int).SetBytes(b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v vmUTStackItemType) toLower() vmUTStackItemType {
|
||||
return vmUTStackItemType(strings.ToLower(string(v)))
|
||||
}
|
||||
|
||||
func (v *vmUTScript) UnmarshalJSON(data []byte) error {
|
||||
b, err := decodeBytes(data)
|
||||
if err != nil {
|
||||
var ops []string
|
||||
if err := json.Unmarshal(data, &ops); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*v = vmUTScript(b)
|
||||
var script []byte
|
||||
for i := range ops {
|
||||
if b, ok := decodeSingle(ops[i]); ok {
|
||||
script = append(script, b...)
|
||||
} else {
|
||||
const regex = `(?P<hex>(?:0x)?[0-9a-zA-Z]+)\*(?P<num>[0-9]+)`
|
||||
re := regexp.MustCompile(regex)
|
||||
ss := re.FindStringSubmatch(ops[i])
|
||||
if len(ss) != 3 {
|
||||
return fmt.Errorf("invalid script part: %s", ops[i])
|
||||
}
|
||||
b, ok := decodeSingle(ss[1])
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid script part: %s", ops[i])
|
||||
}
|
||||
num, err := strconv.Atoi(ss[2])
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid script part: %s", ops[i])
|
||||
}
|
||||
for i := 0; i < num; i++ {
|
||||
script = append(script, b...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*v = script
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeSingle(s string) ([]byte, bool) {
|
||||
if op, err := opcode.FromString(s); err == nil {
|
||||
return []byte{byte(op)}, true
|
||||
}
|
||||
b, err := decodeHex(s)
|
||||
return b, err == nil
|
||||
}
|
||||
|
||||
func (v vmUTActionType) toLower() vmUTActionType {
|
||||
return vmUTActionType(strings.ToLower(string(v)))
|
||||
}
|
||||
|
||||
func (v *vmUTActionType) UnmarshalJSON(data []byte) error {
|
||||
return json.Unmarshal(data, (*string)(v))
|
||||
}
|
||||
|
@ -312,14 +378,14 @@ func (v *vmUTStackItem) UnmarshalJSON(data []byte) error {
|
|||
|
||||
v.Type = si.Type
|
||||
|
||||
switch si.Type {
|
||||
switch typ := si.Type.toLower(); typ {
|
||||
case typeArray, typeStruct:
|
||||
var a []vmUTStackItem
|
||||
if err := json.Unmarshal(si.Value, &a); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = a
|
||||
case typeInteger:
|
||||
case typeInteger, typePointer:
|
||||
num := new(big.Int)
|
||||
var a int64
|
||||
var s string
|
||||
|
@ -330,27 +396,57 @@ func (v *vmUTStackItem) UnmarshalJSON(data []byte) error {
|
|||
} else {
|
||||
panic(fmt.Sprintf("invalid integer: %v", si.Value))
|
||||
}
|
||||
v.Value = num
|
||||
if typ == typePointer {
|
||||
v.Value = int(num.Int64())
|
||||
} else {
|
||||
v.Value = num
|
||||
}
|
||||
case typeBoolean:
|
||||
var b bool
|
||||
if err := json.Unmarshal(si.Value, &b); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = b
|
||||
case typeByteArray:
|
||||
case typeByteString, typeBuffer:
|
||||
b, err := decodeBytes(si.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = b
|
||||
case typeInterop:
|
||||
case typeInterop, typeNull:
|
||||
v.Value = nil
|
||||
case typeMap:
|
||||
var m map[string]vmUTStackItem
|
||||
if err := json.Unmarshal(si.Value, &m); err != nil {
|
||||
return err
|
||||
// we want to have the same order as in test file, so a custom decoder is used
|
||||
d := json.NewDecoder(bytes.NewReader(si.Value))
|
||||
if tok, err := d.Token(); err != nil || tok != json.Delim('{') {
|
||||
return fmt.Errorf("invalid map start")
|
||||
}
|
||||
v.Value = m
|
||||
|
||||
result := NewMapItem()
|
||||
for {
|
||||
tok, err := d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
} else if tok == json.Delim('}') {
|
||||
break
|
||||
}
|
||||
key, ok := tok.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("string expected in map key")
|
||||
}
|
||||
|
||||
var it vmUTStackItem
|
||||
if err := d.Decode(&it); err != nil {
|
||||
return fmt.Errorf("can't decode map value: %v", err)
|
||||
}
|
||||
|
||||
item := jsonStringToInteger(key)
|
||||
if item == nil {
|
||||
return fmt.Errorf("can't unmarshal StackItem %s", key)
|
||||
}
|
||||
result.Add(item, it.toStackItem())
|
||||
}
|
||||
v.Value = result
|
||||
case typeString:
|
||||
panic("not implemented")
|
||||
default:
|
||||
|
@ -366,12 +462,18 @@ func decodeBytes(data []byte) ([]byte, error) {
|
|||
return []byte{}, nil
|
||||
}
|
||||
|
||||
hdata := data[3 : len(data)-1]
|
||||
if b, err := hex.DecodeString(string(hdata)); err == nil {
|
||||
data = data[1 : len(data)-1] // strip quotes
|
||||
if b, err := decodeHex(string(data)); err == nil {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
data = data[1 : len(data)-1]
|
||||
r := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(data))
|
||||
return ioutil.ReadAll(r)
|
||||
}
|
||||
|
||||
func decodeHex(s string) ([]byte, error) {
|
||||
if strings.HasPrefix(s, "0x") {
|
||||
s = s[2:]
|
||||
}
|
||||
return hex.DecodeString(s)
|
||||
}
|
||||
|
|
20
pkg/vm/opcode/from_string.go
Normal file
20
pkg/vm/opcode/from_string.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package opcode
|
||||
|
||||
import "errors"
|
||||
|
||||
var stringToOpcode = make(map[string]Opcode)
|
||||
|
||||
func init() {
|
||||
for i := 0; i < 255; i++ {
|
||||
op := Opcode(i)
|
||||
stringToOpcode[op.String()] = op
|
||||
}
|
||||
}
|
||||
|
||||
// FromString converts string representation to and opcode itself.
|
||||
func FromString(s string) (Opcode, error) {
|
||||
if op, ok := stringToOpcode[s]; ok {
|
||||
return op, nil
|
||||
}
|
||||
return 0, errors.New("invalid opcode")
|
||||
}
|
|
@ -46,25 +46,25 @@ const (
|
|||
// Flow control
|
||||
NOP Opcode = 0x21
|
||||
JMP Opcode = 0x22
|
||||
JMPL Opcode = 0x23
|
||||
JMPL Opcode = 0x23 // JMP_L
|
||||
JMPIF Opcode = 0x24
|
||||
JMPIFL Opcode = 0x25
|
||||
JMPIFL Opcode = 0x25 // JMPIF_L
|
||||
JMPIFNOT Opcode = 0x26
|
||||
JMPIFNOTL Opcode = 0x27
|
||||
JMPIFNOTL Opcode = 0x27 // JMPIFNOT_L
|
||||
JMPEQ Opcode = 0x28
|
||||
JMPEQL Opcode = 0x29
|
||||
JMPEQL Opcode = 0x29 // JMPEQ_L
|
||||
JMPNE Opcode = 0x2A
|
||||
JMPNEL Opcode = 0x2B
|
||||
JMPNEL Opcode = 0x2B // JMPNE_L
|
||||
JMPGT Opcode = 0x2C
|
||||
JMPGTL Opcode = 0x2D
|
||||
JMPGTL Opcode = 0x2D // JMPGT_L
|
||||
JMPGE Opcode = 0x2E
|
||||
JMPGEL Opcode = 0x2F
|
||||
JMPGEL Opcode = 0x2F // JMPGE_L
|
||||
JMPLT Opcode = 0x30
|
||||
JMPLTL Opcode = 0x31
|
||||
JMPLTL Opcode = 0x31 // JMPLT_L
|
||||
JMPLE Opcode = 0x32
|
||||
JMPLEL Opcode = 0x33
|
||||
JMPLEL Opcode = 0x33 // JMPLE_L
|
||||
CALL Opcode = 0x34
|
||||
CALLL Opcode = 0x35
|
||||
CALLL Opcode = 0x35 // CALL_L
|
||||
CALLA Opcode = 0x36
|
||||
|
||||
// Exceptions
|
||||
|
@ -86,8 +86,8 @@ const (
|
|||
PICK Opcode = 0x4D
|
||||
TUCK Opcode = 0x4E
|
||||
SWAP Opcode = 0x50
|
||||
OLDPUSH1 Opcode = 0x51 // FIXME remove #927
|
||||
ROT Opcode = 0x51
|
||||
OLDPUSH1 Opcode = 0x51 // FIXME remove #927
|
||||
ROLL Opcode = 0x52
|
||||
REVERSE3 Opcode = 0x53
|
||||
REVERSE4 Opcode = 0x54
|
||||
|
@ -193,7 +193,7 @@ const (
|
|||
UNPACK Opcode = 0xC1
|
||||
NEWARRAY0 Opcode = 0xC2
|
||||
NEWARRAY Opcode = 0xC3
|
||||
NEWARRAYT Opcode = 0xC4
|
||||
NEWARRAYT Opcode = 0xC4 // NEWARRAY_T
|
||||
NEWSTRUCT0 Opcode = 0xC5
|
||||
NEWSTRUCT Opcode = 0xC6
|
||||
NEWMAP Opcode = 0xC8
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by "stringer -type Opcode"; DO NOT EDIT.
|
||||
// Code generated by "stringer -type Opcode -linecomment"; DO NOT EDIT.
|
||||
|
||||
package opcode
|
||||
|
||||
|
@ -76,8 +76,8 @@ func _() {
|
|||
_ = x[PICK-77]
|
||||
_ = x[TUCK-78]
|
||||
_ = x[SWAP-80]
|
||||
_ = x[OLDPUSH1-81]
|
||||
_ = x[ROT-81]
|
||||
_ = x[OLDPUSH1-81]
|
||||
_ = x[ROLL-82]
|
||||
_ = x[REVERSE3-83]
|
||||
_ = x[REVERSE4-84]
|
||||
|
@ -192,7 +192,7 @@ func _() {
|
|||
_ = x[CONVERT-219]
|
||||
}
|
||||
|
||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLCALLAABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENINITSSLOTINITSLOTLDSFLD0LDSFLD1LDSFLD2LDSFLD3LDSFLD4LDSFLD5LDSFLD6LDSFLDSTSFLD0STSFLD1STSFLD2STSFLD3STSFLD4STSFLD5STSFLD6STSFLDLDLOC0LDLOC1LDLOC2LDLOC3LDLOC4LDLOC5LDLOC6LDLOCSTLOC0STLOC1STLOC2STLOC3STLOC4STLOC5STLOC6STLOCLDARG0LDARG1LDARG2LDARG3LDARG4LDARG5LDARG6LDARGSTARG0STARG1STARG2STARG3STARG4STARG5STARG6STARGNEWBUFFERMEMCPYCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT"
|
||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMP_LJMPIFJMPIF_LJMPIFNOTJMPIFNOT_LJMPEQJMPEQ_LJMPNEJMPNE_LJMPGTJMPGT_LJMPGEJMPGE_LJMPLTJMPLT_LJMPLEJMPLE_LCALLCALL_LCALLAABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPROTROLLREVERSE3REVERSE4REVERSENINITSSLOTINITSLOTLDSFLD0LDSFLD1LDSFLD2LDSFLD3LDSFLD4LDSFLD5LDSFLD6LDSFLDSTSFLD0STSFLD1STSFLD2STSFLD3STSFLD4STSFLD5STSFLD6STSFLDLDLOC0LDLOC1LDLOC2LDLOC3LDLOC4LDLOC5LDLOC6LDLOCSTLOC0STLOC1STLOC2STLOC3STLOC4STLOC5STLOC6STLOCLDARG0LDARG1LDARG2LDARG3LDARG4LDARG5LDARG6LDARGSTARG0STARG1STARG2STARG3STARG4STARG5STARG6STARGNEWBUFFERMEMCPYCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAY_TNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT"
|
||||
|
||||
var _Opcode_map = map[Opcode]string{
|
||||
0: _Opcode_name[0:8],
|
||||
|
@ -226,154 +226,154 @@ var _Opcode_map = map[Opcode]string{
|
|||
32: _Opcode_name[187:193],
|
||||
33: _Opcode_name[193:196],
|
||||
34: _Opcode_name[196:199],
|
||||
35: _Opcode_name[199:203],
|
||||
36: _Opcode_name[203:208],
|
||||
37: _Opcode_name[208:214],
|
||||
38: _Opcode_name[214:222],
|
||||
39: _Opcode_name[222:231],
|
||||
40: _Opcode_name[231:236],
|
||||
41: _Opcode_name[236:242],
|
||||
42: _Opcode_name[242:247],
|
||||
43: _Opcode_name[247:253],
|
||||
44: _Opcode_name[253:258],
|
||||
45: _Opcode_name[258:264],
|
||||
46: _Opcode_name[264:269],
|
||||
47: _Opcode_name[269:275],
|
||||
48: _Opcode_name[275:280],
|
||||
49: _Opcode_name[280:286],
|
||||
50: _Opcode_name[286:291],
|
||||
51: _Opcode_name[291:297],
|
||||
52: _Opcode_name[297:301],
|
||||
53: _Opcode_name[301:306],
|
||||
54: _Opcode_name[306:311],
|
||||
55: _Opcode_name[311:316],
|
||||
56: _Opcode_name[316:322],
|
||||
58: _Opcode_name[322:327],
|
||||
64: _Opcode_name[327:330],
|
||||
65: _Opcode_name[330:337],
|
||||
67: _Opcode_name[337:342],
|
||||
69: _Opcode_name[342:346],
|
||||
70: _Opcode_name[346:349],
|
||||
72: _Opcode_name[349:354],
|
||||
73: _Opcode_name[354:359],
|
||||
74: _Opcode_name[359:362],
|
||||
75: _Opcode_name[362:366],
|
||||
77: _Opcode_name[366:370],
|
||||
78: _Opcode_name[370:374],
|
||||
80: _Opcode_name[374:378],
|
||||
81: _Opcode_name[378:386],
|
||||
82: _Opcode_name[386:390],
|
||||
83: _Opcode_name[390:398],
|
||||
84: _Opcode_name[398:406],
|
||||
85: _Opcode_name[406:414],
|
||||
86: _Opcode_name[414:423],
|
||||
87: _Opcode_name[423:431],
|
||||
88: _Opcode_name[431:438],
|
||||
89: _Opcode_name[438:445],
|
||||
90: _Opcode_name[445:452],
|
||||
91: _Opcode_name[452:459],
|
||||
92: _Opcode_name[459:466],
|
||||
93: _Opcode_name[466:473],
|
||||
94: _Opcode_name[473:480],
|
||||
95: _Opcode_name[480:486],
|
||||
96: _Opcode_name[486:493],
|
||||
97: _Opcode_name[493:500],
|
||||
98: _Opcode_name[500:507],
|
||||
99: _Opcode_name[507:514],
|
||||
100: _Opcode_name[514:521],
|
||||
101: _Opcode_name[521:528],
|
||||
102: _Opcode_name[528:535],
|
||||
103: _Opcode_name[535:541],
|
||||
104: _Opcode_name[541:547],
|
||||
105: _Opcode_name[547:553],
|
||||
106: _Opcode_name[553:559],
|
||||
107: _Opcode_name[559:565],
|
||||
108: _Opcode_name[565:571],
|
||||
109: _Opcode_name[571:577],
|
||||
110: _Opcode_name[577:583],
|
||||
111: _Opcode_name[583:588],
|
||||
112: _Opcode_name[588:594],
|
||||
113: _Opcode_name[594:600],
|
||||
114: _Opcode_name[600:606],
|
||||
115: _Opcode_name[606:612],
|
||||
116: _Opcode_name[612:618],
|
||||
117: _Opcode_name[618:624],
|
||||
118: _Opcode_name[624:630],
|
||||
119: _Opcode_name[630:635],
|
||||
120: _Opcode_name[635:641],
|
||||
121: _Opcode_name[641:647],
|
||||
122: _Opcode_name[647:653],
|
||||
123: _Opcode_name[653:659],
|
||||
124: _Opcode_name[659:665],
|
||||
125: _Opcode_name[665:671],
|
||||
126: _Opcode_name[671:677],
|
||||
127: _Opcode_name[677:682],
|
||||
128: _Opcode_name[682:688],
|
||||
129: _Opcode_name[688:694],
|
||||
130: _Opcode_name[694:700],
|
||||
131: _Opcode_name[700:706],
|
||||
132: _Opcode_name[706:712],
|
||||
133: _Opcode_name[712:718],
|
||||
134: _Opcode_name[718:724],
|
||||
135: _Opcode_name[724:729],
|
||||
136: _Opcode_name[729:738],
|
||||
137: _Opcode_name[738:744],
|
||||
139: _Opcode_name[744:747],
|
||||
140: _Opcode_name[747:753],
|
||||
141: _Opcode_name[753:757],
|
||||
142: _Opcode_name[757:762],
|
||||
144: _Opcode_name[762:768],
|
||||
145: _Opcode_name[768:771],
|
||||
146: _Opcode_name[771:773],
|
||||
147: _Opcode_name[773:776],
|
||||
151: _Opcode_name[776:781],
|
||||
152: _Opcode_name[781:789],
|
||||
153: _Opcode_name[789:793],
|
||||
154: _Opcode_name[793:796],
|
||||
155: _Opcode_name[796:802],
|
||||
156: _Opcode_name[802:805],
|
||||
157: _Opcode_name[805:808],
|
||||
158: _Opcode_name[808:811],
|
||||
159: _Opcode_name[811:814],
|
||||
160: _Opcode_name[814:817],
|
||||
161: _Opcode_name[817:820],
|
||||
162: _Opcode_name[820:823],
|
||||
168: _Opcode_name[823:826],
|
||||
169: _Opcode_name[826:829],
|
||||
170: _Opcode_name[829:832],
|
||||
171: _Opcode_name[832:839],
|
||||
172: _Opcode_name[839:845],
|
||||
177: _Opcode_name[845:847],
|
||||
179: _Opcode_name[847:855],
|
||||
180: _Opcode_name[855:866],
|
||||
181: _Opcode_name[866:868],
|
||||
182: _Opcode_name[868:871],
|
||||
183: _Opcode_name[871:873],
|
||||
184: _Opcode_name[873:876],
|
||||
185: _Opcode_name[876:879],
|
||||
186: _Opcode_name[879:882],
|
||||
187: _Opcode_name[882:888],
|
||||
192: _Opcode_name[888:892],
|
||||
193: _Opcode_name[892:898],
|
||||
194: _Opcode_name[898:907],
|
||||
195: _Opcode_name[907:915],
|
||||
196: _Opcode_name[915:924],
|
||||
197: _Opcode_name[924:934],
|
||||
198: _Opcode_name[934:943],
|
||||
200: _Opcode_name[943:949],
|
||||
202: _Opcode_name[949:953],
|
||||
203: _Opcode_name[953:959],
|
||||
204: _Opcode_name[959:963],
|
||||
205: _Opcode_name[963:969],
|
||||
206: _Opcode_name[969:977],
|
||||
207: _Opcode_name[977:983],
|
||||
208: _Opcode_name[983:990],
|
||||
209: _Opcode_name[990:1002],
|
||||
210: _Opcode_name[1002:1008],
|
||||
211: _Opcode_name[1008:1018],
|
||||
216: _Opcode_name[1018:1024],
|
||||
217: _Opcode_name[1024:1030],
|
||||
219: _Opcode_name[1030:1037],
|
||||
35: _Opcode_name[199:204],
|
||||
36: _Opcode_name[204:209],
|
||||
37: _Opcode_name[209:216],
|
||||
38: _Opcode_name[216:224],
|
||||
39: _Opcode_name[224:234],
|
||||
40: _Opcode_name[234:239],
|
||||
41: _Opcode_name[239:246],
|
||||
42: _Opcode_name[246:251],
|
||||
43: _Opcode_name[251:258],
|
||||
44: _Opcode_name[258:263],
|
||||
45: _Opcode_name[263:270],
|
||||
46: _Opcode_name[270:275],
|
||||
47: _Opcode_name[275:282],
|
||||
48: _Opcode_name[282:287],
|
||||
49: _Opcode_name[287:294],
|
||||
50: _Opcode_name[294:299],
|
||||
51: _Opcode_name[299:306],
|
||||
52: _Opcode_name[306:310],
|
||||
53: _Opcode_name[310:316],
|
||||
54: _Opcode_name[316:321],
|
||||
55: _Opcode_name[321:326],
|
||||
56: _Opcode_name[326:332],
|
||||
58: _Opcode_name[332:337],
|
||||
64: _Opcode_name[337:340],
|
||||
65: _Opcode_name[340:347],
|
||||
67: _Opcode_name[347:352],
|
||||
69: _Opcode_name[352:356],
|
||||
70: _Opcode_name[356:359],
|
||||
72: _Opcode_name[359:364],
|
||||
73: _Opcode_name[364:369],
|
||||
74: _Opcode_name[369:372],
|
||||
75: _Opcode_name[372:376],
|
||||
77: _Opcode_name[376:380],
|
||||
78: _Opcode_name[380:384],
|
||||
80: _Opcode_name[384:388],
|
||||
81: _Opcode_name[388:391],
|
||||
82: _Opcode_name[391:395],
|
||||
83: _Opcode_name[395:403],
|
||||
84: _Opcode_name[403:411],
|
||||
85: _Opcode_name[411:419],
|
||||
86: _Opcode_name[419:428],
|
||||
87: _Opcode_name[428:436],
|
||||
88: _Opcode_name[436:443],
|
||||
89: _Opcode_name[443:450],
|
||||
90: _Opcode_name[450:457],
|
||||
91: _Opcode_name[457:464],
|
||||
92: _Opcode_name[464:471],
|
||||
93: _Opcode_name[471:478],
|
||||
94: _Opcode_name[478:485],
|
||||
95: _Opcode_name[485:491],
|
||||
96: _Opcode_name[491:498],
|
||||
97: _Opcode_name[498:505],
|
||||
98: _Opcode_name[505:512],
|
||||
99: _Opcode_name[512:519],
|
||||
100: _Opcode_name[519:526],
|
||||
101: _Opcode_name[526:533],
|
||||
102: _Opcode_name[533:540],
|
||||
103: _Opcode_name[540:546],
|
||||
104: _Opcode_name[546:552],
|
||||
105: _Opcode_name[552:558],
|
||||
106: _Opcode_name[558:564],
|
||||
107: _Opcode_name[564:570],
|
||||
108: _Opcode_name[570:576],
|
||||
109: _Opcode_name[576:582],
|
||||
110: _Opcode_name[582:588],
|
||||
111: _Opcode_name[588:593],
|
||||
112: _Opcode_name[593:599],
|
||||
113: _Opcode_name[599:605],
|
||||
114: _Opcode_name[605:611],
|
||||
115: _Opcode_name[611:617],
|
||||
116: _Opcode_name[617:623],
|
||||
117: _Opcode_name[623:629],
|
||||
118: _Opcode_name[629:635],
|
||||
119: _Opcode_name[635:640],
|
||||
120: _Opcode_name[640:646],
|
||||
121: _Opcode_name[646:652],
|
||||
122: _Opcode_name[652:658],
|
||||
123: _Opcode_name[658:664],
|
||||
124: _Opcode_name[664:670],
|
||||
125: _Opcode_name[670:676],
|
||||
126: _Opcode_name[676:682],
|
||||
127: _Opcode_name[682:687],
|
||||
128: _Opcode_name[687:693],
|
||||
129: _Opcode_name[693:699],
|
||||
130: _Opcode_name[699:705],
|
||||
131: _Opcode_name[705:711],
|
||||
132: _Opcode_name[711:717],
|
||||
133: _Opcode_name[717:723],
|
||||
134: _Opcode_name[723:729],
|
||||
135: _Opcode_name[729:734],
|
||||
136: _Opcode_name[734:743],
|
||||
137: _Opcode_name[743:749],
|
||||
139: _Opcode_name[749:752],
|
||||
140: _Opcode_name[752:758],
|
||||
141: _Opcode_name[758:762],
|
||||
142: _Opcode_name[762:767],
|
||||
144: _Opcode_name[767:773],
|
||||
145: _Opcode_name[773:776],
|
||||
146: _Opcode_name[776:778],
|
||||
147: _Opcode_name[778:781],
|
||||
151: _Opcode_name[781:786],
|
||||
152: _Opcode_name[786:794],
|
||||
153: _Opcode_name[794:798],
|
||||
154: _Opcode_name[798:801],
|
||||
155: _Opcode_name[801:807],
|
||||
156: _Opcode_name[807:810],
|
||||
157: _Opcode_name[810:813],
|
||||
158: _Opcode_name[813:816],
|
||||
159: _Opcode_name[816:819],
|
||||
160: _Opcode_name[819:822],
|
||||
161: _Opcode_name[822:825],
|
||||
162: _Opcode_name[825:828],
|
||||
168: _Opcode_name[828:831],
|
||||
169: _Opcode_name[831:834],
|
||||
170: _Opcode_name[834:837],
|
||||
171: _Opcode_name[837:844],
|
||||
172: _Opcode_name[844:850],
|
||||
177: _Opcode_name[850:852],
|
||||
179: _Opcode_name[852:860],
|
||||
180: _Opcode_name[860:871],
|
||||
181: _Opcode_name[871:873],
|
||||
182: _Opcode_name[873:876],
|
||||
183: _Opcode_name[876:878],
|
||||
184: _Opcode_name[878:881],
|
||||
185: _Opcode_name[881:884],
|
||||
186: _Opcode_name[884:887],
|
||||
187: _Opcode_name[887:893],
|
||||
192: _Opcode_name[893:897],
|
||||
193: _Opcode_name[897:903],
|
||||
194: _Opcode_name[903:912],
|
||||
195: _Opcode_name[912:920],
|
||||
196: _Opcode_name[920:930],
|
||||
197: _Opcode_name[930:940],
|
||||
198: _Opcode_name[940:949],
|
||||
200: _Opcode_name[949:955],
|
||||
202: _Opcode_name[955:959],
|
||||
203: _Opcode_name[959:965],
|
||||
204: _Opcode_name[965:969],
|
||||
205: _Opcode_name[969:975],
|
||||
206: _Opcode_name[975:983],
|
||||
207: _Opcode_name[983:989],
|
||||
208: _Opcode_name[989:996],
|
||||
209: _Opcode_name[996:1008],
|
||||
210: _Opcode_name[1008:1014],
|
||||
211: _Opcode_name[1014:1024],
|
||||
216: _Opcode_name[1024:1030],
|
||||
217: _Opcode_name[1030:1036],
|
||||
219: _Opcode_name[1036:1043],
|
||||
}
|
||||
|
||||
func (i Opcode) String() string {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Nothing more to test here, really.
|
||||
|
@ -18,3 +19,12 @@ func TestStringer(t *testing.T) {
|
|||
assert.Equal(t, s, o.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromString(t *testing.T) {
|
||||
_, err := FromString("abcdef")
|
||||
require.Error(t, err)
|
||||
|
||||
op, err := FromString(MUL.String())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, MUL, op)
|
||||
}
|
||||
|
|
|
@ -225,7 +225,9 @@ func (i *StructItem) Convert(typ StackItemType) (StackItem, error) {
|
|||
case StructT:
|
||||
return i, nil
|
||||
case ArrayT:
|
||||
return NewArrayItem(i.value), nil
|
||||
arr := make([]StackItem, len(i.value))
|
||||
copy(arr, i.value)
|
||||
return NewArrayItem(arr), nil
|
||||
case BooleanT:
|
||||
return NewBoolItem(i.Bool()), nil
|
||||
default:
|
||||
|
@ -641,7 +643,9 @@ func (i *ArrayItem) Convert(typ StackItemType) (StackItem, error) {
|
|||
case ArrayT:
|
||||
return i, nil
|
||||
case StructT:
|
||||
return NewStructItem(i.value), nil
|
||||
arr := make([]StackItem, len(i.value))
|
||||
copy(arr, i.value)
|
||||
return NewStructItem(arr), nil
|
||||
case BooleanT:
|
||||
return NewBoolItem(i.Bool()), nil
|
||||
default:
|
||||
|
|
59
pkg/vm/vm.go
59
pkg/vm/vm.go
|
@ -338,7 +338,7 @@ func (v *VM) Run() error {
|
|||
// check for breakpoint before executing the next instruction
|
||||
ctx := v.Context()
|
||||
if ctx != nil && ctx.atBreakPoint() {
|
||||
v.state |= breakState
|
||||
v.state = breakState
|
||||
}
|
||||
switch {
|
||||
case v.state.HasFlag(faultState):
|
||||
|
@ -376,7 +376,7 @@ func (v *VM) StepInto() error {
|
|||
ctx := v.Context()
|
||||
|
||||
if ctx == nil {
|
||||
v.state |= haltState
|
||||
v.state = haltState
|
||||
}
|
||||
|
||||
if v.HasStopped() {
|
||||
|
@ -518,17 +518,14 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
}
|
||||
|
||||
switch op {
|
||||
case opcode.PUSHM1, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3,
|
||||
case opcode.PUSHM1, opcode.PUSH0, opcode.PUSH1, opcode.PUSH2, opcode.PUSH3,
|
||||
opcode.PUSH4, opcode.PUSH5, opcode.PUSH6, opcode.PUSH7,
|
||||
opcode.PUSH8, opcode.PUSH9, opcode.PUSH10, opcode.PUSH11,
|
||||
opcode.PUSH12, opcode.PUSH13, opcode.PUSH14, opcode.PUSH15,
|
||||
opcode.PUSH16:
|
||||
val := int(op) - int(opcode.PUSH1) + 1
|
||||
val := int(op) - int(opcode.PUSH0)
|
||||
v.estack.PushVal(val)
|
||||
|
||||
case opcode.PUSH0:
|
||||
v.estack.PushVal([]byte{})
|
||||
|
||||
case opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4:
|
||||
v.estack.PushVal(parameter)
|
||||
|
||||
|
@ -697,7 +694,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
}
|
||||
s := v.estack.Pop().Bytes()
|
||||
if t := len(s); l > t {
|
||||
l = t
|
||||
panic("size is too big")
|
||||
}
|
||||
v.estack.PushVal(NewBufferItem(s[:l]))
|
||||
|
||||
|
@ -984,46 +981,28 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
|
||||
case opcode.NEWARRAY, opcode.NEWARRAYT:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *StructItem:
|
||||
arr := make([]StackItem, len(t.value))
|
||||
copy(arr, t.value)
|
||||
v.estack.PushVal(&ArrayItem{arr})
|
||||
case *ArrayItem:
|
||||
v.estack.PushVal(t)
|
||||
default:
|
||||
n := item.BigInt().Int64()
|
||||
if n > MaxArraySize {
|
||||
panic("too long array")
|
||||
}
|
||||
typ := BooleanT
|
||||
if op == opcode.NEWARRAYT {
|
||||
typ = StackItemType(parameter[0])
|
||||
}
|
||||
items := makeArrayOfType(int(n), typ)
|
||||
v.estack.PushVal(&ArrayItem{items})
|
||||
n := item.BigInt().Int64()
|
||||
if n > MaxArraySize {
|
||||
panic("too long array")
|
||||
}
|
||||
typ := AnyT
|
||||
if op == opcode.NEWARRAYT {
|
||||
typ = StackItemType(parameter[0])
|
||||
}
|
||||
items := makeArrayOfType(int(n), typ)
|
||||
v.estack.PushVal(&ArrayItem{items})
|
||||
|
||||
case opcode.NEWSTRUCT0:
|
||||
v.estack.PushVal(&StructItem{[]StackItem{}})
|
||||
|
||||
case opcode.NEWSTRUCT:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *ArrayItem:
|
||||
arr := make([]StackItem, len(t.value))
|
||||
copy(arr, t.value)
|
||||
v.estack.PushVal(&StructItem{arr})
|
||||
case *StructItem:
|
||||
v.estack.PushVal(t)
|
||||
default:
|
||||
n := item.BigInt().Int64()
|
||||
if n > MaxArraySize {
|
||||
panic("too long struct")
|
||||
}
|
||||
items := makeArrayOfType(int(n), BooleanT)
|
||||
v.estack.PushVal(&StructItem{items})
|
||||
n := item.BigInt().Int64()
|
||||
if n > MaxArraySize {
|
||||
panic("too long struct")
|
||||
}
|
||||
items := makeArrayOfType(int(n), AnyT)
|
||||
v.estack.PushVal(&StructItem{items})
|
||||
|
||||
case opcode.APPEND:
|
||||
itemElem := v.estack.Pop()
|
||||
|
|
|
@ -372,7 +372,7 @@ func appendBigStruct(size uint16) []opcode.Opcode {
|
|||
return append(prog,
|
||||
opcode.INITSSLOT, 1,
|
||||
opcode.PUSHINT16, opcode.Opcode(size), opcode.Opcode(size>>8), // LE
|
||||
opcode.PACK, opcode.NEWSTRUCT,
|
||||
opcode.PACK, opcode.CONVERT, opcode.Opcode(StructT),
|
||||
opcode.STSFLD0, opcode.LDSFLD0,
|
||||
opcode.DUP,
|
||||
opcode.PUSH0, opcode.NEWARRAY,
|
||||
|
@ -401,20 +401,19 @@ func TestStackLimit(t *testing.T) {
|
|||
{opcode.NEWARRAY, 3}, // array + 2 items
|
||||
{opcode.STSFLD0, 3},
|
||||
{opcode.LDSFLD0, 4},
|
||||
{opcode.NEWSTRUCT, 6}, // all items are copied
|
||||
{opcode.NEWMAP, 7},
|
||||
{opcode.DUP, 8},
|
||||
{opcode.PUSH2, 9},
|
||||
{opcode.LDSFLD0, 10},
|
||||
{opcode.SETITEM, 8}, // -3 items and 1 new element in map
|
||||
{opcode.DUP, 9},
|
||||
{opcode.PUSH2, 10},
|
||||
{opcode.LDSFLD0, 11},
|
||||
{opcode.SETITEM, 8}, // -3 items and no new elements in map
|
||||
{opcode.DUP, 9},
|
||||
{opcode.PUSH2, 10},
|
||||
{opcode.REMOVE, 7}, // as we have right after NEWMAP
|
||||
{opcode.DROP, 6}, // DROP map with no elements
|
||||
{opcode.NEWMAP, 5},
|
||||
{opcode.DUP, 6},
|
||||
{opcode.PUSH2, 7},
|
||||
{opcode.LDSFLD0, 8},
|
||||
{opcode.SETITEM, 6}, // -3 items and 1 new element in map
|
||||
{opcode.DUP, 7},
|
||||
{opcode.PUSH2, 8},
|
||||
{opcode.LDSFLD0, 9},
|
||||
{opcode.SETITEM, 6}, // -3 items and no new elements in map
|
||||
{opcode.DUP, 7},
|
||||
{opcode.PUSH2, 8},
|
||||
{opcode.REMOVE, 5}, // as we have right after NEWMAP
|
||||
{opcode.DROP, 4}, // DROP map with no elements
|
||||
}
|
||||
|
||||
prog := make([]opcode.Opcode, len(expected)+2)
|
||||
|
@ -1188,45 +1187,37 @@ func TestNEWARRAYArray(t *testing.T) {
|
|||
prog := makeProgram(opcode.NEWARRAY)
|
||||
t.Run("ByteArray", getTestFuncForVM(prog, NewArrayItem([]StackItem{}), []byte{}))
|
||||
t.Run("BadSize", getTestFuncForVM(prog, nil, MaxArraySize+1))
|
||||
t.Run("Integer", getTestFuncForVM(prog, []StackItem{NewBoolItem(false)}, 1))
|
||||
|
||||
arr := []StackItem{makeStackItem(42)}
|
||||
t.Run("Array", getTestFuncForVM(prog, arr, arr))
|
||||
t.Run("Struct", getTestFuncForVM(prog, arr, NewStructItem(arr)))
|
||||
t.Run("Integer", getTestFuncForVM(prog, []StackItem{NullItem{}}, 1))
|
||||
}
|
||||
|
||||
func testNEWARRAYIssue437(t *testing.T, i1, i2 opcode.Opcode, appended bool) {
|
||||
func testNEWARRAYIssue437(t *testing.T, i1 opcode.Opcode, t2 StackItemType, appended bool) {
|
||||
prog := makeProgram(
|
||||
opcode.PUSH2, i1,
|
||||
opcode.DUP, opcode.PUSH3, opcode.APPEND,
|
||||
opcode.INITSSLOT, 1,
|
||||
opcode.STSFLD0, opcode.LDSFLD0, i2,
|
||||
opcode.STSFLD0, opcode.LDSFLD0, opcode.CONVERT, opcode.Opcode(t2),
|
||||
opcode.DUP, opcode.PUSH4, opcode.APPEND,
|
||||
opcode.LDSFLD0, opcode.PUSH5, opcode.APPEND)
|
||||
vm := load(prog)
|
||||
vm.Run()
|
||||
|
||||
arr := makeArrayOfType(4, BooleanT)
|
||||
arr := makeArrayOfType(4, AnyT)
|
||||
arr[2] = makeStackItem(3)
|
||||
arr[3] = makeStackItem(4)
|
||||
if appended {
|
||||
arr = append(arr, makeStackItem(5))
|
||||
}
|
||||
|
||||
assert.Equal(t, false, vm.HasFailed())
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
if i2 == opcode.NEWARRAY {
|
||||
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
||||
if t2 == ArrayT {
|
||||
runWithArgs(t, prog, &ArrayItem{arr})
|
||||
} else {
|
||||
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
||||
runWithArgs(t, prog, &StructItem{arr})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNEWARRAYIssue437(t *testing.T) {
|
||||
t.Run("Array+Array", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWARRAY, opcode.NEWARRAY, true) })
|
||||
t.Run("Struct+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWSTRUCT, opcode.NEWSTRUCT, true) })
|
||||
t.Run("Array+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWARRAY, opcode.NEWSTRUCT, false) })
|
||||
t.Run("Struct+Array", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWSTRUCT, opcode.NEWARRAY, false) })
|
||||
t.Run("Array+Array", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWARRAY, ArrayT, true) })
|
||||
t.Run("Struct+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWSTRUCT, StructT, true) })
|
||||
t.Run("Array+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWARRAY, StructT, false) })
|
||||
t.Run("Struct+Array", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWSTRUCT, ArrayT, false) })
|
||||
}
|
||||
|
||||
func TestNEWARRAYT(t *testing.T) {
|
||||
|
@ -1247,11 +1238,7 @@ func TestNEWSTRUCT(t *testing.T) {
|
|||
prog := makeProgram(opcode.NEWSTRUCT)
|
||||
t.Run("ByteArray", getTestFuncForVM(prog, NewStructItem([]StackItem{}), []byte{}))
|
||||
t.Run("BadSize", getTestFuncForVM(prog, nil, MaxArraySize+1))
|
||||
t.Run("Integer", getTestFuncForVM(prog, NewStructItem([]StackItem{NewBoolItem(false)}), 1))
|
||||
|
||||
arr := []StackItem{makeStackItem(42)}
|
||||
t.Run("Array", getTestFuncForVM(prog, NewStructItem(arr), NewArrayItem(arr)))
|
||||
t.Run("Struct", getTestFuncForVM(prog, NewStructItem(arr), NewStructItem(arr)))
|
||||
t.Run("Integer", getTestFuncForVM(prog, NewStructItem([]StackItem{NullItem{}}), 1))
|
||||
}
|
||||
|
||||
func TestAPPEND(t *testing.T) {
|
||||
|
@ -1827,7 +1814,7 @@ func TestLEFT(t *testing.T) {
|
|||
t.Run("NoString", getTestFuncForVM(prog, nil, 2))
|
||||
t.Run("NegativeLen", getTestFuncForVM(prog, nil, "abcdef", -1))
|
||||
t.Run("Good", getTestFuncForVM(prog, NewBufferItem([]byte("ab")), "abcdef", 2))
|
||||
t.Run("GoodBigLen", getTestFuncForVM(prog, NewBufferItem([]byte("abcdef")), "abcdef", 8))
|
||||
t.Run("BadBigLen", getTestFuncForVM(prog, nil, "abcdef", 8))
|
||||
}
|
||||
|
||||
func TestRIGHT(t *testing.T) {
|
||||
|
@ -1903,14 +1890,12 @@ func TestREVERSEITEMS(t *testing.T) {
|
|||
t.Run("Buffer", getTestFuncForVM(prog, NewBufferItem([]byte{3, 2, 1}), NewBufferItem([]byte{1, 2, 3})))
|
||||
}
|
||||
|
||||
func testREVERSEITEMSIssue437(t *testing.T, i1, i2 opcode.Opcode, reversed bool) {
|
||||
func testREVERSEITEMSIssue437(t *testing.T, i1 opcode.Opcode, t2 StackItemType, reversed bool) {
|
||||
prog := makeProgram(
|
||||
opcode.PUSH0, i1,
|
||||
opcode.DUP, opcode.PUSH1, opcode.APPEND,
|
||||
opcode.DUP, opcode.PUSH2, opcode.APPEND,
|
||||
opcode.DUP, i2, opcode.REVERSEITEMS)
|
||||
vm := load(prog)
|
||||
vm.Run()
|
||||
opcode.DUP, opcode.CONVERT, opcode.Opcode(t2), opcode.REVERSEITEMS)
|
||||
|
||||
arr := make([]StackItem, 2)
|
||||
if reversed {
|
||||
|
@ -1920,20 +1905,19 @@ func testREVERSEITEMSIssue437(t *testing.T, i1, i2 opcode.Opcode, reversed bool)
|
|||
arr[0] = makeStackItem(1)
|
||||
arr[1] = makeStackItem(2)
|
||||
}
|
||||
assert.Equal(t, false, vm.HasFailed())
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
|
||||
if i1 == opcode.NEWARRAY {
|
||||
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
||||
runWithArgs(t, prog, &ArrayItem{arr})
|
||||
} else {
|
||||
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
||||
runWithArgs(t, prog, &StructItem{arr})
|
||||
}
|
||||
}
|
||||
|
||||
func TestREVERSEITEMSIssue437(t *testing.T) {
|
||||
t.Run("Array+Array", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWARRAY, opcode.NEWARRAY, true) })
|
||||
t.Run("Struct+Struct", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWSTRUCT, opcode.NEWSTRUCT, true) })
|
||||
t.Run("Array+Struct", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWARRAY, opcode.NEWSTRUCT, false) })
|
||||
t.Run("Struct+Array", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWSTRUCT, opcode.NEWARRAY, false) })
|
||||
t.Run("Array+Array", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWARRAY, ArrayT, true) })
|
||||
t.Run("Struct+Struct", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWSTRUCT, StructT, true) })
|
||||
t.Run("Array+Struct", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWARRAY, StructT, false) })
|
||||
t.Run("Struct+Array", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWSTRUCT, ArrayT, false) })
|
||||
}
|
||||
|
||||
func TestREVERSEITEMSGoodOneElem(t *testing.T) {
|
||||
|
@ -2471,7 +2455,9 @@ func makeProgram(opcodes ...opcode.Opcode) []byte {
|
|||
|
||||
func load(prog []byte) *VM {
|
||||
vm := New()
|
||||
vm.LoadScript(prog)
|
||||
if len(prog) != 0 {
|
||||
vm.LoadScript(prog)
|
||||
}
|
||||
return vm
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue