OSDN Git Service

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