Human Readable Bitcoin Payment Instructions

Various Bitcoin and other cryptocurrency applications have developed human-readable names for payment instructions over time, with marketplace adoption signaling strong demand for it from users. Having a standard way to resolve a human-readable name into Bitcoin payment instructions is a very useful primitive. I’ve written up (and implemented) a draft BIP to do this using DNSSEC at bips/bip-XXXX.mediawiki at d46a29ff4b4ac27210bc81474ae18e4802141324 · TheBlueMatt/bips · GitHub which has a number of advantages over the existing LN Address as well as being generic for all Bitcoin payment forms (see the rationale section for more info).

By resolving DNS names to bitcoin: URIs, it is also highly extensible - any Bitcoin payment scheme that defines a bitcoin: URI query parameter doesn’t have to do anything and can support this resolution scheme (as long as they have a static invoice format, so no BOLT11).

2 Likes

Did you consider an approach like having matt@mattcorallo.com first resolve _bitcoin-payment.mattcorrallo.com to an LN node’s address via DNSSEC, and then you query that node via an LN onion message for a bolt12 invoice for matt ? For domains shared between many users (eg x.com or visa.com or bankofamerica.com), that might provide substantially better privacy, and might also be easier to deploy since you don’t have to export your list of LN users into your DNS db?

The BIP doesn’t specify that, but that’s supported for the LN usecase! Because the various parts of the overall flow are relevant to different groups the total spec is somewhat confusingly split across three places, but most of the lightning-specific stuff is at Define blip-0032, DNSSEC proof querying over onion messages by TheBlueMatt · Pull Request #32 · lightning/blips · GitHub and indeed includes a flow like that (but we make the payer only do a single DNS lookup by requiring such deployments use a wildcard to return the “ask node X for the offer” result).

That doesn’t result in the privacy advantage that you note, but I also wanted to keep this generic for all of Bitcoin (including on-chain, fedimint, cashu, silent payments, whatever) so kind of want to avoid explicitly baking in a lightning onion message dependency. Of course that means its annoying to add on-chain addresses for large custodians, but maybe after lightning they can invest in figuring out how to run bind and create a zonefile…turns out even with a million or ten records it works just fine :slight_smile:

The current bLIP spec there may change in that currently it adds two round trips (one to ask for a standard offer, then one to turn that offer into an invoice_request), but I may want to change that to an offer where you include the user/domain in the invoice_request. Needs some discussion with lightning folks to figure that out I think.

That was exactly one of the flows I proposed in Future of lightning address · GitHub

I think it is useful and simple indeed, especially for lightning providers who want minimal DNS operational burden.

EDIT: this is covered in the bLIP that Matt created: Define blip-0032, DNSSEC proof querying over onion messages by TheBlueMatt · Pull Request #32 · lightning/blips · GitHub

This is the omlookup path: a domain that has many users would create a single DNS record *.user._bitcoin-payment.domain. containing a blinded path to themselves (which may actually be a 0-hop blinded path directly exposing their node_id). Clients then use that blinded path to request an offer for a specific user via an onion message.

1 Like

How do you want to handle testnet and signet(s)? Perhaps ._bitcoin-testnet-payment and ._bitcoin-signet-payment?

I have this itchy feeling of wanting to avoid the word “bitcoin” in both the subdomain and the record, to make both filtering and creating a map of all domains “involving” bitcoin require at least a few more seconds of effort.

Why use BIP21 style URI’s inside the text record? And why have a single big record for all payment types? For example instead of matt.user._bitcoin-payment.mattcorallo.com. 3600 IN TXT "bitcoin:?b12=lno1q... you could have matt.user.b12._bitcoin-payment.mattcorallo.com. 3600 IN TXT "lno1q....

I guess one argument could be that using a single big record makes it hide what the payer is looking for. But you can just query all of them. Or is a single query easier to implement?

One record per address type potentially avoids having to deal with the 255 character limit for TXT records.

1 Like

Sorry, I don’t generally check delving so usually miss replies, feel free to reply on the BIP PR.

I have not given it any thought, honestly.

Maybe? The protocol will always be fairly identifiable, including addresses which are going to be fairly easy to google and figure out, I think.

Because its already a well-defined format for communicating multiple payment instructions in a way that most wallets support. Why reinvent the wheel?

Because then a sender has to add extra logic to enumerate the set of supported formats and send multiple queries. Most senders already have logic to handle dealing with a single BIP 21 with multiple payment instructions, so we should just capitalize on that by giving them a simple API to fetch a BIP 21 to feed into their existing logic.

No such limit exists.

@MattCorallo Hi Matt, I am trying to query your dns example (matt.user._bitcoin-payment.mattcorallo.com) and there are two strings in the response:

“bitcoin:?lno=lno1qsgqmqvgm96frzdg8m0gc6nzeqffvzsqzrxqy32afmr3jn9ggkwg3egfwch2hy0l6jut6vfd8vpsc3h89l6u3dm4q2d6nuamav3w27xvdmv3lpgklhg7l5teypqz9l53hj7zvuaenh34xqsz2sa967yzqkylfu9xtcd5ymcmfp32h083e805y7jfd236w9afhavqqvl8uyma7x77yun4ehe9pnhu2gekjguexmxpqjcr2j” “822xr7q34p078gzslf9wpwz5y57alxu99s0z2ql0kfqvwhzycqq45ehh58xnfpuek80hw6spvwrvttjrrq9pphh0dpydh06qqspp5uq4gpyt6n9mwexde44qv7lstzzq60nr40ff38u27un6y53aypmx0p4qruk2tf9mjwqlhxak4znvna5y”

What is the second string starting with "822xr7q3…?

Oh I see, they are just split into two parts. The first part has exactly 255 characters, so there must be some limit and the result is split in two by something along the way…

Indeed, that’s a DNS-level quirk on how it encodes long strings on the wire. Your DNS software really shouldn’t be displaying that quirk to you but indeed you can always just combine the strings.