zcash / zips

Zcash Improvement Proposals
https://zips.z.cash
MIT License
273 stars 156 forks source link

[ZIP 321] Specify payment request URIs #347

Closed daira closed 4 years ago

daira commented 7 years ago

Issue by nathan-at-least Monday Nov 21, 2016 at 21:18 UTC Originally opened as https://github.com/zcash/zips/issues/94


A payment request is an opaque string which specifies details of a requested payment, such as recipient, amount, perhaps some details of the memo field contents, perhaps some UX prescriptions.

Originally posted as zcash/zcash#1877, here's that description quoted:

The intent of this specification is to streamline usability for common use cases of payments between users and vendors or perhaps user-to-user.

Note: I'm wary of 'early specification' before we have solid real life use cases. More input from third parties such as wallet makers and 'service vendors' (eg: exchanges, shopping cart providers, etc…) is important.

The basic idea is to introduce a new entity called a Payment Request. This is an encoded blob that's distinct from addresses or any other encoded entity. A vendor wishing to receive payment generates this, and a wallet consumes it, then does some user interaction to execute it. An important sticking point is wallet user authentication of the request.

We should start simple and keep it simple and concrete to known real-world use cases.

A Usage Story:

Here is a UX that I believe has good request authentication:

The user is on a website and expresses the desire to purchase an item, such as by clicking a checkout button after reviewing an order.
That page displays a QR code along with an order number which is high-entropy / unguessable.
The user scans the QR code with their wallet.
The wallet describes the payment amount, the order number, and a description of the items.
The user accepts/cancels the payment request.

Design Principles (Based off of the Story):

Notice two forms of user authentication here:

The wallet only displays the request in response to a user explicitly scanning a QR code, so the user learns to trust the request based on their assessment of the QR code's origin. For example, if a QR code appears in a forum post from a user, the hope is that a user realizes that the user or the website could have generated that request.
The website displays and order number, and so does the wallet, (and importantly) the order number cannot be guessed/spoofed.

Notice forms of 'authentication' that are problematic and potentially dangerous do not exist in this example:

The wallet doesn't display the domain name of the site. (Indeed, the site might be some distributed system like OpenBazaar which doesn't have domain names, or the QR code could be a request from a user on a forum without the explicit coordination of the website hosting that forum.)
There is no other form of indication of the source of the request other than the order number and the 'innate source' of the QR code display and scanning process.
There are no third-party attestations as to the origin of the request such as certificate authority systems or decentralized naming systems.
The data encoded by the QR code is opaque to the user (actually never directly seen) and should not be used by them to authenticate the request.

Notice that this story requires wallets to meet usability requirements, so if the specification we adopt supports this kind of story it would encompass both data formats as well as usability requirements (eg: the wallet must not display a request due to an 'ambiently triggered event' such as a website javascript calling a showRequest() call at its discretion, and must only show a request in response to an explicit user-authenticatable action such as scanning a QR code or pasting in a request blob).

Note, this is distinct from [#2310] although they interact.

jasondavies commented 7 years ago

One possible way to encode a payment request, {z-addr, memo}, is to extend BIP21 to include a "memo" parameter, i.e. zcash:<z-addr>?memo=<memo>. This can then be displayed using a QR code. The encoding of the memo field itself would need specifying: it could simply be encoded using RFC 3986 percent-encoding, or alternatively it could be hex-encoded.

Note that BIP21-style Zcash addresses (both t- and z-addrs) are already in use "in the wild", e.g. the Wikileaks donation links (both the hyperlinks and the QR codes), but of course without use of a "memo" parameter (I haven't seen this used anywhere yet).

daira commented 5 years ago

I've renamed this to "Specify payment request URIs" and assigned a ZIP number derived from BIP 21. Note that:

If there is an objection to either of these effects, speak up!

tromer commented 5 years ago

The payment request encoding may need to contain different information if the payment will be done using a secure channel instead of a recipient z-address (discussed in zcash/zcash#2432).

It would be nice to have a single encoding that supports both use cases.

tromer commented 5 years ago

Re https://github.com/zcash/zcash/issues/2319#issuecomment-321063481: The Zcash Foundation grants platform also uses BIP21-style zcash:t3...?amount=... payment request URIs.

tromer commented 5 years ago

Do we want support for these URIs in zcashd RPC?

Perhaps: zcash-cli z_sendmany "t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd" '[{"request": "zcash:ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf?amount=5.0&memo=squeamish+ossifrage"}]'

Or should the parsing be left to higher-level software?

What do other coins do (e.g., Bitcoin for BIP21)?

tromer commented 5 years ago

The just-funded Zcash Foundation grant for Zcash Point-Of-Sale will also use the zcash:saplingpaymentaddress?amount=0.12345678&memo=ordernumber format (according to its discussion comments).

zancas commented 3 years ago

One possible way to encode a payment request, {z-addr, memo}, is to extend BIP21 to include a "memo" parameter, i.e. zcash:<z-addr>?memo=<memo>. This can then be displayed using a QR code. The encoding of the memo field itself would need specifying: it could simply be encoded using RFC 3986 percent-encoding, or alternatively it could be hex-encoded.

Note that BIP21-style Zcash addresses (both t- and z-addrs) are already in use "in the wild", e.g. the Wikileaks donation links (both the hyperlinks and the QR codes), but of course without use of a "memo" parameter (I haven't seen this used anywhere yet).

I'd like to agitate for calling it anything other than memo since that overloads the term with the memo field.

nuttycom commented 3 years ago

I'd like to agitate for calling it anything other than memo since that overloads the term with the memo field.

The precise intent of this is exactly that the contents of the "memo" parameter be inserted into the "memo" field of the shielded output in the generated transaction. This is so that the vendor can ensure that the purchaser includes an order ID in the memo field, for example. So it's not overloaded at all.

AArnott commented 1 year ago

The ZIP doesn't include any sample use of the req- prefix, so I wonder: is the req- prefix considered part of the parameter name, or just an optional prefix that can be prepended to any already defined parameter? For example, should my parsing implementation consider req-amount to be an alias of the amount parameter?

nuttycom commented 1 year ago

@AArnott At present, there are no required parameters specified. You'll notice that the reqparam production is defined in the "forward compatibility" section. The reqparam production was added to allow for future changes to the specification without explicit versioning; instead, if a parameter is added in the future where an existing parser might misinterpret the payment request and produce the wrong result, compliant parsers will produce an error instead. What this means is that your parser should look for variables having the req- prefix, but if it encounters any at all (since none have yet been specified) your parser should report an error.

As an example of a potential future change that might necessitate the introduction of a req- parameter, once ZSA functionality is active on the network it might make sense to introduce a req-currency parameter that can specify the currency in which the payment recipient wishes to be paid. A parser that does not understand the req-currency parameter will be unable to correctly interpret the payment request, and should therefore return an error.

AArnott commented 1 year ago

Thanks. I think there is an opportunity for using it more. For example req-memo could indicate that the memo field must be copied into the payment screen, and perhaps locked so the user cannot change it. But I guess such a thing will need a follow-up ZIP.

nuttycom commented 1 year ago

Thanks. I think there is an opportunity for using it more. For example req-memo could indicate that the memo field must be copied into the payment screen, and perhaps locked so the user cannot change it. But I guess such a thing will need a follow-up ZIP.

The ZIP 321 specification is a living document, so changes and additions to it can be proposed via the ordinary pull-request process; zips PRs are reviewed and eventually approved or rejected by the ZIP editors.

AArnott commented 1 year ago

Oh! I thought once ZIPs were ratified they couldn't be substantially changed. I do have an active PR that changes this ZIP and a few others, but it's just typo fixes.

nuttycom commented 1 year ago

Oh! I thought once ZIPs were ratified they couldn't be substantially changed. I do have an active PR that changes this ZIP and a few others, but it's just typo fixes.

It varies a bit by ZIP, based upon the character of the ZIP itself, but updating ZIPs is pretty common; for example, if you look at the "NU5 ZIPs" section at https://zips.z.cash/ you'll see a number of ZIPs were updated in order to facilitate NU5 deployment.

nuttycom commented 1 year ago

Speaking of which, @daira I think that ZIP 321 should probably be transitioned from Proposed to Active.