OSDN Git Service

Feat(BVM): change op not (#1861)
[bytom/bytom.git] / protocol / vm / numeric.go
1 package vm
2
3 import (
4         "math"
5
6         "github.com/holiman/uint256"
7
8         "github.com/bytom/bytom/math/checked"
9 )
10
11 func op1Add(vm *virtualMachine) error {
12         err := vm.applyCost(2)
13         if err != nil {
14                 return err
15         }
16
17         n, err := vm.popBigInt(true)
18         if err != nil {
19                 return err
20         }
21
22         num, ok := checked.NewUInt256("1")
23         if !ok {
24                 return ErrBadValue
25         }
26
27         if num.Add(n, num); num.Sign() < 0 {
28                 return ErrRange
29         }
30
31         return vm.pushBigInt(num, true)
32 }
33
34 func op1Sub(vm *virtualMachine) error {
35         err := vm.applyCost(2)
36         if err != nil {
37                 return err
38         }
39
40         n, err := vm.popBigInt(true)
41         if err != nil {
42                 return err
43         }
44
45         num, ok := checked.NewUInt256("1")
46         if !ok {
47                 return ErrBadValue
48         }
49
50         if num.Sub(n, num); num.Sign() < 0 {
51                 return ErrRange
52         }
53
54         return vm.pushBigInt(num, true)
55 }
56
57 func op2Mul(vm *virtualMachine) error {
58         err := vm.applyCost(2)
59         if err != nil {
60                 return err
61         }
62
63         n, err := vm.popBigInt(true)
64         if err != nil {
65                 return err
66         }
67
68         num, ok := checked.NewUInt256("2")
69         if !ok {
70                 return ErrBadValue
71         }
72
73         if num.Mul(n, num); num.Sign() < 0 {
74                 return ErrRange
75         }
76
77         return vm.pushBigInt(num, true)
78 }
79
80 func op2Div(vm *virtualMachine) error {
81         err := vm.applyCost(2)
82         if err != nil {
83                 return err
84         }
85
86         n, err := vm.popBigInt(true)
87         if err != nil {
88                 return err
89         }
90
91         return vm.pushBigInt(n.Rsh(n,1), true)
92 }
93
94 func opNegate(vm *virtualMachine) error {
95         err := vm.applyCost(2)
96         if err != nil {
97                 return err
98         }
99         n, err := vm.popInt64(true)
100         if err != nil {
101                 return err
102         }
103         res, ok := checked.NegateInt64(n)
104         if !ok {
105                 return ErrRange
106         }
107         return vm.pushInt64(res, true)
108 }
109
110 func opAbs(vm *virtualMachine) error {
111         err := vm.applyCost(2)
112         if err != nil {
113                 return err
114         }
115         n, err := vm.popInt64(true)
116         if err != nil {
117                 return err
118         }
119         if n == math.MinInt64 {
120                 return ErrRange
121         }
122         if n < 0 {
123                 n = -n
124         }
125         return vm.pushInt64(n, true)
126 }
127
128 func opNot(vm *virtualMachine) error {
129         err := vm.applyCost(2)
130         if err != nil {
131                 return err
132         }
133
134         n, err := vm.popBigInt(true)
135         if err != nil {
136                 return err
137         }
138
139         return vm.pushBool(n.Cmp(uint256.NewInt()) == 0, true)
140 }
141
142 func op0NotEqual(vm *virtualMachine) error {
143         err := vm.applyCost(2)
144         if err != nil {
145                 return err
146         }
147
148         n, err := vm.popBigInt(true)
149         if err != nil {
150                 return err
151         }
152
153         return vm.pushBool(n.Cmp(uint256.NewInt()) != 0, true)
154 }
155
156 func opAdd(vm *virtualMachine) error {
157         err := vm.applyCost(2)
158         if err != nil {
159                 return err
160         }
161         y, err := vm.popInt64(true)
162         if err != nil {
163                 return err
164         }
165         x, err := vm.popInt64(true)
166         if err != nil {
167                 return err
168         }
169         res, ok := checked.AddInt64(x, y)
170         if !ok {
171                 return ErrRange
172         }
173         return vm.pushInt64(res, true)
174 }
175
176 func opSub(vm *virtualMachine) error {
177         err := vm.applyCost(2)
178         if err != nil {
179                 return err
180         }
181         y, err := vm.popInt64(true)
182         if err != nil {
183                 return err
184         }
185         x, err := vm.popInt64(true)
186         if err != nil {
187                 return err
188         }
189         res, ok := checked.SubInt64(x, y)
190         if !ok {
191                 return ErrRange
192         }
193         return vm.pushInt64(res, true)
194 }
195
196 func opMul(vm *virtualMachine) error {
197         err := vm.applyCost(8)
198         if err != nil {
199                 return err
200         }
201         y, err := vm.popInt64(true)
202         if err != nil {
203                 return err
204         }
205         x, err := vm.popInt64(true)
206         if err != nil {
207                 return err
208         }
209         res, ok := checked.MulInt64(x, y)
210         if !ok {
211                 return ErrRange
212         }
213         return vm.pushInt64(res, true)
214 }
215
216 func opDiv(vm *virtualMachine) error {
217         err := vm.applyCost(8)
218         if err != nil {
219                 return err
220         }
221         y, err := vm.popInt64(true)
222         if err != nil {
223                 return err
224         }
225         x, err := vm.popInt64(true)
226         if err != nil {
227                 return err
228         }
229         if y == 0 {
230                 return ErrDivZero
231         }
232         res, ok := checked.DivInt64(x, y)
233         if !ok {
234                 return ErrRange
235         }
236         return vm.pushInt64(res, true)
237 }
238
239 func opMod(vm *virtualMachine) error {
240         err := vm.applyCost(8)
241         if err != nil {
242                 return err
243         }
244         y, err := vm.popInt64(true)
245         if err != nil {
246                 return err
247         }
248         x, err := vm.popInt64(true)
249         if err != nil {
250                 return err
251         }
252         if y == 0 {
253                 return ErrDivZero
254         }
255
256         res, ok := checked.ModInt64(x, y)
257         if !ok {
258                 return ErrRange
259         }
260
261         // Go's modulus operator produces the wrong result for mixed-sign
262         // operands
263         if res != 0 && (x >= 0) != (y >= 0) {
264                 res += y
265         }
266
267         return vm.pushInt64(res, true)
268 }
269
270 func opLshift(vm *virtualMachine) error {
271         err := vm.applyCost(8)
272         if err != nil {
273                 return err
274         }
275         y, err := vm.popInt64(true)
276         if err != nil {
277                 return err
278         }
279         if y < 0 {
280                 return ErrBadValue
281         }
282         x, err := vm.popInt64(true)
283         if err != nil {
284                 return err
285         }
286         if x == 0 || y == 0 {
287                 return vm.pushInt64(x, true)
288         }
289
290         res, ok := checked.LshiftInt64(x, y)
291         if !ok {
292                 return ErrRange
293         }
294
295         return vm.pushInt64(res, true)
296 }
297
298 func opRshift(vm *virtualMachine) error {
299         err := vm.applyCost(8)
300         if err != nil {
301                 return err
302         }
303         y, err := vm.popInt64(true)
304         if err != nil {
305                 return err
306         }
307         x, err := vm.popInt64(true)
308         if err != nil {
309                 return err
310         }
311         if y < 0 {
312                 return ErrBadValue
313         }
314         return vm.pushInt64(x>>uint64(y), true)
315 }
316
317 func opBoolAnd(vm *virtualMachine) error {
318         err := vm.applyCost(2)
319         if err != nil {
320                 return err
321         }
322         b, err := vm.pop(true)
323         if err != nil {
324                 return err
325         }
326         a, err := vm.pop(true)
327         if err != nil {
328                 return err
329         }
330         return vm.pushBool(AsBool(a) && AsBool(b), true)
331 }
332
333 func opBoolOr(vm *virtualMachine) error {
334         err := vm.applyCost(2)
335         if err != nil {
336                 return err
337         }
338         b, err := vm.pop(true)
339         if err != nil {
340                 return err
341         }
342         a, err := vm.pop(true)
343         if err != nil {
344                 return err
345         }
346         return vm.pushBool(AsBool(a) || AsBool(b), true)
347 }
348
349 const (
350         cmpLess = iota
351         cmpLessEqual
352         cmpGreater
353         cmpGreaterEqual
354         cmpEqual
355         cmpNotEqual
356 )
357
358 func opNumEqual(vm *virtualMachine) error {
359         return doNumCompare(vm, cmpEqual)
360 }
361
362 func opNumEqualVerify(vm *virtualMachine) error {
363         err := vm.applyCost(2)
364         if err != nil {
365                 return err
366         }
367         y, err := vm.popInt64(true)
368         if err != nil {
369                 return err
370         }
371         x, err := vm.popInt64(true)
372         if err != nil {
373                 return err
374         }
375         if x == y {
376                 return nil
377         }
378         return ErrVerifyFailed
379 }
380
381 func opNumNotEqual(vm *virtualMachine) error {
382         return doNumCompare(vm, cmpNotEqual)
383 }
384
385 func opLessThan(vm *virtualMachine) error {
386         return doNumCompare(vm, cmpLess)
387 }
388
389 func opGreaterThan(vm *virtualMachine) error {
390         return doNumCompare(vm, cmpGreater)
391 }
392
393 func opLessThanOrEqual(vm *virtualMachine) error {
394         return doNumCompare(vm, cmpLessEqual)
395 }
396
397 func opGreaterThanOrEqual(vm *virtualMachine) error {
398         return doNumCompare(vm, cmpGreaterEqual)
399 }
400
401 func doNumCompare(vm *virtualMachine, op int) error {
402         err := vm.applyCost(2)
403         if err != nil {
404                 return err
405         }
406         y, err := vm.popBigInt(true)
407         if err != nil {
408                 return err
409         }
410         x, err := vm.popBigInt(true)
411         if err != nil {
412                 return err
413         }
414         var res bool
415         switch op {
416         case cmpLess:
417                 res = x.Cmp(y) < 0
418         case cmpLessEqual:
419                 res = x.Cmp(y) <= 0
420         case cmpGreater:
421                 res = x.Cmp(y) > 0
422         case cmpGreaterEqual:
423                 res = x.Cmp(y) >= 0
424         case cmpEqual:
425                 res = x.Cmp(y) == 0
426         case cmpNotEqual:
427                 res = x.Cmp(y) != 0
428         }
429         return vm.pushBool(res, true)
430 }
431
432 func opMin(vm *virtualMachine) error {
433         err := vm.applyCost(2)
434         if err != nil {
435                 return err
436         }
437         y, err := vm.popInt64(true)
438         if err != nil {
439                 return err
440         }
441         x, err := vm.popInt64(true)
442         if err != nil {
443                 return err
444         }
445         if x > y {
446                 x = y
447         }
448         return vm.pushInt64(x, true)
449 }
450
451 func opMax(vm *virtualMachine) error {
452         err := vm.applyCost(2)
453         if err != nil {
454                 return err
455         }
456         y, err := vm.popInt64(true)
457         if err != nil {
458                 return err
459         }
460         x, err := vm.popInt64(true)
461         if err != nil {
462                 return err
463         }
464         if x < y {
465                 x = y
466         }
467         return vm.pushInt64(x, true)
468 }
469
470 func opWithin(vm *virtualMachine) error {
471         err := vm.applyCost(4)
472         if err != nil {
473                 return err
474         }
475         max, err := vm.popInt64(true)
476         if err != nil {
477                 return err
478         }
479         min, err := vm.popInt64(true)
480         if err != nil {
481                 return err
482         }
483         x, err := vm.popInt64(true)
484         if err != nil {
485                 return err
486         }
487         return vm.pushBool(x >= min && x < max, true)
488 }