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  }