github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/vm/stack.go (about)

     1  package vm
     2  
     3  import "github.com/bytom/bytom/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  }