-
Notifications
You must be signed in to change notification settings - Fork 492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Include BIP 353 name info in invoice_request
s
#1180
base: master
Are you sure you want to change the base?
Conversation
Signed-off-by: Rusty Russell <[email protected]>
It's far easier to validate these on parsing than to hand-validate them elsewhere. I didn't turn `alias` or `error` into this, though they're similar (`alias` can have a nul terminator). Signed-off-by: Rusty Russell <[email protected]>
Signed-off-by: Rusty Russell <[email protected]>
A BOLT11 "invoice" has proven too low-level for human use in many scenarios. Efforts like lnurl have covered the gap, but integrating some of such higher layers into the lightning protocol itself has many advantages. This draft defines three new things: 1. A new invoice format. I know, this is painful, but it maps almost 1:1 to the current format (though signatures are very different), is easier to implement, and easier to send via the lightning network itself. 2. Formats for an "offer", which for all intents and purposes serves as the new, persistent invoice for users. 3. Format for an "invoice_request": this is a message sent via the lightning network itself to receive the real invoice, or can be used directly in a send-money scenario (e.g. ATM). The offer (for accepting payments) or invoice_request (for sending payments) are usually presented via a QR code or similar, the replies are sent using onion messages. Each copies fields from the prior so it stands alone, to allow statelessness. Features which have been deliberately omitted for the initial version: - Recurrence. - Invoice replacement ("don't accept that old payment!") - Payer proof for refunds. I need to thank everyone who gave detailed feedback, particularly: 1. Thomas H of ACINQ (https://github.com/thomash-acinq) 2. Joost Jager (https://github.com/joostjager) 3. Aditya Sharma (https://github.com/adi2011) 4. Rene Pickhardt (https://github.com/renepickhardt) 5. Bastien Teinturier (https://github.com/t-bast) 6. Valentine Wallace of LDK (https://github.com/valentinewallace) 7. Matt Corallo of LDK (https://github.com/BlueMatt) 8. Jeffrey Czyz of Square Crypto (https://github.com/jkczyz) Also @bjarnemagnussen, @ellemouton, @animatedbarber, @617a7a, @instagibbs, and @eupn. Signed-off-by: Rusty Russell <[email protected]>
Signed-off-by: Rusty Russell <[email protected]>
Regenerated bolt12/signature-test.json; for some reason jq reordered a few fields, but it now shows the complete signature.
bolt12/format-string-test.json is now a valid offer.
Signed-off-by: Rusty Russell <[email protected]>
Offers may contain blinded paths to allow for greater recipient privacy. However, they come at a cost of increased QR code size as each hop requires a 33-byte `point` for the `next_node_id`. Allow using `short_channel_id` instead, which only requires 8 bytes. Still allow for use of `next_node_id` for cases where the blinded path may not involve channel counterparties or for long-lived offers, which may outlive the given channels.
Offers may contain blinded paths to allow for greater recipient privacy. However, they come at a cost of increased QR code size as the introduction node requires a 33-byte `point`. Define a new `sciddir_or_pubkey` fundamental type such that either a point or a reference to one in a `channel_announcement` can be used. This is backwards compatible with `point`. Use this new type for the `blinded_path` subtype's `first_node_id`.
Add example of scid first-id for blinded path (thanks jkczyz!)
Remove leftover reference to direct invoices (thanks jkczyz!)
describe the offer_amount/currency/invreq_amount/invoice_amount purpose
make offer_node_id optional, if they specify offer_paths. 1. We now tell them explicitly where to send the onion message. 2. We use this as shorthand later when they're supposed to check the reply. 3. Raw invoice_requests cannot set `offer_paths`, so we add `invreq_paths` for this. Thanks to thomash-acinq and jkczyz!
Make offer_description optional if there's no amount; this is the common "tip" case. Note that this implies a minimal offer is simply a bech32 encoding of the offer_node_id field, or "lno1" + bech32(0x2242<node_id>). This might become normalized as the "default offer" to which you can throw sats to a node directly?
Since we say you should forward via short_channel_id: 1. Allow setting it! 2. Make it clear that it must be a public scid or an alias (no probing!). 3. Make it clear what to do if both are set!
Recent spec meeting brought up various things: 1. Resending the same invoice: we key of invreq_payer_id, but ACINQ is considering reuse for some cases. We should key off invreq_metadata which is required, actually unique and is supposed to be unguessable. 2. Move this caching description from the invoice section to the "invoice_request reader" section: I couldn't find it! 3. Renamed offer_node_id to offer_issuer_id (Matt points out, it may be a node_id, but it's basically the key used to sign the invoice) 4. The spec says you must send a message to offer_node_id if it's set: that's backwards, you must use blinded paths if offered, and only fall back to this as a node id if there are none. Signed-off-by: Rusty Russell <[email protected]>
Make the ranges big (1BN), so people can self-assign, but still ensure they don't overlap. Signed-off-by: Rusty Russell <[email protected]>
BIP 353 defines a method for resolving Human Readable Names (in the form ₿`name`@`domain`) into bitcoin: URIs. In order to use them with BOLT 12 with a wildcard DNS entry which resolves to a single BOLT 12 offer for all `name`s in a domain, we need a way to disambiguate the `name` being paid in an `invoice_request` which we provide here by simply copying the HRN into the `invoice_request`.
Thanks for sharing this. I'm not sure how the node receiving an Let's assume that Bob is the domain owner and Alice the end user ( What does Bob do with this Does Bob instead reply to Carol with an offer from Alice and Carol then follows up with another |
Obviously this isn't an issue for custodial services, so I assume you're asking about non-custodial. In this case Bob would have to issue an invoice using a For async payments its a bit more complicated, but Alice can simply register her payment parameters with Bob rather than a full static invoice, which Bob can turn into his own static async invoice for Alice. Its a chunk of additional protocol work to implement, so IMO people should just put a few 100k DNS entries in a zone (which is super trivial, just dont use some hosted DNS garbage that charges you $$$$$ to store 5MiB of data), but someone could build this if they want. I think this will likely be used much more for custodial services where its trivial.
Why? You could reasonably argue that many wallets won't implement BIP 353 sending and thus it should be a bLIP, but it seems like all of the major lightning implementations will need to support this field (as at least some of their users will implement BIP 353 sending), which implies it should be here. |
That means Alice will create an invoice for an offer created by Bob, not her own offer...I'm not sure how messy it will be to implement: since Alice doesn't have the private key for Bob's offer, she can't sign that invoice. So that's probably the wrong approach, and you're instead proposing that Bob is creating and signing the invoice, but the blinded path leads to Alice? So when receiving the payment, Alice just needs to be ok with the fact that the offer wasn't generated by her. The issue with that scheme is that it's not TOFU: for every payment, Bob has an opportunity to cheat and generate invoices that are actually for him. Wouldn't it be a better idea to use the DNS resolution to (somehow) obtain an offer from Alice? This would be TOFU, but then the offer can be verified IRL, and afterwards the payer is guaranteed that they'll keep paying Alice whenever they reuse this offer. This way payers store the offer they received, and don't need to make DNS requests the next time they want to pay Alice.
That is indeed my preferred option as well, this is a simpler flow!
I wasn't saying that this PR shouldn't be in the BOLT, but rather that the additional protocol we're mentioning should be a bLIP. I agree that this BIP 353 field in |
Right, I think we're on the same page. Having Alice create the offer is probably a non-starter. Luckily if Alice builds the blinded path she doesn't know that she didn't create the offer. She just sees the blinded path she generated in an HTLC :)
Yea, I agree, you could have some scheme where you fetch an offer instead (which is how the original bLIP was specified), but I wanted to avoid the extra round-trip during normal payment flows. Sadly, BIP 353 is somewhat limited in TOFU-ness as you do need to revalidate the DNS records occasionally (often on the order of a day, depending on DNS settings, both to let people rotate addresses if they want but also to make sure the domain hasn't expired). A wallet can (and maybe should) of course warn the sender if the recipient info has changed, but its never perfect TOFU.
If you're able to "verify IRL" you shouldn't be using BIP 353 :).
Ah, okay! I have no intention of specifying that protocol. If people want to offer BIP 353 names for non-custodial wallets they'll have to either build it or just deal with running BIND/KNOT/etc themselves 🤷♂️. |
Thanks, that's clear enough! I agree on all points 👍 |
Based on #798,