OSDN Git Service

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