github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/vm/numeric.go (about)

     1  package vm
     2  
     3  import (
     4  	"github.com/holiman/uint256"
     5  )
     6  
     7  func op1Add(vm *virtualMachine) error {
     8  	if err := vm.applyCost(2); err != nil {
     9  		return err
    10  	}
    11  
    12  	n, err := vm.popBigInt(true)
    13  	if err != nil {
    14  		return err
    15  	}
    16  
    17  	num := uint256.NewInt(1)
    18  	if num.Add(n, num); num.Sign() < 0 {
    19  		return ErrRange
    20  	}
    21  
    22  	return vm.pushBigInt(num, true)
    23  }
    24  
    25  func op1Sub(vm *virtualMachine) error {
    26  	if err := vm.applyCost(2); err != nil {
    27  		return err
    28  	}
    29  
    30  	n, err := vm.popBigInt(true)
    31  	if err != nil {
    32  		return err
    33  	}
    34  
    35  	num := uint256.NewInt(1)
    36  	if num.Sub(n, num); num.Sign() < 0 {
    37  		return ErrRange
    38  	}
    39  
    40  	return vm.pushBigInt(num, true)
    41  }
    42  
    43  func op2Mul(vm *virtualMachine) error {
    44  	if err := vm.applyCost(2); err != nil {
    45  		return err
    46  	}
    47  
    48  	n, err := vm.popBigInt(true)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	num := uint256.NewInt(2)
    54  	if num.Mul(n, num); num.Sign() < 0 {
    55  		return ErrRange
    56  	}
    57  
    58  	return vm.pushBigInt(num, true)
    59  }
    60  
    61  func op2Div(vm *virtualMachine) error {
    62  	err := vm.applyCost(2)
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	n, err := vm.popBigInt(true)
    68  	if err != nil {
    69  		return err
    70  	}
    71  
    72  	return vm.pushBigInt(n.Rsh(n, 1), true)
    73  }
    74  
    75  func opNot(vm *virtualMachine) error {
    76  	if err := vm.applyCost(2); err != nil {
    77  		return err
    78  	}
    79  
    80  	n, err := vm.popBigInt(true)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	return vm.pushBool(n.Cmp(uint256.NewInt(0)) == 0, true)
    86  }
    87  
    88  func op0NotEqual(vm *virtualMachine) error {
    89  	if err := vm.applyCost(2); err != nil {
    90  		return err
    91  	}
    92  
    93  	n, err := vm.popBigInt(true)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	return vm.pushBool(n.Cmp(uint256.NewInt(0)) != 0, true)
    99  }
   100  
   101  func opAdd(vm *virtualMachine) error {
   102  	if err := vm.applyCost(2); err != nil {
   103  		return err
   104  	}
   105  
   106  	y, err := vm.popBigInt(true)
   107  	if err != nil {
   108  		return err
   109  	}
   110  
   111  	x, err := vm.popBigInt(true)
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  	if x.Add(x, y); x.Sign() < 0 {
   117  		return ErrRange
   118  	}
   119  
   120  	return vm.pushBigInt(x, true)
   121  }
   122  
   123  func opSub(vm *virtualMachine) error {
   124  	if err := vm.applyCost(2); err != nil {
   125  		return err
   126  	}
   127  
   128  	y, err := vm.popBigInt(true)
   129  	if err != nil {
   130  		return err
   131  	}
   132  
   133  	x, err := vm.popBigInt(true)
   134  	if err != nil {
   135  		return err
   136  	}
   137  
   138  	if x.Sub(x, y); x.Sign() < 0 {
   139  		return ErrRange
   140  	}
   141  
   142  	return vm.pushBigInt(x, true)
   143  }
   144  
   145  func opMul(vm *virtualMachine) error {
   146  	if err := vm.applyCost(8); err != nil {
   147  		return err
   148  	}
   149  
   150  	y, err := vm.popBigInt(true)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	x, err := vm.popBigInt(true)
   156  	if err != nil {
   157  		return err
   158  	}
   159  
   160  	if _, overflow := x.MulOverflow(x, y); overflow || x.Sign() < 0 {
   161  		return ErrRange
   162  	}
   163  
   164  	return vm.pushBigInt(x, true)
   165  }
   166  
   167  func opDiv(vm *virtualMachine) error {
   168  	if err := vm.applyCost(8); err != nil {
   169  		return err
   170  	}
   171  
   172  	y, err := vm.popBigInt(true)
   173  	if err != nil {
   174  		return err
   175  	}
   176  
   177  	x, err := vm.popBigInt(true)
   178  	if err != nil {
   179  		return err
   180  	}
   181  
   182  	if y.IsZero() {
   183  		return ErrDivZero
   184  	}
   185  
   186  	return vm.pushBigInt(x.Div(x, y), true)
   187  }
   188  
   189  func opMod(vm *virtualMachine) error {
   190  	if err := vm.applyCost(8); err != nil {
   191  		return err
   192  	}
   193  
   194  	y, err := vm.popBigInt(true)
   195  	if err != nil {
   196  		return err
   197  	}
   198  
   199  	x, err := vm.popBigInt(true)
   200  	if err != nil {
   201  		return err
   202  	}
   203  
   204  	if y.IsZero() {
   205  		return ErrDivZero
   206  	}
   207  
   208  	return vm.pushBigInt(x.Mod(x, y), true)
   209  }
   210  
   211  func opLshift(vm *virtualMachine) error {
   212  	if err := vm.applyCost(8); err != nil {
   213  		return err
   214  	}
   215  
   216  	y, err := vm.popBigInt(true)
   217  	if err != nil {
   218  		return err
   219  	}
   220  
   221  	x, err := vm.popBigInt(true)
   222  	if err != nil {
   223  		return err
   224  	}
   225  
   226  	if y.LtUint64(256) {
   227  		x.Lsh(x, uint(y.Uint64()))
   228  	} else {
   229  		x.Clear()
   230  	}
   231  
   232  	if x.Sign() < 0 {
   233  		return ErrRange
   234  	}
   235  	return vm.pushBigInt(x, true)
   236  }
   237  
   238  func opRshift(vm *virtualMachine) error {
   239  	if err := vm.applyCost(8); err != nil {
   240  		return err
   241  	}
   242  
   243  	y, err := vm.popBigInt(true)
   244  	if err != nil {
   245  		return err
   246  	}
   247  
   248  	x, err := vm.popBigInt(true)
   249  	if err != nil {
   250  		return err
   251  	}
   252  
   253  	if y.LtUint64(256) {
   254  		x.Rsh(x, uint(y.Uint64()))
   255  	} else {
   256  		x.Clear()
   257  	}
   258  
   259  	return vm.pushBigInt(x, true)
   260  }
   261  
   262  func opBoolAnd(vm *virtualMachine) error {
   263  	if err := vm.applyCost(2); err != nil {
   264  		return err
   265  	}
   266  
   267  	b, err := vm.pop(true)
   268  	if err != nil {
   269  		return err
   270  	}
   271  
   272  	a, err := vm.pop(true)
   273  	if err != nil {
   274  		return err
   275  	}
   276  	return vm.pushBool(AsBool(a) && AsBool(b), true)
   277  }
   278  
   279  func opBoolOr(vm *virtualMachine) error {
   280  	if err := vm.applyCost(2); err != nil {
   281  		return err
   282  	}
   283  
   284  	b, err := vm.pop(true)
   285  	if err != nil {
   286  		return err
   287  	}
   288  
   289  	a, err := vm.pop(true)
   290  	if err != nil {
   291  		return err
   292  	}
   293  	return vm.pushBool(AsBool(a) || AsBool(b), true)
   294  }
   295  
   296  const (
   297  	cmpLess = iota
   298  	cmpLessEqual
   299  	cmpGreater
   300  	cmpGreaterEqual
   301  	cmpEqual
   302  	cmpNotEqual
   303  )
   304  
   305  func opNumEqual(vm *virtualMachine) error {
   306  	return doNumCompare(vm, cmpEqual)
   307  }
   308  
   309  func opNumEqualVerify(vm *virtualMachine) error {
   310  	if err := vm.applyCost(2); err != nil {
   311  		return err
   312  	}
   313  
   314  	y, err := vm.popBigInt(true)
   315  	if err != nil {
   316  		return err
   317  	}
   318  
   319  	x, err := vm.popBigInt(true)
   320  	if err != nil {
   321  		return err
   322  	}
   323  
   324  	if x.Eq(y) {
   325  		return nil
   326  	}
   327  	return ErrVerifyFailed
   328  }
   329  
   330  func opNumNotEqual(vm *virtualMachine) error {
   331  	return doNumCompare(vm, cmpNotEqual)
   332  }
   333  
   334  func opLessThan(vm *virtualMachine) error {
   335  	return doNumCompare(vm, cmpLess)
   336  }
   337  
   338  func opGreaterThan(vm *virtualMachine) error {
   339  	return doNumCompare(vm, cmpGreater)
   340  }
   341  
   342  func opLessThanOrEqual(vm *virtualMachine) error {
   343  	return doNumCompare(vm, cmpLessEqual)
   344  }
   345  
   346  func opGreaterThanOrEqual(vm *virtualMachine) error {
   347  	return doNumCompare(vm, cmpGreaterEqual)
   348  }
   349  
   350  func doNumCompare(vm *virtualMachine, op int) error {
   351  	if err := vm.applyCost(2); err != nil {
   352  		return err
   353  	}
   354  
   355  	y, err := vm.popBigInt(true)
   356  	if err != nil {
   357  		return err
   358  	}
   359  
   360  	x, err := vm.popBigInt(true)
   361  	if err != nil {
   362  		return err
   363  	}
   364  
   365  	var res bool
   366  	switch op {
   367  	case cmpLess:
   368  		res = x.Cmp(y) < 0
   369  	case cmpLessEqual:
   370  		res = x.Cmp(y) <= 0
   371  	case cmpGreater:
   372  		res = x.Cmp(y) > 0
   373  	case cmpGreaterEqual:
   374  		res = x.Cmp(y) >= 0
   375  	case cmpEqual:
   376  		res = x.Cmp(y) == 0
   377  	case cmpNotEqual:
   378  		res = x.Cmp(y) != 0
   379  	}
   380  	return vm.pushBool(res, true)
   381  }
   382  
   383  func opMin(vm *virtualMachine) error {
   384  	if err := vm.applyCost(2); err != nil {
   385  		return err
   386  	}
   387  
   388  	y, err := vm.popBigInt(true)
   389  	if err != nil {
   390  		return err
   391  	}
   392  
   393  	x, err := vm.popBigInt(true)
   394  	if err != nil {
   395  		return err
   396  	}
   397  
   398  	if x.Cmp(y) > 0 {
   399  		return vm.pushBigInt(y, true)
   400  	}
   401  	return vm.pushBigInt(x, true)
   402  }
   403  
   404  func opMax(vm *virtualMachine) error {
   405  	if err := vm.applyCost(2); err != nil {
   406  		return err
   407  	}
   408  
   409  	y, err := vm.popBigInt(true)
   410  	if err != nil {
   411  		return err
   412  	}
   413  
   414  	x, err := vm.popBigInt(true)
   415  	if err != nil {
   416  		return err
   417  	}
   418  
   419  	if x.Cmp(y) < 0 {
   420  		return vm.pushBigInt(y, true)
   421  	}
   422  	return vm.pushBigInt(x, true)
   423  }
   424  
   425  func opWithin(vm *virtualMachine) error {
   426  	if err := vm.applyCost(4); err != nil {
   427  		return err
   428  	}
   429  
   430  	max, err := vm.popBigInt(true)
   431  	if err != nil {
   432  		return err
   433  	}
   434  
   435  	min, err := vm.popBigInt(true)
   436  	if err != nil {
   437  		return err
   438  	}
   439  
   440  	x, err := vm.popBigInt(true)
   441  	if err != nil {
   442  		return err
   443  	}
   444  
   445  	return vm.pushBool(x.Cmp(min) >= 0 && x.Cmp(max) < 0, true)
   446  }