github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/vm/bitwise.go (about) 1 package vm 2 3 import "bytes" 4 5 func opInvert(vm *virtualMachine) error { 6 if err := vm.applyCost(1); err != nil { 7 return err 8 } 9 10 top, err := vm.top() 11 if err != nil { 12 return err 13 } 14 15 if err = vm.applyCost(int64(len(top))); err != nil { 16 return err 17 } 18 // Could rewrite top in place but maybe it's a shared data 19 // structure? 20 newTop := make([]byte, 0, len(top)) 21 for _, b := range top { 22 newTop = append(newTop, ^b) 23 } 24 vm.dataStack[len(vm.dataStack)-1] = newTop 25 return nil 26 } 27 28 func opAnd(vm *virtualMachine) error { 29 if err := vm.applyCost(1); err != nil { 30 return err 31 } 32 33 b, err := vm.pop(true) 34 if err != nil { 35 return err 36 } 37 38 a, err := vm.pop(true) 39 if err != nil { 40 return err 41 } 42 43 min, max := len(a), len(b) 44 if min > max { 45 min, max = max, min 46 } 47 48 if err = vm.applyCost(int64(min)); err != nil { 49 return err 50 } 51 52 res := make([]byte, 0, min) 53 for i := 0; i < min; i++ { 54 res = append(res, a[i]&b[i]) 55 } 56 return vm.pushDataStack(res, true) 57 } 58 59 func opOr(vm *virtualMachine) error { 60 return doOr(vm, false) 61 } 62 63 func opXor(vm *virtualMachine) error { 64 return doOr(vm, true) 65 } 66 67 func doOr(vm *virtualMachine, xor bool) error { 68 if err := vm.applyCost(1); err != nil { 69 return err 70 } 71 72 b, err := vm.pop(true) 73 if err != nil { 74 return err 75 } 76 77 a, err := vm.pop(true) 78 if err != nil { 79 return err 80 } 81 82 min, max := len(a), len(b) 83 if min > max { 84 min, max = max, min 85 } 86 87 if err = vm.applyCost(int64(max)); err != nil { 88 return err 89 } 90 91 res := make([]byte, 0, max) 92 for i := 0; i < max; i++ { 93 var aByte, bByte, resByte byte 94 if i >= len(a) { 95 aByte = 0 96 } else { 97 aByte = a[i] 98 } 99 if i >= len(b) { 100 bByte = 0 101 } else { 102 bByte = b[i] 103 } 104 if xor { 105 resByte = aByte ^ bByte 106 } else { 107 resByte = aByte | bByte 108 } 109 110 res = append(res, resByte) 111 } 112 return vm.pushDataStack(res, true) 113 } 114 115 func opEqual(vm *virtualMachine) error { 116 res, err := doEqual(vm) 117 if err != nil { 118 return err 119 } 120 121 return vm.pushBool(res, true) 122 } 123 124 func opEqualVerify(vm *virtualMachine) error { 125 res, err := doEqual(vm) 126 if err != nil { 127 return err 128 } 129 130 if res { 131 return nil 132 } 133 return ErrVerifyFailed 134 } 135 136 func doEqual(vm *virtualMachine) (bool, error) { 137 if err := vm.applyCost(1); err != nil { 138 return false, err 139 } 140 141 b, err := vm.pop(true) 142 if err != nil { 143 return false, err 144 } 145 146 a, err := vm.pop(true) 147 if err != nil { 148 return false, err 149 } 150 151 min, max := len(a), len(b) 152 if min > max { 153 min, max = max, min 154 } 155 156 if err = vm.applyCost(int64(min)); err != nil { 157 return false, err 158 } 159 return bytes.Equal(a, b), nil 160 }