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