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

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