github.com/bchainhub/blockbook@v0.3.2/bchain/coins/xzc/zcoinparser_test.go (about) 1 // +build unittest 2 3 package xzc 4 5 import ( 6 "bytes" 7 "encoding/hex" 8 "encoding/json" 9 "io/ioutil" 10 "math/big" 11 "os" 12 "reflect" 13 "strings" 14 "testing" 15 16 "blockbook/bchain" 17 "blockbook/bchain/coins/btc" 18 19 "github.com/martinboehm/btcutil/chaincfg" 20 ) 21 22 var ( 23 testTx1, testTx2, testTx3, testTx4 bchain.Tx 24 testTxPacked1, testTxPacked2, testTxPacked3, testTxPacked4 string 25 rawBlock1, rawBlock2 string 26 jsonTx json.RawMessage 27 ) 28 29 func readHexs(path string) []string { 30 raw, err := ioutil.ReadFile(path) 31 if err != nil { 32 panic(err) 33 } 34 rawStr := string(raw) 35 raws := strings.Split(rawStr, "\n") 36 return raws 37 } 38 39 func init() { 40 rawBlocks := readHexs("./testdata/rawblock.hex") 41 rawBlock1 = rawBlocks[0] 42 rawBlock2 = rawBlocks[1] 43 44 hextxs := readHexs("./testdata/txs.hex") 45 rawTestTx1 := hextxs[0] 46 rawTestTx2 := hextxs[1] 47 rawTestTx3 := hextxs[2] 48 rawTestTx4 := hextxs[3] 49 50 rawSpendHex := readHexs("./testdata/rawspend.hex")[0] 51 52 rawSpendTx, err := ioutil.ReadFile("./testdata/spendtx.json") 53 if err != nil { 54 panic(err) 55 } 56 jsonTx = json.RawMessage(rawSpendTx) 57 58 testTxPackeds := readHexs("./testdata/packedtxs.hex") 59 testTxPacked1 = testTxPackeds[0] 60 testTxPacked2 = testTxPackeds[1] 61 testTxPacked3 = testTxPackeds[2] 62 testTxPacked4 = testTxPackeds[3] 63 64 testTx1 = bchain.Tx{ 65 Hex: rawTestTx1, 66 Blocktime: 1533980594, 67 Time: 1533980594, 68 Txid: "9d9e759dd970d86df9e105a7d4f671543bc16a03b6c5d2b48895f2a00aa7dd23", 69 LockTime: 0, 70 Vin: []bchain.Vin{ 71 { 72 ScriptSig: bchain.ScriptSig{ 73 Hex: "47304402205b7d9c9aae790b69017651e10134735928df3b4a4a2feacc9568eb4fa133ed5902203f21a399385ce29dd79831ea34aa535612aa4314c5bd0b002bbbc9bcd2de1436012102b8d462740c99032a00083ac7028879acec244849e54ad0a04ea87f632f54b1d2", 74 }, 75 Txid: "463a2d66b04636a014da35724909425f3403d9d786dd4f79780de50d47b18716", 76 Vout: 1, 77 Sequence: 4294967294, 78 }, 79 }, 80 Vout: []bchain.Vout{ 81 { 82 ValueSat: *big.NewInt(18188266638), 83 N: 0, 84 ScriptPubKey: bchain.ScriptPubKey{ 85 Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28", 86 }, 87 }, 88 { 89 ValueSat: *big.NewInt(18188266638), 90 N: 1, 91 ScriptPubKey: bchain.ScriptPubKey{ 92 Hex: "76a914c963f917c7f23cb4243e079db33107571b87690588ac", 93 Addresses: []string{ 94 "aK5KKi8qqDbspcXFfDjx8UBGMouhYbYZVp", 95 }, 96 }, 97 }, 98 }, 99 } 100 101 testTx2 = bchain.Tx{ 102 Hex: rawTestTx2, 103 Blocktime: 1481277009, 104 Time: 1481277009, 105 Txid: "3d721fdce2855e2b4a54b74a26edd58a7262e1f195b5acaaae7832be6e0b3d32", 106 LockTime: 0, 107 Vin: []bchain.Vin{ 108 { 109 ScriptSig: bchain.ScriptSig{ 110 Hex: rawSpendHex, 111 }, 112 Txid: "0000000000000000000000000000000000000000000000000000000000000000", 113 Vout: 4294967295, 114 Sequence: 2, 115 }, 116 }, 117 Vout: []bchain.Vout{ 118 { 119 ValueSat: *big.NewInt(5000000000), 120 N: 0, 121 ScriptPubKey: bchain.ScriptPubKey{ 122 Hex: "76a914b9e262e30df03e88ccea312652bc83ca7290c8fc88ac", 123 Addresses: []string{ 124 "aHfKwzFZMiSxDuNL4jts819nh57t2yJG1h", 125 }, 126 }, 127 }, 128 }, 129 } 130 131 testTx3 = bchain.Tx{ 132 Hex: rawTestTx3, 133 Blocktime: 1547091829, 134 Time: 1547091829, 135 Txid: "96ae951083651f141d1fb2719c76d47e5a3ad421b81905f679c0edb60f2de0ff", 136 LockTime: 126200, 137 Vin: []bchain.Vin{ 138 { 139 ScriptSig: bchain.ScriptSig{ 140 Hex: "483045022100bdc6b51c114617e29e28390dc9b3ad95b833ca3d1f0429ba667c58a667f9124702204ca2ed362dd9ef723ddbdcf4185b47c28b127a36f46bc4717662be863309b3e601210387e7ff08b953e3736955408fc6ebcd8aa84a04cc4b45758ea29cc2cfe1820535", 141 }, 142 Txid: "448ccfd9c3f375be8701b86aff355a230dbe240334233f2ed476fcae6abd295d", 143 Vout: 1, 144 Sequence: 4294967294, 145 }, 146 }, 147 Vout: []bchain.Vout{ 148 { 149 ValueSat: *big.NewInt(42000000000), 150 N: 0, 151 ScriptPubKey: bchain.ScriptPubKey{ 152 Hex: "76a91429bef7962c5c65a2f0f4f7d9ec791866c54f851688ac", 153 Addresses: []string{ 154 "a4XCDQ7AnRH9opZ4h6LcG3g7ocSV2SbBmS", 155 }, 156 }, 157 }, 158 { 159 ValueSat: *big.NewInt(107300000000), 160 N: 1, 161 ScriptPubKey: bchain.ScriptPubKey{ 162 Hex: "76a914e2cee7b71c3a4637dbdfe613f19f4b4f2d070d7f88ac", 163 Addresses: []string{ 164 "aMPiKHB3E1AGPi8kKLknx6j1L4JnKCGkLw", 165 }, 166 }, 167 }, 168 }, 169 } 170 171 testTx4 = bchain.Tx{ 172 Hex: rawTestTx4, 173 Blocktime: 1533977563, 174 Time: 1533977563, 175 Txid: "914ccbdb72f593e5def15978cf5891e1384a1b85e89374fc1c440c074c6dd286", 176 LockTime: 0, 177 Vin: []bchain.Vin{ 178 { 179 Coinbase: "03a1860104dba36e5b082a00077c00000000052f6d70682f", 180 Sequence: 0, 181 }, 182 }, 183 Vout: []bchain.Vout{ 184 { 185 ValueSat: *big.NewInt(2800200000), 186 N: 0, 187 ScriptPubKey: bchain.ScriptPubKey{ 188 Hex: "76a91436e086acf6561a68ba64196e7b92b606d0b8516688ac", 189 Addresses: []string{ 190 "a5idCcHN8WYxvFCeBXSXvMPrZHuBkZmqEJ", 191 }, 192 }, 193 }, 194 { 195 ValueSat: *big.NewInt(1500000000), 196 N: 1, 197 ScriptPubKey: bchain.ScriptPubKey{ 198 Hex: "76a914381a5dd1a279e8e63e67cde39ecfa61a99dd2ba288ac", 199 Addresses: []string{ 200 "a5q7Ad4okSFFVh5adyqx5DT21RTxJykpUM", 201 }, 202 }, 203 }, 204 { 205 ValueSat: *big.NewInt(100000000), 206 N: 2, 207 ScriptPubKey: bchain.ScriptPubKey{ 208 Hex: "76a9147d9ed014fc4e603fca7c2e3f9097fb7d0fb487fc88ac", 209 Addresses: []string{ 210 "aCAgTPgtYcA4EysU4UKC86EQd5cTtHtCcr", 211 }, 212 }, 213 }, 214 { 215 ValueSat: *big.NewInt(100000000), 216 N: 3, 217 ScriptPubKey: bchain.ScriptPubKey{ 218 Hex: "76a914bc7e5a5234db3ab82d74c396ad2b2af419b7517488ac", 219 Addresses: []string{ 220 "aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD", 221 }, 222 }, 223 }, 224 { 225 ValueSat: *big.NewInt(100000000), 226 N: 4, 227 ScriptPubKey: bchain.ScriptPubKey{ 228 Hex: "76a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac", 229 Addresses: []string{ 230 "a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3", 231 }, 232 }, 233 }, 234 { 235 ValueSat: *big.NewInt(300000000), 236 N: 5, 237 ScriptPubKey: bchain.ScriptPubKey{ 238 Hex: "76a9140654dd9b856f2ece1d56cb4ee5043cd9398d962c88ac", 239 Addresses: []string{ 240 "a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3", 241 }, 242 }, 243 }, 244 { 245 ValueSat: *big.NewInt(100000000), 246 N: 6, 247 ScriptPubKey: bchain.ScriptPubKey{ 248 Hex: "76a9140b4bfb256ef4bfa360e3b9e66e53a0bd84d196bc88ac", 249 Addresses: []string{ 250 "a1kCCGddf5pMXSipLVD9hBG2MGGVNaJ15U", 251 }, 252 }, 253 }, 254 }, 255 } 256 } 257 258 func TestMain(m *testing.M) { 259 c := m.Run() 260 chaincfg.ResetParams() 261 os.Exit(c) 262 } 263 264 func TestGetAddrDesc(t *testing.T) { 265 type args struct { 266 tx bchain.Tx 267 parser *ZcoinParser 268 } 269 tests := []struct { 270 name string 271 args args 272 }{ 273 { 274 name: "xzc-1", 275 args: args{ 276 tx: testTx1, 277 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 278 }, 279 }, 280 // FIXME: work around handle zerocoin spend as coinbase 281 // { 282 // name: "xzc-2", 283 // args: args{ 284 // tx: testTx2, 285 // parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 286 // }, 287 // }, 288 { 289 name: "xzc-3", 290 args: args{ 291 tx: testTx3, 292 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 293 }, 294 }, 295 } 296 for _, tt := range tests { 297 t.Run(tt.name, func(t *testing.T) { 298 for n, vout := range tt.args.tx.Vout { 299 got1, err := tt.args.parser.GetAddrDescFromVout(&vout) 300 if err != nil { 301 t.Errorf("getAddrDescFromVout() error = %v, vout = %d", err, n) 302 return 303 } 304 305 // normal vout 306 if len(vout.ScriptPubKey.Addresses) >= 1 { 307 got2, err := tt.args.parser.GetAddrDescFromAddress(vout.ScriptPubKey.Addresses[0]) 308 if err != nil { 309 t.Errorf("getAddrDescFromAddress() error = %v, vout = %d", err, n) 310 return 311 } 312 if !bytes.Equal(got1, got2) { 313 t.Errorf("Address descriptors mismatch: got1 = %v, got2 = %v", got1, got2) 314 } 315 } 316 } 317 }) 318 } 319 } 320 321 func TestGetAddrDescFromVoutForMint(t *testing.T) { 322 type args struct { 323 vout bchain.Vout 324 } 325 tests := []struct { 326 name string 327 args args 328 want string 329 wantErr bool 330 }{ 331 { 332 name: "OP_RETURN", 333 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "6a072020f1686f6a20"}}}, 334 want: "6a072020f1686f6a20", 335 wantErr: false, 336 }, 337 { 338 name: "OP_ZEROCOINMINT", 339 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28"}}}, 340 want: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28", 341 wantErr: false, 342 }, 343 { 344 name: "OP_SIGMAMINT", 345 args: args{vout: bchain.Vout{ScriptPubKey: bchain.ScriptPubKey{Hex: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000"}}}, 346 want: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000", 347 wantErr: false, 348 }, 349 } 350 parser := NewZcoinParser(GetChainParams("main"), &btc.Configuration{}) 351 352 for _, tt := range tests { 353 t.Run(tt.name, func(t *testing.T) { 354 got, err := parser.GetAddrDescFromVout(&tt.args.vout) 355 if (err != nil) != tt.wantErr { 356 t.Errorf("GetAddrDescFromVout() error = %v, wantErr %v", err, tt.wantErr) 357 return 358 } 359 h := hex.EncodeToString(got) 360 if !reflect.DeepEqual(h, tt.want) { 361 t.Errorf("GetAddrDescFromVout() = %v, want %v", h, tt.want) 362 } 363 }) 364 } 365 } 366 367 func TestGetAddressesFromAddrDescForMint(t *testing.T) { 368 type args struct { 369 script string 370 } 371 tests := []struct { 372 name string 373 args args 374 want []string 375 want2 bool 376 wantErr bool 377 }{ 378 { 379 name: "OP_RETURN hex", 380 args: args{script: "6a072020f1686f6a20"}, 381 want: []string{"OP_RETURN 2020f1686f6a20"}, 382 want2: false, 383 wantErr: false, 384 }, 385 { 386 name: "OP_ZEROCOINMINT size hex", 387 args: args{script: "c10280004c80f767f3ee79953c67a7ed386dcccf1243619eb4bbbe414a3982dd94a83c1b69ac52d6ab3b653a3e05c4e4516c8dfe1e58ada40461bc5835a4a0d0387a51c29ac11b72ae25bbcdef745f50ad08f08b3e9bc2c31a35444398a490e65ac090e9f341f1abdebe47e57e8237ac25d098e951b4164a35caea29f30acb50b12e4425df28"}, 388 want: []string{"Zeromint"}, 389 want2: false, 390 wantErr: false, 391 }, 392 { 393 name: "OP_SIGMAMINT size hex", 394 args: args{script: "c317dcee5b8b2c5b79728abc3a39abc54682b31a4e18f5abb6f34dc8089544763b0000"}, 395 want: []string{"Sigmamint"}, 396 want2: false, 397 wantErr: false, 398 }, 399 } 400 parser := NewZcoinParser(GetChainParams("main"), &btc.Configuration{}) 401 402 for _, tt := range tests { 403 t.Run(tt.name, func(t *testing.T) { 404 b, _ := hex.DecodeString(tt.args.script) 405 got, got2, err := parser.GetAddressesFromAddrDesc(b) 406 if (err != nil) != tt.wantErr { 407 t.Errorf("GetAddressesFromAddrDesc() error = %v, wantErr %v", err, tt.wantErr) 408 return 409 } 410 if !reflect.DeepEqual(got, tt.want) { 411 t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.want) 412 } 413 if !reflect.DeepEqual(got2, tt.want2) { 414 t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.want2) 415 } 416 }) 417 } 418 } 419 420 func TestPackTx(t *testing.T) { 421 type args struct { 422 tx bchain.Tx 423 height uint32 424 blockTime int64 425 parser *ZcoinParser 426 } 427 tests := []struct { 428 name string 429 args args 430 want string 431 wantErr bool 432 }{ 433 { 434 name: "xzc-1", 435 args: args{ 436 tx: testTx1, 437 height: 100002, 438 blockTime: 1533980594, 439 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 440 }, 441 want: testTxPacked1, 442 wantErr: false, 443 }, 444 // FIXME: work around handle zerocoin spend as coinbase 445 // { 446 // name: "xzc-2", 447 // args: args{ 448 // tx: testTx2, 449 // height: 11002, 450 // blockTime: 1481277009, 451 // parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 452 // }, 453 // want: testTxPacked2, 454 // wantErr: true, 455 // }, 456 { 457 name: "xzc-3", 458 args: args{ 459 tx: testTx3, 460 height: 126202, 461 blockTime: 1547091829, 462 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 463 }, 464 want: testTxPacked3, 465 wantErr: false, 466 }, 467 { 468 name: "xzc-coinbase", 469 args: args{ 470 tx: testTx4, 471 height: 100001, 472 blockTime: 1533977563, 473 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 474 }, 475 want: testTxPacked4, 476 wantErr: false, 477 }, 478 } 479 for _, tt := range tests { 480 t.Run(tt.name, func(t *testing.T) { 481 got, err := tt.args.parser.PackTx(&tt.args.tx, tt.args.height, tt.args.blockTime) 482 if (err != nil) != tt.wantErr { 483 t.Errorf("packTx() error = %v, wantErr %v", err, tt.wantErr) 484 return 485 } 486 if !tt.wantErr { 487 h := hex.EncodeToString(got) 488 if !reflect.DeepEqual(h, tt.want) { 489 t.Errorf("packTx() = %v, want %v", h, tt.want) 490 } 491 } 492 }) 493 } 494 } 495 496 func TestUnpackTx(t *testing.T) { 497 type args struct { 498 packedTx string 499 parser *ZcoinParser 500 } 501 tests := []struct { 502 name string 503 args args 504 want *bchain.Tx 505 want1 uint32 506 wantErr bool 507 }{ 508 { 509 name: "xzc-1", 510 args: args{ 511 packedTx: testTxPacked1, 512 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 513 }, 514 want: &testTx1, 515 want1: 100002, 516 wantErr: false, 517 }, 518 // FIXME: work around handle zerocoin spend as coinbase 519 // { 520 // name: "xzc-2", 521 // args: args{ 522 // packedTx: testTxPacked2, 523 // parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 524 // }, 525 // want: &testTx2, 526 // want1: 11002, 527 // wantErr: true, 528 // }, 529 { 530 name: "xzc-3", 531 args: args{ 532 packedTx: testTxPacked3, 533 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 534 }, 535 want: &testTx3, 536 want1: 126202, 537 wantErr: false, 538 }, 539 { 540 name: "xzc-coinbase", 541 args: args{ 542 packedTx: testTxPacked4, 543 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 544 }, 545 want: &testTx4, 546 want1: 100001, 547 wantErr: false, 548 }, 549 } 550 for _, tt := range tests { 551 t.Run(tt.name, func(t *testing.T) { 552 b, _ := hex.DecodeString(tt.args.packedTx) 553 got, got1, err := tt.args.parser.UnpackTx(b) 554 if (err != nil) != tt.wantErr { 555 t.Errorf("unpackTx() error = %v, wantErr %v", err, tt.wantErr) 556 return 557 } 558 559 if !tt.wantErr { 560 if !reflect.DeepEqual(got, tt.want) { 561 t.Errorf("unpackTx() got = %v, want %v", got, tt.want) 562 } 563 if got1 != tt.want1 { 564 t.Errorf("unpackTx() got1 = %v, want %v", got1, tt.want1) 565 } 566 } 567 }) 568 } 569 } 570 571 func TestParseBlock(t *testing.T) { 572 type args struct { 573 rawBlock string 574 parser *ZcoinParser 575 } 576 tests := []struct { 577 name string 578 args args 579 want *bchain.Block 580 wantTxs int 581 wantErr bool 582 }{ 583 { 584 name: "normal-block", 585 args: args{ 586 rawBlock: rawBlock1, 587 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 588 }, 589 want: &bchain.Block{ 590 BlockHeader: bchain.BlockHeader{ 591 Size: 200286, 592 Time: 1547120622, 593 }, 594 }, 595 wantTxs: 3, 596 wantErr: false, 597 }, 598 { 599 name: "spend-block", 600 args: args{ 601 rawBlock: rawBlock2, 602 parser: NewZcoinParser(GetChainParams("main"), &btc.Configuration{}), 603 }, 604 want: &bchain.Block{ 605 BlockHeader: bchain.BlockHeader{ 606 Size: 25298, 607 Time: 1482107572, 608 }, 609 }, 610 wantTxs: 4, 611 wantErr: false, 612 }, 613 } 614 615 for _, tt := range tests { 616 t.Run(tt.name, func(t *testing.T) { 617 b, _ := hex.DecodeString(tt.args.rawBlock) 618 got, err := tt.args.parser.ParseBlock(b) 619 if (err != nil) != tt.wantErr { 620 t.Errorf("parseBlock() error = %+v", err) 621 } 622 623 if got != nil { 624 625 if !reflect.DeepEqual(got.BlockHeader, tt.want.BlockHeader) { 626 t.Errorf("parseBlock() got = %v, want %v", got.BlockHeader, tt.want.BlockHeader) 627 } 628 629 if len(got.Txs) != tt.wantTxs { 630 t.Errorf("parseBlock() txs length got = %d, want %d", len(got.Txs), tt.wantTxs) 631 } 632 } 633 }) 634 } 635 }