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 }