Open t-bast opened 4 months ago
One downside here is it relies on the recipient using a static offer signing pubkey, which by default they almost certainly should not do. A radically different approach would be to use something like bLIP #31 to use separate key material from the offer id to do a mutual handshake without using static keys.
One downside here is it relies on the recipient using a static offer signing pubkey, which by default they almost certainly should not do. A radically different approach would be to use something like bLIP https://github.com/lightning/blips/pull/31 to use separate key material from the offer id to do a mutual handshake without using static keys.
It is very important in my opinion that "adding a contact" is as simple as entering a BIP 353 address or scanning a QR code and clicking a "store contact" button. It is also very important to make it easy to add to any wallet to guarantee compatibility across the ecosystem.
The simplest way I can see to achieve that is to use key material from the Bolt 12 offer directly. This is why I chose to use a key that already needs to be in any valid offer, even though the drawback is that it's a bit of a layering violation (by deriving a key used for paying from a key used to get paid).
It seems to me that alternatives will:
It is very important in my opinion that "adding a contact" is as simple as entering a BIP 353 address or scanning a QR code and clicking a "store contact" button. It is also very important to make it easy to add to any wallet to guarantee compatibility across the ecosystem.
The simplest way I can see to achieve that is to use key material from the Bolt 12 offer directly.
I don't think bLIP 32 breaks either of those?
This is why I chose to use a key that already needs to be in any valid offer, even though the drawback is that it's a bit of a layering violation (by deriving a key used for paying from a key used to get paid).
There's two issues here, not just the one -
(A) IMO the re-use of the offer signing pubkey as the key to use for this authentication is not just a layering violation but breaks potentially important use-cases (eg custodial services can't use this, doubly so if they have more than one node). But that's not to say you can't by default use the offer signing key as the authentication key...
For example, when you pay an offer, if the recipient is willing to be authenticated, the invoice can specify an alternative "authentication key"/BP which is used to identify this recipient. Then, if the server is willing to be authenticated they can send an onion message to the node and share their authentication key.
Because this authentication should only ever be used if both ends have the other one in their contact list, just using a commonly available key is not sufficient.
(B) but much more importantly, the use of the offer signing key as the authentication key completely breaks BOLT 12. You must not use the same offer signing key for all of your offers. A static public offer is one thing but for this to work when I scan an offer you also have to reuse the same signing key on every offer, allowing someone to match a fresh offer against my public BIP 353 one.
Further, I'm very afraid of this design because people are absolutely going to implement it in the naive way - always reuse the payer-key no matter who the recipient is - which is very very much not okay.
(B) but much more importantly, the use of the offer signing key as the authentication key completely breaks BOLT 12. You must not use the same offer signing key for all of your offers. A static public offer is one thing but for this to work when I scan an offer you also have to reuse the same signing key on every offer, allowing someone to match a fresh offer against my public BIP 353 one.
I don't understand, that's not at all what I'm specifying here? When you'd pay one of your trusted contact, you would use the offer signing key of the current offer you're using in your BIP 353 address (which you can rotate with a different signing key). But previous offers or offers you're using for other purposes have no reason to use the same key?
I don't think bLIP 32 breaks either of those?
You mean bLIP 31? It doesn't break those assumptions, but I don't see how you fetch/configure the "list of acceptable public keys they wish to exchange messages with" you're mentioning in there if those aren't included in Bolt 12 offers. Or do you mean that you'd like to use bLIP 31, but use the offer signing keys of your contacts as that "list of acceptable public keys" so that they are directly contained in the Bolt 12 offers or your contacts and in their BIP 353 address?
Because if the keys from that "list of acceptable public keys they wish to exchange messages with" does not come from Bolt 12 offers, then we need a new protocol to exchange those keys and somehow include them in BIP 353, which can quickly get messy and hard to get widespread compatibility...
So overall, I'm not at all against using bLIP 31 instead of what I'm proposing here, but I'd like to see a more detailed design that shows how to use it for contact authentication if you could write it down.
I don't understand, that's not at all what I'm specifying here? When you'd pay one of your trusted contact, you would use the offer signing key of the current offer you're using in your BIP 353 address (which you can rotate with a different signing key). But previous offers or offers you're using for other purposes have no reason to use the same key?
Sure they do? Having a "contact list" where I can pay someone in person and it doesn't show up as the person in my contacts list is weird? Or, inversely, having a "contact list" where I won't show up as the sender if you've paid you in person before but not via BIP 353 is weird?
More generally, I may occasionally change my BIP 353 for various reasons, and I don't want my entire contact feature to break just because I changed it? That seems like a weird user footgun.
You mean bLIP 31? It doesn't break those assumptions, but I don't see how you fetch/configure the "list of acceptable public keys they wish to exchange messages with" you're mentioning in there if those aren't included in Bolt 12 offers. Or do you mean that you'd like to use bLIP 31, but use the offer signing keys of your contacts as that "list of acceptable public keys" so that they are directly contained in the Bolt 12 offers or your contacts and in their BIP 353 address?
Sorry, yes, bLIP 31. Indeed, bLIP 31 doesn't solve the issue here, it just gives us a building block for doing this in a more mutual and private way. We still have to solve key distribution.
We could pick from a few different key distribution methods, depending on what properties we want, for example, if we assume that users know their own BIP 353 (or can figure it out in a reasonable way):
(a) when receiving an invoice_request
with the BIP 353 destination fields filled in, a node derives a public key from the BIP 353 destination fields and some authentication secret key, including that public key in their invoice
,
(b) when receiving an invoice
for any payment destination which is in their contact list, a user stores the authentication public key,
(b) when paying, nodes use their known BIP 353 and their authentication secret to derive their authentication key and attempt to initiate a bLIP 31 session with all stored contact authentication public keys.
This allows payments to be identified even if they scan a QR code after storing a contact, but it does rely on using BIP 353 for the contact list (maybe that's the intended use anyway? Just means you can't store a contact from an offer directly). It also means recipients can't track senders unless they are mutually in each others' contacts, which I think is an important property. It also allows for multiple "identities" for one node, though the assumption that a node knows its BIP 353 may be strong.
More generally, I may occasionally change my BIP 353 for various reasons, and I don't want my entire contact feature to break just because I changed it? That seems like a weird user footgun.
That's a good point. I'm biased because in Phoenix we deterministically derive a "default" offer from the user's seed (which allows seamlessly restoring it to a different device), but I agree that this is only one out of many possible strategies for mobile wallets, and being able to rotate your default offer without breaking your contact lists is important. It could also make sense to give different offers to different people to more easily account for payments from different use-cases.
As you note, this does force us to decouple the "contact key" from offers themselves and thus may require re-thinking the UX for adding contacts a bit. Would it make sense to simply include a new "lnck" (LN contact key) field in BIP 21 URIs that contains our contact pubkey? This way we separate it from the offer itself, but our BIP 353 address can include it in the returned URI, and the QR code for receiving Bolt 12 payments shown by wallets could use this BIP 21 URI as well (instead encoding just the Bolt 12 offer).
Based on the discussions we had in this PR so far, I think it's worth discussing the various options before actually specifying a bLIP. I've started the discussion here, please take a look and tell me what you think: https://delvingbitcoin.org/t/bolt-12-trusted-contacts/1046
@jklein24 @TheBlueMatt I have completely re-written this bLIP based on the whiteboard session we had during the lightning summit with Rusty, this is now ready for review as I'm chasing concept ACK before adding this to Phoenix!
We don't use payer_id
s anymore, don't modify offers, but rather include a new contact_secret
field in our invoice_request
s to contacts and some payment information to allow them to pay us back.
Bolt 12 introduces offers, which are static lightning "addresses". An offer can be stored and reused to pay the same node many times. It then becomes natural to associate Bolt 12 offers to your friends and contacts.
When sending payments to contacts, you may want them to know that the payment came from you. We propose a scheme to optionally include contact information in outgoing payments to allow the recipient to:
This feature provides a better UX for lightning wallets, by making payments between contacts look very similar to fiat payment applications.