3 import "github.com/blockchain/math/checked"
5 func opToAltStack(vm *virtualMachine) error {
10 if len(vm.dataStack) == 0 {
11 return ErrDataStackUnderflow
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]
19 func opFromAltStack(vm *virtualMachine) error {
20 err := vm.applyCost(2)
24 if len(vm.altStack) == 0 {
25 return ErrAltStackUnderflow
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]
33 func op2Drop(vm *virtualMachine) error {
34 err := vm.applyCost(2)
38 for i := 0; i < 2; i++ {
39 _, err = vm.pop(false)
47 func op2Dup(vm *virtualMachine) error {
51 func op3Dup(vm *virtualMachine) error {
55 func nDup(vm *virtualMachine, n int) error {
56 err := vm.applyCost(int64(n))
60 if len(vm.dataStack) < n {
61 return ErrDataStackUnderflow
63 for i := 0; i < n; i++ {
64 err = vm.push(vm.dataStack[len(vm.dataStack)-n], false)
72 func op2Over(vm *virtualMachine) error {
73 err := vm.applyCost(2)
77 if len(vm.dataStack) < 4 {
78 return ErrDataStackUnderflow
80 for i := 0; i < 2; i++ {
81 err = vm.push(vm.dataStack[len(vm.dataStack)-4], false)
89 func op2Rot(vm *virtualMachine) error {
90 err := vm.applyCost(2)
94 if len(vm.dataStack) < 6 {
95 return ErrDataStackUnderflow
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
106 func op2Swap(vm *virtualMachine) error {
107 err := vm.applyCost(2)
111 if len(vm.dataStack) < 4 {
112 return ErrDataStackUnderflow
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
123 func opIfDup(vm *virtualMachine) error {
124 err := vm.applyCost(1)
128 item, err := vm.top()
133 err = vm.push(item, false)
141 func opDepth(vm *virtualMachine) error {
142 err := vm.applyCost(1)
146 err = vm.pushInt64(int64(len(vm.dataStack)), false)
153 func opDrop(vm *virtualMachine) error {
154 err := vm.applyCost(1)
158 _, err = vm.pop(false)
165 func opDup(vm *virtualMachine) error {
169 func opNip(vm *virtualMachine) error {
170 err := vm.applyCost(1)
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)
184 // now put the top item back
185 vm.dataStack = append(vm.dataStack, top)
189 func opOver(vm *virtualMachine) error {
190 err := vm.applyCost(1)
194 if len(vm.dataStack) < 2 {
195 return ErrDataStackUnderflow
197 err = vm.push(vm.dataStack[len(vm.dataStack)-2], false)
204 func opPick(vm *virtualMachine) error {
205 err := vm.applyCost(2)
209 n, err := vm.popInt64(false)
216 off, ok := checked.AddInt64(n, 1)
220 if int64(len(vm.dataStack)) < off {
221 return ErrDataStackUnderflow
223 err = vm.push(vm.dataStack[int64(len(vm.dataStack))-(off)], false)
230 func opRoll(vm *virtualMachine) error {
231 err := vm.applyCost(2)
235 n, err := vm.popInt64(false)
242 off, ok := checked.AddInt64(n, 1)
253 func opRot(vm *virtualMachine) error {
254 err := vm.applyCost(2)
265 func rot(vm *virtualMachine, n int64) error {
269 if int64(len(vm.dataStack)) < n {
270 return ErrDataStackUnderflow
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
281 func opSwap(vm *virtualMachine) error {
282 err := vm.applyCost(1)
286 l := len(vm.dataStack)
288 return ErrDataStackUnderflow
290 vm.dataStack[l-1], vm.dataStack[l-2] = vm.dataStack[l-2], vm.dataStack[l-1]
294 func opTuck(vm *virtualMachine) error {
295 err := vm.applyCost(1)
299 if len(vm.dataStack) < 2 {
300 return ErrDataStackUnderflow
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)
310 vm.dataStack = append(vm.dataStack, top2...)