github.com/lbryio/lbcd@v0.22.119/txscript/standard_test.go (about) 1 // Copyright (c) 2013-2020 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 "errors" 11 "reflect" 12 "testing" 13 14 "github.com/lbryio/lbcd/chaincfg" 15 "github.com/lbryio/lbcd/wire" 16 btcutil "github.com/lbryio/lbcutil" 17 ) 18 19 // mustParseShortForm parses the passed short form script and returns the 20 // resulting bytes. It panics if an error occurs. This is only used in the 21 // tests as a helper since the only way it can fail is if there is an error in 22 // the test source code. 23 func mustParseShortForm(script string) []byte { 24 s, err := parseShortForm(script) 25 if err != nil { 26 panic("invalid short form script in test source: err " + 27 err.Error() + ", script: " + script) 28 } 29 30 return s 31 } 32 33 // newAddressPubKey returns a new btcutil.AddressPubKey from the provided 34 // serialized public key. It panics if an error occurs. This is only used in 35 // the tests as a helper since the only way it can fail is if there is an error 36 // in the test source code. 37 func newAddressPubKey(serializedPubKey []byte) btcutil.Address { 38 addr, err := btcutil.NewAddressPubKey(serializedPubKey, 39 &chaincfg.MainNetParams) 40 if err != nil { 41 panic("invalid public key in test source") 42 } 43 44 return addr 45 } 46 47 // newAddressPubKeyHash returns a new btcutil.AddressPubKeyHash from the 48 // provided hash. It panics if an error occurs. This is only used in the tests 49 // as a helper since the only way it can fail is if there is an error in the 50 // test source code. 51 func newAddressPubKeyHash(pkHash []byte) btcutil.Address { 52 addr, err := btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.MainNetParams) 53 if err != nil { 54 panic("invalid public key hash in test source") 55 } 56 57 return addr 58 } 59 60 // newAddressScriptHash returns a new btcutil.AddressScriptHash from the 61 // provided hash. It panics if an error occurs. This is only used in the tests 62 // as a helper since the only way it can fail is if there is an error in the 63 // test source code. 64 func newAddressScriptHash(scriptHash []byte) btcutil.Address { 65 addr, err := btcutil.NewAddressScriptHashFromHash(scriptHash, 66 &chaincfg.MainNetParams) 67 if err != nil { 68 panic("invalid script hash in test source") 69 } 70 71 return addr 72 } 73 74 // TestExtractPkScriptAddrs ensures that extracting the type, addresses, and 75 // number of required signatures from PkScripts works as intended. 76 func TestExtractPkScriptAddrs(t *testing.T) { 77 t.Parallel() 78 79 tests := []struct { 80 name string 81 script []byte 82 addrs []btcutil.Address 83 reqSigs int 84 class ScriptClass 85 }{ 86 { 87 name: "standard p2pk with compressed pubkey (0x02)", 88 script: hexToBytes("2102192d74d0cb94344c9569c2e779015" + 89 "73d8d7903c3ebec3a957724895dca52c6b4ac"), 90 addrs: []btcutil.Address{ 91 newAddressPubKey(hexToBytes("02192d74d0cb9434" + 92 "4c9569c2e77901573d8d7903c3ebec3a9577" + 93 "24895dca52c6b4")), 94 }, 95 reqSigs: 1, 96 class: PubKeyTy, 97 }, 98 { 99 name: "standard p2pk with uncompressed pubkey (0x04)", 100 script: hexToBytes("410411db93e1dcdb8a016b49840f8c53b" + 101 "c1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddf" + 102 "b84ccf9744464f82e160bfa9b8b64f9d4c03f999b864" + 103 "3f656b412a3ac"), 104 addrs: []btcutil.Address{ 105 newAddressPubKey(hexToBytes("0411db93e1dcdb8a" + 106 "016b49840f8c53bc1eb68a382e97b1482eca" + 107 "d7b148a6909a5cb2e0eaddfb84ccf9744464" + 108 "f82e160bfa9b8b64f9d4c03f999b8643f656" + 109 "b412a3")), 110 }, 111 reqSigs: 1, 112 class: PubKeyTy, 113 }, 114 { 115 name: "standard p2pk with hybrid pubkey (0x06)", 116 script: hexToBytes("4106192d74d0cb94344c9569c2e779015" + 117 "73d8d7903c3ebec3a957724895dca52c6b40d4526483" + 118 "8c0bd96852662ce6a847b197376830160c6d2eb5e6a4" + 119 "c44d33f453eac"), 120 addrs: []btcutil.Address{ 121 newAddressPubKey(hexToBytes("06192d74d0cb9434" + 122 "4c9569c2e77901573d8d7903c3ebec3a9577" + 123 "24895dca52c6b40d45264838c0bd96852662" + 124 "ce6a847b197376830160c6d2eb5e6a4c44d3" + 125 "3f453e")), 126 }, 127 reqSigs: 1, 128 class: PubKeyTy, 129 }, 130 { 131 name: "standard p2pk with compressed pubkey (0x03)", 132 script: hexToBytes("2103b0bd634234abbb1ba1e986e884185" + 133 "c61cf43e001f9137f23c2c409273eb16e65ac"), 134 addrs: []btcutil.Address{ 135 newAddressPubKey(hexToBytes("03b0bd634234abbb" + 136 "1ba1e986e884185c61cf43e001f9137f23c2" + 137 "c409273eb16e65")), 138 }, 139 reqSigs: 1, 140 class: PubKeyTy, 141 }, 142 { 143 name: "2nd standard p2pk with uncompressed pubkey (0x04)", 144 script: hexToBytes("4104b0bd634234abbb1ba1e986e884185" + 145 "c61cf43e001f9137f23c2c409273eb16e6537a576782" + 146 "eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3" + 147 "c1e0908ef7bac"), 148 addrs: []btcutil.Address{ 149 newAddressPubKey(hexToBytes("04b0bd634234abbb" + 150 "1ba1e986e884185c61cf43e001f9137f23c2" + 151 "c409273eb16e6537a576782eba668a7ef8bd" + 152 "3b3cfb1edb7117ab65129b8a2e681f3c1e09" + 153 "08ef7b")), 154 }, 155 reqSigs: 1, 156 class: PubKeyTy, 157 }, 158 { 159 name: "standard p2pk with hybrid pubkey (0x07)", 160 script: hexToBytes("4107b0bd634234abbb1ba1e986e884185" + 161 "c61cf43e001f9137f23c2c409273eb16e6537a576782" + 162 "eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3" + 163 "c1e0908ef7bac"), 164 addrs: []btcutil.Address{ 165 newAddressPubKey(hexToBytes("07b0bd634234abbb" + 166 "1ba1e986e884185c61cf43e001f9137f23c2" + 167 "c409273eb16e6537a576782eba668a7ef8bd" + 168 "3b3cfb1edb7117ab65129b8a2e681f3c1e09" + 169 "08ef7b")), 170 }, 171 reqSigs: 1, 172 class: PubKeyTy, 173 }, 174 { 175 name: "standard p2pkh", 176 script: hexToBytes("76a914ad06dd6ddee55cbca9a9e3713bd" + 177 "7587509a3056488ac"), 178 addrs: []btcutil.Address{ 179 newAddressPubKeyHash(hexToBytes("ad06dd6ddee5" + 180 "5cbca9a9e3713bd7587509a30564")), 181 }, 182 reqSigs: 1, 183 class: PubKeyHashTy, 184 }, 185 { 186 name: "standard p2sh", 187 script: hexToBytes("a91463bcc565f9e68ee0189dd5cc67f1b" + 188 "0e5f02f45cb87"), 189 addrs: []btcutil.Address{ 190 newAddressScriptHash(hexToBytes("63bcc565f9e6" + 191 "8ee0189dd5cc67f1b0e5f02f45cb")), 192 }, 193 reqSigs: 1, 194 class: ScriptHashTy, 195 }, 196 // from real tx 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1, vout 0 197 { 198 name: "standard 1 of 2 multisig", 199 script: hexToBytes("514104cc71eb30d653c0c3163990c47b9" + 200 "76f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a47" + 201 "3e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d1" + 202 "1fcdd0d348ac4410461cbdcc5409fb4b4d42b51d3338" + 203 "1354d80e550078cb532a34bfa2fcfdeb7d76519aecc6" + 204 "2770f5b0e4ef8551946d8a540911abe3e7854a26f39f" + 205 "58b25c15342af52ae"), 206 addrs: []btcutil.Address{ 207 newAddressPubKey(hexToBytes("04cc71eb30d653c0" + 208 "c3163990c47b976f3fb3f37cccdcbedb169a" + 209 "1dfef58bbfbfaff7d8a473e7e2e6d317b87b" + 210 "afe8bde97e3cf8f065dec022b51d11fcdd0d" + 211 "348ac4")), 212 newAddressPubKey(hexToBytes("0461cbdcc5409fb4" + 213 "b4d42b51d33381354d80e550078cb532a34b" + 214 "fa2fcfdeb7d76519aecc62770f5b0e4ef855" + 215 "1946d8a540911abe3e7854a26f39f58b25c1" + 216 "5342af")), 217 }, 218 reqSigs: 1, 219 class: MultiSigTy, 220 }, 221 // from real tx d646f82bd5fbdb94a36872ce460f97662b80c3050ad3209bef9d1e398ea277ab, vin 1 222 { 223 name: "standard 2 of 3 multisig", 224 script: hexToBytes("524104cb9c3c222c5f7a7d3b9bd152f36" + 225 "3a0b6d54c9eb312c4d4f9af1e8551b6c421a6a4ab0e2" + 226 "9105f24de20ff463c1c91fcf3bf662cdde4783d4799f" + 227 "787cb7c08869b4104ccc588420deeebea22a7e900cc8" + 228 "b68620d2212c374604e3487ca08f1ff3ae12bdc63951" + 229 "4d0ec8612a2d3c519f084d9a00cbbe3b53d071e9b09e" + 230 "71e610b036aa24104ab47ad1939edcb3db65f7fedea6" + 231 "2bbf781c5410d3f22a7a3a56ffefb2238af8627363bd" + 232 "f2ed97c1f89784a1aecdb43384f11d2acc64443c7fc2" + 233 "99cef0400421a53ae"), 234 addrs: []btcutil.Address{ 235 newAddressPubKey(hexToBytes("04cb9c3c222c5f7a" + 236 "7d3b9bd152f363a0b6d54c9eb312c4d4f9af" + 237 "1e8551b6c421a6a4ab0e29105f24de20ff46" + 238 "3c1c91fcf3bf662cdde4783d4799f787cb7c" + 239 "08869b")), 240 newAddressPubKey(hexToBytes("04ccc588420deeeb" + 241 "ea22a7e900cc8b68620d2212c374604e3487" + 242 "ca08f1ff3ae12bdc639514d0ec8612a2d3c5" + 243 "19f084d9a00cbbe3b53d071e9b09e71e610b" + 244 "036aa2")), 245 newAddressPubKey(hexToBytes("04ab47ad1939edcb" + 246 "3db65f7fedea62bbf781c5410d3f22a7a3a5" + 247 "6ffefb2238af8627363bdf2ed97c1f89784a" + 248 "1aecdb43384f11d2acc64443c7fc299cef04" + 249 "00421a")), 250 }, 251 reqSigs: 2, 252 class: MultiSigTy, 253 }, 254 255 // The below are nonstandard script due to things such as 256 // invalid pubkeys, failure to parse, and not being of a 257 // standard form. 258 259 { 260 name: "p2pk with uncompressed pk missing OP_CHECKSIG", 261 script: hexToBytes("410411db93e1dcdb8a016b49840f8c53b" + 262 "c1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddf" + 263 "b84ccf9744464f82e160bfa9b8b64f9d4c03f999b864" + 264 "3f656b412a3"), 265 addrs: nil, 266 reqSigs: 0, 267 class: NonStandardTy, 268 }, 269 { 270 name: "valid signature from a sigscript - no addresses", 271 script: hexToBytes("47304402204e45e16932b8af514961a1d" + 272 "3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41022" + 273 "0181522ec8eca07de4860a4acdd12909d831cc56cbba" + 274 "c4622082221a8768d1d0901"), 275 addrs: nil, 276 reqSigs: 0, 277 class: NonStandardTy, 278 }, 279 // Note the technically the pubkey is the second item on the 280 // stack, but since the address extraction intentionally only 281 // works with standard PkScripts, this should not return any 282 // addresses. 283 { 284 name: "valid sigscript to reedeem p2pk - no addresses", 285 script: hexToBytes("493046022100ddc69738bf2336318e4e0" + 286 "41a5a77f305da87428ab1606f023260017854350ddc0" + 287 "22100817af09d2eec36862d16009852b7e3a0f6dd765" + 288 "98290b7834e1453660367e07a014104cd4240c198e12" + 289 "523b6f9cb9f5bed06de1ba37e96a1bbd13745fcf9d11" + 290 "c25b1dff9a519675d198804ba9962d3eca2d5937d58e" + 291 "5a75a71042d40388a4d307f887d"), 292 addrs: nil, 293 reqSigs: 0, 294 class: NonStandardTy, 295 }, 296 // from real tx 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 0 297 // invalid public keys 298 { 299 name: "1 of 3 multisig with invalid pubkeys", 300 script: hexToBytes("51411c2200007353455857696b696c656" + 301 "16b73204361626c6567617465204261636b75700a0a6" + 302 "361626c65676174652d3230313031323034313831312" + 303 "e377a0a0a446f41776e6c6f61642074686520666f6c6" + 304 "c6f77696e67207472616e73616374696f6e732077697" + 305 "468205361746f736869204e616b616d6f746f2773206" + 306 "46f776e6c6f61416420746f6f6c2077686963680a636" + 307 "16e20626520666f756e6420696e207472616e7361637" + 308 "4696f6e2036633533636439383731313965663739376" + 309 "435616463636453ae"), 310 addrs: []btcutil.Address{}, 311 reqSigs: 1, 312 class: MultiSigTy, 313 }, 314 // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44 315 // invalid public keys 316 { 317 name: "1 of 3 multisig with invalid pubkeys 2", 318 script: hexToBytes("514134633365633235396337346461636" + 319 "536666430383862343463656638630a6336366263313" + 320 "93936633862393461333831316233363536313866653" + 321 "16539623162354136636163636539393361333938386" + 322 "134363966636336643664616266640a3236363363666" + 323 "13963663463303363363039633539336333653931666" + 324 "56465373032392131323364643432643235363339643" + 325 "338613663663530616234636434340a00000053ae"), 326 addrs: []btcutil.Address{}, 327 reqSigs: 1, 328 class: MultiSigTy, 329 }, 330 { 331 name: "empty script", 332 script: []byte{}, 333 addrs: nil, 334 reqSigs: 0, 335 class: NonStandardTy, 336 }, 337 { 338 name: "script that does not parse", 339 script: []byte{OP_DATA_45}, 340 addrs: nil, 341 reqSigs: 0, 342 class: NonStandardTy, 343 }, 344 } 345 346 t.Logf("Running %d tests.", len(tests)) 347 for i, test := range tests { 348 class, addrs, reqSigs, err := ExtractPkScriptAddrs( 349 test.script, &chaincfg.MainNetParams) 350 if err != nil { 351 } 352 353 if !reflect.DeepEqual(addrs, test.addrs) { 354 t.Errorf("ExtractPkScriptAddrs #%d (%s) unexpected "+ 355 "addresses\ngot %v\nwant %v", i, test.name, 356 addrs, test.addrs) 357 continue 358 } 359 360 if reqSigs != test.reqSigs { 361 t.Errorf("ExtractPkScriptAddrs #%d (%s) unexpected "+ 362 "number of required signatures - got %d, "+ 363 "want %d", i, test.name, reqSigs, test.reqSigs) 364 continue 365 } 366 367 if class != test.class { 368 t.Errorf("ExtractPkScriptAddrs #%d (%s) unexpected "+ 369 "script type - got %s, want %s", i, test.name, 370 class, test.class) 371 continue 372 } 373 } 374 } 375 376 // TestCalcScriptInfo ensures the CalcScriptInfo provides the expected results 377 // for various valid and invalid script pairs. 378 func TestCalcScriptInfo(t *testing.T) { 379 t.Parallel() 380 381 tests := []struct { 382 name string 383 sigScript string 384 pkScript string 385 witness []string 386 387 bip16 bool 388 segwit bool 389 390 scriptInfo ScriptInfo 391 scriptInfoErr error 392 }{ 393 { 394 // Invented scripts, the hashes do not match 395 // Truncated version of test below: 396 name: "pkscript doesn't parse", 397 sigScript: "1 81 DATA_8 2DUP EQUAL NOT VERIFY ABS " + 398 "SWAP ABS EQUAL", 399 pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" + 400 "3152205ec4f59c", 401 bip16: true, 402 scriptInfoErr: scriptError(ErrMalformedPush, ""), 403 }, 404 { 405 name: "sigScript doesn't parse", 406 // Truncated version of p2sh script below. 407 sigScript: "1 81 DATA_8 2DUP EQUAL NOT VERIFY ABS " + 408 "SWAP ABS", 409 pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" + 410 "3152205ec4f59c74 EQUAL", 411 bip16: true, 412 scriptInfoErr: scriptError(ErrMalformedPush, ""), 413 }, 414 { 415 // Invented scripts, the hashes do not match 416 name: "p2sh standard script", 417 sigScript: "1 81 DATA_25 DUP HASH160 DATA_20 0x010203" + 418 "0405060708090a0b0c0d0e0f1011121314 EQUALVERIFY " + 419 "CHECKSIG", 420 pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" + 421 "3152205ec4f59c74 EQUAL", 422 bip16: true, 423 scriptInfo: ScriptInfo{ 424 PkScriptClass: ScriptHashTy, 425 NumInputs: 3, 426 ExpectedInputs: 3, // nonstandard p2sh. 427 SigOps: 1, 428 }, 429 }, 430 { 431 // from 567a53d1ce19ce3d07711885168484439965501536d0d0294c5d46d46c10e53b 432 // from the blockchain. 433 name: "p2sh nonstandard script", 434 sigScript: "1 81 DATA_8 2DUP EQUAL NOT VERIFY ABS " + 435 "SWAP ABS EQUAL", 436 pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" + 437 "3152205ec4f59c74 EQUAL", 438 bip16: true, 439 scriptInfo: ScriptInfo{ 440 PkScriptClass: ScriptHashTy, 441 NumInputs: 3, 442 ExpectedInputs: -1, // nonstandard p2sh. 443 SigOps: 0, 444 }, 445 }, 446 { 447 // Script is invented, numbers all fake. 448 name: "multisig script", 449 // Extra 0 arg on the end for OP_CHECKMULTISIG bug. 450 sigScript: "1 1 1 0", 451 pkScript: "3 " + 452 "DATA_33 0x0102030405060708090a0b0c0d0e0f1011" + 453 "12131415161718191a1b1c1d1e1f2021 DATA_33 " + 454 "0x0102030405060708090a0b0c0d0e0f101112131415" + 455 "161718191a1b1c1d1e1f2021 DATA_33 0x010203040" + 456 "5060708090a0b0c0d0e0f101112131415161718191a1" + 457 "b1c1d1e1f2021 3 CHECKMULTISIG", 458 bip16: true, 459 scriptInfo: ScriptInfo{ 460 PkScriptClass: MultiSigTy, 461 NumInputs: 4, 462 ExpectedInputs: 4, 463 SigOps: 3, 464 }, 465 }, 466 { 467 // A v0 p2wkh spend. 468 name: "p2wkh script", 469 pkScript: "OP_0 DATA_20 0x365ab47888e150ff46f8d51bce36dcd680f1283f", 470 witness: []string{ 471 "3045022100ee9fe8f9487afa977" + 472 "6647ebcf0883ce0cd37454d7ce19889d34ba2c9" + 473 "9ce5a9f402200341cb469d0efd3955acb9e46" + 474 "f568d7e2cc10f9084aaff94ced6dc50a59134ad01", 475 "03f0000d0639a22bfaf217e4c9428" + 476 "9c2b0cc7fa1036f7fd5d9f61a9d6ec153100e", 477 }, 478 segwit: true, 479 scriptInfo: ScriptInfo{ 480 PkScriptClass: WitnessV0PubKeyHashTy, 481 NumInputs: 2, 482 ExpectedInputs: 2, 483 SigOps: 1, 484 }, 485 }, 486 { 487 // Nested p2sh v0 488 name: "p2wkh nested inside p2sh", 489 pkScript: "HASH160 DATA_20 " + 490 "0xb3a84b564602a9d68b4c9f19c2ea61458ff7826c EQUAL", 491 sigScript: "DATA_22 0x0014ad0ffa2e387f07e7ead14dc56d5a97dbd6ff5a23", 492 witness: []string{ 493 "3045022100cb1c2ac1ff1d57d" + 494 "db98f7bdead905f8bf5bcc8641b029ce8eef25" + 495 "c75a9e22a4702203be621b5c86b771288706be5" + 496 "a7eee1db4fceabf9afb7583c1cc6ee3f8297b21201", 497 "03f0000d0639a22bfaf217e4c9" + 498 "4289c2b0cc7fa1036f7fd5d9f61a9d6ec153100e", 499 }, 500 segwit: true, 501 bip16: true, 502 scriptInfo: ScriptInfo{ 503 PkScriptClass: ScriptHashTy, 504 NumInputs: 3, 505 ExpectedInputs: 3, 506 SigOps: 1, 507 }, 508 }, 509 { 510 // A v0 p2wsh spend. 511 name: "p2wsh spend of a p2wkh witness script", 512 pkScript: "0 DATA_32 0xe112b88a0cd87ba387f44" + 513 "9d443ee2596eb353beb1f0351ab2cba8909d875db23", 514 witness: []string{ 515 "3045022100cb1c2ac1ff1d57d" + 516 "db98f7bdead905f8bf5bcc8641b029ce8eef25" + 517 "c75a9e22a4702203be621b5c86b771288706be5" + 518 "a7eee1db4fceabf9afb7583c1cc6ee3f8297b21201", 519 "03f0000d0639a22bfaf217e4c9" + 520 "4289c2b0cc7fa1036f7fd5d9f61a9d6ec153100e", 521 "76a914064977cb7b4a2e0c9680df0ef696e9e0e296b39988ac", 522 }, 523 segwit: true, 524 scriptInfo: ScriptInfo{ 525 PkScriptClass: WitnessV0ScriptHashTy, 526 NumInputs: 3, 527 ExpectedInputs: 3, 528 SigOps: 1, 529 }, 530 }, 531 } 532 533 for _, test := range tests { 534 sigScript := mustParseShortForm(test.sigScript) 535 pkScript := mustParseShortForm(test.pkScript) 536 537 var witness wire.TxWitness 538 539 for _, witElement := range test.witness { 540 wit, err := hex.DecodeString(witElement) 541 if err != nil { 542 t.Fatalf("unable to decode witness "+ 543 "element: %v", err) 544 } 545 546 witness = append(witness, wit) 547 } 548 549 si, err := CalcScriptInfo(sigScript, pkScript, witness, 550 test.bip16, test.segwit) 551 if e := tstCheckScriptError(err, test.scriptInfoErr); e != nil { 552 t.Errorf("scriptinfo test %q: %v", test.name, e) 553 continue 554 } 555 if err != nil { 556 continue 557 } 558 559 if *si != test.scriptInfo { 560 t.Errorf("%s: scriptinfo doesn't match expected. "+ 561 "got: %q expected %q", test.name, *si, 562 test.scriptInfo) 563 continue 564 } 565 } 566 } 567 568 // bogusAddress implements the btcutil.Address interface so the tests can ensure 569 // unsupported address types are handled properly. 570 type bogusAddress struct{} 571 572 // EncodeAddress simply returns an empty string. It exists to satisfy the 573 // btcutil.Address interface. 574 func (b *bogusAddress) EncodeAddress() string { 575 return "" 576 } 577 578 // ScriptAddress simply returns an empty byte slice. It exists to satisfy the 579 // btcutil.Address interface. 580 func (b *bogusAddress) ScriptAddress() []byte { 581 return nil 582 } 583 584 // IsForNet lies blatantly to satisfy the btcutil.Address interface. 585 func (b *bogusAddress) IsForNet(chainParams *chaincfg.Params) bool { 586 return true // why not? 587 } 588 589 // String simply returns an empty string. It exists to satisfy the 590 // btcutil.Address interface. 591 func (b *bogusAddress) String() string { 592 return "" 593 } 594 595 // TestPayToAddrScript ensures the PayToAddrScript function generates the 596 // correct scripts for the various types of addresses. 597 func TestPayToAddrScript(t *testing.T) { 598 t.Parallel() 599 600 // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX 601 p2pkhMain, err := btcutil.NewAddressPubKeyHash(hexToBytes("e34cce70c86"+ 602 "373273efcc54ce7d2a491bb4a0e84"), &chaincfg.MainNetParams) 603 if err != nil { 604 t.Fatalf("Unable to create public key hash address: %v", err) 605 } 606 607 // Taken from transaction: 608 // b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d 609 p2shMain, _ := btcutil.NewAddressScriptHashFromHash(hexToBytes("e8c300"+ 610 "c87986efa84c37c0519929019ef86eb5b4"), &chaincfg.MainNetParams) 611 if err != nil { 612 t.Fatalf("Unable to create script hash address: %v", err) 613 } 614 615 // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg 616 p2pkCompressedMain, err := btcutil.NewAddressPubKey(hexToBytes("02192d"+ 617 "74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), 618 &chaincfg.MainNetParams) 619 if err != nil { 620 t.Fatalf("Unable to create pubkey address (compressed): %v", 621 err) 622 } 623 p2pkCompressed2Main, err := btcutil.NewAddressPubKey(hexToBytes("03b0b"+ 624 "d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), 625 &chaincfg.MainNetParams) 626 if err != nil { 627 t.Fatalf("Unable to create pubkey address (compressed 2): %v", 628 err) 629 } 630 631 p2pkUncompressedMain, err := btcutil.NewAddressPubKey(hexToBytes("0411"+ 632 "db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+ 633 "cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+ 634 "12a3"), &chaincfg.MainNetParams) 635 if err != nil { 636 t.Fatalf("Unable to create pubkey address (uncompressed): %v", 637 err) 638 } 639 640 // Errors used in the tests below defined here for convenience and to 641 // keep the horizontal test size shorter. 642 errUnsupportedAddress := scriptError(ErrUnsupportedAddress, "") 643 644 tests := []struct { 645 in btcutil.Address 646 expected string 647 err error 648 }{ 649 // pay-to-pubkey-hash address on mainnet 650 { 651 p2pkhMain, 652 "DUP HASH160 DATA_20 0xe34cce70c86373273efcc54ce7d2a4" + 653 "91bb4a0e8488 CHECKSIG", 654 nil, 655 }, 656 // pay-to-script-hash address on mainnet 657 { 658 p2shMain, 659 "HASH160 DATA_20 0xe8c300c87986efa84c37c0519929019ef8" + 660 "6eb5b4 EQUAL", 661 nil, 662 }, 663 // pay-to-pubkey address on mainnet. compressed key. 664 { 665 p2pkCompressedMain, 666 "DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c3" + 667 "ebec3a957724895dca52c6b4 CHECKSIG", 668 nil, 669 }, 670 // pay-to-pubkey address on mainnet. compressed key (other way). 671 { 672 p2pkCompressed2Main, 673 "DATA_33 0x03b0bd634234abbb1ba1e986e884185c61cf43e001" + 674 "f9137f23c2c409273eb16e65 CHECKSIG", 675 nil, 676 }, 677 // pay-to-pubkey address on mainnet. uncompressed key. 678 { 679 p2pkUncompressedMain, 680 "DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382e" + 681 "97b1482ecad7b148a6909a5cb2e0eaddfb84ccf97444" + 682 "64f82e160bfa9b8b64f9d4c03f999b8643f656b412a3 " + 683 "CHECKSIG", 684 nil, 685 }, 686 687 // Supported address types with nil pointers. 688 {(*btcutil.AddressPubKeyHash)(nil), "", errUnsupportedAddress}, 689 {(*btcutil.AddressScriptHash)(nil), "", errUnsupportedAddress}, 690 {(*btcutil.AddressPubKey)(nil), "", errUnsupportedAddress}, 691 692 // Unsupported address type. 693 {&bogusAddress{}, "", errUnsupportedAddress}, 694 } 695 696 t.Logf("Running %d tests", len(tests)) 697 for i, test := range tests { 698 pkScript, err := PayToAddrScript(test.in) 699 if e := tstCheckScriptError(err, test.err); e != nil { 700 t.Errorf("PayToAddrScript #%d unexpected error - "+ 701 "got %v, want %v", i, err, test.err) 702 continue 703 } 704 705 expected := mustParseShortForm(test.expected) 706 if !bytes.Equal(pkScript, expected) { 707 t.Errorf("PayToAddrScript #%d got: %x\nwant: %x", 708 i, pkScript, expected) 709 continue 710 } 711 } 712 } 713 714 // TestMultiSigScript ensures the MultiSigScript function returns the expected 715 // scripts and errors. 716 func TestMultiSigScript(t *testing.T) { 717 t.Parallel() 718 719 // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg 720 p2pkCompressedMain, err := btcutil.NewAddressPubKey(hexToBytes("02192d"+ 721 "74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), 722 &chaincfg.MainNetParams) 723 if err != nil { 724 t.Fatalf("Unable to create pubkey address (compressed): %v", 725 err) 726 } 727 p2pkCompressed2Main, err := btcutil.NewAddressPubKey(hexToBytes("03b0b"+ 728 "d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), 729 &chaincfg.MainNetParams) 730 if err != nil { 731 t.Fatalf("Unable to create pubkey address (compressed 2): %v", 732 err) 733 } 734 735 p2pkUncompressedMain, err := btcutil.NewAddressPubKey(hexToBytes("0411"+ 736 "db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+ 737 "cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+ 738 "12a3"), &chaincfg.MainNetParams) 739 if err != nil { 740 t.Fatalf("Unable to create pubkey address (uncompressed): %v", 741 err) 742 } 743 744 tests := []struct { 745 keys []*btcutil.AddressPubKey 746 nrequired int 747 expected string 748 err error 749 }{ 750 { 751 []*btcutil.AddressPubKey{ 752 p2pkCompressedMain, 753 p2pkCompressed2Main, 754 }, 755 1, 756 "1 DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c" + 757 "3ebec3a957724895dca52c6b4 DATA_33 0x03b0bd634" + 758 "234abbb1ba1e986e884185c61cf43e001f9137f23c2c4" + 759 "09273eb16e65 2 CHECKMULTISIG", 760 nil, 761 }, 762 { 763 []*btcutil.AddressPubKey{ 764 p2pkCompressedMain, 765 p2pkCompressed2Main, 766 }, 767 2, 768 "2 DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c" + 769 "3ebec3a957724895dca52c6b4 DATA_33 0x03b0bd634" + 770 "234abbb1ba1e986e884185c61cf43e001f9137f23c2c4" + 771 "09273eb16e65 2 CHECKMULTISIG", 772 nil, 773 }, 774 { 775 []*btcutil.AddressPubKey{ 776 p2pkCompressedMain, 777 p2pkCompressed2Main, 778 }, 779 3, 780 "", 781 scriptError(ErrTooManyRequiredSigs, ""), 782 }, 783 { 784 []*btcutil.AddressPubKey{ 785 p2pkUncompressedMain, 786 }, 787 1, 788 "1 DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382" + 789 "e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf97444" + 790 "64f82e160bfa9b8b64f9d4c03f999b8643f656b412a3 " + 791 "1 CHECKMULTISIG", 792 nil, 793 }, 794 { 795 []*btcutil.AddressPubKey{ 796 p2pkUncompressedMain, 797 }, 798 2, 799 "", 800 scriptError(ErrTooManyRequiredSigs, ""), 801 }, 802 } 803 804 t.Logf("Running %d tests", len(tests)) 805 for i, test := range tests { 806 script, err := MultiSigScript(test.keys, test.nrequired) 807 if e := tstCheckScriptError(err, test.err); e != nil { 808 t.Errorf("MultiSigScript #%d: %v", i, e) 809 continue 810 } 811 812 expected := mustParseShortForm(test.expected) 813 if !bytes.Equal(script, expected) { 814 t.Errorf("MultiSigScript #%d got: %x\nwant: %x", 815 i, script, expected) 816 continue 817 } 818 } 819 } 820 821 // TestCalcMultiSigStats ensures the CalcMutliSigStats function returns the 822 // expected errors. 823 func TestCalcMultiSigStats(t *testing.T) { 824 t.Parallel() 825 826 tests := []struct { 827 name string 828 script string 829 err error 830 }{ 831 { 832 name: "short script", 833 script: "0x046708afdb0fe5548271967f1a67130b7105cd6a828" + 834 "e03909a67962e0ea1f61d", 835 err: scriptError(ErrNotMultisigScript, ""), 836 }, 837 { 838 name: "stack underflow", 839 script: "RETURN DATA_41 0x046708afdb0fe5548271967f1a" + 840 "67130b7105cd6a828e03909a67962e0ea1f61deb649f6" + 841 "bc3f4cef308", 842 err: scriptError(ErrNotMultisigScript, ""), 843 }, 844 { 845 name: "multisig script", 846 script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da45329a0" + 847 "0357b3a7886211ab414d55a 1 CHECKMULTISIG", 848 err: nil, 849 }, 850 } 851 852 for i, test := range tests { 853 script := mustParseShortForm(test.script) 854 _, _, err := CalcMultiSigStats(script) 855 if e := tstCheckScriptError(err, test.err); e != nil { 856 t.Errorf("CalcMultiSigStats #%d (%s): %v", i, test.name, 857 e) 858 continue 859 } 860 } 861 } 862 863 // scriptClassTests houses several test scripts used to ensure various class 864 // determination is working as expected. It's defined as a test global versus 865 // inside a function scope since this spans both the standard tests and the 866 // consensus tests (pay-to-script-hash is part of consensus). 867 var scriptClassTests = []struct { 868 name string 869 script string 870 class ScriptClass 871 }{ 872 { 873 name: "Pay Pubkey", 874 script: "DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382e" + 875 "97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e16" + 876 "0bfa9b8b64f9d4c03f999b8643f656b412a3 CHECKSIG", 877 class: PubKeyTy, 878 }, 879 // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea 880 { 881 name: "Pay PubkeyHash", 882 script: "DUP HASH160 DATA_20 0x660d4ef3a743e3e696ad990364e555" + 883 "c271ad504b EQUALVERIFY CHECKSIG", 884 class: PubKeyHashTy, 885 }, 886 // part of tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b 887 // codeseparator parts have been elided. (bitcoin core's checks for 888 // multisig type doesn't have codesep either). 889 { 890 name: "multisig", 891 script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da4" + 892 "5329a00357b3a7886211ab414d55a 1 CHECKMULTISIG", 893 class: MultiSigTy, 894 }, 895 // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d 896 { 897 name: "P2SH", 898 script: "HASH160 DATA_20 0x433ec2ac1ffa1b7b7d027f564529c57197f" + 899 "9ae88 EQUAL", 900 class: ScriptHashTy, 901 }, 902 903 { 904 // Nulldata with no data at all. 905 name: "nulldata no data", 906 script: "RETURN", 907 class: NullDataTy, 908 }, 909 { 910 // Nulldata with single zero push. 911 name: "nulldata zero", 912 script: "RETURN 0", 913 class: NullDataTy, 914 }, 915 { 916 // Nulldata with small integer push. 917 name: "nulldata small int", 918 script: "RETURN 1", 919 class: NullDataTy, 920 }, 921 { 922 // Nulldata with max small integer push. 923 name: "nulldata max small int", 924 script: "RETURN 16", 925 class: NullDataTy, 926 }, 927 { 928 // Nulldata with small data push. 929 name: "nulldata small data", 930 script: "RETURN DATA_8 0x046708afdb0fe554", 931 class: NullDataTy, 932 }, 933 { 934 // Canonical nulldata with 60-byte data push. 935 name: "canonical nulldata 60-byte push", 936 script: "RETURN 0x3c 0x046708afdb0fe5548271967f1a67130b7105cd" + 937 "6a828e03909a67962e0ea1f61deb649f6bc3f4cef3046708afdb" + 938 "0fe5548271967f1a67130b7105cd6a", 939 class: NullDataTy, 940 }, 941 { 942 // Non-canonical nulldata with 60-byte data push. 943 name: "non-canonical nulldata 60-byte push", 944 script: "RETURN PUSHDATA1 0x3c 0x046708afdb0fe5548271967f1a67" + 945 "130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" + 946 "046708afdb0fe5548271967f1a67130b7105cd6a", 947 class: NullDataTy, 948 }, 949 { 950 // Nulldata with max allowed data to be considered standard. 951 name: "nulldata max standard push", 952 script: "RETURN PUSHDATA1 0x50 0x046708afdb0fe5548271967f1a67" + 953 "130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" + 954 "046708afdb0fe5548271967f1a67130b7105cd6a828e03909a67" + 955 "962e0ea1f61deb649f6bc3f4cef3", 956 class: NullDataTy, 957 }, 958 { 959 // Nulldata with more than max allowed data to be considered 960 // standard (so therefore nonstandard) 961 name: "nulldata exceed max standard push", 962 script: "RETURN PUSHDATA1 0x51 0x046708afdb0fe5548271967f1a67" + 963 "130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" + 964 "046708afdb0fe5548271967f1a67130b7105cd6a828e03909a67" + 965 "962e0ea1f61deb649f6bc3f4cef308", 966 class: NonStandardTy, 967 }, 968 { 969 // Almost nulldata, but add an additional opcode after the data 970 // to make it nonstandard. 971 name: "almost nulldata", 972 script: "RETURN 4 TRUE", 973 class: NonStandardTy, 974 }, 975 976 // The next few are almost multisig (it is the more complex script type) 977 // but with various changes to make it fail. 978 { 979 // Multisig but invalid nsigs. 980 name: "strange 1", 981 script: "DUP DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da45" + 982 "329a00357b3a7886211ab414d55a 1 CHECKMULTISIG", 983 class: NonStandardTy, 984 }, 985 { 986 // Multisig but invalid pubkey. 987 name: "strange 2", 988 script: "1 1 1 CHECKMULTISIG", 989 class: NonStandardTy, 990 }, 991 { 992 // Multisig but no matching npubkeys opcode. 993 name: "strange 3", 994 script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da4532" + 995 "9a00357b3a7886211ab414d55a DATA_33 0x0232abdc893e7f0" + 996 "631364d7fd01cb33d24da45329a00357b3a7886211ab414d55a " + 997 "CHECKMULTISIG", 998 class: NonStandardTy, 999 }, 1000 { 1001 // Multisig but with multisigverify. 1002 name: "strange 4", 1003 script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da4532" + 1004 "9a00357b3a7886211ab414d55a 1 CHECKMULTISIGVERIFY", 1005 class: NonStandardTy, 1006 }, 1007 { 1008 // Multisig but wrong length. 1009 name: "strange 5", 1010 script: "1 CHECKMULTISIG", 1011 class: NonStandardTy, 1012 }, 1013 { 1014 name: "doesn't parse", 1015 script: "DATA_5 0x01020304", 1016 class: NonStandardTy, 1017 }, 1018 { 1019 name: "multisig script with wrong number of pubkeys", 1020 script: "2 " + 1021 "DATA_33 " + 1022 "0x027adf5df7c965a2d46203c781bd4dd8" + 1023 "21f11844136f6673af7cc5a4a05cd29380 " + 1024 "DATA_33 " + 1025 "0x02c08f3de8ee2de9be7bd770f4c10eb0" + 1026 "d6ff1dd81ee96eedd3a9d4aeaf86695e80 " + 1027 "3 CHECKMULTISIG", 1028 class: NonStandardTy, 1029 }, 1030 1031 // New standard segwit script templates. 1032 { 1033 // A pay to witness pub key hash pk script. 1034 name: "Pay To Witness PubkeyHash", 1035 script: "0 DATA_20 0x1d0f172a0ecb48aee1be1f2687d2963ae33f71a1", 1036 class: WitnessV0PubKeyHashTy, 1037 }, 1038 { 1039 // A pay to witness scripthash pk script. 1040 name: "Pay To Witness Scripthash", 1041 script: "0 DATA_32 0x9f96ade4b41d5433f4eda31e1738ec2b36f6e7d1420d94a6af99801a88f7f7ff", 1042 class: WitnessV0ScriptHashTy, 1043 }, 1044 } 1045 1046 // TestScriptClass ensures all the scripts in scriptClassTests have the expected 1047 // class. 1048 func TestScriptClass(t *testing.T) { 1049 t.Parallel() 1050 1051 for _, test := range scriptClassTests { 1052 script := mustParseShortForm(test.script) 1053 class := GetScriptClass(script) 1054 if class != test.class { 1055 t.Errorf("%s: expected %s got %s (script %x)", test.name, 1056 test.class, class, script) 1057 continue 1058 } 1059 } 1060 } 1061 1062 // TestStringifyClass ensures the script class string returns the expected 1063 // string for each script class. 1064 func TestStringifyClass(t *testing.T) { 1065 t.Parallel() 1066 1067 tests := []struct { 1068 name string 1069 class ScriptClass 1070 stringed string 1071 }{ 1072 { 1073 name: "nonstandardty", 1074 class: NonStandardTy, 1075 stringed: "nonstandard", 1076 }, 1077 { 1078 name: "pubkey", 1079 class: PubKeyTy, 1080 stringed: "pubkey", 1081 }, 1082 { 1083 name: "pubkeyhash", 1084 class: PubKeyHashTy, 1085 stringed: "pubkeyhash", 1086 }, 1087 { 1088 name: "witnesspubkeyhash", 1089 class: WitnessV0PubKeyHashTy, 1090 stringed: "witness_v0_keyhash", 1091 }, 1092 { 1093 name: "scripthash", 1094 class: ScriptHashTy, 1095 stringed: "scripthash", 1096 }, 1097 { 1098 name: "witnessscripthash", 1099 class: WitnessV0ScriptHashTy, 1100 stringed: "witness_v0_scripthash", 1101 }, 1102 { 1103 name: "multisigty", 1104 class: MultiSigTy, 1105 stringed: "multisig", 1106 }, 1107 { 1108 name: "nulldataty", 1109 class: NullDataTy, 1110 stringed: "nulldata", 1111 }, 1112 { 1113 name: "broken", 1114 class: ScriptClass(255), 1115 stringed: "Invalid", 1116 }, 1117 } 1118 1119 for _, test := range tests { 1120 typeString := test.class.String() 1121 if typeString != test.stringed { 1122 t.Errorf("%s: got %#q, want %#q", test.name, 1123 typeString, test.stringed) 1124 } 1125 } 1126 } 1127 1128 // TestNullDataScript tests whether NullDataScript returns a valid script. 1129 func TestNullDataScript(t *testing.T) { 1130 tests := []struct { 1131 name string 1132 data []byte 1133 expected []byte 1134 err error 1135 class ScriptClass 1136 }{ 1137 { 1138 name: "small int", 1139 data: hexToBytes("01"), 1140 expected: mustParseShortForm("RETURN 1"), 1141 err: nil, 1142 class: NullDataTy, 1143 }, 1144 { 1145 name: "max small int", 1146 data: hexToBytes("10"), 1147 expected: mustParseShortForm("RETURN 16"), 1148 err: nil, 1149 class: NullDataTy, 1150 }, 1151 { 1152 name: "data of size before OP_PUSHDATA1 is needed", 1153 data: hexToBytes("0102030405060708090a0b0c0d0e0f10111" + 1154 "2131415161718"), 1155 expected: mustParseShortForm("RETURN 0x18 0x01020304" + 1156 "05060708090a0b0c0d0e0f101112131415161718"), 1157 err: nil, 1158 class: NullDataTy, 1159 }, 1160 { 1161 name: "just right", 1162 data: hexToBytes("000102030405060708090a0b0c0d0e0f101" + 1163 "112131415161718191a1b1c1d1e1f202122232425262" + 1164 "728292a2b2c2d2e2f303132333435363738393a3b3c3" + 1165 "d3e3f404142434445464748494a4b4c4d4e4f"), 1166 expected: mustParseShortForm("RETURN PUSHDATA1 0x50 " + 1167 "0x000102030405060708090a0b0c0d0e0f101112131" + 1168 "415161718191a1b1c1d1e1f20212223242526272829" + 1169 "2a2b2c2d2e2f303132333435363738393a3b3c3d3e3" + 1170 "f404142434445464748494a4b4c4d4e4f"), 1171 err: nil, 1172 class: NullDataTy, 1173 }, 1174 { 1175 name: "too big", 1176 data: hexToBytes("000102030405060708090a0b0c0d0e0f101" + 1177 "112131415161718191a1b1c1d1e1f202122232425262" + 1178 "728292a2b2c2d2e2f303132333435363738393a3b3c3" + 1179 "d3e3f404142434445464748494a4b4c4d4e4f50"), 1180 expected: nil, 1181 err: scriptError(ErrTooMuchNullData, ""), 1182 class: NonStandardTy, 1183 }, 1184 } 1185 1186 for i, test := range tests { 1187 script, err := NullDataScript(test.data) 1188 if e := tstCheckScriptError(err, test.err); e != nil { 1189 t.Errorf("NullDataScript: #%d (%s): %v", i, test.name, 1190 e) 1191 continue 1192 1193 } 1194 1195 // Check that the expected result was returned. 1196 if !bytes.Equal(script, test.expected) { 1197 t.Errorf("NullDataScript: #%d (%s) wrong result\n"+ 1198 "got: %x\nwant: %x", i, test.name, script, 1199 test.expected) 1200 continue 1201 } 1202 1203 // Check that the script has the correct type. 1204 scriptType := GetScriptClass(script) 1205 if scriptType != test.class { 1206 t.Errorf("GetScriptClass: #%d (%s) wrong result -- "+ 1207 "got: %v, want: %v", i, test.name, scriptType, 1208 test.class) 1209 continue 1210 } 1211 } 1212 } 1213 1214 // TestNewScriptClass tests whether NewScriptClass returns a valid ScriptClass. 1215 func TestNewScriptClass(t *testing.T) { 1216 tests := []struct { 1217 name string 1218 scriptName string 1219 want *ScriptClass 1220 wantErr error 1221 }{ 1222 { 1223 name: "NewScriptClass - ok", 1224 scriptName: NullDataTy.String(), 1225 want: func() *ScriptClass { 1226 s := NullDataTy 1227 return &s 1228 }(), 1229 }, 1230 { 1231 name: "NewScriptClass - invalid", 1232 scriptName: "foo", 1233 wantErr: ErrUnsupportedScriptType, 1234 }, 1235 } 1236 for _, tt := range tests { 1237 t.Run(tt.name, func(t *testing.T) { 1238 got, err := NewScriptClass(tt.scriptName) 1239 if err != nil && !errors.Is(err, tt.wantErr) { 1240 t.Errorf("NewScriptClass() error = %v, wantErr %v", err, tt.wantErr) 1241 return 1242 } 1243 1244 if !reflect.DeepEqual(got, tt.want) { 1245 t.Errorf("NewScriptClass() got = %v, want %v", got, tt.want) 1246 } 1247 }) 1248 } 1249 }