-
Notifications
You must be signed in to change notification settings - Fork 55
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
[Lip 10] Libra ID Spec #82
Conversation
cec4df8
to
acde48e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly just small nits. Will come back and review the meat of the protocol
27638f2
to
0a0e359
Compare
lips/lip-10.md
Outdated
``` | ||
|
||
* Receiver Libra ID domain should belong to the Receiver VASP. Otherwise, Receiver VASP should return the `400` error code. | ||
* Sender Libra ID should have a Libra ID domain that belongs to Sender VASP. If receiver VASP makes a decision on how much information to share, based on the sender Libra ID, it should enforce this property and return 400 error code, if VASP tries to impersonate a user from Libra ID domain that it does not own. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Sender Libra ID should have a Libra ID domain that belongs to Sender VASP. If receiver VASP makes a decision on how much information to share, based on the sender Libra ID, it should enforce this property and return 400 error code, if VASP tries to impersonate a user from Libra ID domain that it does not own. | |
* Sender Libra ID must have a Libra ID domain that belongs to Sender VASP. If this is not the case, the Receiver VASP should return the `400` error code | |
* Receiver VASP may optionally choose how much information to share based on the sender Libra ID. If Receiver VASP decides to not share data, it should return `400` error code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I edited it to split it out for how I believe you intended it to read, but I actually think that we shouldn't return the same error code for "i don't want to share information" that we do for "this person doesn't exist". In one of those cases, you can still choose to send money to them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried to rephrase it. I think if VASP don't want to share info, but user exists, they can just return empty user object(e.g. not sharing any fields). Otherwise return error
"amount": "<amount>", | ||
"currency": "<currency>" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think these are needed? For example, what if a VASP pre-fetches this info before their user has filled out the payment amounts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For prefetching, VASP should use info endpoint, this is payment endpoint, so I think currency / amount is needed
```json | ||
{ | ||
"receiver_address": "<Receiver VASP on-chain account address>", | ||
"reference_id": "<Payment_Reference_ID>", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, as I look at it more, I do wonder if we actually need two endpoints. It feels like this is really just one endpoint that has a flag for if you want a reference ID or not. Otherwise, they are effectively the same thing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me two separate endpoints makes more sense. Yes they share some fields (like there is sender/receiver), but there are also many fields that are not shared (info endpoint don't have amounts/coin in request, and does not return reference/account address)
They also have different semantics - info endpoint is 'read' endpoint, while 'pay' is a 'write' endpoint as it needs to create an entry in the database
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an open write API, this is dangerous. Folks will mess this up and have vulnerabilities.
**Response:** | ||
```json | ||
{ | ||
"receiver_address": "<Receiver VASP on-chain account address>", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to specify for this and all fields more info about them. Is this bech32?
cba91f8
to
79eb818
Compare
cc @bmaurer |
9564ed4
to
d5e28af
Compare
lips/lip-10.md
Outdated
|
||
`https://<hostname>:<port>/pay.<protocol_version>/<endpoint>` | ||
|
||
* All Libra ID endpoints use the same `base_url` and same `compliance_public_key` for authentication as other off-chain APIs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might make sense to break out standards for APIs into its own LIP. This is lacking a bit of specificity.
|
||
If a user does not exist, VASP can choose to return an HTTP error, or the empty User Object, depending on it’s privacy choices. | ||
|
||
## Profile Picture URI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May make sense to discuss privacy implications (e.g., if you just hot link to another VASP that VASP can track how often the profile pic is accessed). Generally at least for FB we have it as a best practice that you always proxy this type of access.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bmaurer can you explain the hot links and how FB proxies it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is an implementation detail that someone can easily screw up as long as the URL returns an image we are good to go.
lips/lip-10.md
Outdated
* VASPs can have multiple libra-id-domains associated, though it is not expected to be common | ||
|
||
## Multiple accounts per user | ||
VASPs should not assume that Libra ID uniquely identifies the user within the system. Users that have accounts with different VASPs would have different Libra ID within each VASP. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MUST NOT? (this happens a lot through this document... not going to audit each instance. I think it's worth doing a pass to audit the use of MUST/SHOULD/MAY)
At a higher level: it feels like we have a lot of overlap with the off-chain protocol / subaddresses. For example:
I worry that we start to get complexity from different permutations of these APIs. Is there anything we can do to be more uniform here? Both subaddresses and LibraID are a way to reference a user within a VASP. Why entirely different flows for the two methods? It's OK if we have regrets about APIs we designed for subaddresses and want to go a different direction. But in that case, can we come up with a new API that is unifying vs one that only addresses a subset of the use cases. |
lips/lip-10.md
Outdated
* For peer-2-peer payments, Libra ID allows a user to provide a human-readable ‘address’ to the sender. Basically, instead of sending a [lip-5 address](https://github.com/libra/lip/blob/master/lips/lip-5.md) (that needs to be refreshed for each payment, ideally), the receiver can just share their Libra ID once. In this case Libra ID plays the role of an email address for payments. Benefits for this use case: | ||
* Libra ID is a user-friendly identifier, unlike lip-5 addresses | ||
* The Libra ID resolution process can facilitate the exchange of rich information(e.g. nicknames, profile picture, etc.) about both the sender and receiver of the payment | ||
* While it is encouraged for VASPs to treat subaddresses as single-use currently, Libra ID allows for this anonymity on-chain to be handled in a much simpler manner. LibraID can be shared once with wallet apps transparently resolving the LibraID into a new identifier for each transaction (and thereby preventing linkability which could happen if subaddresses were re-used). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- It's not clear from this why reusing an identifier generated from a LibraID is less likely/less problematic than reusing a subaddress
- I think this could be explained more clearly without the references to subaddresses. Perhaps you could have a separate bullet that says "A Libra ID is a persistent user identifier. By contrast, a subaddress is an ephemeral user identifier that should only be used in a single transaction"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed wording there, let me know what you think
lips/lip-10.md
Outdated
* For the merchant use case, Libra ID allows users to self-identify to merchants. In this case, Libra ID plays the role of credit card number or also can be seen as a variant of OpenID-type protocol. | ||
|
||
## Examples in other blockchains | ||
Ripple proposes PayID. PayID has some similarity to the current proposal, but is not entirely identical. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Link to PayID doc or proposal?
- I think you should either do a more detailed compare/contrast with PayID or kill this section. As-is, this section might make it seem like we're vaguely aware of PayID but haven't really looked into it enough to motivate the need for or a new standard or crisply explain the key similarities/differences. For example: does PayID also support intra-chain payments (and if so, could we use it if we thought we might eventually want X-chain payments or didn't want to develop a new standard)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some thought I removed PayID section from the doc. We spent some time researching it, however perhaps it is safer to just not discuss this as part of the LIP
lips/lip-10.md
Outdated
* Maximum length: 63 characters | ||
* libra-id-domains are published on the chain | ||
* Each libra-id-domain is uniquely associated with single VASP | ||
* VASPs can have multiple libra-id-domains associated, though it is not expected to be common |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some motivation for this might be helpful (and could also justify the "not expected to be common" caveat)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is actually more details and motivation below when discussing on-chain format and restrictions there. I am going to remove this item and keep this section focused on high level overview of ID structure, to avoid duplication and confusion
lips/lip-10.md
Outdated
* Each libra-id-domain is uniquely associated with single VASP | ||
* VASPs can have multiple libra-id-domains associated, though it is not expected to be common | ||
|
||
## Multiple accounts per user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section feels more like an extension of "motivation" or a "use-cases" section than a section describing multiple accounts per user. For example, the temporary/situational ID idea is cool and not necessarily related to multiple accounts/user (e.g., publicly shared Libra ID for donations).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So main motivation to this question is because some people might ask 'is libra id identifying a user, or specific account of the user". So this section is trying to clarify that. Do you think i need to add some clarification for it?
lips/lip-10.md
Outdated
* The `LibraIdDomains` contains a list of `LibraIdDomain` structs that can be associated with a VASP. As such, it is possible to register more than one Libra ID Domain for a given VASP. We are providing this opportunity to support possible situations when two VASPs merge into one, or when a company wants to provide multiple wallet apps, while having only a single VASP parent account on the chain. | ||
* Only special Treasury Compliance account(address `0xB1E55D`) can manipulate LibraIdDomains resource: | ||
* Only TC account can create and publish LibraIdDomains resource | ||
* Only TC account can add, remove or update an LibraIdDomain within LibraIdDomains resource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once one VASP removes a LibraIdDomain, can another VASP use the same one? And if so, is a VASP allowed to sell a LibraIdDomain to another VASP?
Answering the the first question with "no" might help to avoid squatting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think since LA is allocating those 'domains' to the VASPs, there is no really problem with squatting, similarly all the questions about what happens to removed domain, etc, can be resolved by LA when specific case is reviewed. Do you think we need to include this details here?
lips/lip-10.md
Outdated
* Libra ID is a user-friendly identifier, unlike lip-5 addresses | ||
* The Libra ID resolution process can facilitate the exchange of rich information(e.g. nicknames, profile picture, etc.) about both the sender and receiver of the payment | ||
* While it is encouraged for VASPs to treat subaddresses as single-use currently, Libra ID allows for this anonymity on-chain to be handled in a much simpler manner. LibraID can be shared once with wallet apps transparently resolving the LibraID into a new identifier for each transaction (and thereby preventing linkability which could happen if subaddresses were re-used). | ||
* For the merchant use case, Libra ID allows users to self-identify to merchants. In this case, Libra ID plays the role of credit card number or also can be seen as a variant of OpenID-type protocol. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The analogy with credit card number seems a bit odd because my credit card number is private info, but a LibraID sounds more like a public email address
- Does the owner of a LibraID authenticate themselves to the merchant somehow (and if not, are there potentially bad consequences)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- There is some analogy in a sense that you enter your cc number in order to get 'routed' to the bank
- I wanted to cover it in merchant flow doc, but tldr is - yes, you need login into wallet app / web site to use your libra ID
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you enter your cc number, you don't get routed to the bank (issuer). It is used as an authorizing token of the payment. The first several digits are indeed the routing path, but we may use only the Libra ID domain for that purpose.
lips/lip-10.md
Outdated
In order to support peer-2-peer payments, VASPs need to implement two Libra ID endpoints: | ||
|
||
|
||
* **Info endpoint** for querying optional information about the receiver. VASPs can provide this endpoint to improve UX and security of payment, but they are not obligated to - VASPs may choose not to share any information about the user via this endpoint, including whether the user exists or not |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will they make the decision not to share information?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added example inline
lips/lip-10.md
Outdated
|
||
`https://<hostname>:<port>/pay.<protocol_version>/<endpoint>` | ||
|
||
* All Libra ID endpoints use the same `base_url` and same `compliance_public_key` for authentication as other off-chain APIs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does using compliance_public_key
make sense here? We need it for for TR because the signature will be checked on-chain, but LibraID seems like it could use a more conventional authentication mechanism. Not my area of expertise at all, but maybe someone who knows a lot about web authentication could weigh in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think currently compliance_public_key
is simply overloaded - it is used to both signing KYC metadata, and for signing the requests. However, this is how things are set in lip-1(main offchain lip), and this document just re-states it for clarity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the first beginning, we wanted to use different keys for TLS/KYC and so on. Later we decided a single key for less maintenance cost. From this point of view, another "conventional authentication mechanism" seems to make things more complicated.
cc @kchalkias
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow, that compliance key is an ed25519 key for signing metadata that appears on chain. I don't know why we need a compliance key in this place that is strictly used for dual attestation. This is too overloaded and has no meaning in the rest of this document. Also if we add an IP for each address, what are we doing? Can we clarify the purpose of a wallet uri?
ead73c5
to
ec9ae32
Compare
beb0a41
to
d017282
Compare
lips/lip-10.md
Outdated
* Libra ID is a user-friendly identifier, unlike lip-5 addresses | ||
* The Libra ID resolution process can facilitate the exchange of rich information(e.g. nicknames, profile picture, etc.) about both the sender and receiver of the payment | ||
* While it is encouraged for VASPs to treat subaddresses as single-use currently, Libra ID allows for this anonymity on-chain to be handled in a much simpler manner. LibraID can be shared once with wallet apps transparently resolving the LibraID into a new identifier for each transaction (and thereby preventing linkability which could happen if subaddresses were re-used). | ||
* For the merchant use case, Libra ID allows users to self-identify to merchants. In this case, Libra ID plays the role of credit card number or also can be seen as a variant of OpenID-type protocol. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you enter your cc number, you don't get routed to the bank (issuer). It is used as an authorizing token of the payment. The first several digits are indeed the routing path, but we may use only the Libra ID domain for that purpose.
lips/lip-10.md
Outdated
|
||
* All Libra ID endpoints are nested under `pay.<version>` URI path: | ||
|
||
`https://<hostname>:<port>/pay.<protocol_version>/<endpoint>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest to follow the exist scheme of URI from the off-chain protocol (https://<hostname>:<port>/<protocol_version>/<LocalVASPAddress>/<RemoteVASPAddress>/<endpoint>
) -
A. It makes the system more widely consistent
B. How should the receiving VASP authenticate/verify the requested content? It must get the other VASP info to get its public key, or is there something else that I'm missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I agree with this, I will change URL to make it more uniform
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: we are actually discussing whether to remove the "LocalVASPAddress", "RemoteVASPAddress" from the URL format in lip-1
B. How should the receiving VASP authenticate/verify the requested content? It must get the other VASP info to get its public key, or is there something else that I'm missing?
In LIP-1 , it says
All transmitted requests/responses are signed by the sending party using the JWS Signature standard (with the Ed25519 / EdDSA ciphersuite, and compact encoding). The party's on-chain compliance key shall be used to sign these messages. This ensures all information and meta-data about payments is authenticated and cannot be repudiated.
cc @danprinz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My question was regarding where in the request can one find the sending VASP address. It either be written in the request body, or as part of the path (like in LIP-1).
If the receiver has the address at hand it should be easy to verify the request content.
If LIP-1 is going to be changed to any other format (I would suggest a more RESTful one) we should keep this one as close and consistent as we can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with this comment. Let's match LIP-1 and instead of command add a new action (query? get_libra_id? etc.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's update here
lips/lip-10.md
Outdated
## Info endpoint | ||
|
||
``` | ||
POST https://<hostname>:<port>/pay.<protocol_version>/info |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that using OpenAPI (3) spec would be a more convenient way to describe the API and also could be used in a wide range of web frameworks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks different than format in LIP-1's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right. I just wondered if OpenAPI spec would be more readable and common to use. Maybe we should adapt it in LIP-1 as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update to LIP1 but why are we repeating this information?
lips/lip-10.md
Outdated
* Receiver Libra ID domain must belong to the Receiver VASP. Otherwise, Receiver VASP must return the `400` error code. | ||
* Sender Libra ID must have a Libra ID domain that belongs to Sender VASP. If this is not the case, the Receiver VASP should return the `400` error code | ||
* Receiver VASP may optionally choose how much information to share based on the sender Libra ID. If Receiver VASP decides to not share data, it should return an empty `User Object` with only `libra_id` field set | ||
* If user is not found, the VASP should return error code `400` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not sticking to HTTP standards and reply with 404?
400 should be a signal of a bad request, and I would argue that if the target user is not found doesn't mean an error or a bad request
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above and below, we say if VASP can choose not to share whether the Libra ID exists or not. Do we want to have a very clear answer format to remove the ambiguity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes and let's use 404.
lips/lip-10.md
Outdated
## Pay endpoint | ||
|
||
``` | ||
POST https://<hostname>:<port>/pay.<protocol_version>/pay |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a "proper" off-chain command and should be treated as such. We should aim to have the reasoning behind the URI scheme. (see above)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you talking about adding <LocalVASPAddress>/<RemoteVASPAddress>
part (agree with that) or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
both the <LocalVASPAddress>/<RemoteVASPAddress>
part and the pay
resource name.
In general, LIP-1 (and LIP-8 as its extension) uses a single resource URI (/command
) as the main entry point to all off-chain communication.
We should either keep it as is (and adapt /command
notation here) or change it across all LIPs to be a logical representation of resources and actions.
I also think that we should stick to the main principles of LIP-1 CommandRequestObject and CommandResponseObject as it makes things easier for developers to have a one consistent protocol scheme/format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We specifically chose not to use command request/response style here to keep it simpler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gdanezis ^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd agree with @danprinz here. If we are going to treat this as an action, then it should be using the same command structure as is used in LIP-1 and LIP-8. That keeps us consistent and also means we don't need to re-state so much and make it seems sort of like LIP-1 but sort of its own thing
* Regex: `^[a-zA-Z0-9][a-zA-Z0-9-]+$` | ||
* Maximum length: 63 characters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why regex and maximum length are different from user-id's ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I glad you asked :)
Wanted to make sure that total length is power of 2(128).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for what purpose? what are we gaining by having limits? except maybe this should be limited due to being on chain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think usually you want to have length limits on any data structures. For example, some VASPs are probably going to store Libra IDs in SQL database, and they might want to use some column type that have length limit
lips/lip-10.md
Outdated
* Each libra-id-domain is uniquely associated with single VASP | ||
|
||
## Multiple accounts per user | ||
VASPs must not assume that Libra ID uniquely identifies the user within the system. Users that have accounts with different VASPs would have different Libra ID within each VASP. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we mean "user-id" here instead of "Libra ID"?
lips/lip-10.md
Outdated
|
||
struct LibraIdDomain { | ||
domain: vector<u8>, // Utf-8 encoding | ||
wallet_uri: vector<u8>, // ASCII encoding (use url-escape for non-ASCII characters) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how is wallet_uri gonna be used, if it has more functionalities other than display?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is related for merchant, since right now we don't have LIP for merchant flow, I am just going to remove it
lips/lip-10.md
Outdated
|
||
* All Libra ID endpoints are nested under `pay.<version>` URI path: | ||
|
||
`https://<hostname>:<port>/pay.<protocol_version>/<endpoint>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: we are actually discussing whether to remove the "LocalVASPAddress", "RemoteVASPAddress" from the URL format in lip-1
B. How should the receiving VASP authenticate/verify the requested content? It must get the other VASP info to get its public key, or is there something else that I'm missing?
In LIP-1 , it says
All transmitted requests/responses are signed by the sending party using the JWS Signature standard (with the Ed25519 / EdDSA ciphersuite, and compact encoding). The party's on-chain compliance key shall be used to sign these messages. This ensures all information and meta-data about payments is authenticated and cannot be repudiated.
cc @danprinz
lips/lip-10.md
Outdated
|
||
`https://<hostname>:<port>/pay.<protocol_version>/<endpoint>` | ||
|
||
* All Libra ID endpoints use the same `base_url` and same `compliance_public_key` for authentication as other off-chain APIs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the first beginning, we wanted to use different keys for TLS/KYC and so on. Later we decided a single key for less maintenance cost. From this point of view, another "conventional authentication mechanism" seems to make things more complicated.
cc @kchalkias
|
||
* `Payment_Reference_ID` returned by this endpoint is not signed for KYC purposes. This means that payment above KYC threshold can not be submitted right away using the provided Payment_Reference_ID. Instead, sender VASP needs to proceed to KYC endpoint to negotiate the signed Reference ID. | ||
|
||
* KYC endpoint API will be updated to accept `Payment_Reference_ID` returned by the Libra ID endpoint instead of address/subaddress. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a big change:
- if I understand it correctly, it means that we always need to call Libra ID endpoint before KYC (to get the reference ID) end point API. I'm afraid this introduces new issues. For example, what if receive does not recognizes the reference_id ?
- even though we want to replace address/subaddress with Libra ID, can we just use libra ID in the KYC endpoint API to save round trips?
- from compatibility's perspective, we should add the support for Libra ID/Reference ID first, and then gradually deprecate address/subaddress
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed, we would want to state there is an additional KYC API that supports this... alternatively I would recommend that the payment_reference_id be subaddress
|display_name |str | N | Display name of the user. Usually a full name | | ||
|profile_picture |str | N | Profile picture URL(see below) | | ||
|
||
If a user does not exist, VASP can choose to return an HTTP error, or the empty User Object, depending on it’s privacy choices. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we explicitly set a message for "not intended to share information", or "information unknown"? I think this helps clarify the results for sender, so they have better wordings to communicate to their users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would strike "depending on it's privacy choices"
If a user does not exist or has enabled contact-list mode, the VASP may choose to return either an HTTP 404 error or an empty User Object.
|
||
If a user does not exist, VASP can choose to return an HTTP error, or the empty User Object, depending on it’s privacy choices. | ||
|
||
## Profile Picture URI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bmaurer can you explain the hot links and how FB proxies it?
## Profile Picture URI | ||
Profile picture URI is a URI that represents a profile picture of a user. Wallet app must support two possible URI schemas for profile picture. | ||
|
||
* **Https schema.** If URI starts with https:, wallet must attempt to fetch profile picture from the HTTP URI provided. When fetching this URI wallet app will not provide any authentication. Wallet app will use GET method to fetch the profile picture specified using https schema. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When fetching this URI wallet app will not provide any authentication.
So basically it means VASPs want to expires URIs often.
lips/lip-10.md
Outdated
* **Info endpoint** for querying optional information about the receiver. VASPs can provide this endpoint to improve UX and security of payment, but they are not obligated to - VASPs may choose not to share any information about the user via this endpoint, including whether the user exists or not. | ||
* *For example*: VASP can have notion of 'contact list' and only share information if the sender is in receiver's contacts | ||
* **Payment endpoint** to perform actual money transfer. | ||
|
||
Common considerations: | ||
|
||
* For both endpoints, all communications are signed via the same mechanism as for other off-chain communications, see the [Payloads section of lip-1](https://github.com/libra/lip/blob/master/lips/lip-1.mdx#payloads) for details. As such, all vasp-2-vasp communications are authenticated. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a lot of this and down makes it seem like this is separate but similar to LIP-1, but to me it makes more sense to state it as an extension of LIP-1 that adds new functionality (basically a query API and a new command in the normal API). Then you don't really need to re-state the things of LIP-1 which I think kind of add confusion since we only state some of the things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we could say that this is an extension of Lip1 and make it clear how it is, I think that would be a win.
lips/lip-10.md
Outdated
|
||
* All Libra ID endpoints are nested under `pay.<version>` URI path: | ||
|
||
`https://<hostname>:<port>/pay.<protocol_version>/<endpoint>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with this comment. Let's match LIP-1 and instead of command add a new action (query? get_libra_id? etc.)
lips/lip-10.md
Outdated
## Pay endpoint | ||
|
||
``` | ||
POST https://<hostname>:<port>/pay.<protocol_version>/pay |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd agree with @danprinz here. If we are going to treat this as an action, then it should be using the same command structure as is used in LIP-1 and LIP-8. That keeps us consistent and also means we don't need to re-state so much and make it seems sort of like LIP-1 but sort of its own thing
d017282
to
45f795c
Compare
45f795c
to
1d1bbb9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of comments.... overall the story does make sense, here are my major blockers before moving this to draft:
- Clean up the writing and make it tighter -- most of my feedback is in this category -- in general, I might recommend that we avoid crappy editor frameworks like GitHub and consider a first draft in a shared editor but let's save that battle for another day :D
- The user story should be near the top of this document and tie together the two properties provided: easy use and anonymity on chain
- The document is not particularly searchable the profile_picture_uri is only contained once, you should reuse the exact format in the section that describes it so that idiots like me can easily search for it
- diminutives / abbreviations should not be in technical documents examples: txn and app
- Unify the URL scheme with Lip-1
- Each portion of the Lip should be very clear -- what is the wallet_uri, why are we discussing the compliance endpoint and key, what is the specific use case of each endpoint
- Having a writable endpoint is a no go for me, I won't block on this principle but there are really great techniques to support time valid identifiers that require a zero write API -- for example get_reference_id(user_id, txn_metadata) -> hash(secret_receiver, user_id, txn_metadata)
- Would recommend considering how to make the payment reference id compatible with a subaddress otherwise we're going to have confusing APIs or alternatively define a scheme that makes it clear that one is a libra id and the other is a subaddress
Feel free to setup some time with me if that would help.
lips/lip-10.md
Outdated
# Motivation | ||
Libra ID provides a convenient way to identify a user's account within a VASP. There are two main use cases for Libra ID: | ||
* For peer-2-peer payments, Libra ID allows a user to provide a human-readable ‘identifier’ to the sender. Basically, instead of sending a [lip-5 address](https://github.com/libra/lip/blob/master/lips/lip-5.md) (that needs to be refreshed for each payment, ideally), the receiver can just share their Libra ID once. In this case Libra ID plays the role of an email address for payments. Benefits for this use case: | ||
* Libra ID is a user-friendly, human-readable identifier, unlike lip-5 addresses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant with the first point
* For peer-2-peer payments, Libra ID allows a user to provide a human-readable ‘identifier’ to the sender. Basically, instead of sending a [lip-5 address](https://github.com/libra/lip/blob/master/lips/lip-5.md) (that needs to be refreshed for each payment, ideally), the receiver can just share their Libra ID once. In this case Libra ID plays the role of an email address for payments. Benefits for this use case: | ||
* Libra ID is a user-friendly, human-readable identifier, unlike lip-5 addresses | ||
* The Libra ID resolution process can facilitate the exchange of rich information(e.g. nicknames, profile picture, etc.) about both the sender and receiver of the payment | ||
* Libra ID provides better privacy compared to using sub-addresses, because Libra ID is not shared on the chain and will always use a single-use identifier for the on-chain ID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is technically correct, I could derive distinct subaddresses for each individual.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not always true.
Example is this - you and friends went to restaurant and you paid for everyone. Now you have a group chat in <messenger of your choice>
and want to share your Libra wallet address so that they can pay you back.
There is no convenient way to share lip-5 address so that participants can only send money, but not track payments from others. Of course in theory you can create subaddress for each, but this is not practical
In addition to describing the format of the Libra ID, this LIP also describes the off-chain protocol for the peer-2-peer payment with Libra ID. | ||
|
||
# Motivation | ||
Libra ID provides a convenient way to identify a user's account within a VASP. There are two main use cases for Libra ID: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following structure is a bit too much of us versus them. Instead I think it would be more influential to state the goal of the Libra ID framework, which seems to be:
- human-readable helping individuals recognize and remember it just as easily as an email address or a social networking handle
- built-in anonymization of on-chain metadata
And stating it like this makes it very easy to parse out the value. You can then have a related works section if you really want to make comparison to other technologies / solutions within the Libra tech space.
|
||
This LIP describes Libra ID - the human-readable identifier for user accounts. | ||
|
||
In addition to describing the format of the Libra ID, this LIP also describes the off-chain protocol for the peer-2-peer payment with Libra ID. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would just merge the line 14 to state that this describes human-readable identifier for user accounts and the off-chain protocol for peer-2-peer payments with this identifier.
|
||
* `Payment_Reference_ID` returned by this endpoint is not signed for KYC purposes. This means that payment above KYC threshold can not be submitted right away using the provided Payment_Reference_ID. Instead, sender VASP needs to proceed to KYC endpoint to negotiate the signed Reference ID. | ||
|
||
* KYC endpoint API will be updated to accept `Payment_Reference_ID` returned by the Libra ID endpoint instead of address/subaddress. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed, we would want to state there is an additional KYC API that supports this... alternatively I would recommend that the payment_reference_id be subaddress
|
||
All fields, except for `libra_id`, in this object are optional - VASP can choose to share either of those fields or none. | ||
|
||
Additionally, all fields in this object are informational - **they must not be used for KYC and only intended for UI purposes**. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rewrite are information, that is they are intended for UI purposes only and explicitly not establishing KYC.
|display_name |str | N | Display name of the user. Usually a full name | | ||
|profile_picture |str | N | Profile picture URL(see below) | | ||
|
||
If a user does not exist, VASP can choose to return an HTTP error, or the empty User Object, depending on it’s privacy choices. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would strike "depending on it's privacy choices"
If a user does not exist or has enabled contact-list mode, the VASP may choose to return either an HTTP 404 error or an empty User Object.
|
||
If a user does not exist, VASP can choose to return an HTTP error, or the empty User Object, depending on it’s privacy choices. | ||
|
||
## Profile Picture URI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is an implementation detail that someone can easily screw up as long as the URL returns an image we are good to go.
lips/lip-10.md
Outdated
* Ex.: *data:image/gif;base64,AAAAAAAA* | ||
* **Unencrypted http** schema must not be used to share profile pictures. | ||
|
||
Vasps can return a user profile picture in either format. HTTPS schema is more traditional, however using data schema allows to show profile pictures faster and avoid an extra HTTP request between VASPs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not required.
I am not sure I understand, how does generating reference id with libra id different comparing to generating reference ID during KYC? Are you saying it is bad in both cases, or there is something special about libra id, that does not make it work here, but it works for KYC?
There is a hope that with Libra ID we can actually deprecate subaddresses altogether, given their privacy implications. |
Fix some davidw comments
823ca23
to
3e2eac7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
welcome to the club
Let's continue to tighten this up in ensuing copies:
- clearer story around building an indexer / move events
- how this works with lip 1
- general massaging with flow as we go
Open questions
Libra ID separator
Contenders: @, # and $
“@”:
(-) Too easy to confuse with an email
“$”:
(+/-) Already used by Ripple’s Pay ID
(+/-) Can be seen as an affiliation with USD. However, it is fairly common to use $ as a sign for “money”, rather than a specific currency, so this can also be a plus.
(+) Can be used unencoded in the URLs
“#”:
(-) If placed into URL strictly requires a URL encoding
Libra ID domain - single word or a domain name
Single word(e.g. andrey$novi):
(+) Fewer symbols to write
Domain name(e.g. andrey$novi.com):
(+) In the future if we allow unhosted wallets, we can switch to DNS lookups
(+) For the merchant use case, can create a merchant APP url using string manipulation
Profile picture sizes and image formats
We can put some limits on maximum file size and image resolution.