OSDN Git Service

Feat(BVM): change op add (#1862)
[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
162         y, err := vm.popBigInt(true)
163         if err != nil {
164                 return err
165         }
166
167         x, err := vm.popBigInt(true)
168         if err != nil {
169                 return err
170         }
171
172         if x.Add(x, y); x.Sign() < 0 {
173                 return ErrRange
174         }
175
176         return vm.pushBigInt(x, true)
177 }
178
179 func opSub(vm *virtualMachine) error {
180         err := vm.applyCost(2)
181         if err != nil {
182                 return err
183         }
184         y, err := vm.popInt64(true)
185         if err != nil {
186                 return err
187         }
188         x, err := vm.popInt64(true)
189         if err != nil {
190                 return err
191         }
192         res, ok := checked.SubInt64(x, y)
193         if !ok {
194                 return ErrRange
195         }
196         return vm.pushInt64(res, true)
197 }
198
199 func opMul(vm *virtualMachine) error {
200         err := vm.applyCost(8)
201         if err != nil {
202                 return err
203         }
204         y, err := vm.popInt64(true)
205         if err != nil {
206                 return err
207         }
208         x, err := vm.popInt64(true)
209         if err != nil {
210                 return err
211         }
212         res, ok := checked.MulInt64(x, y)
213         if !ok {
214                 return ErrRange
215         }
216         return vm.pushInt64(res, true)
217 }
218
219 func opDiv(vm *virtualMachine) error {
220         err := vm.applyCost(8)
221         if err != nil {
222                 return err
223         }
224         y, err := vm.popInt64(true)
225         if err != nil {
226                 return err
227         }
228         x, err := vm.popInt64(true)
229         if err != nil {
230                 return err
231         }
232         if y == 0 {
233                 return ErrDivZero
234         }
235         res, ok := checked.DivInt64(x, y)
236         if !ok {
237                 return ErrRange
238         }
239         return vm.pushInt64(res, true)
240 }
241
242 func opMod(vm *virtualMachine) error {
243         err := vm.applyCost(8)
244         if err != nil {
245                 return err
246         }
247         y, err := vm.popInt64(true)
248         if err != nil {
249                 return err
250         }
251         x, err := vm.popInt64(true)
252         if err != nil {
253                 return err
254         }
255         if y == 0 {
256                 return ErrDivZero
257         }
258
259         res, ok := checked.ModInt64(x, y)
260         if !ok {
261                 return ErrRange
262         }
263
264         // Go's modulus operator produces the wrong result for mixed-sign
265         // operands
266         if res != 0 && (x >= 0) != (y >= 0) {
267                 res += y
268         }
269
270         return vm.pushInt64(res, true)
271 }
272
273 func opLshift(vm *virtualMachine) error {
274         err := vm.applyCost(8)
275         if err != nil {
276                 return err
277         }
278         y, err := vm.popInt64(true)
279         if err != nil {
280                 return err
281         }
282         if y < 0 {
283                 return ErrBadValue
284         }
285         x, err := vm.popInt64(true)
286         if err != nil {
287                 return err
288         }
289         if x == 0 || y == 0 {
290                 return vm.pushInt64(x, true)
291         }
292
293         res, ok := checked.LshiftInt64(x, y)
294         if !ok {
295                 return ErrRange
296         }
297
298         return vm.pushInt64(res, true)
299 }
300
301 func opRshift(vm *virtualMachine) error {
302         err := vm.applyCost(8)
303         if err != nil {
304                 return err
305         }
306         y, err := vm.popInt64(true)
307         if err != nil {
308                 return err
309         }
310         x, err := vm.popInt64(true)
311         if err != nil {
312                 return err
313         }
314         if y < 0 {
315                 return ErrBadValue
316         }
317         return vm.pushInt64(x>>uint64(y), true)
318 }
319
320 func opBoolAnd(vm *virtualMachine) error {
321         err := vm.applyCost(2)
322         if err != nil {
323                 return err
324         }
325         b, err := vm.pop(true)
326         if err != nil {
327                 return err
328         }
329         a, err := vm.pop(true)
330         if err != nil {
331                 return err
332         }
333         return vm.pushBool(AsBool(a) && AsBool(b), true)
334 }
335
336 func opBoolOr(vm *virtualMachine) error {
337         err := vm.applyCost(2)
338         if err != nil {
339                 return err
340         }
341         b, err := vm.pop(true)
342         if err != nil {
343                 return err
344         }
345         a, err := vm.pop(true)
346         if err != nil {
347                 return err
348         }
349         return vm.pushBool(AsBool(a) || AsBool(b), true)
350 }
351
352 const (
353         cmpLess = iota
354         cmpLessEqual
355         cmpGreater
356         cmpGreaterEqual
357         cmpEqual
358         cmpNotEqual
359 )
360
361 func opNumEqual(vm *virtualMachine) error {
362         return doNumCompare(vm, cmpEqual)
363 }
364
365 func opNumEqualVerify(vm *virtualMachine) error {
366         err := vm.applyCost(2)
367         if err != nil {
368                 return err
369         }
370         y, err := vm.popInt64(true)
371         if err != nil {
372                 return err
373         }
374         x, err := vm.popInt64(true)
375         if err != nil {
376                 return err
377         }
378         if x == y {
379                 return nil
380         }
381         return ErrVerifyFailed
382 }
383
384 func opNumNotEqual(vm *virtualMachine) error {
385         return doNumCompare(vm, cmpNotEqual)
386 }
387
388 func opLessThan(vm *virtualMachine) error {
389         return doNumCompare(vm, cmpLess)
390 }
391
392 func opGreaterThan(vm *virtualMachine) error {
393         return doNumCompare(vm, cmpGreater)
394 }
395
396 func opLessThanOrEqual(vm *virtualMachine) error {
397         return doNumCompare(vm, cmpLessEqual)
398 }
399
400 func opGreaterThanOrEqual(vm *virtualMachine) error {
401         return doNumCompare(vm, cmpGreaterEqual)
402 }
403
404 func doNumCompare(vm *virtualMachine, op int) error {
405         err := vm.applyCost(2)
406         if err != nil {
407                 return err
408         }
409         y, err := vm.popBigInt(true)
410         if err != nil {
411                 return err
412         }
413         x, err := vm.popBigInt(true)
414         if err != nil {
415                 return err
416         }
417         var res bool
418         switch op {
419         case cmpLess:
420                 res = x.Cmp(y) < 0
421         case cmpLessEqual:
422                 res = x.Cmp(y) <= 0
423         case cmpGreater:
424                 res = x.Cmp(y) > 0
425         case cmpGreaterEqual:
426                 res = x.Cmp(y) >= 0
427         case cmpEqual:
428                 res = x.Cmp(y) == 0
429         case cmpNotEqual:
430                 res = x.Cmp(y) != 0
431         }
432         return vm.pushBool(res, true)
433 }
434
435 func opMin(vm *virtualMachine) error {
436         err := vm.applyCost(2)
437         if err != nil {
438                 return err
439         }
440         y, err := vm.popInt64(true)
441         if err != nil {
442                 return err
443         }
444         x, err := vm.popInt64(true)
445         if err != nil {
446                 return err
447         }
448         if x > y {
449                 x = y
450         }
451         return vm.pushInt64(x, true)
452 }
453
454 func opMax(vm *virtualMachine) error {
455         err := vm.applyCost(2)
456         if err != nil {
457                 return err
458         }
459         y, err := vm.popInt64(true)
460         if err != nil {
461                 return err
462         }
463         x, err := vm.popInt64(true)
464         if err != nil {
465                 return err
466         }
467         if x < y {
468                 x = y
469         }
470         return vm.pushInt64(x, true)
471 }
472
473 func opWithin(vm *virtualMachine) error {
474         err := vm.applyCost(4)
475         if err != nil {
476                 return err
477         }
478         max, err := vm.popInt64(true)
479         if err != nil {
480                 return err
481         }
482         min, err := vm.popInt64(true)
483         if err != nil {
484                 return err
485         }
486         x, err := vm.popInt64(true)
487         if err != nil {
488                 return err
489         }
490         return vm.pushBool(x >= min && x < max, true)
491 }