github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/vm/numeric_test.go (about) 1 package vm 2 3 import ( 4 "fmt" 5 "math" 6 "testing" 7 8 "github.com/bytom/bytom/testutil" 9 ) 10 11 func TestNumericOps(t *testing.T) { 12 type testStruct struct { 13 op Op 14 startVM *virtualMachine 15 wantErr error 16 wantVM *virtualMachine 17 } 18 cases := []testStruct{{ 19 op: OP_1ADD, 20 startVM: &virtualMachine{ 21 runLimit: 50000, 22 dataStack: [][]byte{{2}}, 23 }, 24 wantVM: &virtualMachine{ 25 runLimit: 49998, 26 dataStack: [][]byte{{3}}, 27 }, 28 }, { 29 op: OP_1SUB, 30 startVM: &virtualMachine{ 31 runLimit: 50000, 32 dataStack: [][]byte{{2}}, 33 }, 34 wantVM: &virtualMachine{ 35 runLimit: 49998, 36 dataStack: [][]byte{{1}}, 37 }, 38 }, { 39 op: OP_2MUL, 40 startVM: &virtualMachine{ 41 runLimit: 50000, 42 dataStack: [][]byte{{2}}, 43 }, 44 wantVM: &virtualMachine{ 45 runLimit: 49998, 46 dataStack: [][]byte{{4}}, 47 }, 48 }, { 49 op: OP_2DIV, 50 startVM: &virtualMachine{ 51 runLimit: 50000, 52 dataStack: [][]byte{{2}}, 53 }, 54 wantVM: &virtualMachine{ 55 runLimit: 49998, 56 dataStack: [][]byte{{1}}, 57 }, 58 }, { 59 op: OP_2DIV, 60 startVM: &virtualMachine{ 61 runLimit: 50000, 62 dataStack: [][]byte{Int64Bytes(-2)}, 63 }, 64 wantVM: &virtualMachine{ 65 runLimit: 49998, 66 dataStack: [][]byte{Int64Bytes(-1)}, 67 }, 68 }, { 69 op: OP_2DIV, 70 startVM: &virtualMachine{ 71 runLimit: 50000, 72 dataStack: [][]byte{Int64Bytes(-1)}, 73 }, 74 wantVM: &virtualMachine{ 75 runLimit: 49998, 76 dataStack: [][]byte{Int64Bytes(-1)}, 77 }, 78 }, { 79 op: OP_NEGATE, 80 startVM: &virtualMachine{ 81 runLimit: 50000, 82 dataStack: [][]byte{{2}}, 83 }, 84 wantVM: &virtualMachine{ 85 runLimit: 49998, 86 deferredCost: 7, 87 dataStack: [][]byte{Int64Bytes(-2)}, 88 }, 89 }, { 90 op: OP_ABS, 91 startVM: &virtualMachine{ 92 runLimit: 50000, 93 dataStack: [][]byte{{2}}, 94 }, 95 wantVM: &virtualMachine{ 96 runLimit: 49998, 97 dataStack: [][]byte{{2}}, 98 }, 99 }, { 100 op: OP_ABS, 101 startVM: &virtualMachine{ 102 runLimit: 50000, 103 dataStack: [][]byte{Int64Bytes(-2)}, 104 }, 105 wantVM: &virtualMachine{ 106 runLimit: 49998, 107 deferredCost: -7, 108 dataStack: [][]byte{{2}}, 109 }, 110 }, { 111 op: OP_NOT, 112 startVM: &virtualMachine{ 113 runLimit: 50000, 114 dataStack: [][]byte{{2}}, 115 }, 116 wantVM: &virtualMachine{ 117 runLimit: 49998, 118 deferredCost: -1, 119 dataStack: [][]byte{{}}, 120 }, 121 }, { 122 op: OP_0NOTEQUAL, 123 startVM: &virtualMachine{ 124 runLimit: 50000, 125 dataStack: [][]byte{{2}}, 126 }, 127 wantVM: &virtualMachine{ 128 runLimit: 49998, 129 dataStack: [][]byte{{1}}, 130 }, 131 }, { 132 op: OP_ADD, 133 startVM: &virtualMachine{ 134 runLimit: 50000, 135 dataStack: [][]byte{{2}, {1}}, 136 }, 137 wantVM: &virtualMachine{ 138 runLimit: 49998, 139 deferredCost: -9, 140 dataStack: [][]byte{{3}}, 141 }, 142 }, { 143 op: OP_SUB, 144 startVM: &virtualMachine{ 145 runLimit: 50000, 146 dataStack: [][]byte{{2}, {1}}, 147 }, 148 wantVM: &virtualMachine{ 149 runLimit: 49998, 150 deferredCost: -9, 151 dataStack: [][]byte{{1}}, 152 }, 153 }, { 154 op: OP_MUL, 155 startVM: &virtualMachine{ 156 runLimit: 50000, 157 dataStack: [][]byte{{2}, {1}}, 158 }, 159 wantVM: &virtualMachine{ 160 runLimit: 49992, 161 deferredCost: -9, 162 dataStack: [][]byte{{2}}, 163 }, 164 }, { 165 op: OP_DIV, 166 startVM: &virtualMachine{ 167 runLimit: 50000, 168 dataStack: [][]byte{{2}, {1}}, 169 }, 170 wantVM: &virtualMachine{ 171 runLimit: 49992, 172 deferredCost: -9, 173 dataStack: [][]byte{{2}}, 174 }, 175 }, { 176 op: OP_DIV, 177 startVM: &virtualMachine{ 178 runLimit: 50000, 179 dataStack: [][]byte{Int64Bytes(-2), {1}}, 180 }, 181 wantVM: &virtualMachine{ 182 runLimit: 49992, 183 deferredCost: -9, 184 dataStack: [][]byte{Int64Bytes(-2)}, 185 }, 186 }, { 187 op: OP_DIV, 188 startVM: &virtualMachine{ 189 runLimit: 50000, 190 dataStack: [][]byte{Int64Bytes(-2), Int64Bytes(-1)}, 191 }, 192 wantVM: &virtualMachine{ 193 runLimit: 49992, 194 deferredCost: -23, 195 dataStack: [][]byte{{2}}, 196 }, 197 }, { 198 op: OP_DIV, 199 startVM: &virtualMachine{ 200 runLimit: 50000, 201 dataStack: [][]byte{Int64Bytes(-3), Int64Bytes(2)}, 202 }, 203 wantVM: &virtualMachine{ 204 runLimit: 49992, 205 deferredCost: -9, 206 dataStack: [][]byte{Int64Bytes(-1)}, 207 }, 208 }, { 209 op: OP_DIV, 210 startVM: &virtualMachine{ 211 runLimit: 50000, 212 dataStack: [][]byte{{2}, {}}, 213 }, 214 wantErr: ErrDivZero, 215 }, { 216 op: OP_MOD, 217 startVM: &virtualMachine{ 218 runLimit: 50000, 219 dataStack: [][]byte{{2}, {1}}, 220 }, 221 wantVM: &virtualMachine{ 222 runLimit: 49992, 223 deferredCost: -10, 224 dataStack: [][]byte{{}}, 225 }, 226 }, { 227 op: OP_MOD, 228 startVM: &virtualMachine{ 229 runLimit: 50000, 230 dataStack: [][]byte{Int64Bytes(-12), {10}}, 231 }, 232 wantVM: &virtualMachine{ 233 runLimit: 49992, 234 deferredCost: -16, 235 dataStack: [][]byte{{8}}, 236 }, 237 }, { 238 op: OP_MOD, 239 startVM: &virtualMachine{ 240 runLimit: 50000, 241 dataStack: [][]byte{{2}, {0}}, 242 }, 243 wantErr: ErrDivZero, 244 }, { 245 op: OP_LSHIFT, 246 startVM: &virtualMachine{ 247 runLimit: 50000, 248 dataStack: [][]byte{{2}, {1}}, 249 }, 250 wantVM: &virtualMachine{ 251 runLimit: 49992, 252 deferredCost: -9, 253 dataStack: [][]byte{{4}}, 254 }, 255 }, { 256 op: OP_LSHIFT, 257 startVM: &virtualMachine{ 258 runLimit: 50000, 259 dataStack: [][]byte{Int64Bytes(-2), {1}}, 260 }, 261 wantVM: &virtualMachine{ 262 runLimit: 49992, 263 deferredCost: -9, 264 dataStack: [][]byte{Int64Bytes(-4)}, 265 }, 266 }, { 267 op: OP_RSHIFT, 268 startVM: &virtualMachine{ 269 runLimit: 50000, 270 dataStack: [][]byte{{2}, {1}}, 271 }, 272 wantVM: &virtualMachine{ 273 runLimit: 49992, 274 deferredCost: -9, 275 dataStack: [][]byte{{1}}, 276 }, 277 }, { 278 op: OP_RSHIFT, 279 startVM: &virtualMachine{ 280 runLimit: 50000, 281 dataStack: [][]byte{Int64Bytes(-2), {1}}, 282 }, 283 wantVM: &virtualMachine{ 284 runLimit: 49992, 285 deferredCost: -9, 286 dataStack: [][]byte{Int64Bytes(-1)}, 287 }, 288 }, { 289 op: OP_BOOLAND, 290 startVM: &virtualMachine{ 291 runLimit: 50000, 292 dataStack: [][]byte{{2}, {1}}, 293 }, 294 wantVM: &virtualMachine{ 295 runLimit: 49998, 296 deferredCost: -9, 297 dataStack: [][]byte{{1}}, 298 }, 299 }, { 300 op: OP_BOOLOR, 301 startVM: &virtualMachine{ 302 runLimit: 50000, 303 dataStack: [][]byte{{2}, {1}}, 304 }, 305 wantVM: &virtualMachine{ 306 runLimit: 49998, 307 deferredCost: -9, 308 dataStack: [][]byte{{1}}, 309 }, 310 }, { 311 op: OP_NUMEQUAL, 312 startVM: &virtualMachine{ 313 runLimit: 50000, 314 dataStack: [][]byte{{2}, {1}}, 315 }, 316 wantVM: &virtualMachine{ 317 runLimit: 49998, 318 deferredCost: -10, 319 dataStack: [][]byte{{}}, 320 }, 321 }, { 322 op: OP_NUMEQUALVERIFY, 323 startVM: &virtualMachine{ 324 runLimit: 50000, 325 dataStack: [][]byte{{2}, {2}}, 326 }, 327 wantVM: &virtualMachine{ 328 runLimit: 49998, 329 deferredCost: -18, 330 dataStack: [][]byte{}, 331 }, 332 }, { 333 op: OP_NUMEQUALVERIFY, 334 startVM: &virtualMachine{ 335 runLimit: 50000, 336 dataStack: [][]byte{{1}, {2}}, 337 }, 338 wantErr: ErrVerifyFailed, 339 }, { 340 op: OP_NUMNOTEQUAL, 341 startVM: &virtualMachine{ 342 runLimit: 50000, 343 dataStack: [][]byte{{2}, {1}}, 344 }, 345 wantVM: &virtualMachine{ 346 runLimit: 49998, 347 deferredCost: -9, 348 dataStack: [][]byte{{1}}, 349 }, 350 }, { 351 op: OP_LESSTHAN, 352 startVM: &virtualMachine{ 353 runLimit: 50000, 354 dataStack: [][]byte{{2}, {1}}, 355 }, 356 wantVM: &virtualMachine{ 357 runLimit: 49998, 358 deferredCost: -10, 359 dataStack: [][]byte{{}}, 360 }, 361 }, { 362 op: OP_LESSTHANOREQUAL, 363 startVM: &virtualMachine{ 364 runLimit: 50000, 365 dataStack: [][]byte{{2}, {1}}, 366 }, 367 wantVM: &virtualMachine{ 368 runLimit: 49998, 369 deferredCost: -10, 370 dataStack: [][]byte{{}}, 371 }, 372 }, { 373 op: OP_GREATERTHAN, 374 startVM: &virtualMachine{ 375 runLimit: 50000, 376 dataStack: [][]byte{{2}, {1}}, 377 }, 378 wantVM: &virtualMachine{ 379 runLimit: 49998, 380 deferredCost: -9, 381 dataStack: [][]byte{{1}}, 382 }, 383 }, { 384 op: OP_GREATERTHANOREQUAL, 385 startVM: &virtualMachine{ 386 runLimit: 50000, 387 dataStack: [][]byte{{2}, {1}}, 388 }, 389 wantVM: &virtualMachine{ 390 runLimit: 49998, 391 deferredCost: -9, 392 dataStack: [][]byte{{1}}, 393 }, 394 }, { 395 op: OP_MIN, 396 startVM: &virtualMachine{ 397 runLimit: 50000, 398 dataStack: [][]byte{{2}, {1}}, 399 }, 400 wantVM: &virtualMachine{ 401 runLimit: 49998, 402 deferredCost: -9, 403 dataStack: [][]byte{{1}}, 404 }, 405 }, { 406 op: OP_MIN, 407 startVM: &virtualMachine{ 408 runLimit: 50000, 409 dataStack: [][]byte{{1}, {2}}, 410 }, 411 wantVM: &virtualMachine{ 412 runLimit: 49998, 413 deferredCost: -9, 414 dataStack: [][]byte{{1}}, 415 }, 416 }, { 417 op: OP_MAX, 418 startVM: &virtualMachine{ 419 runLimit: 50000, 420 dataStack: [][]byte{{2}, {1}}, 421 }, 422 wantVM: &virtualMachine{ 423 runLimit: 49998, 424 deferredCost: -9, 425 dataStack: [][]byte{{2}}, 426 }, 427 }, { 428 op: OP_MAX, 429 startVM: &virtualMachine{ 430 runLimit: 50000, 431 dataStack: [][]byte{{1}, {2}}, 432 }, 433 wantVM: &virtualMachine{ 434 runLimit: 49998, 435 deferredCost: -9, 436 dataStack: [][]byte{{2}}, 437 }, 438 }, { 439 op: OP_WITHIN, 440 startVM: &virtualMachine{ 441 runLimit: 50000, 442 dataStack: [][]byte{{1}, {1}, {2}}, 443 }, 444 wantVM: &virtualMachine{ 445 runLimit: 49996, 446 deferredCost: -18, 447 dataStack: [][]byte{{1}}, 448 }, 449 }} 450 451 numops := []Op{ 452 OP_1ADD, OP_1SUB, OP_2MUL, OP_2DIV, OP_NEGATE, OP_ABS, OP_NOT, OP_0NOTEQUAL, 453 OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_LSHIFT, OP_RSHIFT, OP_BOOLAND, 454 OP_BOOLOR, OP_NUMEQUAL, OP_NUMEQUALVERIFY, OP_NUMNOTEQUAL, OP_LESSTHAN, 455 OP_LESSTHANOREQUAL, OP_GREATERTHAN, OP_GREATERTHANOREQUAL, OP_MIN, OP_MAX, OP_WITHIN, 456 } 457 458 for _, op := range numops { 459 cases = append(cases, testStruct{ 460 op: op, 461 startVM: &virtualMachine{ 462 runLimit: 0, 463 dataStack: [][]byte{{2}, {2}, {2}}, 464 }, 465 wantErr: ErrRunLimitExceeded, 466 }) 467 } 468 469 for i, c := range cases { 470 err := ops[c.op].fn(c.startVM) 471 472 if err != c.wantErr { 473 t.Errorf("case %d, op %s: got err = %v want %v", i, ops[c.op].name, err, c.wantErr) 474 continue 475 } 476 if c.wantErr != nil { 477 continue 478 } 479 480 if !testutil.DeepEqual(c.startVM, c.wantVM) { 481 t.Errorf("case %d, op %s: unexpected vm result\n\tgot: %+v\n\twant: %+v\n", i, ops[c.op].name, c.startVM, c.wantVM) 482 } 483 } 484 } 485 486 func TestRangeErrs(t *testing.T) { 487 cases := []struct { 488 prog string 489 expectRangeErr bool 490 }{ 491 {"0 1ADD", false}, 492 {fmt.Sprintf("%d 1ADD", int64(math.MinInt64)), false}, 493 {fmt.Sprintf("%d 1ADD", int64(math.MaxInt64)-1), false}, 494 {fmt.Sprintf("%d 1ADD", int64(math.MaxInt64)), true}, 495 {"0 1SUB", false}, 496 {fmt.Sprintf("%d 1SUB", int64(math.MaxInt64)), false}, 497 {fmt.Sprintf("%d 1SUB", int64(math.MinInt64)+1), false}, 498 {fmt.Sprintf("%d 1SUB", int64(math.MinInt64)), true}, 499 {"1 2MUL", false}, 500 {fmt.Sprintf("%d 2MUL", int64(math.MaxInt64)/2-1), false}, 501 {fmt.Sprintf("%d 2MUL", int64(math.MaxInt64)/2+1), true}, 502 {fmt.Sprintf("%d 2MUL", int64(math.MinInt64)/2+1), false}, 503 {fmt.Sprintf("%d 2MUL", int64(math.MinInt64)/2-1), true}, 504 {"1 NEGATE", false}, 505 {"-1 NEGATE", false}, 506 {fmt.Sprintf("%d NEGATE", int64(math.MaxInt64)), false}, 507 {fmt.Sprintf("%d NEGATE", int64(math.MinInt64)), true}, 508 {"1 ABS", false}, 509 {"-1 ABS", false}, 510 {fmt.Sprintf("%d ABS", int64(math.MaxInt64)), false}, 511 {fmt.Sprintf("%d ABS", int64(math.MinInt64)), true}, 512 {"2 3 ADD", false}, 513 {fmt.Sprintf("%d %d ADD", int64(math.MinInt64), int64(math.MaxInt64)), false}, 514 {fmt.Sprintf("%d %d ADD", int64(math.MaxInt64)/2-1, int64(math.MaxInt64)/2-2), false}, 515 {fmt.Sprintf("%d %d ADD", int64(math.MaxInt64)/2+1, int64(math.MaxInt64)/2+2), true}, 516 {fmt.Sprintf("%d %d ADD", int64(math.MinInt64)/2+1, int64(math.MinInt64)/2+2), false}, 517 {fmt.Sprintf("%d %d ADD", int64(math.MinInt64)/2-1, int64(math.MinInt64)/2-2), true}, 518 {"2 3 SUB", false}, 519 {fmt.Sprintf("1 %d SUB", int64(math.MaxInt64)), false}, 520 {fmt.Sprintf("-1 %d SUB", int64(math.MinInt64)), false}, 521 {fmt.Sprintf("1 %d SUB", int64(math.MinInt64)), true}, 522 {fmt.Sprintf("-1 %d SUB", int64(math.MaxInt64)), false}, 523 {fmt.Sprintf("-2 %d SUB", int64(math.MaxInt64)), true}, 524 {"1 2 LSHIFT", false}, 525 {"-1 2 LSHIFT", false}, 526 {"-1 63 LSHIFT", false}, 527 {"-1 64 LSHIFT", true}, 528 {"0 64 LSHIFT", false}, 529 {"1 62 LSHIFT", false}, 530 {"1 63 LSHIFT", true}, 531 {fmt.Sprintf("%d 0 LSHIFT", int64(math.MaxInt64)), false}, 532 {fmt.Sprintf("%d 1 LSHIFT", int64(math.MaxInt64)), true}, 533 {fmt.Sprintf("%d 1 LSHIFT", int64(math.MaxInt64)/2), false}, 534 {fmt.Sprintf("%d 2 LSHIFT", int64(math.MaxInt64)/2), true}, 535 {fmt.Sprintf("%d 0 LSHIFT", int64(math.MinInt64)), false}, 536 {fmt.Sprintf("%d 1 LSHIFT", int64(math.MinInt64)), true}, 537 {fmt.Sprintf("%d 1 LSHIFT", int64(math.MinInt64)/2), false}, 538 {fmt.Sprintf("%d 2 LSHIFT", int64(math.MinInt64)/2), true}, 539 } 540 541 for i, c := range cases { 542 prog, _ := Assemble(c.prog) 543 vm := &virtualMachine{ 544 program: prog, 545 runLimit: 50000, 546 } 547 err := vm.run() 548 switch err { 549 case nil: 550 if c.expectRangeErr { 551 t.Errorf("case %d (%s): expected range error, got none", i, c.prog) 552 } 553 case ErrRange: 554 if !c.expectRangeErr { 555 t.Errorf("case %d (%s): got unexpected range error", i, c.prog) 556 } 557 default: 558 if c.expectRangeErr { 559 t.Errorf("case %d (%s): expected range error, got %s", i, c.prog, err) 560 } else { 561 t.Errorf("case %d (%s): got unexpected error %s", i, c.prog, err) 562 } 563 } 564 } 565 }