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