github.com/btcsuite/btcd@v0.24.0/txscript/scriptnum_test.go (about) 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 5 package txscript 6 7 import ( 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. 17 func 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. 27 func 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. 91 func 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, maxScriptNumLen, true, errMinimalData}, 108 109 // Minimally encoded valid values with minimal encoding flag. 110 // Should not error and return expected integral number. 111 {nil, 0, maxScriptNumLen, true, nil}, 112 {hexToBytes("01"), 1, maxScriptNumLen, true, nil}, 113 {hexToBytes("81"), -1, maxScriptNumLen, true, nil}, 114 {hexToBytes("7f"), 127, maxScriptNumLen, true, nil}, 115 {hexToBytes("ff"), -127, maxScriptNumLen, true, nil}, 116 {hexToBytes("8000"), 128, maxScriptNumLen, true, nil}, 117 {hexToBytes("8080"), -128, maxScriptNumLen, true, nil}, 118 {hexToBytes("8100"), 129, maxScriptNumLen, true, nil}, 119 {hexToBytes("8180"), -129, maxScriptNumLen, true, nil}, 120 {hexToBytes("0001"), 256, maxScriptNumLen, true, nil}, 121 {hexToBytes("0081"), -256, maxScriptNumLen, true, nil}, 122 {hexToBytes("ff7f"), 32767, maxScriptNumLen, true, nil}, 123 {hexToBytes("ffff"), -32767, maxScriptNumLen, true, nil}, 124 {hexToBytes("008000"), 32768, maxScriptNumLen, true, nil}, 125 {hexToBytes("008080"), -32768, maxScriptNumLen, true, nil}, 126 {hexToBytes("ffff00"), 65535, maxScriptNumLen, true, nil}, 127 {hexToBytes("ffff80"), -65535, maxScriptNumLen, true, nil}, 128 {hexToBytes("000008"), 524288, maxScriptNumLen, true, nil}, 129 {hexToBytes("000088"), -524288, maxScriptNumLen, true, nil}, 130 {hexToBytes("000070"), 7340032, maxScriptNumLen, true, nil}, 131 {hexToBytes("0000f0"), -7340032, maxScriptNumLen, true, nil}, 132 {hexToBytes("00008000"), 8388608, maxScriptNumLen, true, nil}, 133 {hexToBytes("00008080"), -8388608, maxScriptNumLen, true, nil}, 134 {hexToBytes("ffffff7f"), 2147483647, maxScriptNumLen, true, nil}, 135 {hexToBytes("ffffffff"), -2147483647, maxScriptNumLen, 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, maxScriptNumLen, true, errNumTooBig}, 149 {hexToBytes("0000008080"), 0, maxScriptNumLen, true, errNumTooBig}, 150 {hexToBytes("0000009000"), 0, maxScriptNumLen, true, errNumTooBig}, 151 {hexToBytes("0000009080"), 0, maxScriptNumLen, true, errNumTooBig}, 152 {hexToBytes("ffffffff00"), 0, maxScriptNumLen, true, errNumTooBig}, 153 {hexToBytes("ffffffff80"), 0, maxScriptNumLen, true, errNumTooBig}, 154 {hexToBytes("0000000001"), 0, maxScriptNumLen, true, errNumTooBig}, 155 {hexToBytes("0000000081"), 0, maxScriptNumLen, true, errNumTooBig}, 156 {hexToBytes("ffffffffffff00"), 0, maxScriptNumLen, true, errNumTooBig}, 157 {hexToBytes("ffffffffffff80"), 0, maxScriptNumLen, true, errNumTooBig}, 158 {hexToBytes("ffffffffffffff00"), 0, maxScriptNumLen, true, errNumTooBig}, 159 {hexToBytes("ffffffffffffff80"), 0, maxScriptNumLen, true, errNumTooBig}, 160 {hexToBytes("ffffffffffffff7f"), 0, maxScriptNumLen, true, errNumTooBig}, 161 {hexToBytes("ffffffffffffffff"), 0, maxScriptNumLen, 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, maxScriptNumLen, true, errMinimalData}, // 0 166 {hexToBytes("0100"), 0, maxScriptNumLen, true, errMinimalData}, // 1 167 {hexToBytes("7f00"), 0, maxScriptNumLen, true, errMinimalData}, // 127 168 {hexToBytes("800000"), 0, maxScriptNumLen, true, errMinimalData}, // 128 169 {hexToBytes("810000"), 0, maxScriptNumLen, true, errMinimalData}, // 129 170 {hexToBytes("000100"), 0, maxScriptNumLen, true, errMinimalData}, // 256 171 {hexToBytes("ff7f00"), 0, maxScriptNumLen, true, errMinimalData}, // 32767 172 {hexToBytes("00800000"), 0, maxScriptNumLen, true, errMinimalData}, // 32768 173 {hexToBytes("ffff0000"), 0, maxScriptNumLen, true, errMinimalData}, // 65535 174 {hexToBytes("00000800"), 0, maxScriptNumLen, true, errMinimalData}, // 524288 175 {hexToBytes("00007000"), 0, maxScriptNumLen, 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, maxScriptNumLen, false, nil}, 182 {hexToBytes("0100"), 1, maxScriptNumLen, false, nil}, 183 {hexToBytes("7f00"), 127, maxScriptNumLen, false, nil}, 184 {hexToBytes("800000"), 128, maxScriptNumLen, false, nil}, 185 {hexToBytes("810000"), 129, maxScriptNumLen, false, nil}, 186 {hexToBytes("000100"), 256, maxScriptNumLen, false, nil}, 187 {hexToBytes("ff7f00"), 32767, maxScriptNumLen, false, nil}, 188 {hexToBytes("00800000"), 32768, maxScriptNumLen, false, nil}, 189 {hexToBytes("ffff0000"), 65535, maxScriptNumLen, false, nil}, 190 {hexToBytes("00000800"), 524288, maxScriptNumLen, false, nil}, 191 {hexToBytes("00007000"), 7340032, maxScriptNumLen, 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. 216 func 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 }