This document proposes new endpoints to support invoicing, that incidentally also address the long-standing tipping reserve expiration problem.
We want to support a limited number of PULL payment requests where a purse is created for a reserve without immediately requiring a purse fee. However, we must prevent users from excessively creating purses (and uploading contracts) as we do not want the exchange to be abused as a storage layer. Furthermore, it would be good if the user sending a PULL payment request was properly identified to the payer.
This design addresses bugs #7269 and #7274.
- Effectively limit the number of open purses created by each individual (or require purse fees if limit is exceeded).
- Ensure user has done KYC before doing a merge. (Assuming the exchange does KYC at all.)
- Use information from KYC process to help payer identify payee.
- Reasonable UX and overall design impact.
- Wallets may want to pay for the reserve with coins (reserve fresh, not created via bank transfer), while tipping merchants likely want to pay from the reserve balance itself. So both styles of payment should be supported.
Unclear in the current proposal are:
- Here (and in other places!), the payment of the KYC fee remains, eh, obscure. This should probably be part of the KYC endpoints, and not for each KYC-trigger.
- Proposed table structure does not properly capture if user paid extra for more purses (I could open for 3 years, then pay for 5x purses in year 1, but should not automatically get 5x purses in years 2/3).
Allow users to tie their identity to a reserve “on demand” and when doing so
account_fee, bump the number of open purses threshold in the
reserves table and stop auto-closing of the reserve. This will ensure that
the users can withdraw the reserve balance into their wallet even after a
longer time period. This helps if the invoice is paid after a significant
delay, and also addresses the unwanted tipping reserve closure
problem. Introduce a way to force an immediate closure of a reserve, allowing
P2P reserve from invoices to be send to a bank account (this allows a wallet
to be used for convenient invoicing and not strictly require the wallet to
receive the funds) and also allowing the user to recover funds from a tipping
reserve after tips are no longer issued.
The solution needs three new tables for:
- account creation data:
- signature affirming desire to create account
- KYC requirement row
- account creation payment data:
- serial (for replication)
- coin signature (affirming payment)
- amount contributed
- account creation link (serial row ID)
- reserve closure request data:
- serial (for replication)
- reserve signature
- target account payto:// URI
Specifically, the solution involves three new endpoints:
- This new endpoint
/reserve/$RID/openallows the user to pay (for a year) to create a fixed number of purses and to keep the reserve
open(preventing auto-close); the endpoint typically triggers a first (balance-independent) KYC process (451) for a new KYC operation
invoicing(unless KYC is off).
- Upon completion of the
invoicingKYC, the wallet must again try to
/open. If successful, the wallet may be asked to pay the annual fee (402). However, usually the wallet should be aware of the fee, and already have included a suitable deposit in the POST to the endpoint.
- Once the annual fee is paid, the now open reserve is set to a non-zero counter of allowed concurrently open purses, and the expiration time of the reserve is bumped to the end of the time period for which the fee was paid.
- This new endpoint
/reserve/$RID/attestallows the user to obtain exchange-signed KYC information about themselves. This will basically be a list of (GANA standardized) attributes and exchange signatures. The user can then choose which of these attributes to include when invoicing. The available set of attributes may differ depending on the KYC providers configured and the attributes returned by the KYC logic. We may choose to not use any fancy cryptography here, and simply sign the different attributes individually. However, we should always sign over the
$RIDto ensure that the resulting signatures are meaningful.
- When receiving an invoice (PULL payment request), we may want to mandate a certain minimal set of attributes that should always be included, and if that is absent warn the receiver that the sender of the invoice did not properly identify themselves.
- By making this a new endpoint, the client can re-request the signatures on-demand. This is useful if we use the EdDSA online signatures of the exchange, which likely expire long before the user changes their attributes.
- This new endpoint
/reserve/$RID/closeallows the user to force-close a reserve that has not yet expired. This is useful in case invoices have been paid into the reserve and the user wants to get their money out. The
closeendpoint must be provided with an appropriate payto://-URI as reserves that were filled by P2P merge operations may not already have an associated bank account (empty
We could require the target account to be already specified on
However, that prevents people from invoicing that have no account (or we’d
have to allow
payto://void/, which then prevents people from closing later
if they got a bank account at a later stage).
We could allow an amount to be specified on
close to partially wire the
funds in a reserve. However, reserves are not supposed to be used as bank
accounts (either to wallet or exceptionally to bank account, please!), and
this would conflict with the current implementation of the
taler-exchange-closer. So no amount is likely better for minimal
regulatory and implementation trouble.
Closing a reserve could also prevent the future use of the reserve for invoicing. Right now, the specification allows this to continue, effectively allowing users to repeatedly close an account to drain its funds to a bank account instead of into a wallet.
We could mandate a fixed set of attributes. However, it is unclear whether all exchanges will always have KYC providers enabled that offer any particular set of attributes. It is conceivable that some exchanges may not run with any kind of KYC, or just with phone-number validation, while others may require government IDs but not phone numbers. So we can easily end up with completely disjunct sets of attributes across operators.
We could not warn users if insufficient attributes were provided in an invoice. However, that seems dangerous, especially as fake invoices are a common attacker trick.
We could use attribute-based credentials (ABC) for the attestations. Benefits and (complexity) drawbacks of such a change should be discussed with Martin.
Quite a bit of work to implement.
(This should be filled in with results from discussions on mailing lists / personal communication.)