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 }