github.com/decred/dcrlnd@v0.7.6/zpay32/invoice_internal_test.go (about) 1 package zpay32 2 3 import ( 4 "encoding/binary" 5 "math" 6 "reflect" 7 "testing" 8 "time" 9 10 "github.com/decred/dcrd/bech32" 11 "github.com/decred/dcrd/chaincfg/v3" 12 "github.com/decred/dcrd/dcrec/secp256k1/v4" 13 "github.com/decred/dcrd/txscript/v4/stdaddr" 14 "github.com/decred/dcrlnd/lnwire" 15 ) 16 17 // TestDecodeAmount ensures that the amount string in the hrp of the Invoice 18 // properly gets decoded into MilliAtoms. 19 func TestDecodeAmount(t *testing.T) { 20 t.Parallel() 21 22 tests := []struct { 23 amount string 24 valid bool 25 result lnwire.MilliAtom 26 }{ 27 { 28 amount: "", 29 valid: false, 30 }, 31 { 32 amount: "20n00", 33 valid: false, 34 }, 35 { 36 amount: "2000y", 37 valid: false, 38 }, 39 { 40 amount: "2000mm", 41 valid: false, 42 }, 43 { 44 amount: "2000nm", 45 valid: false, 46 }, 47 { 48 amount: "m", 49 valid: false, 50 }, 51 { 52 amount: "1p", // pDCR 53 valid: false, // too small 54 }, 55 { 56 amount: "1109p", // pDCR 57 valid: false, // not divisible by 10 58 }, 59 { 60 amount: "-10p", // pDCR 61 valid: false, // negative amount 62 }, 63 { 64 amount: "10p", // pDCR 65 valid: true, 66 result: 1, // mAt 67 }, 68 { 69 amount: "1000p", // pDCR 70 valid: true, 71 result: 100, // mAt 72 }, 73 { 74 amount: "1n", // nDCR 75 valid: true, 76 result: 100, // mAt 77 }, 78 { 79 amount: "9000n", // nDCR 80 valid: true, 81 result: 900000, // mAt 82 }, 83 { 84 amount: "9u", // uDCR 85 valid: true, 86 result: 900000, // mAt 87 }, 88 { 89 amount: "2000u", // uDCR 90 valid: true, 91 result: 200000000, // mAt 92 }, 93 { 94 amount: "2m", // mDCR 95 valid: true, 96 result: 200000000, // mAt 97 }, 98 { 99 amount: "2000m", // mDCR 100 valid: true, 101 result: 200000000000, // mAt 102 }, 103 { 104 amount: "2", // DCR 105 valid: true, 106 result: 200000000000, // mAt 107 }, 108 { 109 amount: "2000", // DCR 110 valid: true, 111 result: 200000000000000, // mAt 112 }, 113 { 114 amount: "2009", // DCR 115 valid: true, 116 result: 200900000000000, // mAt 117 }, 118 { 119 amount: "1234", // DCR 120 valid: true, 121 result: 123400000000000, // mAt 122 }, 123 { 124 amount: "21000000", // DCR 125 valid: true, 126 result: 2100000000000000000, // mAt 127 }, 128 } 129 130 for i, test := range tests { 131 at, err := decodeAmount(test.amount) 132 if (err == nil) != test.valid { 133 t.Errorf("amount decoding test %d failed: %v", i, err) 134 return 135 } 136 if test.valid && at != test.result { 137 t.Fatalf("test %d failed decoding amount, expected %v, "+ 138 "got %v", i, test.result, at) 139 } 140 } 141 } 142 143 // TestEncodeAmount checks that the given amount in MilliAtoms gets encoded 144 // into the shortest possible amount string. 145 func TestEncodeAmount(t *testing.T) { 146 t.Parallel() 147 148 tests := []struct { 149 mat lnwire.MilliAtom 150 valid bool 151 result string 152 }{ 153 { 154 mat: 1, // mAt 155 valid: true, 156 result: "10p", // pDCR 157 }, 158 { 159 mat: 120, // mAt 160 valid: true, 161 result: "1200p", // pDCR 162 }, 163 { 164 mat: 100, // mAt 165 valid: true, 166 result: "1n", // nDCR 167 }, 168 { 169 mat: 900000, // mAt 170 valid: true, 171 result: "9u", // uDCR 172 }, 173 { 174 mat: 200000000, // mAt 175 valid: true, 176 result: "2m", // mDCR 177 }, 178 { 179 mat: 200000000000, // mAt 180 valid: true, 181 result: "2", // DCR 182 }, 183 { 184 mat: 200000000000000, // mAt 185 valid: true, 186 result: "2000", // DCR 187 }, 188 { 189 mat: 200900000000000, // mAt 190 valid: true, 191 result: "2009", // DCR 192 }, 193 { 194 mat: 123400000000000, // mAt 195 valid: true, 196 result: "1234", // DCR 197 }, 198 { 199 mat: 2100000000000000000, // mAt 200 valid: true, 201 result: "21000000", // DCR 202 }, 203 } 204 205 for i, test := range tests { 206 shortened, err := encodeAmount(test.mat) 207 if (err == nil) != test.valid { 208 t.Errorf("amount encoding test %d failed: %v", i, err) 209 return 210 } 211 if test.valid && shortened != test.result { 212 t.Fatalf("test %d failed encoding amount, expected %v, "+ 213 "got %v", i, test.result, shortened) 214 } 215 } 216 } 217 218 // TestParseTimestamp checks that the 35 bit timestamp is properly parsed. 219 func TestParseTimestamp(t *testing.T) { 220 t.Parallel() 221 222 tests := []struct { 223 data []byte 224 valid bool 225 result uint64 226 }{ 227 { 228 data: []byte(""), 229 valid: false, // empty data 230 }, 231 { 232 data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 233 valid: false, // data too short 234 }, 235 { 236 data: []byte{0x01, 0x0c, 0x12, 0x1f, 0x1c, 0x19, 0x02}, 237 valid: true, // timestamp 1496314658 238 result: 1496314658, 239 }, 240 } 241 242 for i, test := range tests { 243 time, err := parseTimestamp(test.data) 244 if (err == nil) != test.valid { 245 t.Errorf("timestamp decoding test %d failed: %v", i, err) 246 return 247 } 248 if test.valid && time != test.result { 249 t.Fatalf("test %d failed decoding timestamp: "+ 250 "expected %d, got %d", 251 i, test.result, time) 252 return 253 } 254 } 255 } 256 257 // TestParseFieldDataLength checks that the 16 bit length is properly parsed. 258 func TestParseFieldDataLength(t *testing.T) { 259 t.Parallel() 260 261 tests := []struct { 262 data []byte 263 valid bool 264 result uint16 265 }{ 266 { 267 data: []byte{}, 268 valid: false, // empty data 269 }, 270 { 271 data: []byte{0x0}, 272 valid: false, // data too short 273 }, 274 { 275 data: []byte{0x0, 0x0, 0x0}, 276 valid: false, // data too long 277 }, 278 { 279 data: []byte{0x0, 0x0}, 280 valid: true, 281 result: 0, 282 }, 283 { 284 data: []byte{0x1f, 0x1f}, 285 valid: true, 286 result: 1023, 287 }, 288 { 289 // The first byte is <= 3 bits long. 290 data: []byte{0x1, 0x2}, 291 valid: true, 292 result: 34, 293 }, 294 { 295 // The first byte is > 3 bits long. 296 data: []byte{0xa, 0x0}, 297 valid: true, 298 result: 320, 299 }, 300 } 301 302 for i, test := range tests { 303 length, err := parseFieldDataLength(test.data) 304 if (err == nil) != test.valid { 305 t.Errorf("field data length decoding test %d failed: %v", i, err) 306 return 307 } 308 if test.valid && length != test.result { 309 t.Fatalf("test %d failed decoding field data length: "+ 310 "expected %d, got %d", 311 i, test.result, length) 312 return 313 } 314 } 315 } 316 317 // TestParse32Bytes checks that the payment hash is properly parsed. 318 // If the data does not have a length of 52 bytes, we skip over parsing the 319 // field and do not return an error. 320 func TestParse32Bytes(t *testing.T) { 321 t.Parallel() 322 323 testPaymentHashData, _ := bech32.ConvertBits(testPaymentHash[:], 8, 5, true) 324 325 tests := []struct { 326 data []byte 327 valid bool 328 result *[32]byte 329 }{ 330 { 331 data: []byte{}, 332 valid: true, 333 result: nil, // skip unknown length, not 52 bytes 334 }, 335 { 336 data: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 337 valid: true, 338 result: nil, // skip unknown length, not 52 bytes 339 }, 340 { 341 data: testPaymentHashData, 342 valid: true, 343 result: &testPaymentHash, 344 }, 345 { 346 data: append(testPaymentHashData, 0x0), 347 valid: true, 348 result: nil, // skip unknown length, not 52 bytes 349 }, 350 } 351 352 for i, test := range tests { 353 paymentHash, err := parse32Bytes(test.data) 354 if (err == nil) != test.valid { 355 t.Errorf("payment hash decoding test %d failed: %v", i, err) 356 return 357 } 358 if test.valid && !compareHashes(paymentHash, test.result) { 359 t.Fatalf("test %d failed decoding payment hash: "+ 360 "expected %x, got %x", 361 i, *test.result, *paymentHash) 362 return 363 } 364 } 365 } 366 367 // TestParseDescription checks that the description is properly parsed. 368 func TestParseDescription(t *testing.T) { 369 t.Parallel() 370 371 testCupOfCoffeeData, _ := bech32.ConvertBits([]byte(testCupOfCoffee), 8, 5, true) 372 testPleaseConsiderData, _ := bech32.ConvertBits([]byte(testPleaseConsider), 8, 5, true) 373 374 tests := []struct { 375 data []byte 376 valid bool 377 result *string 378 }{ 379 { 380 data: []byte{}, 381 valid: true, 382 result: &testEmptyString, 383 }, 384 { 385 data: testCupOfCoffeeData, 386 valid: true, 387 result: &testCupOfCoffee, 388 }, 389 { 390 data: testPleaseConsiderData, 391 valid: true, 392 result: &testPleaseConsider, 393 }, 394 } 395 396 for i, test := range tests { 397 description, err := parseDescription(test.data) 398 if (err == nil) != test.valid { 399 t.Errorf("description decoding test %d failed: %v", i, err) 400 return 401 } 402 if test.valid && !reflect.DeepEqual(description, test.result) { 403 t.Fatalf("test %d failed decoding description: "+ 404 "expected \"%s\", got \"%s\"", 405 i, *test.result, *description) 406 return 407 } 408 } 409 } 410 411 // TestParseDestination checks that the destination is properly parsed. 412 // If the data does not have a length of 53 bytes, we skip over parsing the 413 // field and do not return an error. 414 func TestParseDestination(t *testing.T) { 415 t.Parallel() 416 417 testPubKeyData, _ := bech32.ConvertBits(testPubKey.SerializeCompressed(), 8, 5, true) 418 419 tests := []struct { 420 data []byte 421 valid bool 422 result *secp256k1.PublicKey 423 }{ 424 { 425 data: []byte{}, 426 valid: true, 427 result: nil, // skip unknown length, not 53 bytes 428 }, 429 { 430 data: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 431 valid: true, 432 result: nil, // skip unknown length, not 53 bytes 433 }, 434 { 435 data: testPubKeyData, 436 valid: true, 437 result: testPubKey, 438 }, 439 { 440 data: append(testPubKeyData, 0x0), 441 valid: true, 442 result: nil, // skip unknown length, not 53 bytes 443 }, 444 } 445 446 for i, test := range tests { 447 destination, err := parseDestination(test.data) 448 if (err == nil) != test.valid { 449 t.Errorf("destination decoding test %d failed: %v", i, err) 450 return 451 } 452 if test.valid && !comparePubkeys(destination, test.result) { 453 t.Fatalf("test %d failed decoding destination: "+ 454 "expected %x, got %x", 455 i, test.result.SerializeCompressed(), destination.SerializeCompressed()) 456 return 457 } 458 } 459 } 460 461 // TestParseExpiry checks that the expiry is properly parsed. 462 func TestParseExpiry(t *testing.T) { 463 t.Parallel() 464 465 tests := []struct { 466 data []byte 467 valid bool 468 result *time.Duration 469 }{ 470 { 471 data: []byte{}, 472 valid: true, 473 result: &testExpiry0, 474 }, 475 { 476 data: []byte{0x1, 0x1c}, 477 valid: true, 478 result: &testExpiry60, 479 }, 480 { 481 data: []byte{ 482 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 483 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 484 0xc, 0x3, 485 }, 486 valid: false, // data too long 487 }, 488 } 489 490 for i, test := range tests { 491 expiry, err := parseExpiry(test.data) 492 if (err == nil) != test.valid { 493 t.Errorf("expiry decoding test %d failed: %v", i, err) 494 return 495 } 496 if test.valid && !reflect.DeepEqual(expiry, test.result) { 497 t.Fatalf("test %d failed decoding expiry: "+ 498 "expected expiry %v, got %v", 499 i, *test.result, *expiry) 500 return 501 } 502 } 503 } 504 505 // TestParseMinFinalCLTVExpiry checks that the minFinalCLTVExpiry is properly 506 // parsed. 507 func TestParseMinFinalCLTVExpiry(t *testing.T) { 508 t.Parallel() 509 510 tests := []struct { 511 data []byte 512 valid bool 513 result uint64 514 }{ 515 { 516 data: []byte{}, 517 valid: true, 518 result: 0, 519 }, 520 { 521 data: []byte{0x1, 0x1c}, 522 valid: true, 523 result: 60, 524 }, 525 { 526 data: []byte{ 527 0x1, 0x2, 0x3, 0x4, 0x5, 528 0x6, 0x7, 0x8, 0x9, 0xa, 529 0xb, 0xc, 530 }, 531 valid: true, 532 result: 38390726480144748, 533 }, 534 { 535 data: []byte{ 536 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 537 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 538 0xc, 0x94, 539 }, 540 valid: false, // data too long 541 }, 542 } 543 544 for i, test := range tests { 545 expiry, err := parseMinFinalCLTVExpiry(test.data) 546 if (err == nil) != test.valid { 547 t.Errorf("minFinalCLTVExpiry decoding test %d failed: %v", i, err) 548 return 549 } 550 if test.valid && *expiry != test.result { 551 t.Fatalf("test %d failed decoding minFinalCLTVExpiry: "+ 552 "expected %d, got %d", 553 i, test.result, *expiry) 554 return 555 } 556 } 557 } 558 559 // TestParseMinFinalCLTVExpiry tests that were able to properly encode/decode 560 // the math.MaxUint64 integer without panicking. 561 func TestParseMaxUint64Expiry(t *testing.T) { 562 t.Parallel() 563 564 expiry := uint64(math.MaxUint64) 565 566 expiryBytes := uint64ToBase32(expiry) 567 568 expiryReParse, err := base32ToUint64(expiryBytes) 569 if err != nil { 570 t.Fatalf("unable to parse uint64: %v", err) 571 } 572 573 if expiryReParse != expiry { 574 t.Fatalf("wrong expiry: expected %v got %v", expiry, 575 expiryReParse) 576 } 577 } 578 579 // TestParseFallbackAddr checks that the fallback address is properly parsed. 580 func TestParseFallbackAddr(t *testing.T) { 581 t.Parallel() 582 583 testAddrTestnetData, _ := bech32.ConvertBits(testAddrTestnet.(stdaddr.Hash160er).Hash160()[:], 8, 5, true) 584 testAddrTestnetDataWithVersion := append([]byte{17}, testAddrTestnetData...) 585 586 testRustyAddrData, _ := bech32.ConvertBits(testRustyAddr.(stdaddr.Hash160er).Hash160()[:], 8, 5, true) 587 testRustyAddrDataWithVersion := append([]byte{17}, testRustyAddrData...) 588 589 testAddrMainnetP2SHData, _ := bech32.ConvertBits(testAddrMainnetP2SH.(stdaddr.Hash160er).Hash160()[:], 8, 5, true) 590 testAddrMainnetP2SHDataWithVersion := append([]byte{18}, testAddrMainnetP2SHData...) 591 592 tests := []struct { 593 data []byte 594 net *chaincfg.Params 595 valid bool 596 result stdaddr.Address 597 }{ 598 { 599 data: []byte{}, 600 valid: false, // empty data 601 }, 602 { 603 data: []byte{0x0}, 604 valid: false, // data too short, version without address 605 }, 606 { 607 data: testAddrTestnetDataWithVersion, 608 net: chaincfg.TestNet3Params(), 609 valid: true, 610 result: testAddrTestnet, 611 }, 612 { 613 data: testRustyAddrDataWithVersion, 614 net: chaincfg.MainNetParams(), 615 valid: true, 616 result: testRustyAddr, 617 }, 618 { 619 data: testAddrMainnetP2SHDataWithVersion, 620 net: chaincfg.MainNetParams(), 621 valid: true, 622 result: testAddrMainnetP2SH, 623 }, 624 } 625 626 for i, test := range tests { 627 fallbackAddr, err := parseFallbackAddr(test.data, test.net) 628 if (err == nil) != test.valid { 629 t.Errorf("fallback addr decoding test %d failed: %v", i, err) 630 return 631 } 632 if test.valid && !reflect.DeepEqual(test.result, fallbackAddr) { 633 t.Fatalf("test %d failed decoding fallback addr: "+ 634 "expected %v, got %v", 635 i, test.result, fallbackAddr) 636 return 637 } 638 } 639 } 640 641 // TestParseRouteHint checks that the routing info is properly parsed. 642 func TestParseRouteHint(t *testing.T) { 643 t.Parallel() 644 645 testSingleHopData := make([]byte, 0, len(testSingleHop)) 646 for _, r := range testSingleHop { 647 base256 := make([]byte, 51) 648 copy(base256[:33], r.NodeID.SerializeCompressed()) 649 binary.BigEndian.PutUint64(base256[33:41], r.ChannelID) 650 binary.BigEndian.PutUint32(base256[41:45], r.FeeBaseMAtoms) 651 binary.BigEndian.PutUint32(base256[45:49], r.FeeProportionalMillionths) 652 binary.BigEndian.PutUint16(base256[49:51], r.CLTVExpiryDelta) 653 testSingleHopData = append(testSingleHopData, base256...) 654 } 655 testSingleHopData, _ = bech32.ConvertBits(testSingleHopData, 8, 5, true) 656 657 testDoubleHopData := make([]byte, 0, len(testDoubleHop)) 658 for _, r := range testDoubleHop { 659 base256 := make([]byte, 51) 660 copy(base256[:33], r.NodeID.SerializeCompressed()) 661 binary.BigEndian.PutUint64(base256[33:41], r.ChannelID) 662 binary.BigEndian.PutUint32(base256[41:45], r.FeeBaseMAtoms) 663 binary.BigEndian.PutUint32(base256[45:49], r.FeeProportionalMillionths) 664 binary.BigEndian.PutUint16(base256[49:51], r.CLTVExpiryDelta) 665 testDoubleHopData = append(testDoubleHopData, base256...) 666 } 667 testDoubleHopData, _ = bech32.ConvertBits(testDoubleHopData, 8, 5, true) 668 669 tests := []struct { 670 data []byte 671 valid bool 672 result []HopHint 673 }{ 674 { 675 data: []byte{0x0, 0x0, 0x0, 0x0}, 676 valid: false, // data too short, not multiple of 51 bytes 677 }, 678 { 679 data: []byte{}, 680 valid: true, 681 result: []HopHint{}, 682 }, 683 { 684 data: testSingleHopData, 685 valid: true, 686 result: testSingleHop, 687 }, 688 { 689 data: append(testSingleHopData, 0x0), 690 valid: false, // data too long, not multiple of 51 bytes 691 }, 692 { 693 data: testDoubleHopData, 694 valid: true, 695 result: testDoubleHop, 696 }, 697 } 698 699 for i, test := range tests { 700 routeHint, err := parseRouteHint(test.data) 701 if (err == nil) != test.valid { 702 t.Errorf("routing info decoding test %d failed: %v", i, err) 703 return 704 } 705 if test.valid { 706 if err := compareRouteHints(test.result, routeHint); err != nil { 707 t.Fatalf("test %d failed decoding routing info: %v", i, err) 708 } 709 } 710 } 711 } 712 713 // TestParseTaggedFields checks that tagged field data is correctly parsed or 714 // errors as expected. 715 func TestParseTaggedFields(t *testing.T) { 716 t.Parallel() 717 718 netParams := chaincfg.RegNetParams() 719 720 tests := []struct { 721 name string 722 data []byte 723 wantErr error 724 }{ 725 { 726 name: "nil data", 727 data: nil, 728 }, 729 { 730 name: "empty data", 731 data: []byte{}, 732 }, 733 { 734 // Type 0xff cannot be encoded in a single 5-bit 735 // element, so it's technically invalid but 736 // parseTaggedFields doesn't error on non-5bpp 737 // compatible codes so we can use a code in tests which 738 // will never become known in the future. 739 name: "valid unknown field", 740 data: []byte{0xff, 0x00, 0x00}, 741 }, 742 { 743 name: "unknown field valid data", 744 data: []byte{0xff, 0x00, 0x01, 0xab}, 745 }, 746 { 747 name: "only type specified", 748 data: []byte{0x0d}, 749 wantErr: ErrBrokenTaggedField, 750 }, 751 { 752 name: "not enough bytes for len", 753 data: []byte{0x0d, 0x00}, 754 wantErr: ErrBrokenTaggedField, 755 }, 756 { 757 name: "no bytes after len", 758 data: []byte{0x0d, 0x00, 0x01}, 759 wantErr: ErrInvalidFieldLength, 760 }, 761 { 762 name: "not enough bytes after len", 763 data: []byte{0x0d, 0x00, 0x02, 0x01}, 764 wantErr: ErrInvalidFieldLength, 765 }, 766 { 767 name: "not enough bytes after len with unknown type", 768 data: []byte{0xff, 0x00, 0x02, 0x01}, 769 wantErr: ErrInvalidFieldLength, 770 }, 771 } 772 for _, tc := range tests { 773 t.Run(tc.name, func(t *testing.T) { 774 var invoice Invoice 775 gotErr := parseTaggedFields(&invoice, tc.data, netParams) 776 if tc.wantErr != gotErr { 777 t.Fatalf("Unexpected error. want=%v got=%v", 778 tc.wantErr, gotErr) 779 } 780 }) 781 } 782 }