1// Copyright (c) 2015-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
5package txscript
6
7import (
8	"bytes"
9	"encoding/hex"
10	"testing"
11)
12
13// hexToBytes converts the passed hex string into bytes and will panic if there
14// is an error.  This is only provided for the hard-coded constants so errors in
15// the source code can be detected. It will only (and must only) be called with
16// hard-coded values.
17func hexToBytes(s string) []byte {
18	b, err := hex.DecodeString(s)
19	if err != nil {
20		panic("invalid hex in source file: " + s)
21	}
22	return b
23}
24
25// TestScriptNumBytes ensures that converting from integral script numbers to
26// byte representations works as expected.
27func TestScriptNumBytes(t *testing.T) {
28	t.Parallel()
29
30	tests := []struct {
31		num        scriptNum
32		serialized []byte
33	}{
34		{0, nil},
35		{1, hexToBytes("01")},
36		{-1, hexToBytes("81")},
37		{127, hexToBytes("7f")},
38		{-127, hexToBytes("ff")},
39		{128, hexToBytes("8000")},
40		{-128, hexToBytes("8080")},
41		{129, hexToBytes("8100")},
42		{-129, hexToBytes("8180")},
43		{256, hexToBytes("0001")},
44		{-256, hexToBytes("0081")},
45		{32767, hexToBytes("ff7f")},
46		{-32767, hexToBytes("ffff")},
47		{32768, hexToBytes("008000")},
48		{-32768, hexToBytes("008080")},
49		{65535, hexToBytes("ffff00")},
50		{-65535, hexToBytes("ffff80")},
51		{524288, hexToBytes("000008")},
52		{-524288, hexToBytes("000088")},
53		{7340032, hexToBytes("000070")},
54		{-7340032, hexToBytes("0000f0")},
55		{8388608, hexToBytes("00008000")},
56		{-8388608, hexToBytes("00008080")},
57		{2147483647, hexToBytes("ffffff7f")},
58		{-2147483647, hexToBytes("ffffffff")},
59
60		// Values that are out of range for data that is interpreted as
61		// numbers, but are allowed as the result of numeric operations.
62		{2147483648, hexToBytes("0000008000")},
63		{-2147483648, hexToBytes("0000008080")},
64		{2415919104, hexToBytes("0000009000")},
65		{-2415919104, hexToBytes("0000009080")},
66		{4294967295, hexToBytes("ffffffff00")},
67		{-4294967295, hexToBytes("ffffffff80")},
68		{4294967296, hexToBytes("0000000001")},
69		{-4294967296, hexToBytes("0000000081")},
70		{281474976710655, hexToBytes("ffffffffffff00")},
71		{-281474976710655, hexToBytes("ffffffffffff80")},
72		{72057594037927935, hexToBytes("ffffffffffffff00")},
73		{-72057594037927935, hexToBytes("ffffffffffffff80")},
74		{9223372036854775807, hexToBytes("ffffffffffffff7f")},
75		{-9223372036854775807, hexToBytes("ffffffffffffffff")},
76	}
77
78	for _, test := range tests {
79		gotBytes := test.num.Bytes()
80		if !bytes.Equal(gotBytes, test.serialized) {
81			t.Errorf("Bytes: did not get expected bytes for %d - "+
82				"got %x, want %x", test.num, gotBytes,
83				test.serialized)
84			continue
85		}
86	}
87}
88
89// TestMakeScriptNum ensures that converting from byte representations to
90// integral script numbers works as expected.
91func TestMakeScriptNum(t *testing.T) {
92	t.Parallel()
93
94	// Errors used in the tests below defined here for convenience and to
95	// keep the horizontal test size shorter.
96	errNumTooBig := scriptError(ErrNumberTooBig, "")
97	errMinimalData := scriptError(ErrMinimalData, "")
98
99	tests := []struct {
100		serialized      []byte
101		num             scriptNum
102		numLen          int
103		minimalEncoding bool
104		err             error
105	}{
106		// Minimal encoding must reject negative 0.
107		{hexToBytes("80"), 0, defaultScriptNumLen, true, errMinimalData},
108
109		// Minimally encoded valid values with minimal encoding flag.
110		// Should not error and return expected integral number.
111		{nil, 0, defaultScriptNumLen, true, nil},
112		{hexToBytes("01"), 1, defaultScriptNumLen, true, nil},
113		{hexToBytes("81"), -1, defaultScriptNumLen, true, nil},
114		{hexToBytes("7f"), 127, defaultScriptNumLen, true, nil},
115		{hexToBytes("ff"), -127, defaultScriptNumLen, true, nil},
116		{hexToBytes("8000"), 128, defaultScriptNumLen, true, nil},
117		{hexToBytes("8080"), -128, defaultScriptNumLen, true, nil},
118		{hexToBytes("8100"), 129, defaultScriptNumLen, true, nil},
119		{hexToBytes("8180"), -129, defaultScriptNumLen, true, nil},
120		{hexToBytes("0001"), 256, defaultScriptNumLen, true, nil},
121		{hexToBytes("0081"), -256, defaultScriptNumLen, true, nil},
122		{hexToBytes("ff7f"), 32767, defaultScriptNumLen, true, nil},
123		{hexToBytes("ffff"), -32767, defaultScriptNumLen, true, nil},
124		{hexToBytes("008000"), 32768, defaultScriptNumLen, true, nil},
125		{hexToBytes("008080"), -32768, defaultScriptNumLen, true, nil},
126		{hexToBytes("ffff00"), 65535, defaultScriptNumLen, true, nil},
127		{hexToBytes("ffff80"), -65535, defaultScriptNumLen, true, nil},
128		{hexToBytes("000008"), 524288, defaultScriptNumLen, true, nil},
129		{hexToBytes("000088"), -524288, defaultScriptNumLen, true, nil},
130		{hexToBytes("000070"), 7340032, defaultScriptNumLen, true, nil},
131		{hexToBytes("0000f0"), -7340032, defaultScriptNumLen, true, nil},
132		{hexToBytes("00008000"), 8388608, defaultScriptNumLen, true, nil},
133		{hexToBytes("00008080"), -8388608, defaultScriptNumLen, true, nil},
134		{hexToBytes("ffffff7f"), 2147483647, defaultScriptNumLen, true, nil},
135		{hexToBytes("ffffffff"), -2147483647, defaultScriptNumLen, true, nil},
136		{hexToBytes("ffffffff7f"), 549755813887, 5, true, nil},
137		{hexToBytes("ffffffffff"), -549755813887, 5, true, nil},
138		{hexToBytes("ffffffffffffff7f"), 9223372036854775807, 8, true, nil},
139		{hexToBytes("ffffffffffffffff"), -9223372036854775807, 8, true, nil},
140		{hexToBytes("ffffffffffffffff7f"), -1, 9, true, nil},
141		{hexToBytes("ffffffffffffffffff"), 1, 9, true, nil},
142		{hexToBytes("ffffffffffffffffff7f"), -1, 10, true, nil},
143		{hexToBytes("ffffffffffffffffffff"), 1, 10, true, nil},
144
145		// Minimally encoded values that are out of range for data that
146		// is interpreted as script numbers with the minimal encoding
147		// flag set.  Should error and return 0.
148		{hexToBytes("0000008000"), 0, defaultScriptNumLen, true, errNumTooBig},
149		{hexToBytes("0000008080"), 0, defaultScriptNumLen, true, errNumTooBig},
150		{hexToBytes("0000009000"), 0, defaultScriptNumLen, true, errNumTooBig},
151		{hexToBytes("0000009080"), 0, defaultScriptNumLen, true, errNumTooBig},
152		{hexToBytes("ffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
153		{hexToBytes("ffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
154		{hexToBytes("0000000001"), 0, defaultScriptNumLen, true, errNumTooBig},
155		{hexToBytes("0000000081"), 0, defaultScriptNumLen, true, errNumTooBig},
156		{hexToBytes("ffffffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
157		{hexToBytes("ffffffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
158		{hexToBytes("ffffffffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
159		{hexToBytes("ffffffffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
160		{hexToBytes("ffffffffffffff7f"), 0, defaultScriptNumLen, true, errNumTooBig},
161		{hexToBytes("ffffffffffffffff"), 0, defaultScriptNumLen, true, errNumTooBig},
162
163		// Non-minimally encoded, but otherwise valid values with
164		// minimal encoding flag.  Should error and return 0.
165		{hexToBytes("00"), 0, defaultScriptNumLen, true, errMinimalData},       // 0
166		{hexToBytes("0100"), 0, defaultScriptNumLen, true, errMinimalData},     // 1
167		{hexToBytes("7f00"), 0, defaultScriptNumLen, true, errMinimalData},     // 127
168		{hexToBytes("800000"), 0, defaultScriptNumLen, true, errMinimalData},   // 128
169		{hexToBytes("810000"), 0, defaultScriptNumLen, true, errMinimalData},   // 129
170		{hexToBytes("000100"), 0, defaultScriptNumLen, true, errMinimalData},   // 256
171		{hexToBytes("ff7f00"), 0, defaultScriptNumLen, true, errMinimalData},   // 32767
172		{hexToBytes("00800000"), 0, defaultScriptNumLen, true, errMinimalData}, // 32768
173		{hexToBytes("ffff0000"), 0, defaultScriptNumLen, true, errMinimalData}, // 65535
174		{hexToBytes("00000800"), 0, defaultScriptNumLen, true, errMinimalData}, // 524288
175		{hexToBytes("00007000"), 0, defaultScriptNumLen, true, errMinimalData}, // 7340032
176		{hexToBytes("0009000100"), 0, 5, true, errMinimalData},                 // 16779520
177
178		// Non-minimally encoded, but otherwise valid values without
179		// minimal encoding flag.  Should not error and return expected
180		// integral number.
181		{hexToBytes("00"), 0, defaultScriptNumLen, false, nil},
182		{hexToBytes("0100"), 1, defaultScriptNumLen, false, nil},
183		{hexToBytes("7f00"), 127, defaultScriptNumLen, false, nil},
184		{hexToBytes("800000"), 128, defaultScriptNumLen, false, nil},
185		{hexToBytes("810000"), 129, defaultScriptNumLen, false, nil},
186		{hexToBytes("000100"), 256, defaultScriptNumLen, false, nil},
187		{hexToBytes("ff7f00"), 32767, defaultScriptNumLen, false, nil},
188		{hexToBytes("00800000"), 32768, defaultScriptNumLen, false, nil},
189		{hexToBytes("ffff0000"), 65535, defaultScriptNumLen, false, nil},
190		{hexToBytes("00000800"), 524288, defaultScriptNumLen, false, nil},
191		{hexToBytes("00007000"), 7340032, defaultScriptNumLen, false, nil},
192		{hexToBytes("0009000100"), 16779520, 5, false, nil},
193	}
194
195	for _, test := range tests {
196		// Ensure the error code is of the expected type and the error
197		// code matches the value specified in the test instance.
198		gotNum, err := makeScriptNum(test.serialized, test.minimalEncoding,
199			test.numLen)
200		if e := tstCheckScriptError(err, test.err); e != nil {
201			t.Errorf("makeScriptNum(%#x): %v", test.serialized, e)
202			continue
203		}
204
205		if gotNum != test.num {
206			t.Errorf("makeScriptNum(%#x): did not get expected "+
207				"number - got %d, want %d", test.serialized,
208				gotNum, test.num)
209			continue
210		}
211	}
212}
213
214// TestScriptNumInt32 ensures that the Int32 function on script number behaves
215// as expected.
216func TestScriptNumInt32(t *testing.T) {
217	t.Parallel()
218
219	tests := []struct {
220		in   scriptNum
221		want int32
222	}{
223		// Values inside the valid int32 range are just the values
224		// themselves cast to an int32.
225		{0, 0},
226		{1, 1},
227		{-1, -1},
228		{127, 127},
229		{-127, -127},
230		{128, 128},
231		{-128, -128},
232		{129, 129},
233		{-129, -129},
234		{256, 256},
235		{-256, -256},
236		{32767, 32767},
237		{-32767, -32767},
238		{32768, 32768},
239		{-32768, -32768},
240		{65535, 65535},
241		{-65535, -65535},
242		{524288, 524288},
243		{-524288, -524288},
244		{7340032, 7340032},
245		{-7340032, -7340032},
246		{8388608, 8388608},
247		{-8388608, -8388608},
248		{2147483647, 2147483647},
249		{-2147483647, -2147483647},
250		{-2147483648, -2147483648},
251
252		// Values outside of the valid int32 range are limited to int32.
253		{2147483648, 2147483647},
254		{-2147483649, -2147483648},
255		{1152921504606846975, 2147483647},
256		{-1152921504606846975, -2147483648},
257		{2305843009213693951, 2147483647},
258		{-2305843009213693951, -2147483648},
259		{4611686018427387903, 2147483647},
260		{-4611686018427387903, -2147483648},
261		{9223372036854775807, 2147483647},
262		{-9223372036854775808, -2147483648},
263	}
264
265	for _, test := range tests {
266		got := test.in.Int32()
267		if got != test.want {
268			t.Errorf("Int32: did not get expected value for %d - "+
269				"got %d, want %d", test.in, got, test.want)
270			continue
271		}
272	}
273}
274