github.com/btcsuite/btcd@v0.24.0/txscript/stack_test.go (about) 1 // Copyright (c) 2013-2017 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package txscript 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "reflect" 12 "testing" 13 ) 14 15 // tstCheckScriptError ensures the type of the two passed errors are of the 16 // same type (either both nil or both of type Error) and their error codes 17 // match when not nil. 18 func tstCheckScriptError(gotErr, wantErr error) error { 19 // Ensure the error code is of the expected type and the error 20 // code matches the value specified in the test instance. 21 if reflect.TypeOf(gotErr) != reflect.TypeOf(wantErr) { 22 return fmt.Errorf("wrong error - got %T (%[1]v), want %T", 23 gotErr, wantErr) 24 } 25 if gotErr == nil { 26 return nil 27 } 28 29 // Ensure the want error type is a script error. 30 werr, ok := wantErr.(Error) 31 if !ok { 32 return fmt.Errorf("unexpected test error type %T", wantErr) 33 } 34 35 // Ensure the error codes match. It's safe to use a raw type assert 36 // here since the code above already proved they are the same type and 37 // the want error is a script error. 38 gotErrorCode := gotErr.(Error).ErrorCode 39 if gotErrorCode != werr.ErrorCode { 40 return fmt.Errorf("mismatched error code - got %v (%v), want %v", 41 gotErrorCode, gotErr, werr.ErrorCode) 42 } 43 44 return nil 45 } 46 47 // TestStack tests that all of the stack operations work as expected. 48 func TestStack(t *testing.T) { 49 t.Parallel() 50 51 tests := []struct { 52 name string 53 before [][]byte 54 operation func(*stack) error 55 err error 56 after [][]byte 57 }{ 58 { 59 "noop", 60 [][]byte{{1}, {2}, {3}, {4}, {5}}, 61 func(s *stack) error { 62 return nil 63 }, 64 nil, 65 [][]byte{{1}, {2}, {3}, {4}, {5}}, 66 }, 67 { 68 "peek underflow (byte)", 69 [][]byte{{1}, {2}, {3}, {4}, {5}}, 70 func(s *stack) error { 71 _, err := s.PeekByteArray(5) 72 return err 73 }, 74 scriptError(ErrInvalidStackOperation, ""), 75 nil, 76 }, 77 { 78 "peek underflow (int)", 79 [][]byte{{1}, {2}, {3}, {4}, {5}}, 80 func(s *stack) error { 81 _, err := s.PeekInt(5) 82 return err 83 }, 84 scriptError(ErrInvalidStackOperation, ""), 85 nil, 86 }, 87 { 88 "peek underflow (bool)", 89 [][]byte{{1}, {2}, {3}, {4}, {5}}, 90 func(s *stack) error { 91 _, err := s.PeekBool(5) 92 return err 93 }, 94 scriptError(ErrInvalidStackOperation, ""), 95 nil, 96 }, 97 { 98 "pop", 99 [][]byte{{1}, {2}, {3}, {4}, {5}}, 100 func(s *stack) error { 101 val, err := s.PopByteArray() 102 if err != nil { 103 return err 104 } 105 if !bytes.Equal(val, []byte{5}) { 106 return errors.New("not equal") 107 } 108 return err 109 }, 110 nil, 111 [][]byte{{1}, {2}, {3}, {4}}, 112 }, 113 { 114 "pop everything", 115 [][]byte{{1}, {2}, {3}, {4}, {5}}, 116 func(s *stack) error { 117 for i := 0; i < 5; i++ { 118 _, err := s.PopByteArray() 119 if err != nil { 120 return err 121 } 122 } 123 return nil 124 }, 125 nil, 126 nil, 127 }, 128 { 129 "pop underflow", 130 [][]byte{{1}, {2}, {3}, {4}, {5}}, 131 func(s *stack) error { 132 for i := 0; i < 6; i++ { 133 _, err := s.PopByteArray() 134 if err != nil { 135 return err 136 } 137 } 138 return nil 139 }, 140 scriptError(ErrInvalidStackOperation, ""), 141 nil, 142 }, 143 { 144 "pop bool", 145 [][]byte{nil}, 146 func(s *stack) error { 147 val, err := s.PopBool() 148 if err != nil { 149 return err 150 } 151 152 if val { 153 return errors.New("unexpected value") 154 } 155 return nil 156 }, 157 nil, 158 nil, 159 }, 160 { 161 "pop bool", 162 [][]byte{{1}}, 163 func(s *stack) error { 164 val, err := s.PopBool() 165 if err != nil { 166 return err 167 } 168 169 if !val { 170 return errors.New("unexpected value") 171 } 172 return nil 173 }, 174 nil, 175 nil, 176 }, 177 { 178 "pop bool", 179 nil, 180 func(s *stack) error { 181 _, err := s.PopBool() 182 return err 183 }, 184 scriptError(ErrInvalidStackOperation, ""), 185 nil, 186 }, 187 { 188 "popInt 0", 189 [][]byte{{0x0}}, 190 func(s *stack) error { 191 v, err := s.PopInt() 192 if err != nil { 193 return err 194 } 195 if v != 0 { 196 return errors.New("0 != 0 on popInt") 197 } 198 return nil 199 }, 200 nil, 201 nil, 202 }, 203 { 204 "popInt -0", 205 [][]byte{{0x80}}, 206 func(s *stack) error { 207 v, err := s.PopInt() 208 if err != nil { 209 return err 210 } 211 if v != 0 { 212 return errors.New("-0 != 0 on popInt") 213 } 214 return nil 215 }, 216 nil, 217 nil, 218 }, 219 { 220 "popInt 1", 221 [][]byte{{0x01}}, 222 func(s *stack) error { 223 v, err := s.PopInt() 224 if err != nil { 225 return err 226 } 227 if v != 1 { 228 return errors.New("1 != 1 on popInt") 229 } 230 return nil 231 }, 232 nil, 233 nil, 234 }, 235 { 236 "popInt 1 leading 0", 237 [][]byte{{0x01, 0x00, 0x00, 0x00}}, 238 func(s *stack) error { 239 v, err := s.PopInt() 240 if err != nil { 241 return err 242 } 243 if v != 1 { 244 fmt.Printf("%v != %v\n", v, 1) 245 return errors.New("1 != 1 on popInt") 246 } 247 return nil 248 }, 249 nil, 250 nil, 251 }, 252 { 253 "popInt -1", 254 [][]byte{{0x81}}, 255 func(s *stack) error { 256 v, err := s.PopInt() 257 if err != nil { 258 return err 259 } 260 if v != -1 { 261 return errors.New("-1 != -1 on popInt") 262 } 263 return nil 264 }, 265 nil, 266 nil, 267 }, 268 { 269 "popInt -1 leading 0", 270 [][]byte{{0x01, 0x00, 0x00, 0x80}}, 271 func(s *stack) error { 272 v, err := s.PopInt() 273 if err != nil { 274 return err 275 } 276 if v != -1 { 277 fmt.Printf("%v != %v\n", v, -1) 278 return errors.New("-1 != -1 on popInt") 279 } 280 return nil 281 }, 282 nil, 283 nil, 284 }, 285 // Triggers the multibyte case in asInt 286 { 287 "popInt -513", 288 [][]byte{{0x1, 0x82}}, 289 func(s *stack) error { 290 v, err := s.PopInt() 291 if err != nil { 292 return err 293 } 294 if v != -513 { 295 fmt.Printf("%v != %v\n", v, -513) 296 return errors.New("1 != 1 on popInt") 297 } 298 return nil 299 }, 300 nil, 301 nil, 302 }, 303 // Confirm that the asInt code doesn't modify the base data. 304 { 305 "peekint nomodify -1", 306 [][]byte{{0x01, 0x00, 0x00, 0x80}}, 307 func(s *stack) error { 308 v, err := s.PeekInt(0) 309 if err != nil { 310 return err 311 } 312 if v != -1 { 313 fmt.Printf("%v != %v\n", v, -1) 314 return errors.New("-1 != -1 on popInt") 315 } 316 return nil 317 }, 318 nil, 319 [][]byte{{0x01, 0x00, 0x00, 0x80}}, 320 }, 321 { 322 "PushInt 0", 323 nil, 324 func(s *stack) error { 325 s.PushInt(scriptNum(0)) 326 return nil 327 }, 328 nil, 329 [][]byte{{}}, 330 }, 331 { 332 "PushInt 1", 333 nil, 334 func(s *stack) error { 335 s.PushInt(scriptNum(1)) 336 return nil 337 }, 338 nil, 339 [][]byte{{0x1}}, 340 }, 341 { 342 "PushInt -1", 343 nil, 344 func(s *stack) error { 345 s.PushInt(scriptNum(-1)) 346 return nil 347 }, 348 nil, 349 [][]byte{{0x81}}, 350 }, 351 { 352 "PushInt two bytes", 353 nil, 354 func(s *stack) error { 355 s.PushInt(scriptNum(256)) 356 return nil 357 }, 358 nil, 359 // little endian.. *sigh* 360 [][]byte{{0x00, 0x01}}, 361 }, 362 { 363 "PushInt leading zeros", 364 nil, 365 func(s *stack) error { 366 // this will have the highbit set 367 s.PushInt(scriptNum(128)) 368 return nil 369 }, 370 nil, 371 [][]byte{{0x80, 0x00}}, 372 }, 373 { 374 "dup", 375 [][]byte{{1}}, 376 func(s *stack) error { 377 return s.DupN(1) 378 }, 379 nil, 380 [][]byte{{1}, {1}}, 381 }, 382 { 383 "dup2", 384 [][]byte{{1}, {2}}, 385 func(s *stack) error { 386 return s.DupN(2) 387 }, 388 nil, 389 [][]byte{{1}, {2}, {1}, {2}}, 390 }, 391 { 392 "dup3", 393 [][]byte{{1}, {2}, {3}}, 394 func(s *stack) error { 395 return s.DupN(3) 396 }, 397 nil, 398 [][]byte{{1}, {2}, {3}, {1}, {2}, {3}}, 399 }, 400 { 401 "dup0", 402 [][]byte{{1}}, 403 func(s *stack) error { 404 return s.DupN(0) 405 }, 406 scriptError(ErrInvalidStackOperation, ""), 407 nil, 408 }, 409 { 410 "dup-1", 411 [][]byte{{1}}, 412 func(s *stack) error { 413 return s.DupN(-1) 414 }, 415 scriptError(ErrInvalidStackOperation, ""), 416 nil, 417 }, 418 { 419 "dup too much", 420 [][]byte{{1}}, 421 func(s *stack) error { 422 return s.DupN(2) 423 }, 424 scriptError(ErrInvalidStackOperation, ""), 425 nil, 426 }, 427 { 428 "PushBool true", 429 nil, 430 func(s *stack) error { 431 s.PushBool(true) 432 433 return nil 434 }, 435 nil, 436 [][]byte{{1}}, 437 }, 438 { 439 "PushBool false", 440 nil, 441 func(s *stack) error { 442 s.PushBool(false) 443 444 return nil 445 }, 446 nil, 447 [][]byte{nil}, 448 }, 449 { 450 "PushBool PopBool", 451 nil, 452 func(s *stack) error { 453 s.PushBool(true) 454 val, err := s.PopBool() 455 if err != nil { 456 return err 457 } 458 if !val { 459 return errors.New("unexpected value") 460 } 461 462 return nil 463 }, 464 nil, 465 nil, 466 }, 467 { 468 "PushBool PopBool 2", 469 nil, 470 func(s *stack) error { 471 s.PushBool(false) 472 val, err := s.PopBool() 473 if err != nil { 474 return err 475 } 476 if val { 477 return errors.New("unexpected value") 478 } 479 480 return nil 481 }, 482 nil, 483 nil, 484 }, 485 { 486 "PushInt PopBool", 487 nil, 488 func(s *stack) error { 489 s.PushInt(scriptNum(1)) 490 val, err := s.PopBool() 491 if err != nil { 492 return err 493 } 494 if !val { 495 return errors.New("unexpected value") 496 } 497 498 return nil 499 }, 500 nil, 501 nil, 502 }, 503 { 504 "PushInt PopBool 2", 505 nil, 506 func(s *stack) error { 507 s.PushInt(scriptNum(0)) 508 val, err := s.PopBool() 509 if err != nil { 510 return err 511 } 512 if val { 513 return errors.New("unexpected value") 514 } 515 516 return nil 517 }, 518 nil, 519 nil, 520 }, 521 { 522 "Nip top", 523 [][]byte{{1}, {2}, {3}}, 524 func(s *stack) error { 525 return s.NipN(0) 526 }, 527 nil, 528 [][]byte{{1}, {2}}, 529 }, 530 { 531 "Nip middle", 532 [][]byte{{1}, {2}, {3}}, 533 func(s *stack) error { 534 return s.NipN(1) 535 }, 536 nil, 537 [][]byte{{1}, {3}}, 538 }, 539 { 540 "Nip low", 541 [][]byte{{1}, {2}, {3}}, 542 func(s *stack) error { 543 return s.NipN(2) 544 }, 545 nil, 546 [][]byte{{2}, {3}}, 547 }, 548 { 549 "Nip too much", 550 [][]byte{{1}, {2}, {3}}, 551 func(s *stack) error { 552 // bite off more than we can chew 553 return s.NipN(3) 554 }, 555 scriptError(ErrInvalidStackOperation, ""), 556 [][]byte{{2}, {3}}, 557 }, 558 { 559 "keep on tucking", 560 [][]byte{{1}, {2}, {3}}, 561 func(s *stack) error { 562 return s.Tuck() 563 }, 564 nil, 565 [][]byte{{1}, {3}, {2}, {3}}, 566 }, 567 { 568 "a little tucked up", 569 [][]byte{{1}}, // too few arguments for tuck 570 func(s *stack) error { 571 return s.Tuck() 572 }, 573 scriptError(ErrInvalidStackOperation, ""), 574 nil, 575 }, 576 { 577 "all tucked up", 578 nil, // too few arguments for tuck 579 func(s *stack) error { 580 return s.Tuck() 581 }, 582 scriptError(ErrInvalidStackOperation, ""), 583 nil, 584 }, 585 { 586 "drop 1", 587 [][]byte{{1}, {2}, {3}, {4}}, 588 func(s *stack) error { 589 return s.DropN(1) 590 }, 591 nil, 592 [][]byte{{1}, {2}, {3}}, 593 }, 594 { 595 "drop 2", 596 [][]byte{{1}, {2}, {3}, {4}}, 597 func(s *stack) error { 598 return s.DropN(2) 599 }, 600 nil, 601 [][]byte{{1}, {2}}, 602 }, 603 { 604 "drop 3", 605 [][]byte{{1}, {2}, {3}, {4}}, 606 func(s *stack) error { 607 return s.DropN(3) 608 }, 609 nil, 610 [][]byte{{1}}, 611 }, 612 { 613 "drop 4", 614 [][]byte{{1}, {2}, {3}, {4}}, 615 func(s *stack) error { 616 return s.DropN(4) 617 }, 618 nil, 619 nil, 620 }, 621 { 622 "drop 4/5", 623 [][]byte{{1}, {2}, {3}, {4}}, 624 func(s *stack) error { 625 return s.DropN(5) 626 }, 627 scriptError(ErrInvalidStackOperation, ""), 628 nil, 629 }, 630 { 631 "drop invalid", 632 [][]byte{{1}, {2}, {3}, {4}}, 633 func(s *stack) error { 634 return s.DropN(0) 635 }, 636 scriptError(ErrInvalidStackOperation, ""), 637 nil, 638 }, 639 { 640 "Rot1", 641 [][]byte{{1}, {2}, {3}, {4}}, 642 func(s *stack) error { 643 return s.RotN(1) 644 }, 645 nil, 646 [][]byte{{1}, {3}, {4}, {2}}, 647 }, 648 { 649 "Rot2", 650 [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, 651 func(s *stack) error { 652 return s.RotN(2) 653 }, 654 nil, 655 [][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, 656 }, 657 { 658 "Rot too little", 659 [][]byte{{1}, {2}}, 660 func(s *stack) error { 661 return s.RotN(1) 662 }, 663 scriptError(ErrInvalidStackOperation, ""), 664 nil, 665 }, 666 { 667 "Rot0", 668 [][]byte{{1}, {2}, {3}}, 669 func(s *stack) error { 670 return s.RotN(0) 671 }, 672 scriptError(ErrInvalidStackOperation, ""), 673 nil, 674 }, 675 { 676 "Swap1", 677 [][]byte{{1}, {2}, {3}, {4}}, 678 func(s *stack) error { 679 return s.SwapN(1) 680 }, 681 nil, 682 [][]byte{{1}, {2}, {4}, {3}}, 683 }, 684 { 685 "Swap2", 686 [][]byte{{1}, {2}, {3}, {4}}, 687 func(s *stack) error { 688 return s.SwapN(2) 689 }, 690 nil, 691 [][]byte{{3}, {4}, {1}, {2}}, 692 }, 693 { 694 "Swap too little", 695 [][]byte{{1}}, 696 func(s *stack) error { 697 return s.SwapN(1) 698 }, 699 scriptError(ErrInvalidStackOperation, ""), 700 nil, 701 }, 702 { 703 "Swap0", 704 [][]byte{{1}, {2}, {3}}, 705 func(s *stack) error { 706 return s.SwapN(0) 707 }, 708 scriptError(ErrInvalidStackOperation, ""), 709 nil, 710 }, 711 { 712 "Over1", 713 [][]byte{{1}, {2}, {3}, {4}}, 714 func(s *stack) error { 715 return s.OverN(1) 716 }, 717 nil, 718 [][]byte{{1}, {2}, {3}, {4}, {3}}, 719 }, 720 { 721 "Over2", 722 [][]byte{{1}, {2}, {3}, {4}}, 723 func(s *stack) error { 724 return s.OverN(2) 725 }, 726 nil, 727 [][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, 728 }, 729 { 730 "Over too little", 731 [][]byte{{1}}, 732 func(s *stack) error { 733 return s.OverN(1) 734 }, 735 scriptError(ErrInvalidStackOperation, ""), 736 nil, 737 }, 738 { 739 "Over0", 740 [][]byte{{1}, {2}, {3}}, 741 func(s *stack) error { 742 return s.OverN(0) 743 }, 744 scriptError(ErrInvalidStackOperation, ""), 745 nil, 746 }, 747 { 748 "Pick1", 749 [][]byte{{1}, {2}, {3}, {4}}, 750 func(s *stack) error { 751 return s.PickN(1) 752 }, 753 nil, 754 [][]byte{{1}, {2}, {3}, {4}, {3}}, 755 }, 756 { 757 "Pick2", 758 [][]byte{{1}, {2}, {3}, {4}}, 759 func(s *stack) error { 760 return s.PickN(2) 761 }, 762 nil, 763 [][]byte{{1}, {2}, {3}, {4}, {2}}, 764 }, 765 { 766 "Pick too little", 767 [][]byte{{1}}, 768 func(s *stack) error { 769 return s.PickN(1) 770 }, 771 scriptError(ErrInvalidStackOperation, ""), 772 nil, 773 }, 774 { 775 "Roll1", 776 [][]byte{{1}, {2}, {3}, {4}}, 777 func(s *stack) error { 778 return s.RollN(1) 779 }, 780 nil, 781 [][]byte{{1}, {2}, {4}, {3}}, 782 }, 783 { 784 "Roll2", 785 [][]byte{{1}, {2}, {3}, {4}}, 786 func(s *stack) error { 787 return s.RollN(2) 788 }, 789 nil, 790 [][]byte{{1}, {3}, {4}, {2}}, 791 }, 792 { 793 "Roll too little", 794 [][]byte{{1}}, 795 func(s *stack) error { 796 return s.RollN(1) 797 }, 798 scriptError(ErrInvalidStackOperation, ""), 799 nil, 800 }, 801 { 802 "Peek bool", 803 [][]byte{{1}}, 804 func(s *stack) error { 805 // Peek bool is otherwise pretty well tested, 806 // just check it works. 807 val, err := s.PeekBool(0) 808 if err != nil { 809 return err 810 } 811 if !val { 812 return errors.New("invalid result") 813 } 814 return nil 815 }, 816 nil, 817 [][]byte{{1}}, 818 }, 819 { 820 "Peek bool 2", 821 [][]byte{nil}, 822 func(s *stack) error { 823 // Peek bool is otherwise pretty well tested, 824 // just check it works. 825 val, err := s.PeekBool(0) 826 if err != nil { 827 return err 828 } 829 if val { 830 return errors.New("invalid result") 831 } 832 return nil 833 }, 834 nil, 835 [][]byte{nil}, 836 }, 837 { 838 "Peek int", 839 [][]byte{{1}}, 840 func(s *stack) error { 841 // Peek int is otherwise pretty well tested, 842 // just check it works. 843 val, err := s.PeekInt(0) 844 if err != nil { 845 return err 846 } 847 if val != 1 { 848 return errors.New("invalid result") 849 } 850 return nil 851 }, 852 nil, 853 [][]byte{{1}}, 854 }, 855 { 856 "Peek int 2", 857 [][]byte{{0}}, 858 func(s *stack) error { 859 // Peek int is otherwise pretty well tested, 860 // just check it works. 861 val, err := s.PeekInt(0) 862 if err != nil { 863 return err 864 } 865 if val != 0 { 866 return errors.New("invalid result") 867 } 868 return nil 869 }, 870 nil, 871 [][]byte{{0}}, 872 }, 873 { 874 "pop int", 875 nil, 876 func(s *stack) error { 877 s.PushInt(scriptNum(1)) 878 // Peek int is otherwise pretty well tested, 879 // just check it works. 880 val, err := s.PopInt() 881 if err != nil { 882 return err 883 } 884 if val != 1 { 885 return errors.New("invalid result") 886 } 887 return nil 888 }, 889 nil, 890 nil, 891 }, 892 { 893 "pop empty", 894 nil, 895 func(s *stack) error { 896 // Peek int is otherwise pretty well tested, 897 // just check it works. 898 _, err := s.PopInt() 899 return err 900 }, 901 scriptError(ErrInvalidStackOperation, ""), 902 nil, 903 }, 904 } 905 906 for _, test := range tests { 907 // Setup the initial stack state and perform the test operation. 908 s := stack{} 909 for i := range test.before { 910 s.PushByteArray(test.before[i]) 911 } 912 err := test.operation(&s) 913 914 // Ensure the error code is of the expected type and the error 915 // code matches the value specified in the test instance. 916 if e := tstCheckScriptError(err, test.err); e != nil { 917 t.Errorf("%s: %v", test.name, e) 918 continue 919 } 920 if err != nil { 921 continue 922 } 923 924 // Ensure the resulting stack is the expected length. 925 if int32(len(test.after)) != s.Depth() { 926 t.Errorf("%s: stack depth doesn't match expected: %v "+ 927 "vs %v", test.name, len(test.after), 928 s.Depth()) 929 continue 930 } 931 932 // Ensure all items of the resulting stack are the expected 933 // values. 934 for i := range test.after { 935 val, err := s.PeekByteArray(s.Depth() - int32(i) - 1) 936 if err != nil { 937 t.Errorf("%s: can't peek %dth stack entry: %v", 938 test.name, i, err) 939 break 940 } 941 942 if !bytes.Equal(val, test.after[i]) { 943 t.Errorf("%s: %dth stack entry doesn't match "+ 944 "expected: %v vs %v", test.name, i, val, 945 test.after[i]) 946 break 947 } 948 } 949 } 950 }