OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / bytom / protocol / vm / stack.go
diff --git a/vendor/github.com/bytom/protocol/vm/stack.go b/vendor/github.com/bytom/protocol/vm/stack.go
new file mode 100644 (file)
index 0000000..0c72755
--- /dev/null
@@ -0,0 +1,312 @@
+package vm
+
+import "github.com/bytom/math/checked"
+
+func opToAltStack(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       if len(vm.dataStack) == 0 {
+               return ErrDataStackUnderflow
+       }
+       // no standard memory cost accounting here
+       vm.altStack = append(vm.altStack, vm.dataStack[len(vm.dataStack)-1])
+       vm.dataStack = vm.dataStack[:len(vm.dataStack)-1]
+       return nil
+}
+
+func opFromAltStack(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       if len(vm.altStack) == 0 {
+               return ErrAltStackUnderflow
+       }
+       // no standard memory cost accounting here
+       vm.dataStack = append(vm.dataStack, vm.altStack[len(vm.altStack)-1])
+       vm.altStack = vm.altStack[:len(vm.altStack)-1]
+       return nil
+}
+
+func op2Drop(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       for i := 0; i < 2; i++ {
+               _, err = vm.pop(false)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func op2Dup(vm *virtualMachine) error {
+       return nDup(vm, 2)
+}
+
+func op3Dup(vm *virtualMachine) error {
+       return nDup(vm, 3)
+}
+
+func nDup(vm *virtualMachine, n int) error {
+       err := vm.applyCost(int64(n))
+       if err != nil {
+               return err
+       }
+       if len(vm.dataStack) < n {
+               return ErrDataStackUnderflow
+       }
+       for i := 0; i < n; i++ {
+               err = vm.push(vm.dataStack[len(vm.dataStack)-n], false)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func op2Over(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       if len(vm.dataStack) < 4 {
+               return ErrDataStackUnderflow
+       }
+       for i := 0; i < 2; i++ {
+               err = vm.push(vm.dataStack[len(vm.dataStack)-4], false)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func op2Rot(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       if len(vm.dataStack) < 6 {
+               return ErrDataStackUnderflow
+       }
+       newStack := make([][]byte, 0, len(vm.dataStack))
+       newStack = append(newStack, vm.dataStack[:len(vm.dataStack)-6]...)
+       newStack = append(newStack, vm.dataStack[len(vm.dataStack)-4:]...)
+       newStack = append(newStack, vm.dataStack[len(vm.dataStack)-6])
+       newStack = append(newStack, vm.dataStack[len(vm.dataStack)-5])
+       vm.dataStack = newStack
+       return nil
+}
+
+func op2Swap(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       if len(vm.dataStack) < 4 {
+               return ErrDataStackUnderflow
+       }
+       newStack := make([][]byte, 0, len(vm.dataStack))
+       newStack = append(newStack, vm.dataStack[:len(vm.dataStack)-4]...)
+       newStack = append(newStack, vm.dataStack[len(vm.dataStack)-2:]...)
+       newStack = append(newStack, vm.dataStack[len(vm.dataStack)-4])
+       newStack = append(newStack, vm.dataStack[len(vm.dataStack)-3])
+       vm.dataStack = newStack
+       return nil
+}
+
+func opIfDup(vm *virtualMachine) error {
+       err := vm.applyCost(1)
+       if err != nil {
+               return err
+       }
+       item, err := vm.top()
+       if err != nil {
+               return err
+       }
+       if AsBool(item) {
+               err = vm.push(item, false)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func opDepth(vm *virtualMachine) error {
+       err := vm.applyCost(1)
+       if err != nil {
+               return err
+       }
+       err = vm.pushInt64(int64(len(vm.dataStack)), false)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+func opDrop(vm *virtualMachine) error {
+       err := vm.applyCost(1)
+       if err != nil {
+               return err
+       }
+       _, err = vm.pop(false)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+func opDup(vm *virtualMachine) error {
+       return nDup(vm, 1)
+}
+
+func opNip(vm *virtualMachine) error {
+       err := vm.applyCost(1)
+       if err != nil {
+               return err
+       }
+       top, err := vm.top()
+       if err != nil {
+               return err
+       }
+       // temporarily pop off the top value with no standard memory accounting
+       vm.dataStack = vm.dataStack[:len(vm.dataStack)-1]
+       _, err = vm.pop(false)
+       if err != nil {
+               return err
+       }
+       // now put the top item back
+       vm.dataStack = append(vm.dataStack, top)
+       return nil
+}
+
+func opOver(vm *virtualMachine) error {
+       err := vm.applyCost(1)
+       if err != nil {
+               return err
+       }
+       if len(vm.dataStack) < 2 {
+               return ErrDataStackUnderflow
+       }
+       err = vm.push(vm.dataStack[len(vm.dataStack)-2], false)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+func opPick(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       n, err := vm.popInt64(false)
+       if err != nil {
+               return err
+       }
+       if n < 0 {
+               return ErrBadValue
+       }
+       off, ok := checked.AddInt64(n, 1)
+       if !ok {
+               return ErrBadValue
+       }
+       if int64(len(vm.dataStack)) < off {
+               return ErrDataStackUnderflow
+       }
+       err = vm.push(vm.dataStack[int64(len(vm.dataStack))-(off)], false)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+func opRoll(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       n, err := vm.popInt64(false)
+       if err != nil {
+               return err
+       }
+       if n < 0 {
+               return ErrBadValue
+       }
+       off, ok := checked.AddInt64(n, 1)
+       if !ok {
+               return ErrBadValue
+       }
+       err = rot(vm, off)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+func opRot(vm *virtualMachine) error {
+       err := vm.applyCost(2)
+       if err != nil {
+               return err
+       }
+       err = rot(vm, 3)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+func rot(vm *virtualMachine, n int64) error {
+       if n < 1 {
+               return ErrBadValue
+       }
+       if int64(len(vm.dataStack)) < n {
+               return ErrDataStackUnderflow
+       }
+       index := int64(len(vm.dataStack)) - n
+       newStack := make([][]byte, 0, len(vm.dataStack))
+       newStack = append(newStack, vm.dataStack[:index]...)
+       newStack = append(newStack, vm.dataStack[index+1:]...)
+       newStack = append(newStack, vm.dataStack[index])
+       vm.dataStack = newStack
+       return nil
+}
+
+func opSwap(vm *virtualMachine) error {
+       err := vm.applyCost(1)
+       if err != nil {
+               return err
+       }
+       l := len(vm.dataStack)
+       if l < 2 {
+               return ErrDataStackUnderflow
+       }
+       vm.dataStack[l-1], vm.dataStack[l-2] = vm.dataStack[l-2], vm.dataStack[l-1]
+       return nil
+}
+
+func opTuck(vm *virtualMachine) error {
+       err := vm.applyCost(1)
+       if err != nil {
+               return err
+       }
+       if len(vm.dataStack) < 2 {
+               return ErrDataStackUnderflow
+       }
+       top2 := make([][]byte, 2)
+       copy(top2, vm.dataStack[len(vm.dataStack)-2:])
+       // temporarily remove the top two items without standard memory accounting
+       vm.dataStack = vm.dataStack[:len(vm.dataStack)-2]
+       err = vm.push(top2[1], false)
+       if err != nil {
+               return err
+       }
+       vm.dataStack = append(vm.dataStack, top2...)
+       return nil
+}