OSDN Git Service

Merge pull request #24 from Bytom/dev_consensus_engine_and_dpos
[bytom/vapor.git] / protocol / vm / bitwise.go
1 package vm
2
3 import (
4         "bytes"
5 )
6
7 func opInvert(vm *virtualMachine) error {
8         err := vm.applyCost(1)
9         if err != nil {
10                 return err
11         }
12         top, err := vm.top()
13         if err != nil {
14                 return err
15         }
16         err = vm.applyCost(int64(len(top)))
17         if err != nil {
18                 return err
19         }
20         // Could rewrite top in place but maybe it's a shared data
21         // structure?
22         newTop := make([]byte, 0, len(top))
23         for _, b := range top {
24                 newTop = append(newTop, ^b)
25         }
26         vm.dataStack[len(vm.dataStack)-1] = newTop
27         return nil
28 }
29
30 func opAnd(vm *virtualMachine) error {
31         err := vm.applyCost(1)
32         if err != nil {
33                 return err
34         }
35         b, err := vm.pop(true)
36         if err != nil {
37                 return err
38         }
39         a, err := vm.pop(true)
40         if err != nil {
41                 return err
42         }
43         min, max := len(a), len(b)
44         if min > max {
45                 min, max = max, min
46         }
47         err = vm.applyCost(int64(min))
48         if err != nil {
49                 return err
50         }
51         res := make([]byte, 0, min)
52         for i := 0; i < min; i++ {
53                 res = append(res, a[i]&b[i])
54         }
55         return vm.push(res, true)
56 }
57
58 func opOr(vm *virtualMachine) error {
59         return doOr(vm, false)
60 }
61
62 func opXor(vm *virtualMachine) error {
63         return doOr(vm, true)
64 }
65
66 func doOr(vm *virtualMachine, xor bool) error {
67         err := vm.applyCost(1)
68         if err != nil {
69                 return err
70         }
71         b, err := vm.pop(true)
72         if err != nil {
73                 return err
74         }
75         a, err := vm.pop(true)
76         if err != nil {
77                 return err
78         }
79         min, max := len(a), len(b)
80         if min > max {
81                 min, max = max, min
82         }
83         err = vm.applyCost(int64(max))
84         if err != nil {
85                 return err
86         }
87         res := make([]byte, 0, max)
88         for i := 0; i < max; i++ {
89                 var aByte, bByte, resByte byte
90                 if i >= len(a) {
91                         aByte = 0
92                 } else {
93                         aByte = a[i]
94                 }
95                 if i >= len(b) {
96                         bByte = 0
97                 } else {
98                         bByte = b[i]
99                 }
100                 if xor {
101                         resByte = aByte ^ bByte
102                 } else {
103                         resByte = aByte | bByte
104                 }
105
106                 res = append(res, resByte)
107         }
108         return vm.push(res, true)
109 }
110
111 func opEqual(vm *virtualMachine) error {
112         res, err := doEqual(vm)
113         if err != nil {
114                 return err
115         }
116         return vm.pushBool(res, true)
117 }
118
119 func opEqualVerify(vm *virtualMachine) error {
120         res, err := doEqual(vm)
121         if err != nil {
122                 return err
123         }
124         if res {
125                 return nil
126         }
127         return ErrVerifyFailed
128 }
129
130 func doEqual(vm *virtualMachine) (bool, error) {
131         err := vm.applyCost(1)
132         if err != nil {
133                 return false, err
134         }
135         b, err := vm.pop(true)
136         if err != nil {
137                 return false, err
138         }
139         a, err := vm.pop(true)
140         if err != nil {
141                 return false, err
142         }
143         min, max := len(a), len(b)
144         if min > max {
145                 min, max = max, min
146         }
147         err = vm.applyCost(int64(min))
148         if err != nil {
149                 return false, err
150         }
151         return bytes.Equal(a, b), nil
152 }