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