Merge pull request #919 from nspcc-dev/feature/arith
vm: reorder arithmetic and bitwise opcodes
This commit is contained in:
commit
40e153030d
10 changed files with 424 additions and 1378 deletions
8
go.sum
8
go.sum
|
@ -129,16 +129,8 @@ github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a h1:ajvxgEe9qY4vvoSm
|
|||
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1 h1:yEx9WznS+rjE0jl0dLujCxuZSIb+UTjF+005TJu/nNI=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200303183127-36d3da79c682 h1:63OWUolW4GcjJR7cThq8hLnMLTwL+sjO3Qf4fo4sx8w=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200303183127-36d3da79c682/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200427132226-05feeca847dd h1:4XKbXahJWlhjVx2cETQz9edHQfe3BQ2JjNdvSKFBelY=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200427132226-05feeca847dd/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200427132226-15a7927772a4 h1:3cFSp4v2u9+S7K1GdLUOP1680EiGEHSBvSI6G2n8XzY=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200427132226-15a7927772a4/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200427132226-342f23599814 h1:iNqBioi0RU2VX9UiGl/GfQKBbZrDWq5KSxQG+dgTaqo=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200427132226-342f23599814/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200427132226-660464796c11 h1:sledsmRo0wzgWNCZir5/CeM0PjhHVP8khnGtOfBCFWk=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200427132226-660464796c11/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||
github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg=
|
||||
github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck=
|
||||
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
|
||||
|
|
|
@ -616,8 +616,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
case n.Op == token.NEQ:
|
||||
// VM has separate opcodes for number and string equality
|
||||
if isStringType(c.typeInfo.Types[n.X].Type) {
|
||||
emit.Opcode(c.prog.BinWriter, opcode.EQUAL)
|
||||
emit.Opcode(c.prog.BinWriter, opcode.NOT)
|
||||
emit.Opcode(c.prog.BinWriter, opcode.NOTEQUAL)
|
||||
} else {
|
||||
emit.Opcode(c.prog.BinWriter, opcode.NUMNOTEQUAL)
|
||||
}
|
||||
|
|
|
@ -47,18 +47,18 @@ type rpcTestCase struct {
|
|||
check func(t *testing.T, e *executor, result interface{})
|
||||
}
|
||||
|
||||
const testContractHash = "7858559a8405f4e4e1834fcff274ddf4f1b8f407"
|
||||
const testContractHash = "642e2f47cc6883f0c196cf0dd3dcbb2333300173"
|
||||
|
||||
var rpcTestCases = map[string][]rpcTestCase{
|
||||
"getapplicationlog": {
|
||||
{
|
||||
name: "positive",
|
||||
params: `["fe1a3678b16eca35209acf85397708eb0f1668e4045ad4cd5d2453d3bc0a0a6d"]`,
|
||||
params: `["953b6e5ba85dd068c2eba5afd2ffdf8ff832b3a791976e2fd896baf5737b2616"]`,
|
||||
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
||||
check: func(t *testing.T, e *executor, acc interface{}) {
|
||||
res, ok := acc.(*result.ApplicationLog)
|
||||
require.True(t, ok)
|
||||
expectedTxHash, err := util.Uint256DecodeStringLE("fe1a3678b16eca35209acf85397708eb0f1668e4045ad4cd5d2453d3bc0a0a6d")
|
||||
expectedTxHash, err := util.Uint256DecodeStringLE("953b6e5ba85dd068c2eba5afd2ffdf8ff832b3a791976e2fd896baf5737b2616")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedTxHash, res.TxHash)
|
||||
assert.Equal(t, 1, len(res.Executions))
|
||||
|
|
BIN
pkg/rpc/server/testdata/test_contract.avm
vendored
BIN
pkg/rpc/server/testdata/test_contract.avm
vendored
Binary file not shown.
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
Binary file not shown.
|
@ -98,38 +98,39 @@ const (
|
|||
RIGHT Opcode = 0x81
|
||||
|
||||
// Bitwise logic
|
||||
INVERT Opcode = 0x83
|
||||
AND Opcode = 0x84
|
||||
OR Opcode = 0x85
|
||||
XOR Opcode = 0x86
|
||||
EQUAL Opcode = 0x87
|
||||
INVERT Opcode = 0x90
|
||||
AND Opcode = 0x91
|
||||
OR Opcode = 0x92
|
||||
XOR Opcode = 0x93
|
||||
EQUAL Opcode = 0x97
|
||||
NOTEQUAL Opcode = 0x98
|
||||
|
||||
// Arithmetic
|
||||
INC Opcode = 0x8B
|
||||
DEC Opcode = 0x8C
|
||||
SIGN Opcode = 0x8D
|
||||
NEGATE Opcode = 0x8F
|
||||
ABS Opcode = 0x90
|
||||
NOT Opcode = 0x91
|
||||
NZ Opcode = 0x92
|
||||
ADD Opcode = 0x93
|
||||
SUB Opcode = 0x94
|
||||
MUL Opcode = 0x95
|
||||
DIV Opcode = 0x96
|
||||
MOD Opcode = 0x97
|
||||
SHL Opcode = 0x98
|
||||
SHR Opcode = 0x99
|
||||
BOOLAND Opcode = 0x9A
|
||||
BOOLOR Opcode = 0x9B
|
||||
NUMEQUAL Opcode = 0x9C
|
||||
NUMNOTEQUAL Opcode = 0x9E
|
||||
LT Opcode = 0x9F
|
||||
GT Opcode = 0xA0
|
||||
LTE Opcode = 0xA1
|
||||
GTE Opcode = 0xA2
|
||||
MIN Opcode = 0xA3
|
||||
MAX Opcode = 0xA4
|
||||
WITHIN Opcode = 0xA5
|
||||
SIGN Opcode = 0x99
|
||||
ABS Opcode = 0x9A
|
||||
NEGATE Opcode = 0x9B
|
||||
INC Opcode = 0x9C
|
||||
DEC Opcode = 0x9D
|
||||
ADD Opcode = 0x9E
|
||||
SUB Opcode = 0x9F
|
||||
MUL Opcode = 0xA0
|
||||
DIV Opcode = 0xA1
|
||||
MOD Opcode = 0xA2
|
||||
SHL Opcode = 0xA8
|
||||
SHR Opcode = 0xA9
|
||||
NOT Opcode = 0xAA
|
||||
BOOLAND Opcode = 0xAB
|
||||
BOOLOR Opcode = 0xAC
|
||||
NZ Opcode = 0xB1
|
||||
NUMEQUAL Opcode = 0xB3
|
||||
NUMNOTEQUAL Opcode = 0xB4
|
||||
LT Opcode = 0xB5
|
||||
LTE Opcode = 0xB6
|
||||
GT Opcode = 0xB7
|
||||
GTE Opcode = 0xB8
|
||||
MIN Opcode = 0xB9
|
||||
MAX Opcode = 0xBA
|
||||
WITHIN Opcode = 0xBB
|
||||
|
||||
// Advanced data structures (arrays, structures, maps)
|
||||
PACK Opcode = 0xC0
|
||||
|
|
|
@ -84,36 +84,36 @@ func _() {
|
|||
_ = x[SUBSTR-127]
|
||||
_ = x[LEFT-128]
|
||||
_ = x[RIGHT-129]
|
||||
_ = x[INVERT-131]
|
||||
_ = x[AND-132]
|
||||
_ = x[OR-133]
|
||||
_ = x[XOR-134]
|
||||
_ = x[EQUAL-135]
|
||||
_ = x[INC-139]
|
||||
_ = x[DEC-140]
|
||||
_ = x[SIGN-141]
|
||||
_ = x[NEGATE-143]
|
||||
_ = x[ABS-144]
|
||||
_ = x[NOT-145]
|
||||
_ = x[NZ-146]
|
||||
_ = x[ADD-147]
|
||||
_ = x[SUB-148]
|
||||
_ = x[MUL-149]
|
||||
_ = x[DIV-150]
|
||||
_ = x[MOD-151]
|
||||
_ = x[SHL-152]
|
||||
_ = x[SHR-153]
|
||||
_ = x[BOOLAND-154]
|
||||
_ = x[BOOLOR-155]
|
||||
_ = x[NUMEQUAL-156]
|
||||
_ = x[NUMNOTEQUAL-158]
|
||||
_ = x[LT-159]
|
||||
_ = x[GT-160]
|
||||
_ = x[LTE-161]
|
||||
_ = x[GTE-162]
|
||||
_ = x[MIN-163]
|
||||
_ = x[MAX-164]
|
||||
_ = x[WITHIN-165]
|
||||
_ = x[INVERT-144]
|
||||
_ = x[AND-145]
|
||||
_ = x[OR-146]
|
||||
_ = x[XOR-147]
|
||||
_ = x[EQUAL-151]
|
||||
_ = x[SIGN-153]
|
||||
_ = x[ABS-154]
|
||||
_ = x[NEGATE-155]
|
||||
_ = x[INC-156]
|
||||
_ = x[DEC-157]
|
||||
_ = x[ADD-158]
|
||||
_ = x[SUB-159]
|
||||
_ = x[MUL-160]
|
||||
_ = x[DIV-161]
|
||||
_ = x[MOD-162]
|
||||
_ = x[SHL-168]
|
||||
_ = x[SHR-169]
|
||||
_ = x[NOT-170]
|
||||
_ = x[BOOLAND-171]
|
||||
_ = x[BOOLOR-172]
|
||||
_ = x[NZ-177]
|
||||
_ = x[NUMEQUAL-179]
|
||||
_ = x[NUMNOTEQUAL-180]
|
||||
_ = x[LT-181]
|
||||
_ = x[LTE-182]
|
||||
_ = x[GT-183]
|
||||
_ = x[GTE-184]
|
||||
_ = x[MIN-185]
|
||||
_ = x[MAX-186]
|
||||
_ = x[WITHIN-187]
|
||||
_ = x[PACK-192]
|
||||
_ = x[UNPACK-193]
|
||||
_ = x[NEWARRAY0-194]
|
||||
|
@ -139,7 +139,7 @@ func _() {
|
|||
_ = x[THROWIFNOT-241]
|
||||
}
|
||||
|
||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERTTHROWTHROWIFNOT"
|
||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERTTHROWTHROWIFNOT"
|
||||
|
||||
var _Opcode_map = map[Opcode]string{
|
||||
0: _Opcode_name[0:8],
|
||||
|
@ -216,36 +216,36 @@ var _Opcode_map = map[Opcode]string{
|
|||
127: _Opcode_name[427:433],
|
||||
128: _Opcode_name[433:437],
|
||||
129: _Opcode_name[437:442],
|
||||
131: _Opcode_name[442:448],
|
||||
132: _Opcode_name[448:451],
|
||||
133: _Opcode_name[451:453],
|
||||
134: _Opcode_name[453:456],
|
||||
135: _Opcode_name[456:461],
|
||||
139: _Opcode_name[461:464],
|
||||
140: _Opcode_name[464:467],
|
||||
141: _Opcode_name[467:471],
|
||||
143: _Opcode_name[471:477],
|
||||
144: _Opcode_name[477:480],
|
||||
145: _Opcode_name[480:483],
|
||||
146: _Opcode_name[483:485],
|
||||
147: _Opcode_name[485:488],
|
||||
148: _Opcode_name[488:491],
|
||||
149: _Opcode_name[491:494],
|
||||
150: _Opcode_name[494:497],
|
||||
151: _Opcode_name[497:500],
|
||||
152: _Opcode_name[500:503],
|
||||
153: _Opcode_name[503:506],
|
||||
154: _Opcode_name[506:513],
|
||||
155: _Opcode_name[513:519],
|
||||
156: _Opcode_name[519:527],
|
||||
158: _Opcode_name[527:538],
|
||||
159: _Opcode_name[538:540],
|
||||
160: _Opcode_name[540:542],
|
||||
161: _Opcode_name[542:545],
|
||||
162: _Opcode_name[545:548],
|
||||
163: _Opcode_name[548:551],
|
||||
164: _Opcode_name[551:554],
|
||||
165: _Opcode_name[554:560],
|
||||
144: _Opcode_name[442:448],
|
||||
145: _Opcode_name[448:451],
|
||||
146: _Opcode_name[451:453],
|
||||
147: _Opcode_name[453:456],
|
||||
151: _Opcode_name[456:461],
|
||||
153: _Opcode_name[461:465],
|
||||
154: _Opcode_name[465:468],
|
||||
155: _Opcode_name[468:474],
|
||||
156: _Opcode_name[474:477],
|
||||
157: _Opcode_name[477:480],
|
||||
158: _Opcode_name[480:483],
|
||||
159: _Opcode_name[483:486],
|
||||
160: _Opcode_name[486:489],
|
||||
161: _Opcode_name[489:492],
|
||||
162: _Opcode_name[492:495],
|
||||
168: _Opcode_name[495:498],
|
||||
169: _Opcode_name[498:501],
|
||||
170: _Opcode_name[501:504],
|
||||
171: _Opcode_name[504:511],
|
||||
172: _Opcode_name[511:517],
|
||||
177: _Opcode_name[517:519],
|
||||
179: _Opcode_name[519:527],
|
||||
180: _Opcode_name[527:538],
|
||||
181: _Opcode_name[538:540],
|
||||
182: _Opcode_name[540:543],
|
||||
183: _Opcode_name[543:545],
|
||||
184: _Opcode_name[545:548],
|
||||
185: _Opcode_name[548:551],
|
||||
186: _Opcode_name[551:554],
|
||||
187: _Opcode_name[554:560],
|
||||
192: _Opcode_name[560:564],
|
||||
193: _Opcode_name[564:570],
|
||||
194: _Opcode_name[570:579],
|
||||
|
|
|
@ -85,9 +85,7 @@ func makeStackItem(v interface{}) StackItem {
|
|||
value: val,
|
||||
}
|
||||
case *big.Int:
|
||||
return &BigIntegerItem{
|
||||
value: val,
|
||||
}
|
||||
return NewBigIntegerItem(val)
|
||||
case StackItem:
|
||||
return val
|
||||
case []int:
|
||||
|
@ -311,6 +309,9 @@ type BigIntegerItem struct {
|
|||
|
||||
// NewBigIntegerItem returns an new BigIntegerItem object.
|
||||
func NewBigIntegerItem(value *big.Int) *BigIntegerItem {
|
||||
if value.BitLen() > MaxBigIntegerSizeBits {
|
||||
panic("integer is too big")
|
||||
}
|
||||
return &BigIntegerItem{
|
||||
value: value,
|
||||
}
|
||||
|
@ -519,7 +520,11 @@ func (i *ByteArrayItem) TryBytes() ([]byte, error) {
|
|||
|
||||
// TryInteger implements StackItem interface.
|
||||
func (i *ByteArrayItem) TryInteger() (*big.Int, error) {
|
||||
return emit.BytesToInt(i.value), nil
|
||||
bi := emit.BytesToInt(i.value)
|
||||
if bi.BitLen() > MaxBigIntegerSizeBits {
|
||||
return nil, errors.New("integer is too big")
|
||||
}
|
||||
return bi, nil
|
||||
}
|
||||
|
||||
// Equals implements StackItem interface.
|
||||
|
|
129
pkg/vm/vm.go
129
pkg/vm/vm.go
|
@ -726,17 +726,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
}
|
||||
v.estack.Pop()
|
||||
|
||||
case opcode.EQUAL:
|
||||
b := v.estack.Pop()
|
||||
if b == nil {
|
||||
panic("no top-level element found")
|
||||
}
|
||||
a := v.estack.Pop()
|
||||
if a == nil {
|
||||
panic("no second-to-the-top element found")
|
||||
}
|
||||
v.estack.PushVal(a.value.Equals(b.value))
|
||||
|
||||
// Bit operations.
|
||||
case opcode.INVERT:
|
||||
// inplace
|
||||
|
@ -759,50 +748,70 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(new(big.Int).Xor(b, a))
|
||||
|
||||
case opcode.EQUAL, opcode.NOTEQUAL:
|
||||
b := v.estack.Pop()
|
||||
if b == nil {
|
||||
panic("no top-level element found")
|
||||
}
|
||||
a := v.estack.Pop()
|
||||
if a == nil {
|
||||
panic("no second-to-the-top element found")
|
||||
}
|
||||
v.estack.PushVal(a.value.Equals(b.value) == (op == opcode.EQUAL))
|
||||
|
||||
// Numeric operations.
|
||||
case opcode.SIGN:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Sign())
|
||||
|
||||
case opcode.ABS:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Abs(x))
|
||||
|
||||
case opcode.NEGATE:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Neg(x))
|
||||
|
||||
case opcode.INC:
|
||||
x := v.estack.Pop().BigInt()
|
||||
a := new(big.Int).Add(x, big.NewInt(1))
|
||||
v.estack.PushVal(a)
|
||||
|
||||
case opcode.DEC:
|
||||
x := v.estack.Pop().BigInt()
|
||||
a := new(big.Int).Sub(x, big.NewInt(1))
|
||||
v.estack.PushVal(a)
|
||||
|
||||
case opcode.ADD:
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(a)
|
||||
b := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(b)
|
||||
|
||||
c := new(big.Int).Add(a, b)
|
||||
v.checkBigIntSize(c)
|
||||
v.estack.PushVal(c)
|
||||
|
||||
case opcode.SUB:
|
||||
b := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(b)
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(a)
|
||||
|
||||
c := new(big.Int).Sub(a, b)
|
||||
v.checkBigIntSize(c)
|
||||
v.estack.PushVal(c)
|
||||
|
||||
case opcode.MUL:
|
||||
a := v.estack.Pop().BigInt()
|
||||
b := v.estack.Pop().BigInt()
|
||||
|
||||
c := new(big.Int).Mul(a, b)
|
||||
v.estack.PushVal(c)
|
||||
|
||||
case opcode.DIV:
|
||||
b := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(b)
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(a)
|
||||
|
||||
v.estack.PushVal(new(big.Int).Quo(a, b))
|
||||
|
||||
case opcode.MUL:
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(a)
|
||||
b := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(b)
|
||||
|
||||
c := new(big.Int).Mul(a, b)
|
||||
v.checkBigIntSize(c)
|
||||
v.estack.PushVal(c)
|
||||
|
||||
case opcode.MOD:
|
||||
b := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(b)
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(a)
|
||||
|
||||
v.estack.PushVal(new(big.Int).Rem(a, b))
|
||||
|
||||
|
@ -814,7 +823,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
panic(fmt.Sprintf("operand must be between %d and %d", 0, maxSHLArg))
|
||||
}
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.checkBigIntSize(a)
|
||||
|
||||
var item big.Int
|
||||
if op == opcode.SHL {
|
||||
|
@ -823,9 +831,12 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
item.Rsh(a, uint(b))
|
||||
}
|
||||
|
||||
v.checkBigIntSize(&item)
|
||||
v.estack.PushVal(&item)
|
||||
|
||||
case opcode.NOT:
|
||||
x := v.estack.Pop().Bool()
|
||||
v.estack.PushVal(!x)
|
||||
|
||||
case opcode.BOOLAND:
|
||||
b := v.estack.Pop().Bool()
|
||||
a := v.estack.Pop().Bool()
|
||||
|
@ -836,6 +847,10 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
a := v.estack.Pop().Bool()
|
||||
v.estack.PushVal(a || b)
|
||||
|
||||
case opcode.NZ:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Sign() != 0)
|
||||
|
||||
case opcode.NUMEQUAL:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
|
@ -851,16 +866,16 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(b) == -1)
|
||||
|
||||
case opcode.GT:
|
||||
b := v.estack.Pop().BigInt()
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(b) == 1)
|
||||
|
||||
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()
|
||||
|
@ -890,38 +905,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(a.Cmp(x) <= 0 && x.Cmp(b) == -1)
|
||||
|
||||
case opcode.INC:
|
||||
x := v.estack.Pop().BigInt()
|
||||
a := new(big.Int).Add(x, big.NewInt(1))
|
||||
v.checkBigIntSize(a)
|
||||
v.estack.PushVal(a)
|
||||
|
||||
case opcode.DEC:
|
||||
x := v.estack.Pop().BigInt()
|
||||
a := new(big.Int).Sub(x, big.NewInt(1))
|
||||
v.checkBigIntSize(a)
|
||||
v.estack.PushVal(a)
|
||||
|
||||
case opcode.SIGN:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Sign())
|
||||
|
||||
case opcode.NEGATE:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Neg(x))
|
||||
|
||||
case opcode.ABS:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Abs(x))
|
||||
|
||||
case opcode.NOT:
|
||||
x := v.estack.Pop().Bool()
|
||||
v.estack.PushVal(!x)
|
||||
|
||||
case opcode.NZ:
|
||||
x := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(x.Cmp(big.NewInt(0)) != 0)
|
||||
|
||||
// Object operations
|
||||
case opcode.NEWARRAY0:
|
||||
v.estack.PushVal(&ArrayItem{[]StackItem{}})
|
||||
|
@ -1527,12 +1510,6 @@ func (v *VM) checkInvocationStackSize() {
|
|||
}
|
||||
}
|
||||
|
||||
func (v *VM) checkBigIntSize(a *big.Int) {
|
||||
if a.BitLen() > MaxBigIntegerSizeBits {
|
||||
panic("big integer is too big")
|
||||
}
|
||||
}
|
||||
|
||||
// bytesToPublicKey is a helper deserializing keys using cache and panicing on
|
||||
// error.
|
||||
func (v *VM) bytesToPublicKey(b []byte) *keys.PublicKey {
|
||||
|
|
1460
pkg/vm/vm_test.go
1460
pkg/vm/vm_test.go
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue