This design document proposes an extension of the Taler protocol that allows payments from customer-to-customer without a merchant.
To be usable as an electronic payment system with cash-like properties, customers should be able to transfer money between themselves without needing to setup anything beyond their wallet(s).
account
is a non-expiring reserve for which entity knowing the
reserve private key has completed a KYC procedure sufficient to enable
receiving income under that address.pouch
is a public-private key pair where the public key is
an exchange address from which any owners of an account
can pick up an amount left at a pouch
assuming they know the pouches
private key.wad
is an exchange-to-exchange wire transfer that wires money
into a group of accounts at the target exchange.A complete solution for customer-to-customer payments consists of three possible operational flows.
payto://taler/$EXCHANGE_BASE_URL/$ACCOUNT_PUB
target address (for which the payee knows the corresponding
account private key)./account/$ACCOUNT_PUB/kyc
allows wallets to request a KYC for an
ACCOUNT_PUB. Such a request may include the requirement to pay
a KYC fee. The KYC fee may be charged to that account (if it exists),
or could be waved if the account was established via a wire transfer
from a partner bank.taler-exchange-wirewatch
cannot cause the long
polling to be resumed, only transfers within the same exchange can benefit
from long polling acceleration./depost
API to deposit coins into
the purse, using payto://taler/$PURSE_PUB
as the target
address. Note that the lack of a hostname indicates that the
target address is a purse.taler://purse/BASE_URL/$PURSE_PRIV
URL./purse/$PURSE_PUB
endpoint to retrieve
the purse history, which includes all deposits and withdrawals
involving the purse./purse/$PURSE_PUB/merge
a
request signed by the purse’s private key to merge the
funds into an account. The signature is only over a salted
hash of the account public key, thus avoiding disclosure of
the account public key in the purse history. The exchange
processes the merge request akin to the logic for payments
into known accounts, as detailed below, except that no
deposit fees are charged at this time. The exchange
confirms the merge, allowing the payee to instantly affirm
to the user that the amount is inbound (even if it may not
be instantly available)./deposit
operation, paying
the usual deposit fee.taler
wire method, and
directly credits the target account.If the payer knows the payee’s account and uses a different exchange,
they POST the coins to a new /wad/MASTER_PUB
endpoint using the master
public key of the target exchange, including a deposit permission,
the base URL of the target exchange, and the target account,
paying a deposit fee and a new wad fee. The wad fees can
be used to cover the cost of the exchange-to-exchange wire transfer.
The payer’s exchange creates a wad grouping all wad requests, executing the transaction when either the wad threshold (maximum number of transactons aggregated per wad) or the wad delay (maximum delay for transfers) has been reached.
If the (aggregated) wire transfer fails (say the
/wire
endpoint of the payee exchange does not
resolve to a valid bank account), the
originating exchange automatically creates a full refund for
all aggregated deposits and purses (refund fees apply).
Note
While the refund fee amount can be reused, these types of refunds are not approved by a merchant’s signature. Thus, we will need a new message type in the coin history to represent these events.
The payee’s exchange observes the wire transfer and uses a GET
/wad/{MASTER_PUB}/{WTID}
request to obtain details about the target
accounts.
When the payer’s exchange is requested to provide information about aggregated transfers under the WTID, it provides a signed list of account public keys and associated amounts that must add up to an amount below the total amount transferred. If they do not, the payee’s exchange does not credit any of the accounts and instead preserves the bogus reply (to justify its inaction with its own auditor) and reports the issue to the auditor of the payer’s exchange (keeping the received funds for future manual resolution).
taler-exchange-wirewatch
and the Taler wire gateway API will
need to be extended to allow passing inbound wire transfers with WTID
and exchange base URL to the exchange. Furthermore, another tool
is needed to lookup the wad data at remote exchanges.
/deposit
.The overall changes required are not small:
/keys
endpoint (similar to closing and wire fees),
requires some work across toolchain (offline signature, etc.)taler
wire method needs special case to possibly bypass
(same exchange scenario, with long-poll trigger) the usual aggregation logic.transfers
requests for pouches
(another separate process)./account/$ACCOUNT_PUB/kyc
endpoint required./purse/$PURSE_PUB/merge
endpoint required.taler-exchange-wirewatch
needs to support receiving pouch closures
and exchange-to-exchange wire transfers with WTIDs.Aside from implementation complexity, the solution has the following drawbacks: