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 }