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