From 9a4ad4a05973648d6476798ce1c52e448729597b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 2 Jul 2025 16:34:19 +0000 Subject: [PATCH 1/2] Use `to_ascii_lowercase` when checking for `lnurl` override start When calling `instructions.to_lowercase().rfind("lnurl")` and then using the resulting value as a slice index in `instructions`, we implicitly assume that any unicode lowercasing will not change the length of any characters. That's probably fine in practice, but it seems like a weird assumption to make, so instead we swap it for `to_ascii_lowercase`. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 04dcd07..f515507 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -947,7 +947,7 @@ impl PaymentInstructions { )) }, } - } else if let Some(idx) = instructions.to_lowercase().rfind("lnurl") { + } else if let Some(idx) = instructions.to_ascii_lowercase().rfind("lnurl") { let mut lnurl_str = &instructions[idx..]; // first try to decode as a bech32-encoded lnurl, if that fails, try to drop a // trailing `&` and decode again, this could a http query param From 8460fd37eca15c53a27f6a4ae54860d5feaad7a1 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 2 Jul 2025 16:35:43 +0000 Subject: [PATCH 2/2] Avoid searching for LNURL override in bitcoin: URIs If we have a bitcoin: URI like `bitcoin:thing?lnurl=LNURL...` we really shouldn't use the LNURL override to only resolve the instructions as LNURL. Instead, we fall back to normal URI parsing. --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index f515507..2ea6c7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -918,6 +918,8 @@ impl PaymentInstructions { supports_proof_of_payment_callbacks: bool, ) -> Result { let supports_pops = supports_proof_of_payment_callbacks; + let (uri_proto, _uri_suffix) = split_once(instructions, ':'); + if let Ok(hrn) = HumanReadableName::from_encoded(instructions) { let resolution = hrn_resolver.resolve_hrn(&hrn).await; let resolution = resolution.map_err(ParseError::HrnResolutionError)?; @@ -947,6 +949,10 @@ impl PaymentInstructions { )) }, } + } else if uri_proto.eq_ignore_ascii_case("bitcoin:") { + // If it looks like a BIP 353 URI, jump straight to parsing it and ignore any LNURL + // overrides. + parse_resolved_instructions(instructions, network, supports_pops, None, None) } else if let Some(idx) = instructions.to_ascii_lowercase().rfind("lnurl") { let mut lnurl_str = &instructions[idx..]; // first try to decode as a bech32-encoded lnurl, if that fails, try to drop a