OSDN Git Service

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