From 2c3fba5f9062d104ef2e50b599df8f7ccd6b7451 Mon Sep 17 00:00:00 2001 From: alltheseas Date: Mon, 2 Feb 2026 14:54:16 -0600 Subject: [PATCH] Add test cases for invoices with longer HRP prefixes Tests for gh-3456 MAX_PREFIX fix: - lnbc100u (10,000 sats) - 7 char HRP baseline - lnbc130130n (13,013 sats) - 11 char HRP, requires MAX_PREFIX > 10 Root cause: Invoices with "odd" sat amounts use nano-BTC encoding which produces longer HRPs that exceeded old MAX_PREFIX limit. Related: #3456 Signed-off-by: alltheseas Co-Authored-By: Claude Opus 4.5 --- damusTests/InvoiceTests.swift | 70 +++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/damusTests/InvoiceTests.swift b/damusTests/InvoiceTests.swift index a486f1a6..a083199e 100644 --- a/damusTests/InvoiceTests.swift +++ b/damusTests/InvoiceTests.swift @@ -197,6 +197,42 @@ final class InvoiceTests: XCTestCase { }) } + // MARK: - Invoice parsing tests for issue #3456 (MAX_PREFIX fix) + // These test invoices with longer HRP prefixes that require MAX_PREFIX > 10 + + /// Test invoice from gh-3456: 10,000 sats (100 micro-BTC) + /// HRP: lnbc100u (7 chars) - should work with old MAX_PREFIX + func testParseInvoice_gh3456_100u() throws { + let invstr = "lnbc100u1p55gjvwpp5fgrv9nq4y5turswulpym74rm2q7jnwvqzqr90y4m7xrjyu8025vshp5jxmcdmqe5kp7kcmsngxxejshcqe5pglk5w9rjgk5ltqc3ada5wlscqzzsxqyz5vqsp5f358u7jquhy20cpxq9r6kspcsd46ksgns0zrx028x2csat2cqzrs9qxpqysgqzwsxjn7wmwc2n9yl3h3pu4ph9mma2w7q6f7h8xxhql0d9nxu90087jru6e30t79l6d70rcphsa65kzw6l5kzz2njr777e8e2m80l4ygqjw8mm3" + + guard let invoice = decode_bolt11(invstr) else { + XCTFail("Failed to decode invoice - MAX_PREFIX may be too small") + return + } + + // 100 micro-BTC = 10,000 sats = 10,000,000 millisats + XCTAssertEqual(invoice.amount, .specific(10_000_000)) + } + + /// Test invoice from gh-3456: 13,013 sats (130130 nano-BTC) + /// HRP: lnbc130130n (11 chars) - requires MAX_PREFIX > 10 + func testParseInvoice_gh3456_130130n() throws { + let invstr = "lnbc130130n1p5h77tgpp5edwq8elur9e66vhd7wf0s75p20hvppna49dsrchel6xkq69tm4aqdq4w3jhxapqvehhygrzda68xcqzzsxqyz5vqsp56cdkune763pdxqy0jk44hhmv784jzf9m8mk8wspyngq2etehadps9qxpqysgquhrggc6a654gyelax0tcqd9gc9hyajt39t8wksgv0n0jy7q95l4htvgqsydz4fvdlgwa72xqddynsy6k3zq0tmhnxva0dfkhcxduh6gpyl0rgn" + + guard let invoice = decode_bolt11(invstr) else { + XCTFail("Failed to decode invoice - MAX_PREFIX may be too small for 11-char HRP") + return + } + + // 130130 nano-BTC = 13,013 sats = 13,013,000 millisats + XCTAssertEqual(invoice.amount, .specific(13_013_000)) + } + + // Note: Tests for lnbc23450n (2345 sats) and lnbc19710n (1971 sats) would require + // real invoice strings. The testParseInvoice_gh3456_130130n test above covers + // the 11-char HRP case which exercises the MAX_PREFIX fix more thoroughly than + // 10-char HRPs would. If specific test invoices become available, add tests here. + /* // gh-3144: It was decided on a standup meeting that we do not need invoices to render, few people use this feature. func testParseInvoice() throws { @@ -229,5 +265,39 @@ final class InvoiceTests: XCTestCase { }) } */ + + /// Tests decoding a BOLT11 invoice using the decode_bolt11 function + func testDecodeBolt11Invoice() throws { + let invstr = "lnbc19710n1p5czpejsp5rmhun0ghrzv9ce0whqn3q2ll8y5kql8mgad90kxlq2zuq784wwuqpp53ks03npkdadza0c8r0qrsgypfx7wsrtr90pqxsgzpcw8yf3358uqhp5vc0usy5w5clt4xwdu6txzgyuxcnyuyd2r6f8ncjacvzrzxtvg50sxq9z0rgqcqpnrzjqt0mfswatysklf4z358sztscs5t0vdghmd5vfe9c9sa0gy6r5pdugrjqtsqqdtcqqyqqqqqqqqqqdpsq8s9qxpqysgq59ja4yg7ayty0cu8etja0unme76d4lm6crzsw5g9uj3h5748xcypwf4ahgyut7vegpz4a6jvq7lj5p8zqutaznjrxgcgnuwejm8cwtsqgzcx97" + + // Try decoding with lowercase (standard format) + var invoice = decode_bolt11(invstr) + + // If lowercase fails, try uppercase + if invoice == nil { + invoice = decode_bolt11(invstr.uppercased()) + } + + guard let decodedInvoice = invoice else { + XCTFail("Failed to decode BOLT11 invoice with both lowercase and uppercase") + return + } + + // Verify that the invoice was successfully decoded + XCTAssertNotNil(decodedInvoice) + + // Verify the invoice has a specific amount (19710 nanosatoshis in the invoice string) + // Note: The amount is encoded as 1971 * 10 = 19710 nanosatoshis = 1,971,000 millisatoshis + switch decodedInvoice.amount { + case .specific(let amount): + XCTAssertGreaterThan(amount, 0, "Invoice amount should be greater than 0") + case .any: + XCTFail("Expected specific amount, got .any") + } + + // Verify basic invoice properties exist + XCTAssertGreaterThan(decodedInvoice.created_at, 0) + XCTAssertGreaterThan(decodedInvoice.expiry, 0) + } }