decred.org/dcrdex@v1.0.3/dex/networks/btc/script_test.go (about) 1 package btc 2 3 import ( 4 "bytes" 5 "crypto/sha256" 6 "encoding/hex" 7 "fmt" 8 "math/rand" 9 "strings" 10 "testing" 11 12 "github.com/btcsuite/btcd/btcec/v2" 13 "github.com/btcsuite/btcd/btcutil" 14 "github.com/btcsuite/btcd/chaincfg" 15 "github.com/btcsuite/btcd/txscript" 16 "github.com/btcsuite/btcd/wire" 17 ) 18 19 var ( 20 tStamp = int64(1574264305) 21 tParams = &chaincfg.MainNetParams 22 invalidScript = []byte{txscript.OP_DATA_75} 23 invalidWitness = [][]byte{{txscript.OP_DATA_75}} 24 ) 25 26 func randBytes(l int) []byte { 27 b := make([]byte, l) 28 rand.Read(b) 29 return b 30 } 31 32 func newPubKey() []byte { 33 priv, err := btcec.NewPrivateKey() 34 if err != nil { 35 fmt.Printf("error creating pubkey: %v\n", err) 36 } 37 return priv.PubKey().SerializeCompressed() 38 } 39 40 type tAddrs struct { 41 pkh *btcutil.AddressPubKeyHash 42 wpkh *btcutil.AddressWitnessPubKeyHash 43 sh *btcutil.AddressScriptHash 44 wsh *btcutil.AddressWitnessScriptHash 45 pk1 *btcutil.AddressPubKey 46 pk2 *btcutil.AddressPubKey 47 multiSig []byte 48 } 49 50 func testAddresses() *tAddrs { 51 p2pkh, _ := btcutil.NewAddressPubKeyHash(randBytes(20), tParams) 52 p2wpkh, _ := btcutil.NewAddressWitnessPubKeyHash(randBytes(20), tParams) 53 p2wsh, _ := btcutil.NewAddressWitnessScriptHash(randBytes(32), tParams) 54 pk1, _ := btcutil.NewAddressPubKey(newPubKey(), tParams) 55 pk2, _ := btcutil.NewAddressPubKey(newPubKey(), tParams) 56 multiSig, _ := txscript.MultiSigScript([]*btcutil.AddressPubKey{pk1, pk2}, 1) 57 p2sh, _ := btcutil.NewAddressScriptHash(multiSig, tParams) 58 return &tAddrs{ 59 pkh: p2pkh, 60 wpkh: p2wpkh, 61 sh: p2sh, 62 wsh: p2wsh, 63 pk1: pk1, 64 pk2: pk2, 65 multiSig: multiSig, 66 } 67 } 68 69 func TestVarIntSizes(t *testing.T) { 70 got := wire.VarIntSerializeSize(uint64(RedeemP2PKHSigScriptSize)) 71 if got != 1 { 72 t.Errorf("Incorrect opcode prefix size %d, want 1", got) 73 } 74 75 got = wire.VarIntSerializeSize(uint64(RedeemP2PKHSigScriptSize)) 76 if got != 1 { 77 t.Errorf("Incorrect opcode prefix size %d, want 1", got) 78 } 79 } 80 81 func TestParseScriptType(t *testing.T) { 82 addrs := testAddresses() 83 84 var scriptType BTCScriptType 85 parse := func(addr btcutil.Address, redeem []byte) { 86 pkScript, err := txscript.PayToAddrScript(addr) 87 if err != nil { 88 t.Fatalf("error creating script for address %s", addr) 89 } 90 scriptType = ParseScriptType(pkScript, redeem) 91 } 92 93 check := func(name string, res bool, exp bool) { 94 if res != exp { 95 t.Fatalf("%s check failed. wanted %t, got %t", name, exp, res) 96 } 97 } 98 99 parse(addrs.pk1, nil) 100 check("p2pk-IsP2PK", scriptType.IsP2PK(), true) 101 check("p2pk-IsP2PKH", scriptType.IsP2PKH(), false) 102 check("p2pk-IsP2SH", scriptType.IsP2SH(), false) 103 check("p2pk-IsP2WPKH", scriptType.IsP2WPKH(), false) 104 check("p2pk-IsP2WSH", scriptType.IsP2WSH(), false) 105 check("p2pk-IsMultiSig", scriptType.IsMultiSig(), false) 106 check("p2pk-IsSegwit", scriptType.IsSegwit(), false) 107 108 parse(addrs.pkh, nil) 109 check("p2pkh-IsP2PK", scriptType.IsP2PK(), false) 110 check("p2pkh-IsP2PKH", scriptType.IsP2PKH(), true) 111 check("p2pkh-IsP2SH", scriptType.IsP2SH(), false) 112 check("p2pkh-IsP2WPKH", scriptType.IsP2WPKH(), false) 113 check("p2pkh-IsP2WSH", scriptType.IsP2WSH(), false) 114 check("p2pkh-IsMultiSig", scriptType.IsMultiSig(), false) 115 check("p2pkh-IsSegwit", scriptType.IsSegwit(), false) 116 117 parse(addrs.wpkh, nil) 118 check("p2wpkh-IsP2PK", scriptType.IsP2PK(), false) 119 check("p2wpkh-IsP2PKH", scriptType.IsP2PKH(), false) 120 check("p2wpkh-IsP2SH", scriptType.IsP2SH(), false) 121 check("p2wpkh-IsP2WPKH", scriptType.IsP2WPKH(), true) 122 check("p2wpkh-IsP2WSH", scriptType.IsP2WSH(), false) 123 check("p2wpkh-IsMultiSig", scriptType.IsMultiSig(), false) 124 check("p2wpkh-IsSegwit", scriptType.IsSegwit(), true) 125 126 parse(addrs.sh, addrs.multiSig) 127 check("p2sh-IsP2PK", scriptType.IsP2PK(), false) 128 check("p2sh-IsP2PKH", scriptType.IsP2PKH(), false) 129 check("p2sh-IsP2SH", scriptType.IsP2SH(), true) 130 check("p2sh-IsP2WPKH", scriptType.IsP2WPKH(), false) 131 check("p2sh-IsP2WSH", scriptType.IsP2WSH(), false) 132 check("p2sh-IsMultiSig", scriptType.IsMultiSig(), true) 133 check("p2sh-IsSegwit", scriptType.IsSegwit(), false) 134 135 parse(addrs.wsh, nil) 136 check("p2wsh-IsP2PK", scriptType.IsP2PK(), false) 137 check("p2wsh-IsP2PKH", scriptType.IsP2PKH(), false) 138 check("p2wsh-IsP2SH", scriptType.IsP2SH(), false) 139 check("p2wsh-IsP2WPKH", scriptType.IsP2WPKH(), false) 140 check("p2wsh-IsP2WSH", scriptType.IsP2WSH(), true) 141 check("p2wsh-IsMultiSig", scriptType.IsMultiSig(), false) 142 check("p2wsh-IsSegwit", scriptType.IsSegwit(), true) 143 } 144 145 func TestMakeContract(t *testing.T) { 146 t.Run("segwit", func(t *testing.T) { 147 testMakeContract(t, true) 148 }) 149 t.Run("non-segwit", func(t *testing.T) { 150 testMakeContract(t, false) 151 }) 152 } 153 154 func testMakeContract(t *testing.T, segwit bool) { 155 var ra, sa, p2sh, p2pkh btcutil.Address 156 if segwit { 157 ra, _ = btcutil.NewAddressWitnessPubKeyHash(randBytes(20), tParams) 158 sa, _ = btcutil.NewAddressWitnessPubKeyHash(randBytes(20), tParams) 159 p2sh, _ = btcutil.NewAddressScriptHash(randBytes(50), tParams) 160 p2pkh, _ = btcutil.NewAddressPubKeyHash(randBytes(20), tParams) 161 } else { 162 ra, _ = btcutil.NewAddressPubKeyHash(randBytes(20), tParams) 163 sa, _ = btcutil.NewAddressPubKeyHash(randBytes(20), tParams) 164 p2sh, _ = btcutil.NewAddressScriptHash(randBytes(50), tParams) 165 p2pkh, _ = btcutil.NewAddressWitnessPubKeyHash(randBytes(20), tParams) 166 } 167 168 // Wrong recipient address type 169 _, err := MakeContract(p2sh, sa, randBytes(32), tStamp, segwit, tParams) 170 if err == nil { 171 t.Fatalf("no error for wrong recipient address type") 172 } 173 174 // Wrong sender address type. 175 _, err = MakeContract(ra, p2pkh, randBytes(32), tStamp, segwit, tParams) 176 if err == nil { 177 t.Fatalf("no error for wrong sender address type") 178 } 179 180 // Bad secret hash 181 _, err = MakeContract(ra, sa, randBytes(10), tStamp, segwit, tParams) 182 if err == nil { 183 t.Fatalf("no error for bad secret hash") 184 } 185 186 // Good to go 187 _, err = MakeContract(ra, sa, randBytes(32), tStamp, segwit, tParams) 188 if err != nil { 189 t.Fatalf("error for valid contract parameters: %v", err) 190 } 191 } 192 193 func TestIsDust(t *testing.T) { 194 pkScript := []byte{0x76, 0xa9, 0x21, 0x03, 0x2f, 0x7e, 0x43, 195 0x0a, 0xa4, 0xc9, 0xd1, 0x59, 0x43, 0x7e, 0x84, 0xb9, 196 0x75, 0xdc, 0x76, 0xd9, 0x00, 0x3b, 0xf0, 0x92, 0x2c, 197 0xf3, 0xaa, 0x45, 0x28, 0x46, 0x4b, 0xab, 0x78, 0x0d, 198 0xba, 0x5e, 0x88, 0xac} 199 200 tests := []struct { 201 name string // test description 202 txOut wire.TxOut 203 relayFee uint64 // minimum relay transaction fee. 204 isDust bool 205 }{ 206 { 207 // Any value is allowed with a zero relay fee. 208 "zero value with zero relay fee", 209 wire.TxOut{Value: 0, PkScript: pkScript}, 210 0, 211 false, 212 }, 213 { 214 // Zero value is dust with any relay fee" 215 "zero value with very small tx fee", 216 wire.TxOut{Value: 0, PkScript: pkScript}, 217 1, 218 true, 219 }, 220 { 221 "38 byte public key script with value 584", 222 wire.TxOut{Value: 584, PkScript: pkScript}, 223 1, 224 true, 225 }, 226 { 227 "38 byte public key script with value 585", 228 wire.TxOut{Value: 585, PkScript: pkScript}, 229 1, 230 false, 231 }, 232 { 233 // Maximum allowed value is never dust. 234 "max satoshi amount is never dust", 235 wire.TxOut{Value: btcutil.MaxSatoshi, PkScript: pkScript}, 236 btcutil.MaxSatoshi / 1000, 237 false, 238 }, 239 { 240 // Maximum int64 value causes overflow. 241 "maximum int64 value", 242 wire.TxOut{Value: 1<<63 - 1, PkScript: pkScript}, 243 1<<63 - 1, 244 true, 245 }, 246 { 247 // Unspendable pkScript due to an invalid public key 248 // script. 249 "unspendable pkScript", 250 wire.TxOut{Value: 5000, PkScript: []byte{0x01}}, 251 0, // no relay fee 252 true, 253 }, 254 } 255 for _, test := range tests { 256 res := IsDust(&test.txOut, test.relayFee) 257 if res != test.isDust { 258 t.Fatalf("Dust test '%s' failed: want %v got %v", 259 test.name, test.isDust, res) 260 } 261 } 262 } 263 264 func TestExtractScriptAddrs(t *testing.T) { 265 // Invalid script 266 _, nonStd, _ := ExtractScriptAddrs(invalidScript, tParams) 267 if !nonStd { 268 t.Errorf("expected non-standard script") 269 } 270 271 addrs := testAddresses() 272 type test struct { 273 addr btcutil.Address 274 nonStd bool 275 script []byte 276 pk int 277 pkh int 278 sigs int 279 } 280 281 tests := []test{ 282 {addrs.pkh, false, nil, 0, 1, 1}, 283 {addrs.sh, false, nil, 0, 1, 1}, 284 {addrs.wpkh, false, nil, 0, 1, 1}, 285 {addrs.wsh, false, nil, 0, 1, 1}, 286 {nil, false, addrs.multiSig, 2, 0, 1}, 287 } 288 289 for _, tt := range tests { 290 s := tt.script 291 if s == nil { 292 s, _ = txscript.PayToAddrScript(tt.addr) 293 } 294 scriptAddrs, nonStd, err := ExtractScriptAddrs(s, tParams) 295 if err != nil { 296 t.Fatalf("error extracting script addresses: %v", err) 297 } 298 if nonStd != tt.nonStd { 299 t.Fatalf("expected nonStd=%v, got %v", tt.nonStd, nonStd) 300 } 301 if scriptAddrs.NumPK != tt.pk { 302 t.Fatalf("wrong number of hash addresses. wanted %d, got %d", tt.pk, scriptAddrs.NumPK) 303 } 304 if scriptAddrs.NumPKH != tt.pkh { 305 t.Fatalf("wrong number of pubkey-hash addresses. wanted %d, got %d", tt.pkh, scriptAddrs.NumPKH) 306 } 307 if scriptAddrs.NRequired != tt.sigs { 308 t.Fatalf("wrong number of required signatures. wanted %d, got %d", tt.sigs, scriptAddrs.NRequired) 309 } 310 } 311 312 } 313 314 func TestExtractSwapDetails(t *testing.T) { 315 t.Run("segwit", func(t *testing.T) { 316 testExtractSwapDetails(t, true) 317 }) 318 t.Run("non-segwit", func(t *testing.T) { 319 testExtractSwapDetails(t, false) 320 }) 321 } 322 323 func testExtractSwapDetails(t *testing.T, segwit bool) { 324 var rAddr, sAddr btcutil.Address 325 if segwit { 326 rAddr, _ = btcutil.NewAddressWitnessPubKeyHash(randBytes(20), tParams) 327 sAddr, _ = btcutil.NewAddressWitnessPubKeyHash(randBytes(20), tParams) 328 } else { 329 rAddr, _ = btcutil.NewAddressPubKeyHash(randBytes(20), tParams) 330 sAddr, _ = btcutil.NewAddressPubKeyHash(randBytes(20), tParams) 331 } 332 333 keyHash := randBytes(32) 334 contract, err := MakeContract(rAddr, sAddr, keyHash, tStamp, segwit, tParams) 335 if err != nil { 336 t.Fatalf("error creating contract: %v", err) 337 } 338 339 sa, ra, lockTime, secretHash, err := ExtractSwapDetails(contract, segwit, tParams) 340 if err != nil { 341 t.Fatalf("error for valid contract: %v", err) 342 } 343 if sa.String() != sAddr.String() { 344 t.Fatalf("sender address mismatch. wanted %s, got %s", sAddr.String(), sa.String()) 345 } 346 if ra.String() != rAddr.String() { 347 t.Fatalf("recipient address mismatch. wanted %s, got %s", rAddr.String(), ra.String()) 348 } 349 if lockTime != uint64(tStamp) { 350 t.Fatalf("incorrect lock time. wanted 5, got %d", lockTime) 351 } 352 if !bytes.Equal(secretHash, keyHash) { 353 t.Fatalf("wrong secret hash. wanted %x, got %x", keyHash, secretHash) 354 } 355 356 // incorrect length 357 _, _, _, _, err = ExtractSwapDetails(contract[:len(contract)-1], segwit, tParams) 358 if err == nil { 359 t.Fatalf("no error for vandalized contract") 360 } else if !strings.HasPrefix(err.Error(), "incorrect swap contract length") { 361 t.Errorf("incorrect error for incorrect swap contract length: %v", err) 362 } 363 364 // bad secret size 365 contract[3] = 250 366 _, _, _, _, err = ExtractSwapDetails(contract, segwit, tParams) 367 if err == nil { 368 t.Fatalf("no error for contract with invalid secret size") 369 } else if !strings.HasPrefix(err.Error(), "invalid secret size") { 370 t.Errorf("incorrect error for invalid secret size: %v", err) 371 } 372 } 373 374 func TestInputInfo(t *testing.T) { 375 addrs := testAddresses() 376 var spendInfo *SpendInfo 377 var err error 378 379 check := func(name string, sigScriptSize, witnessSize uint32, scriptType BTCScriptType) { 380 t.Helper() 381 if spendInfo.SigScriptSize != sigScriptSize { 382 t.Fatalf("%s: wrong SigScriptSize, wanted %d, got %d", name, sigScriptSize, spendInfo.SigScriptSize) 383 } 384 if spendInfo.WitnessSize != witnessSize { 385 t.Fatalf("%s: wrong WitnessSize, wanted %d, got %d", name, witnessSize, spendInfo.WitnessSize) 386 } 387 if spendInfo.ScriptType != scriptType { 388 t.Fatalf("%s: wrong ScriptType, wanted %d, got %d", name, scriptType, spendInfo.ScriptType) 389 } 390 } 391 392 var script []byte 393 payToAddr := func(addr btcutil.Address, redeem []byte) { 394 t.Helper() 395 script, _ = txscript.PayToAddrScript(addr) 396 spendInfo, err = InputInfo(script, redeem, tParams) 397 if err != nil { 398 t.Fatalf("InputInfo script: %v", err) 399 } 400 } 401 402 payToAddr(addrs.pkh, nil) 403 check("p2pkh", RedeemP2PKHSigScriptSize, 0, ScriptP2PKH) 404 405 payToAddr(addrs.sh, addrs.multiSig) 406 check("p2sh", 74+uint32(len(addrs.multiSig))+2, 0, ScriptP2SH|ScriptMultiSig) 407 408 payToAddr(addrs.wpkh, nil) 409 check("p2wpkh", 0, RedeemP2WPKHInputWitnessWeight, ScriptP2PKH|ScriptTypeSegwit) 410 411 payToAddr(addrs.wsh, addrs.multiSig) 412 check("p2wsh", 0, 74+uint32(len(addrs.multiSig))+1, ScriptP2SH|ScriptTypeSegwit|ScriptMultiSig) 413 414 // Unknown script type. 415 _, err = InputInfo([]byte{0x02, 0x03}, nil, tParams) 416 if err == nil { 417 t.Fatalf("no error for unknown script type") 418 } 419 420 // InputInfo P2SH requires a redeem script 421 script, _ = txscript.PayToAddrScript(addrs.sh) 422 _, err = InputInfo(script, nil, tParams) 423 if err == nil { 424 t.Fatalf("no error for missing redeem script") 425 } 426 // Redeem script must be parseable. 427 spendInfo, err = InputInfo(script, invalidScript, tParams) 428 if err != nil { 429 t.Fatalf("failed to parse non-standard script") 430 } 431 if !spendInfo.NonStandardScript { 432 t.Errorf("non-standard script was not detected as such") 433 } 434 } 435 436 func TestFindKeyPush(t *testing.T) { 437 t.Run("segwit", func(t *testing.T) { 438 testFindKeyPush(t, true) 439 }) 440 t.Run("non-segwit", func(t *testing.T) { 441 testFindKeyPush(t, false) 442 }) 443 } 444 445 func testFindKeyPush(t *testing.T, segwit bool) { 446 dummyPrevOut := new(wire.OutPoint) 447 var rAddr, sAddr btcutil.Address 448 if segwit { 449 rAddr, _ = btcutil.NewAddressWitnessPubKeyHash(randBytes(20), tParams) 450 sAddr, _ = btcutil.NewAddressWitnessPubKeyHash(randBytes(20), tParams) 451 } else { 452 rAddr, _ = btcutil.NewAddressPubKeyHash(randBytes(20), tParams) 453 sAddr, _ = btcutil.NewAddressPubKeyHash(randBytes(20), tParams) 454 } 455 456 secret := randBytes(32) 457 secretHash := sha256.Sum256(secret) 458 contract, _ := MakeContract(rAddr, sAddr, secretHash[:], tStamp, segwit, tParams) 459 randomContract, _ := MakeContract(rAddr, sAddr, randBytes(32), tStamp, segwit, tParams) 460 461 var sigScript, contractHash, randoSigScript []byte 462 var witness, randoWitness [][]byte 463 var err error 464 if segwit { 465 witness = RedeemP2WSHContract(contract, randBytes(73), randBytes(33), secret) 466 h := sha256.Sum256(contract) 467 contractHash = h[:] 468 randoWitness = RedeemP2WSHContract(randomContract, randBytes(73), randBytes(33), secret) 469 470 } else { 471 sigScript, err = RedeemP2SHContract(contract, randBytes(73), randBytes(33), secret) 472 if err != nil { 473 t.Fatalf("error creating redeem script: %v", err) 474 } 475 contractHash = btcutil.Hash160(contract) 476 randoSigScript, _ = RedeemP2SHContract(randomContract, randBytes(73), randBytes(33), secret) 477 } 478 479 txIn := wire.NewTxIn(dummyPrevOut, sigScript, witness) 480 481 key, err := FindKeyPush(txIn.Witness, txIn.SignatureScript, contractHash, segwit, tParams) 482 if err != nil { 483 t.Fatalf("findKeyPush error: %v", err) 484 } 485 if !bytes.Equal(key, secret) { 486 t.Fatalf("wrong secret. expected %x, got %x", secret, key) 487 } 488 489 // Empty script is an error. 490 badTx := wire.NewTxIn(dummyPrevOut, nil, nil) 491 _, err = FindKeyPush(badTx.Witness, badTx.SignatureScript, contractHash, segwit, tParams) 492 if err == nil { 493 t.Fatalf("no error for empty script") 494 } 495 496 // Bad script 497 badTx = wire.NewTxIn(dummyPrevOut, invalidScript, invalidWitness) 498 _, err = FindKeyPush(badTx.Witness, badTx.SignatureScript, contractHash, segwit, tParams) 499 if err == nil { 500 t.Fatalf("no error for bad script") 501 } 502 503 // Random but valid contract won't work. 504 badTx = wire.NewTxIn(dummyPrevOut, randoSigScript, randoWitness) 505 _, err = FindKeyPush(badTx.Witness, badTx.SignatureScript, contractHash, segwit, tParams) 506 if err == nil { 507 t.Fatalf("no error for bad script") 508 } 509 } 510 511 func TestExtractContractHash(t *testing.T) { 512 addrs := testAddresses() 513 // non-hex 514 _, err := ExtractContractHash("zz") 515 if err == nil { 516 t.Fatalf("no error for non-hex contract") 517 } 518 // invalid script 519 _, err = ExtractContractHash(hex.EncodeToString(invalidScript)) 520 if err == nil { 521 t.Fatalf("no error for non-hex contract") 522 } 523 // multi-sig 524 _, err = ExtractContractHash(hex.EncodeToString(addrs.multiSig)) 525 if err == nil { 526 t.Fatalf("no error for non-hex contract") 527 } 528 // wrong script types 529 p2pkh, _ := txscript.PayToAddrScript(addrs.pkh) 530 _, err = ExtractContractHash(hex.EncodeToString(p2pkh)) 531 if err == nil { 532 t.Fatalf("no error for non-hex contract") 533 } 534 // ok p2sh 535 p2sh, _ := txscript.PayToAddrScript(addrs.sh) 536 checkHash0 := ExtractScriptHash(p2sh) 537 if !bytes.Equal(checkHash0, addrs.sh.ScriptAddress()) { 538 t.Fatalf("hash mismatch. wanted %x, got %x", addrs.sh.ScriptAddress(), checkHash0) 539 } 540 checkHash, err := ExtractContractHash(hex.EncodeToString(p2sh)) 541 if err != nil { 542 t.Fatalf("error extracting contract hash: %v", err) 543 } 544 if !bytes.Equal(checkHash, addrs.sh.ScriptAddress()) { 545 t.Fatalf("hash mismatch. wanted %x, got %x", addrs.sh.ScriptAddress(), checkHash) 546 } 547 // ok p2wsh 548 p2wsh, _ := txscript.PayToAddrScript(addrs.wsh) 549 checkHash0 = ExtractScriptHash(p2wsh) 550 if !bytes.Equal(checkHash0, addrs.wsh.ScriptAddress()) { 551 t.Fatalf("hash mismatch. wanted %x, got %x", addrs.wsh.ScriptAddress(), checkHash0) 552 } 553 checkHash, err = ExtractContractHash(hex.EncodeToString(p2wsh)) 554 if err != nil { 555 t.Fatalf("error extracting contract hash: %v", err) 556 } 557 if !bytes.Equal(checkHash, addrs.wsh.ScriptAddress()) { 558 t.Fatalf("hash mismatch. wanted %x, got %x", addrs.wsh.ScriptAddress(), checkHash) 559 } 560 } 561 562 func TestMsgTxVBytes(t *testing.T) { 563 // segwit txn 564 segwitTx := "010000000001015018feb13925a5ea9a548ff1af92bca55d3004dc8b1020" + 565 "d99978878f073142d80000000000ffffffff02406c85000000000017a914" + 566 "1feef1e6f0b360d639dba54c5aa337954f09a48087cba6aa000000000016" + 567 "00147916d4dc770017806a316bd907668429b5778b480247304402203d39" + 568 "c9b8088d19beafae1fbb531ae58d3ff2b4d374304729bd8df9ab1d1047d2" + 569 "022061cb714f12d0b60197da46199ed7151426284ec929a23fe457e65417" + 570 "c9b35b980121030375b9725c21dba1dbb6fdb1627a647357052f09bacdde" + 571 "9fc2d05e1a36e6180e00000000" 572 wantSerSize := 223 573 wantVSize := 142 574 575 txHex, _ := hex.DecodeString(segwitTx) 576 msgTx := wire.NewMsgTx(wire.TxVersion) 577 err := msgTx.Deserialize(bytes.NewBuffer(txHex)) 578 if err != nil { 579 t.Fatal(err) 580 } 581 582 gotSerSize := msgTx.SerializeSize() 583 if gotSerSize != wantSerSize { 584 t.Fatalf("wanted serialized tx size %d, got %d", wantSerSize, gotSerSize) 585 } 586 gotVSize := MsgTxVBytes(msgTx) 587 if gotVSize != uint64(wantVSize) { 588 t.Errorf("wanted tx virtual size %d, got %d", wantVSize, gotVSize) 589 } 590 591 // non-segwit txn 592 nonSegwitTX := "01000000019bb9e11de8c39f2102def30807b3124e92a2cb8b2474f85f9e" + 593 "a36d177f74f68100000000f04830450221009f0ea5ba317c1648aefa5864" + 594 "c1bafe9b86b3be742a877a6d362b0fdb7cce81d40220625604c3a0fd89b9" + 595 "3cfc5096fe0af98d32e5e9fe36f65736bee65ea7329641b60121022d099d" + 596 "2055bea94164527afcb0d6bf06a06ddb1186b87331ed48737302b0ec7d20" + 597 "179581e2e2e8abbaadf0231c52071e4f88588fccb78ad5afc0644f88011f" + 598 "a5d4514c616382012088a820c6de3217594af525fb57eaf1f2aae04c305d" + 599 "dc67d465edd325151685fc5a5e428876a914e05c5d2a5f850eee37d12242" + 600 "b64dafdf030a0fb467042609865eb17576a914e9288d333d5a8f343169f0" + 601 "709cb9b577fc758a506888acfeffffff01b860800200000000160014805b" + 602 "83e6b86fc7511f47d4cf95a3048954d3282e00000000" 603 604 wantSerSize = 322 605 wantVSize = 322 606 607 txHex, _ = hex.DecodeString(nonSegwitTX) 608 msgTx = wire.NewMsgTx(wire.TxVersion) 609 err = msgTx.Deserialize(bytes.NewBuffer(txHex)) 610 if err != nil { 611 t.Fatal(err) 612 } 613 614 gotSerSize = msgTx.SerializeSize() 615 if gotSerSize != wantSerSize { 616 t.Fatalf("wanted serialized tx size %d, got %d", wantSerSize, gotSerSize) 617 } 618 gotVSize = MsgTxVBytes(msgTx) 619 if gotVSize != uint64(wantVSize) { 620 t.Errorf("wanted tx virtual size %d, got %d", wantVSize, gotVSize) 621 } 622 }