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

     1  package vm
     2  
     3  import (
     4  	"encoding/binary"
     5  )
     6  
     7  func opVerify(vm *virtualMachine) error {
     8  	err := vm.applyCost(1)
     9  	if err != nil {
    10  		return err
    11  	}
    12  	p, err := vm.pop(true)
    13  	if err != nil {
    14  		return err
    15  	}
    16  	if AsBool(p) {
    17  		return nil
    18  	}
    19  	return ErrVerifyFailed
    20  }
    21  
    22  func opFail(vm *virtualMachine) error {
    23  	err := vm.applyCost(1)
    24  	if err != nil {
    25  		return err
    26  	}
    27  	return ErrReturn
    28  }
    29  
    30  func opCheckPredicate(vm *virtualMachine) error {
    31  	err := vm.applyCost(256)
    32  	if err != nil {
    33  		return err
    34  	}
    35  	vm.deferCost(-256 + 64) // get most of that cost back at the end
    36  	limit, err := vm.popInt64(true)
    37  	if err != nil {
    38  		return err
    39  	}
    40  	predicate, err := vm.pop(true)
    41  	if err != nil {
    42  		return err
    43  	}
    44  	n, err := vm.popInt64(true)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	if limit < 0 {
    49  		return ErrBadValue
    50  	}
    51  	l := int64(len(vm.dataStack))
    52  	if n < 0 {
    53  		n = l
    54  	}
    55  	if n > l {
    56  		return ErrDataStackUnderflow
    57  	}
    58  	if limit == 0 {
    59  		limit = vm.runLimit
    60  	}
    61  	err = vm.applyCost(limit)
    62  	if err != nil {
    63  		return err
    64  	}
    65  
    66  	childVM := virtualMachine{
    67  		context:   vm.context,
    68  		program:   predicate,
    69  		runLimit:  limit,
    70  		depth:     vm.depth + 1,
    71  		dataStack: append([][]byte{}, vm.dataStack[l-n:]...),
    72  	}
    73  	vm.dataStack = vm.dataStack[:l-n]
    74  
    75  	childErr := childVM.run()
    76  
    77  	vm.deferCost(-childVM.runLimit)
    78  	vm.deferCost(-stackCost(childVM.dataStack))
    79  	vm.deferCost(-stackCost(childVM.altStack))
    80  
    81  	return vm.pushBool(childErr == nil && !childVM.falseResult(), true)
    82  }
    83  
    84  func opJump(vm *virtualMachine) error {
    85  	err := vm.applyCost(1)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	address := binary.LittleEndian.Uint32(vm.data)
    90  	vm.nextPC = address
    91  	return nil
    92  }
    93  
    94  func opJumpIf(vm *virtualMachine) error {
    95  	err := vm.applyCost(1)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	p, err := vm.pop(true)
   100  	if err != nil {
   101  		return err
   102  	}
   103  	if AsBool(p) {
   104  		address := binary.LittleEndian.Uint32(vm.data)
   105  		vm.nextPC = address
   106  	}
   107  	return nil
   108  }