diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 466b0d9a3..6bb8b2c62 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -1901,11 +1901,11 @@ func convertToken(tok token.Token, typ types.Type) (opcode.Opcode, error) { case token.LSS: return opcode.LT, nil case token.LEQ: - return opcode.LTE, nil + return opcode.LE, nil case token.GTR: return opcode.GT, nil case token.GEQ: - return opcode.GTE, nil + return opcode.GE, nil case token.EQL: // VM has separate opcodes for number and string equality if isNumber(typ) { diff --git a/pkg/core/fee/opcode.go b/pkg/core/fee/opcode.go index 752255a59..58dbd7f3c 100644 --- a/pkg/core/fee/opcode.go +++ b/pkg/core/fee/opcode.go @@ -173,9 +173,9 @@ var coefficients = map[opcode.Opcode]int64{ opcode.NUMEQUAL: 1 << 3, opcode.NUMNOTEQUAL: 1 << 3, opcode.LT: 1 << 3, - opcode.LTE: 1 << 3, + opcode.LE: 1 << 3, opcode.GT: 1 << 3, - opcode.GTE: 1 << 3, + opcode.GE: 1 << 3, opcode.MIN: 1 << 3, opcode.MAX: 1 << 3, opcode.WITHIN: 1 << 3, diff --git a/pkg/vm/opcode/opcode.go b/pkg/vm/opcode/opcode.go index 06ebd1805..e1fd89a56 100644 --- a/pkg/vm/opcode/opcode.go +++ b/pkg/vm/opcode/opcode.go @@ -188,9 +188,9 @@ const ( NUMEQUAL Opcode = 0xB3 NUMNOTEQUAL Opcode = 0xB4 LT Opcode = 0xB5 - LTE Opcode = 0xB6 + LE Opcode = 0xB6 GT Opcode = 0xB7 - GTE Opcode = 0xB8 + GE Opcode = 0xB8 MIN Opcode = 0xB9 MAX Opcode = 0xBA WITHIN Opcode = 0xBB diff --git a/pkg/vm/opcode/opcode_string.go b/pkg/vm/opcode/opcode_string.go index 9b2f293e3..ddfd47f23 100644 --- a/pkg/vm/opcode/opcode_string.go +++ b/pkg/vm/opcode/opcode_string.go @@ -170,9 +170,9 @@ func _() { _ = x[NUMEQUAL-179] _ = x[NUMNOTEQUAL-180] _ = x[LT-181] - _ = x[LTE-182] + _ = x[LE-182] _ = x[GT-183] - _ = x[GTE-184] + _ = x[GE-184] _ = x[MIN-185] _ = x[MAX-186] _ = x[WITHIN-187] @@ -200,7 +200,7 @@ func _() { _ = x[CONVERT-219] } -const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMP_LJMPIFJMPIF_LJMPIFNOTJMPIFNOT_LJMPEQJMPEQ_LJMPNEJMPNE_LJMPGTJMPGT_LJMPGEJMPGE_LJMPLTJMPLT_LJMPLEJMPLE_LCALLCALL_LCALLACALLTABORTASSERTTHROWTRYTRY_LENDTRYENDTRY_LENDFINALLYRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPROTROLLREVERSE3REVERSE4REVERSENINITSSLOTINITSLOTLDSFLD0LDSFLD1LDSFLD2LDSFLD3LDSFLD4LDSFLD5LDSFLD6LDSFLDSTSFLD0STSFLD1STSFLD2STSFLD3STSFLD4STSFLD5STSFLD6STSFLDLDLOC0LDLOC1LDLOC2LDLOC3LDLOC4LDLOC5LDLOC6LDLOCSTLOC0STLOC1STLOC2STLOC3STLOC4STLOC5STLOC6STLOCLDARG0LDARG1LDARG2LDARG3LDARG4LDARG5LDARG6LDARGSTARG0STARG1STARG2STARG3STARG4STARG5STARG6STARGNEWBUFFERMEMCPYCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODPOWSQRTSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAY_TNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSPOPITEMISNULLISTYPECONVERT" +const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMP_LJMPIFJMPIF_LJMPIFNOTJMPIFNOT_LJMPEQJMPEQ_LJMPNEJMPNE_LJMPGTJMPGT_LJMPGEJMPGE_LJMPLTJMPLT_LJMPLEJMPLE_LCALLCALL_LCALLACALLTABORTASSERTTHROWTRYTRY_LENDTRYENDTRY_LENDFINALLYRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPROTROLLREVERSE3REVERSE4REVERSENINITSSLOTINITSLOTLDSFLD0LDSFLD1LDSFLD2LDSFLD3LDSFLD4LDSFLD5LDSFLD6LDSFLDSTSFLD0STSFLD1STSFLD2STSFLD3STSFLD4STSFLD5STSFLD6STSFLDLDLOC0LDLOC1LDLOC2LDLOC3LDLOC4LDLOC5LDLOC6LDLOCSTLOC0STLOC1STLOC2STLOC3STLOC4STLOC5STLOC6STLOCLDARG0LDARG1LDARG2LDARG3LDARG4LDARG5LDARG6LDARGSTARG0STARG1STARG2STARG3STARG4STARG5STARG6STARGNEWBUFFERMEMCPYCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODPOWSQRTSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLEGTGEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAY_TNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSPOPITEMISNULLISTYPECONVERT" var _Opcode_map = map[Opcode]string{ 0: _Opcode_name[0:8], @@ -363,34 +363,34 @@ var _Opcode_map = map[Opcode]string{ 179: _Opcode_name[896:904], 180: _Opcode_name[904:915], 181: _Opcode_name[915:917], - 182: _Opcode_name[917:920], - 183: _Opcode_name[920:922], - 184: _Opcode_name[922:925], - 185: _Opcode_name[925:928], - 186: _Opcode_name[928:931], - 187: _Opcode_name[931:937], - 192: _Opcode_name[937:941], - 193: _Opcode_name[941:947], - 194: _Opcode_name[947:956], - 195: _Opcode_name[956:964], - 196: _Opcode_name[964:974], - 197: _Opcode_name[974:984], - 198: _Opcode_name[984:993], - 200: _Opcode_name[993:999], - 202: _Opcode_name[999:1003], - 203: _Opcode_name[1003:1009], - 204: _Opcode_name[1009:1013], - 205: _Opcode_name[1013:1019], - 206: _Opcode_name[1019:1027], - 207: _Opcode_name[1027:1033], - 208: _Opcode_name[1033:1040], - 209: _Opcode_name[1040:1052], - 210: _Opcode_name[1052:1058], - 211: _Opcode_name[1058:1068], - 212: _Opcode_name[1068:1075], - 216: _Opcode_name[1075:1081], - 217: _Opcode_name[1081:1087], - 219: _Opcode_name[1087:1094], + 182: _Opcode_name[917:919], + 183: _Opcode_name[919:921], + 184: _Opcode_name[921:923], + 185: _Opcode_name[923:926], + 186: _Opcode_name[926:929], + 187: _Opcode_name[929:935], + 192: _Opcode_name[935:939], + 193: _Opcode_name[939:945], + 194: _Opcode_name[945:954], + 195: _Opcode_name[954:962], + 196: _Opcode_name[962:972], + 197: _Opcode_name[972:982], + 198: _Opcode_name[982:991], + 200: _Opcode_name[991:997], + 202: _Opcode_name[997:1001], + 203: _Opcode_name[1001:1007], + 204: _Opcode_name[1007:1011], + 205: _Opcode_name[1011:1017], + 206: _Opcode_name[1017:1025], + 207: _Opcode_name[1025:1031], + 208: _Opcode_name[1031:1038], + 209: _Opcode_name[1038:1050], + 210: _Opcode_name[1050:1056], + 211: _Opcode_name[1056:1066], + 212: _Opcode_name[1066:1073], + 216: _Opcode_name[1073:1079], + 217: _Opcode_name[1079:1085], + 219: _Opcode_name[1085:1092], } func (i Opcode) String() string { diff --git a/pkg/vm/opcodebench_test.go b/pkg/vm/opcodebench_test.go index 7e03fa538..1657d4151 100644 --- a/pkg/vm/opcodebench_test.go +++ b/pkg/vm/opcodebench_test.go @@ -571,7 +571,7 @@ func BenchmarkOpcodes(t *testing.B) { } binaries := []opcode.Opcode{opcode.AND, opcode.OR, opcode.XOR, opcode.ADD, opcode.SUB, opcode.BOOLAND, opcode.BOOLOR, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, - opcode.LT, opcode.LTE, opcode.GT, opcode.GTE, opcode.MIN, opcode.MAX} + opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX} for _, op := range binaries { t.Run(op.String(), func(t *testing.B) { t.Run("0+0", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 0, 0)) }) diff --git a/pkg/vm/testdata/neo-vm b/pkg/vm/testdata/neo-vm index 3fb22406b..72e546b17 160000 --- a/pkg/vm/testdata/neo-vm +++ b/pkg/vm/testdata/neo-vm @@ -1 +1 @@ -Subproject commit 3fb22406ba72a86fb251c763aea72677f9f9baa2 +Subproject commit 72e546b176401b85a03bc4653eeb177badb42d3b diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 6391167ca..46f106482 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -972,25 +972,27 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro a := v.estack.Pop().BigInt() v.estack.PushVal(a.Cmp(b) != 0) - case opcode.LT: - b := v.estack.Pop().BigInt() - a := v.estack.Pop().BigInt() - v.estack.PushVal(a.Cmp(b) == -1) + case opcode.LT, opcode.LE, opcode.GT, opcode.GE: + eb := v.estack.Pop() + ea := v.estack.Pop() + _, aNil := ea.Item().(stackitem.Null) + _, bNil := eb.Item().(stackitem.Null) - case opcode.LTE: - b := v.estack.Pop().BigInt() - a := v.estack.Pop().BigInt() - v.estack.PushVal(a.Cmp(b) <= 0) - - case opcode.GT: - b := v.estack.Pop().BigInt() - a := v.estack.Pop().BigInt() - v.estack.PushVal(a.Cmp(b) == 1) - - case opcode.GTE: - b := v.estack.Pop().BigInt() - a := v.estack.Pop().BigInt() - v.estack.PushVal(a.Cmp(b) >= 0) + res := !aNil && !bNil + if res { + cmp := ea.BigInt().Cmp(eb.BigInt()) + switch op { + case opcode.LT: + res = cmp == -1 + case opcode.LE: + res = cmp <= 0 + case opcode.GT: + res = cmp == 1 + case opcode.GE: + res = cmp >= 0 + } + } + v.estack.PushVal(res) case opcode.MIN: b := v.estack.Pop().BigInt() diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index b937a9282..5fcaaa89c 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -807,13 +807,25 @@ func TestSHL(t *testing.T) { t.Run("BigResult", getTestFuncForVM(prog, nil, getBigInt(stackitem.MaxBigIntegerSizeBits/2, 0), stackitem.MaxBigIntegerSizeBits/2)) } +func TestArithNullArg(t *testing.T) { + for _, op := range []opcode.Opcode{opcode.LT, opcode.LE, opcode.GT, opcode.GE} { + prog := makeProgram(op) + t.Run(op.String(), func(t *testing.T) { + runWithArgs(t, prog, false, stackitem.Null{}, 0) + runWithArgs(t, prog, false, 0, stackitem.Null{}) + runWithArgs(t, prog, nil, stackitem.NewInterop(nil), 1) // also has `.Value() == nil` + }) + + } +} + func TestLT(t *testing.T) { prog := makeProgram(opcode.LT) runWithArgs(t, prog, false, 4, 3) } -func TestLTE(t *testing.T) { - prog := makeProgram(opcode.LTE) +func TestLE(t *testing.T) { + prog := makeProgram(opcode.LE) runWithArgs(t, prog, true, 2, 3) } @@ -822,8 +834,8 @@ func TestGT(t *testing.T) { runWithArgs(t, prog, true, 9, 3) } -func TestGTE(t *testing.T) { - prog := makeProgram(opcode.GTE) +func TestGE(t *testing.T) { + prog := makeProgram(opcode.GE) runWithArgs(t, prog, true, 3, 3) }