github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/vm/stack.go (about)

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