OSDN Git Service

new repo
[bytom/vapor.git] / protocol / vm / stack.go
1 package vm
2
3 import "github.com/vapor/math/checked"
4
5 func opToAltStack(vm *virtualMachine) error {
6         err := vm.applyCost(2)
7         if err != nil {
8                 return err
9         }
10         if len(vm.dataStack) == 0 {
11                 return ErrDataStackUnderflow
12         }
13         // no standard memory cost accounting here
14         vm.altStack = append(vm.altStack, vm.dataStack[len(vm.dataStack)-1])
15         vm.dataStack = vm.dataStack[:len(vm.dataStack)-1]
16         return nil
17 }
18
19 func opFromAltStack(vm *virtualMachine) error {
20         err := vm.applyCost(2)
21         if err != nil {
22                 return err
23         }
24         if len(vm.altStack) == 0 {
25                 return ErrAltStackUnderflow
26         }
27         // no standard memory cost accounting here
28         vm.dataStack = append(vm.dataStack, vm.altStack[len(vm.altStack)-1])
29         vm.altStack = vm.altStack[:len(vm.altStack)-1]
30         return nil
31 }
32
33 func op2Drop(vm *virtualMachine) error {
34         err := vm.applyCost(2)
35         if err != nil {
36                 return err
37         }
38         for i := 0; i < 2; i++ {
39                 _, err = vm.pop(false)
40                 if err != nil {
41                         return err
42                 }
43         }
44         return nil
45 }
46
47 func op2Dup(vm *virtualMachine) error {
48         return nDup(vm, 2)
49 }
50
51 func op3Dup(vm *virtualMachine) error {
52         return nDup(vm, 3)
53 }
54
55 func nDup(vm *virtualMachine, n int) error {
56         err := vm.applyCost(int64(n))
57         if err != nil {
58                 return err
59         }
60         if len(vm.dataStack) < n {
61                 return ErrDataStackUnderflow
62         }
63         for i := 0; i < n; i++ {
64                 err = vm.push(vm.dataStack[len(vm.dataStack)-n], false)
65                 if err != nil {
66                         return err
67                 }
68         }
69         return nil
70 }
71
72 func op2Over(vm *virtualMachine) error {
73         err := vm.applyCost(2)
74         if err != nil {
75                 return err
76         }
77         if len(vm.dataStack) < 4 {
78                 return ErrDataStackUnderflow
79         }
80         for i := 0; i < 2; i++ {
81                 err = vm.push(vm.dataStack[len(vm.dataStack)-4], false)
82                 if err != nil {
83                         return err
84                 }
85         }
86         return nil
87 }
88
89 func op2Rot(vm *virtualMachine) error {
90         err := vm.applyCost(2)
91         if err != nil {
92                 return err
93         }
94         if len(vm.dataStack) < 6 {
95                 return ErrDataStackUnderflow
96         }
97         newStack := make([][]byte, 0, len(vm.dataStack))
98         newStack = append(newStack, vm.dataStack[:len(vm.dataStack)-6]...)
99         newStack = append(newStack, vm.dataStack[len(vm.dataStack)-4:]...)
100         newStack = append(newStack, vm.dataStack[len(vm.dataStack)-6])
101         newStack = append(newStack, vm.dataStack[len(vm.dataStack)-5])
102         vm.dataStack = newStack
103         return nil
104 }
105
106 func op2Swap(vm *virtualMachine) error {
107         err := vm.applyCost(2)
108         if err != nil {
109                 return err
110         }
111         if len(vm.dataStack) < 4 {
112                 return ErrDataStackUnderflow
113         }
114         newStack := make([][]byte, 0, len(vm.dataStack))
115         newStack = append(newStack, vm.dataStack[:len(vm.dataStack)-4]...)
116         newStack = append(newStack, vm.dataStack[len(vm.dataStack)-2:]...)
117         newStack = append(newStack, vm.dataStack[len(vm.dataStack)-4])
118         newStack = append(newStack, vm.dataStack[len(vm.dataStack)-3])
119         vm.dataStack = newStack
120         return nil
121 }
122
123 func opIfDup(vm *virtualMachine) error {
124         err := vm.applyCost(1)
125         if err != nil {
126                 return err
127         }
128         item, err := vm.top()
129         if err != nil {
130                 return err
131         }
132         if AsBool(item) {
133                 err = vm.push(item, false)
134                 if err != nil {
135                         return err
136                 }
137         }
138         return nil
139 }
140
141 func opDepth(vm *virtualMachine) error {
142         err := vm.applyCost(1)
143         if err != nil {
144                 return err
145         }
146         err = vm.pushInt64(int64(len(vm.dataStack)), false)
147         if err != nil {
148                 return err
149         }
150         return nil
151 }
152
153 func opDrop(vm *virtualMachine) error {
154         err := vm.applyCost(1)
155         if err != nil {
156                 return err
157         }
158         _, err = vm.pop(false)
159         if err != nil {
160                 return err
161         }
162         return nil
163 }
164
165 func opDup(vm *virtualMachine) error {
166         return nDup(vm, 1)
167 }
168
169 func opNip(vm *virtualMachine) error {
170         err := vm.applyCost(1)
171         if err != nil {
172                 return err
173         }
174         top, err := vm.top()
175         if err != nil {
176                 return err
177         }
178         // temporarily pop off the top value with no standard memory accounting
179         vm.dataStack = vm.dataStack[:len(vm.dataStack)-1]
180         _, err = vm.pop(false)
181         if err != nil {
182                 return err
183         }
184         // now put the top item back
185         vm.dataStack = append(vm.dataStack, top)
186         return nil
187 }
188
189 func opOver(vm *virtualMachine) error {
190         err := vm.applyCost(1)
191         if err != nil {
192                 return err
193         }
194         if len(vm.dataStack) < 2 {
195                 return ErrDataStackUnderflow
196         }
197         err = vm.push(vm.dataStack[len(vm.dataStack)-2], false)
198         if err != nil {
199                 return err
200         }
201         return nil
202 }
203
204 func opPick(vm *virtualMachine) error {
205         err := vm.applyCost(2)
206         if err != nil {
207                 return err
208         }
209         n, err := vm.popInt64(false)
210         if err != nil {
211                 return err
212         }
213         if n < 0 {
214                 return ErrBadValue
215         }
216         off, ok := checked.AddInt64(n, 1)
217         if !ok {
218                 return ErrBadValue
219         }
220         if int64(len(vm.dataStack)) < off {
221                 return ErrDataStackUnderflow
222         }
223         err = vm.push(vm.dataStack[int64(len(vm.dataStack))-(off)], false)
224         if err != nil {
225                 return err
226         }
227         return nil
228 }
229
230 func opRoll(vm *virtualMachine) error {
231         err := vm.applyCost(2)
232         if err != nil {
233                 return err
234         }
235         n, err := vm.popInt64(false)
236         if err != nil {
237                 return err
238         }
239         if n < 0 {
240                 return ErrBadValue
241         }
242         off, ok := checked.AddInt64(n, 1)
243         if !ok {
244                 return ErrBadValue
245         }
246         err = rot(vm, off)
247         if err != nil {
248                 return err
249         }
250         return nil
251 }
252
253 func opRot(vm *virtualMachine) error {
254         err := vm.applyCost(2)
255         if err != nil {
256                 return err
257         }
258         err = rot(vm, 3)
259         if err != nil {
260                 return err
261         }
262         return nil
263 }
264
265 func rot(vm *virtualMachine, n int64) error {
266         if n < 1 {
267                 return ErrBadValue
268         }
269         if int64(len(vm.dataStack)) < n {
270                 return ErrDataStackUnderflow
271         }
272         index := int64(len(vm.dataStack)) - n
273         newStack := make([][]byte, 0, len(vm.dataStack))
274         newStack = append(newStack, vm.dataStack[:index]...)
275         newStack = append(newStack, vm.dataStack[index+1:]...)
276         newStack = append(newStack, vm.dataStack[index])
277         vm.dataStack = newStack
278         return nil
279 }
280
281 func opSwap(vm *virtualMachine) error {
282         err := vm.applyCost(1)
283         if err != nil {
284                 return err
285         }
286         l := len(vm.dataStack)
287         if l < 2 {
288                 return ErrDataStackUnderflow
289         }
290         vm.dataStack[l-1], vm.dataStack[l-2] = vm.dataStack[l-2], vm.dataStack[l-1]
291         return nil
292 }
293
294 func opTuck(vm *virtualMachine) error {
295         err := vm.applyCost(1)
296         if err != nil {
297                 return err
298         }
299         if len(vm.dataStack) < 2 {
300                 return ErrDataStackUnderflow
301         }
302         top2 := make([][]byte, 2)
303         copy(top2, vm.dataStack[len(vm.dataStack)-2:])
304         // temporarily remove the top two items without standard memory accounting
305         vm.dataStack = vm.dataStack[:len(vm.dataStack)-2]
306         err = vm.push(top2[1], false)
307         if err != nil {
308                 return err
309         }
310         vm.dataStack = append(vm.dataStack, top2...)
311         return nil
312 }