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