gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-docs] 01/36: first cut at DD13 spec writing


From: gnunet
Subject: [taler-docs] 01/36: first cut at DD13 spec writing
Date: Tue, 22 Jun 2021 19:34:57 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository docs.

commit 446fec10a4e1fb7923f6732f80290fcb6c7bc1af
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon May 3 21:47:14 2021 +0200

    first cut at DD13 spec writing
---
 core/api-exchange.rst | 713 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 712 insertions(+), 1 deletion(-)

diff --git a/core/api-exchange.rst b/core/api-exchange.rst
index 1e9db1d..12cb4e1 100644
--- a/core/api-exchange.rst
+++ b/core/api-exchange.rst
@@ -123,6 +123,15 @@ possibly by using HTTPS.
       // The exchange's currency.
       currency: string;
 
+      // Purse fee, charged only if a purse is abandoned
+      // and was not covered by the account limit.
+      purse_fee: Amount;
+
+      // Non-negative number of concurrent purses that any
+      // account holder is allowed to create without having
+      // to pay the purse_fee.
+      purse_account_limit: integer;
+
       // EdDSA master public key of the exchange, used to sign entries
       // in ``denoms`` and ``signkeys``.
       master_public_key: EddsaPublicKey;
@@ -918,7 +927,7 @@ exchange.
   .. ts:def:: TransactionHistoryItem
 
     // Union discriminated by the "type" field.
-    type ReserveTransaction =
+    type TransactionHistoryItem =
       | ReserveWithdrawTransaction
       | ReserveCreditTransaction
       | ReserveClosingTransaction
@@ -1971,3 +1980,705 @@ Refunds
       // the relevant subset of the transactions.
       history: CoinSpendHistoryItem[];
     }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.. _exchange_w2w:
+
+--------------------------
+Wallet-to-wallet transfers
+--------------------------
+
+TODO for the spec:
+
+  * endpoint to create purse with KYC'ed account OR payment,
+    but without deposit
+  * endpoint to DELETE account is missing (note: may need
+    two variants: bank-administrative (offline key?)
+    and user-driven)
+  * specify new database schema at exchange
+  * specify what each signature is made over precisely
+  * add KYC fee to /keys
+  * add extended account history fee to /keys
+  * add purse 'GET' expiration (purse_expiration is when
+    deposits are no longer allowed, but we may still want
+    to return the purse status for a bit longer, right?
+    Or only as part of the coins/accounts status? What about
+    long-pollers that are active at this expiration time?
+    [should not DELETE the purse data while the long pollers
+    are still potentially waking up, so needs a grace period, at least])
+  * update wire transfer API to enable WAD IDs (and while we are
+    at it, should probably also write extended version to allow
+    _merchants_ to query for their inbound transfers, so spec
+    for both WADs and regular WTID!)
+  * specify WAD ID format (keep separte from
+    WTIDs and reserve public keys!)
+  * Update coin history replies to include purse actions.
+  * Merging a purse into an account that is never KYC'ed means
+    the funds are lost. We need to specify an account expiration
+    time (after funds are merged, but KYC never happens).
+
+Discussion:
+
+  * Should the account-withdraw be a separate endpoint from
+    the reserve withdraw, or should we *extend* the reserve-withdraw
+    with the "missing KYC" response?
+  * Should the account-history be a separate endpoint from
+    the reserve history, or should we *extend* the reserve-history
+    with the new history entries and the payment option?
+  * Should we return somewhere a list of the desired
+    KYC attributes that the wallet should (optionally)
+    POST to the exchange when initiating KYC? (see: "attributes").
+
+Notes:
+
+  * Current API does not allow 'merging' a purse directly into
+    a regular bank account. The merge MUST go into an account.
+  * What do we do with KYC'ed accounts where the user fails to
+    drain the funds? Just keep them? Or do we require getting an
+    IBAN as part of KYC and 'close' the account that way?
+
+
+Purses
+^^^^^^
+
+
+.. http:GET:: /purses/$PURSE_PUB
+
+  Obtain information about a purse. The request header must
+  contain a *Purse-Request-Signature*.
+
+  **Request:**
+
+  *Purse-Request-Signature*: The client must provide Base-32 encoded EdDSA 
signature made with ``$PURSE_PRIV``, affirming its authorization to download 
the purse status.  The purpose used MUST be ``TALER_SIGNATURE_PURSE_STATUS`` 
(NUMBER: TBD).
+
+  :query merge_timeout_ms=NUMBER: *Optional.*  If specified,
+    the exchange
+    will wait up to ``timeout_ms`` milliseconds for completion
+    of a merge operation before sending the HTTP response.
+  :query deposit_timeout_ms=NUMBER: *Optional.*  If specified,
+    the exchange
+    will wait up to ``timeout_ms`` milliseconds for completion
+    of a deposit operation before sending the HTTP response.
+  :query contract=BOOLEAN: *Optional.*  If 'false' is specified,
+    the exchange will not return the encrypted contract, saving
+    bandwidth for clients that already know it.
+
+  **Response:**
+
+  :http:statuscode:`200 OK`:
+    The operation succeeded, the exchange provides details
+    about the purse.
+    The response will include a `PurseStatus` object.
+  :http:statuscode:`401 Unauthorized`:
+    The *Purse-Request-Signature* is invalid.
+    This response comes with a standard `ErrorDetail` response.
+  :http:statuscode:`404 Not found`:
+    The purse is unknown to the exchange.
+
+  **Details:**
+
+  .. ts:def:: PurseStatus
+
+     interface PurseStatus {
+
+      // Total amount that must be paid into the purse.
+      total_purse_amount: Amount;
+
+      // Total amount deposited into the purse so far.
+      total_deposit_amount: Amount;
+
+      // Indicative time by which the purse expires
+      // if it has not been merged into an account. At this
+      // point, all of the deposits made will be auto-refunded.
+      purse_expiration: Timestamp;
+
+      // Indicative time at which the exchange is answering the
+      // status request.  Used as part of `exchange_sig`.
+      status_timestamp: Timestamp;
+
+      // Maximum deposit fees that can be charged under the contract.
+      max_deposit_fees: Amount;
+
+      // SHA-512 hash of the contact of the purse.
+      h_contract_terms: HashCode;
+
+      // EdDSA signature of the exchange affirming the purse status.
+      exchange_sig: EddsaSignature;
+
+      // AES-GCM Encrypted contract terms using encryption
+      // key derived from DH of 'contract_pub' and the 'purse_pub'.
+      // Optional, may be omitted if not desired by the client.
+      e_contract_terms?: byte[];
+
+      // If a merge request was received, information about the
+      // merge request. Omitted if the purse has not yet received
+      // a merge request.
+      merge_request?: MergeRequest;
+
+    }
+
+
+.. http:POST:: /purses/$PURSE_PUB/deposit
+
+  Create a purse without an account, but with associated payment.
+
+  **Request:** The request body must be a `PurseRequest` object.
+
+  **Response:**
+
+  :http:statuscode:`200 OK`:
+    The operation succeeded, the exchange confirms that all
+    coins were deposited into the purse.
+    The response will include a `PursePaymentSuccess` object.
+  :http:statuscode:`202 Accepted`:
+    The payment was accepted, but insufficient to reach the
+    specified purse balance.  The client should make further
+    purse deposits before the expiration deadline.
+    The response will include a `PursePaymentAccepted` object.
+  :http:statuscode:`401 Unauthorized`:
+    A coin signature is invalid.
+    This response comes with a standard `ErrorDetail` response.
+  :http:statuscode:`403 Forbidden`:
+    The server is denying the operation as a purse with a
+    different contract or total amount already exists.
+    This response comes with a standard `PurseConflict` response.
+  :http:statuscode:`404 Not found`:
+    Either the denomination key is not recognized (expired or invalid) or
+    the wire type is not recognized.
+  :http:statuscode:`409 Conflict`:
+    The deposit operation has either failed because a coin has insufficient
+    residual value, or because the same public key of the coin has been
+    previously used with a different denomination.  Which case it is
+    can be decided by looking at the error code
+    (``TALER_EC_EXCHANGE_DEPOSIT_INSUFFICIENT_FUNDS`` or 
``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY``).
+    The fields of the response are the same in both cases.
+    The request should not be repeated again with this coin.
+    In this case, the response is a `PurseDepositDoubleSpendError`.
+    If the value of all successful coins is below the purse fee,
+    the exchange may not setup the purse at all.
+
+
+  **Details:**
+
+  .. ts:def:: PursePaymentSuccess
+
+     interface PursePaymentSuccess {
+
+      // Total amount paid into the purse.
+      total_purse_amount: Amount;
+
+      // Total deposit fees charged.
+      total_deposit_fees: Amount;
+
+      // EdDSA signature of the exchange affirming the payment.
+      // Signs over the above and the purse public key and
+      // the hash of the contract terms.
+      exchange_sig: EddsaSignature;
+
+    }
+
+  .. ts:def:: PursePaymentAccepted
+
+     interface PursePaymentAccepted {
+
+      // Total amount paid so far into the purse, in this
+      // and previous requests.
+      total_amount_deposited: Amount;
+
+      // Total amount contributed by the current request.
+      total_amount_contributed: Amount;
+
+    }
+
+  .. ts:def:: PurseConflict
+
+    interface PurseConflict {
+
+      // Total amount to be paid into the purse as per
+      // the previous request.
+      total_purse_amount: Amount;
+
+      // SHA-512 hash of the contact of the purse.
+      h_contract_terms: HashCode;
+
+      // Indicative time by which the purse should expire
+      // if it has not been merged into an account. At this
+      // point, all of the deposits made should be
+      // auto-refunded.
+      purse_expiration: Timestamp;
+
+      // EdDSA signature of the purse confirming that the
+      // above details hold for this purse.
+      purse_sig: EddsaSignature;
+
+    }
+
+   .. ts:def:: PurseRequest
+
+    interface PurseRequest {
+
+      // EdDSA signature of the purse confirming the key
+      // invariants associated with the purse.
+      // (amount, h_contract_terms, expiration).
+      purse_sig: EddsaSignature;
+
+      // Total amount to be paid into the purse.
+      // Clients may make several requests, i.e. if a
+      // first request failed with a double-spending error.
+      // The exchange will confirm the creation of the
+      // purse once the amount given here is reached.
+      total_purse_amount: Amount;
+
+      // SHA-512 hash of the contact of the purse.
+      h_contract_terms: HashCode;
+
+      // ECDH contract_public key used to encrypt the contract.
+      // Optional as the contract terms may already be known
+      // to the exchange or the other wallet from a different
+      // interaction.
+      contract_pub?: EcdhPublicKey;
+
+      // AES-GCM Encrypted contract terms using encryption
+      // key derived from DH of 'contract_pub' and the 'purse_pub'.
+      // Optional as the contract terms may already be known
+      // to the exchange or the other wallet from a different
+      // interaction.
+      e_contract_terms?: byte[];
+
+      // Client-side timestamp of when the payment was made.
+      timestamp: Timestamp;
+
+      // Indicative time by which the purse should expire
+      // if it has not been merged into an account. At this
+      // point, all of the deposits made will be auto-refunded.
+      purse_expiration: Timestamp;
+
+      // Array of coins being deposited into the purse.
+      deposits: PurseDeposit[];
+    }
+
+  .. ts:def:: PurseDeposit {
+
+      // Public key of the coin being deposited into the purse.
+      coin_pub: EddsaPublicKey;
+
+      // Amount to be deposited, can be a fraction of the
+      // coin's total value.
+      contribution: Amount;
+
+      // Hash of denomination RSA key with which the coin is signed.
+      denom_pub_hash: HashCode;
+
+      // Exchange's unblinded RSA signature of the coin.
+      ub_sig: RsaSignature;
+
+      // Signature of `TALER_PurseDepositRequestPS`,
+      // made by the customer with the
+      // `coin's private key <coin-priv>`.
+      coin_sig: EddsaSignature;
+
+    }
+
+  .. ts:def:: PurseDepositDoubleSpendError
+
+    interface DepositDoubleSpendError {
+      // The string constant "insufficient funds".
+      hint: string;
+
+      // Total amount contributed by the current request.
+      // Note that some coins may have been successfully
+      // deposited into the purse, so the total amount
+      // from these coins is listed here.
+      total_amount_contributed: Amount;
+
+      // Public keys of coins that could not be deposited
+      // into the purse, mapped to the coin's histories.
+      coin_map: EddsaPublicKey -> CoinSpendHistoryItem[];
+    }
+
+
+
+.. http:POST:: /purses/$PURSE_PUB/merge
+
+  Merge purse with account, adding the value of the purse into
+  the account.
+
+  **Request:** The request body must be a `MergeRequest` object.
+
+  :query timeout_ms=NUMBER: *Optional.*  If specified, the exchange will
+    wait up to ``timeout_ms`` milliseconds to receive payment before
+    reporting on the completion of merge operation.  Basically
+    forstalls returning a 202 response for up to timeout milliseconds
+    to possibly return a 200 response instead.
+
+  **Response:**
+
+  :http:statuscode:`200 OK`:
+    The operation succeeded, the exchange confirms that the
+    funds were merged into the account.
+    The response will include a `MergeSuccess` object.
+  :http:statuscode:`202 Accepted`:
+    The operation succeeded, the exchange confirms that the
+    merge request is valid. Alas, the purse was still not
+    funded and thus the actual merge is delayed.
+    The response will include a `MergeAccepted` object.
+  :http:statuscode:`401 Unauthorized`:
+    Account signature is invalid.
+    This response comes with a standard `ErrorDetail` response.
+  :http:statuscode:`404 Not found`:
+    The refund operation failed as we could not find the purse.
+    This response comes with a standard `ErrorDetail` response.
+  :http:statuscode:`410 Gone`:
+    The purse has already expired and thus can no longer be merged.
+    This response comes with a standard `ErrorDetail` response.
+  :http:statuscode:`429 Too Many Requests`:
+    This account is not at this exchange, has not yet passed the
+    KYC checks, or it has exceeded the number of open purses.
+    The client must include payment to create another purse or
+    wait until existing purses have expired.
+
+  **Details:**
+
+  .. ts:def:: MergeSuccess
+
+     interface MergeSuccess {
+
+      // Amount merged (excluding deposit fees).
+      merge_amount: Amount;
+
+      // SHA-512 hash of the contact of the purse.
+      h_contract_terms: HashCode;
+
+      // Time at which the merge came into effect.
+      merge_time: Timestamp;
+
+      // EdDSA signature of the exchange affirming the merge.
+      // Signs over the above and the account public key.
+      exchange_sig: EddsaSignature;
+
+    }
+
+  .. ts:def:: MergeAccepted
+
+    interface MergeAccepted {
+
+      // The number of open purses under the given account.
+      // Useful to calculate how many purses still can be created.
+      open_purses: integer;
+
+    }
+
+  .. ts:def:: MergeRequest
+
+    interface MergeRequest {
+
+      // payto://-URI of the account the purse is to be merged into.
+      // Must be of the form: "payto://taler/EXCHANGE_URL/ACCOUNT_PUB".
+      payto_uri: string;
+
+      // EdDSA signature of the exchange affirming the merge.
+      account_sig: EddsaSignature;
+
+      // EdDSA signature of the purse private key affirming the merge.
+      purse_sig: EddsaSignature;
+
+      // Array of payments made to pay for the creation of the
+      // purse. Can be empty, say if no payment is needed.
+      payments: CreatePurseDeposit[];
+
+    }
+
+  .. ts:def:: CreatePurseDeposit {
+
+      // Public key of the coin being used to pay for creating a purse.
+      coin_pub: EddsaPublicKey;
+
+      // Amount to be deposited, can be a fraction of the
+      // coin's total value.
+      contribution: Amount;
+
+      // Hash of denomination RSA key with which the coin is signed.
+      denom_pub_hash: HashCode;
+
+      // Exchange's unblinded RSA signature of the coin.
+      ub_sig: RsaSignature;
+
+      // Signature of `TALER_PurseCreateRequestPS`,
+      // made by the customer with the
+      // `coin's private key <coin-priv>`.
+      coin_sig: EddsaSignature;
+
+    }
+
+
+
+
+.. _exchange_accounts:
+
+Accounts
+^^^^^^^^
+
+.. http:GET:: /accounts/$ACCOUNT_PUB
+
+  Obtain information about an account. The request header must
+  contain an *Account-Request-Signature*.
+
+  **Request:**
+
+  *Account-Request-Signature*: The client must provide Base-32 encoded EdDSA 
signature made with ``$ACCOUNT_PRIV``, affirming its authorization to access 
the account status.  The purpose used MUST be 
``TALER_SIGNATURE_ACCOUNT_STATUS`` (NUMBER: TBD).
+
+  :query history=BOOLEAN: *Optional.*  If specified, the exchange
+    will return the recent account history.
+    This is still free of charge.
+  :query full_history=BOOLEAN: *Optional.*  If 'true' is specified,
+    the exchange will return the full account history.  This
+    may incur a fee that will be charged to the account.
+
+  **Response:**
+
+  :http:statuscode:`200 OK`:
+    The operation succeeded, the exchange provides details
+    about the account.
+    The response will include a `AccountHistory` object.
+  :http:statuscode:`401 Unauthorized`:
+    The *Account-Request-Signature* is invalid.
+    This response comes with a standard `ErrorDetail` response.
+  :http:statuscode:`404 Not found`:
+    The account is unknown to the exchange.
+
+  **Details:**
+
+  .. ts:def:: AccountHistory
+
+     interface AccountHistory {
+
+      // Current balance of the account.
+      balance: Amount;
+
+      // True if the owner of the account currently satisfies
+      // the required KYC checks.
+      kyc: boolean;
+
+      // Transaction history for this account.
+      history: AccountHistoryItem[];
+    }
+
+  Objects in the transaction history have the following format:
+
+  .. ts:def:: AccountHistoryItem
+
+    // Union discriminated by the "type" field.
+    type AccountHistoryItem =
+      | AccountMergeTransaction
+      | ReserveWithdrawTransaction
+      | ReserveCreditTransaction
+      | ReserveClosingTransaction
+      | ReserveRecoupTransaction;
+
+  .. ts:def:: AccountMergeTransaction
+
+    interface AccountMergeTransaction {
+      type: "MERGE";
+
+      // Amount merged (what was left after fees).
+      amount: Amount;
+
+      // Purse that was merged.
+      purse_pub: EddsaPublicKey;
+
+      // Hash of the contract.
+      h_contract: HashCode;
+
+      // Signature created with the account's private key.
+      account_sig: EddsaSignature;
+
+      // Signature created with the purse's private key.
+      purse_sig: EddsaSignature;
+
+      // Deposit fees that were charged to the purse.
+      deposit_fees: Amount;
+    }
+
+
+.. http:POST:: /accounts
+
+  Create a new account.
+
+  **Request:** The request body must be a `AccountSetupRequest` object.
+
+  :query timeout_ms=NUMBER: *Optional.*  If specified, the exchange will
+    wait up to ``timeout_ms`` milliseconds for the KYC gateway to
+    confirm completion of the KYC process.
+
+  **Response:**
+
+  :http:statuscode:`200 Ok`:
+    The operation succeeded, the exchange confirms that the account
+    can now be used.
+    The response will be an `AccountStatus` object.
+  :http:statuscode:`303 See Other`:
+    The user should be redirected to the provided location to perform
+    the required KYC checks to open the account. Afterwards, the
+    request should be repeated.
+  :http:statuscode:`504 Gateway Timeout`:
+    The exchange did not receive a confirmation from the KYC service
+    within the specified time period. Used when long-polling for the
+    result.
+
+  **Details:**
+
+  .. ts:def:: AccountSetupRequest
+
+     interface AccountSetupRequest {
+
+      // EdDSA public key for the account.
+      account_pub: EddsaPublicKey;
+
+      // EdDSA signature of the account affirming the request
+      // to create the account.
+      account_sig: EddsaPublicKey;
+
+      // Array of payments made to pay for the creation of the
+      // account. Can be empty, say if no payment is needed.
+      payments: CreateAccountDeposit[];
+
+      // Generic key-value map of attributes about the
+      // account owner. Useful to pre-fill KYC forms.
+      // A list of well-known keys is defined in FIXME.
+      attributes: Object;
+
+    }
+
+  .. ts:def:: CreateAccountDeposit {
+
+      // Public key of the coin being used to pay for creating an
+      // account.
+      coin_pub: EddsaPublicKey;
+
+      // Amount to be deposited, can be a fraction of the
+      // coin's total value.
+      contribution: Amount;
+
+      // Hash of denomination RSA key with which the coin is signed.
+      denom_pub_hash: HashCode;
+
+      // Exchange's unblinded RSA signature of the coin.
+      ub_sig: RsaSignature;
+
+      // Signature of `TALER_AccountCreateRequestPS`,
+      // made by the customer with the
+      // `coin's private key <coin-priv>`.
+      coin_sig: EddsaSignature;
+    }
+
+  .. ts:def:: AccountKycStatus
+
+     interface AccountKycStatus {
+
+      // Current time of the exchange, used as part of
+      // what the exchange signs over.
+      now: Timestamp;
+
+      // EdDSA signature of the exchange affirming the account
+      // is KYC'ed.
+      exchange_sig: EddsaSignature;
+
+    }
+
+
+.. http:post:: /accounts/$ACCOUNT_PUB/withdraw
+
+   This endpoint is virtually identical to the withdraw endpoint
+   for reserves, with the only difference being a new response
+   code `303 See Other` which is returned for accounts that
+   have not yet completed the required KYC check.
+
+   **Response**:
+
+   :http:statuscode:`303 See Other`:
+     The user should be redirected to the provided location to perform
+     the required KYC checks to open the account. Afterwards, the
+     request should be repeated.
+
+
+.. _exchange_wads:
+
+
+Wads
+^^^^
+
+These endpoints are used to manage exchange-to-exchange payments in support of
+wallet-to-wallet payments.
+
+
+.. http:GET:: /wads/$WAD_ID
+
+  Obtain information about a wad.
+
+  **Request:**
+
+  **Response:**
+
+  :http:statuscode:`200 OK`:
+    The operation succeeded, the exchange provides details
+    about the wad.
+    The response will include a `WadDetails` object.
+  :http:statuscode:`404 Not found`:
+    The wad is unknown to the exchange.
+
+  **Details:**
+
+  .. ts:def:: WadDetails
+
+     interface WadDetails {
+
+      // Total transfer amount claimed by the exchange.
+      total: Amount;
+
+      // Transfers aggregated in the wad.
+      items: WadItem[];
+    }
+
+  Objects in the wad item list have the following format:
+
+  .. ts:def:: WadItem
+
+    interface WadItem {
+
+      // Amount in the purse.
+      amount: Amount;
+
+      // Purse public key.
+      purse_pub: EddsaPublicKey;
+
+      // Account public key.
+      account_pub: EddsaPublicKey;
+
+      // Hash of the contract.
+      h_contract: HashCode;
+
+      // Signature created with the account's private key.
+      account_sig: EddsaSignature;
+
+      // Signature created with the purse's private key.
+      purse_sig: EddsaSignature;
+
+      // Deposit fees that were charged to the purse.
+      deposit_fees: Amount;
+
+      // Wad fees that was charged to the purse.
+      wad_fees: Amount;
+    }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]