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  }