taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

post-recoup-refresh.rst (9586B)


      1 .. http:post:: /recoup-refresh
      2 
      3   Demand that coins of revoked denominations, which originated from
      4   one particular call to :http:post:`/melt </melt>` and
      5   :http:post:`/reveal-melt </reveal-melt>`, be paid back to the old coin
      6   they were refreshed from.
      7 
      8   All coins in one request MUST originate from the same refresh operation.
      9   The client identifies that operation by the public key of the old coin and
     10   the refresh commitment ``rc`` of the original melt request.  As with
     11   :http:post:`/recoup-withdraw </recoup-withdraw>`, the client discloses the
     12   secret material of the coins to be recouped and provides the envelope
     13   hashes of the other coins of the same operation, so that the exchange can
     14   recompute the hash over the batch of coins it signed and compare it with
     15   the commitment it stored.
     16 
     17   The residual value of each disclosed coin is credited to the old coin.
     18   The old coin may then be spent or melted again, even if the deposit
     19   expiration of its denomination has passed in the meantime (a "zombie"
     20   coin).  The refresh fee paid in the original operation is **not**
     21   recouped.
     22 
     23   The exchange only accepts this request for coins of denominations that
     24   are listed in the ``recoup`` field of :http:get:`/keys </keys>`.
     25 
     26   The base URL for this request may differ from the main base URL of the
     27   exchange. The exchange MUST return a 307 or 308 redirection to the correct
     28   base URL if this is the case.
     29 
     30   This endpoint was introduced in protocol **vRECOUP** and replaces the
     31   former ``/coins/$COIN_PUB/recoup-refresh`` endpoint.
     32 
     33   **Request:**
     34 
     35   The request body must be a `RecoupRefreshRequest` object.
     36 
     37   **Response:**
     38 
     39   :http:statuscode:`200 OK`:
     40     The request was successful and the response is a
     41     `RecoupRefreshResponse`.  Repeating exactly the same request
     42     yields the same response (the signature may differ if the exchange
     43     has rotated its signing key in the meantime), so if the network goes
     44     down before the client can commit the result to disk, the recoup is
     45     not lost.
     46   :http:statuscode:`400 Bad Request`:
     47     The request body is malformed or a parameter is invalid.
     48     This response comes with a standard `ErrorDetail` response.
     49     Possible error codes include ``TALER_EC_GENERIC_PARAMETER_MALFORMED``
     50     (also used if ``coin_data`` does not contain at least one disclosed
     51     coin) and ``TALER_EC_EXCHANGE_RECOUP_REFRESH_BATCH_SIZE_MISMATCH``
     52     (the number of entries in ``coin_data`` differs from the number of
     53     coins the exchange signed in the original refresh operation).
     54   :http:statuscode:`403 Forbidden`:
     55     A signature is invalid.
     56     This response comes with a standard `ErrorDetail` response.
     57     Possible error codes include
     58     ``TALER_EC_EXCHANGE_RECOUP_REFRESH_SIGNATURE_INVALID`` (a ``coin_sig``)
     59     or ``TALER_EC_EXCHANGE_DENOMINATION_SIGNATURE_INVALID``
     60     (a ``denom_sig``).
     61   :http:statuscode:`404 Not found`:
     62     One of the following reasons occurred:
     63 
     64     1. A denomination key is unknown.  The response is a
     65        `DenominationUnknownMessage` with error code
     66        ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN``.
     67     2. The exchange has no record of a refresh operation for the given
     68        ``rc``, or the operation found was not a refresh of
     69        ``old_coin_pub``.  This response comes with a standard `ErrorDetail`
     70        response with error code
     71        ``TALER_EC_EXCHANGE_RECOUP_REFRESH_MELT_NOT_FOUND``.
     72   :http:statuscode:`409 Conflict`:
     73     One of the following reasons occurred:
     74 
     75     1. The hash the exchange recomputed over the ``coin_data`` array does
     76        not match the commitment of the refresh operation, so at least one
     77        disclosed coin was not part of it.  This response comes with a
     78        standard `ErrorDetail` response with error code
     79        ``TALER_EC_EXCHANGE_RECOUP_REFRESH_COMMITMENT_MISMATCH``.
     80     2. The denomination of a disclosed coin differs from the denomination
     81        recorded for that position of the refresh operation.  This
     82        response comes with a standard `ErrorDetail` response with error code
     83        ``TALER_EC_EXCHANGE_RECOUP_REFRESH_DENOMINATION_MISMATCH``.
     84     3. A disclosed coin has no residual value left.  The response is a
     85        `DepositDoubleSpendError` with error code
     86        ``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS``.
     87     4. The same coin public key was previously used with a different
     88        denomination or age commitment.  The response is a
     89        `CoinDenominationConflictError` with error code
     90        ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY``
     91        or a `CoinAgeCommitmentConflictError` with error code
     92        ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH``.
     93 
     94     In all of these cases nothing is credited, not even for the other
     95     coins in the request.
     96   :http:statuscode:`410 Gone`:
     97     The denomination of a disclosed coin is not eligible for recoup.
     98     The response is a `DenominationGoneMessage` with error code
     99     ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED`` (past the deposit
    100     expiration) or ``TALER_EC_EXCHANGE_RECOUP_REFRESH_NOT_ELIGIBLE`` (the
    101     denomination was not revoked).
    102   :http:statuscode:`412 Precondition Failed`:
    103     The denomination of a disclosed coin is not yet valid.
    104     The response is a `DenominationGoneMessage` with error code
    105     ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE``.
    106   :http:statuscode:`413 Request entity too large`:
    107     The uploaded body is to long, it exceeds the size limit.
    108     Returned with an error code of
    109     ``TALER_EC_GENERIC_UPLOAD_EXCEEDS_LIMIT``.
    110   :http:statuscode:`500 Internal Server Error`:
    111     The exchange encountered an internal error.
    112     This response comes with a standard `ErrorDetail` response.
    113     Possible error codes include
    114     ``TALER_EC_EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED``,
    115     ``TALER_EC_GENERIC_DB_FETCH_FAILED``,
    116     ``TALER_EC_GENERIC_DB_COMMIT_FAILED``, or
    117     ``TALER_EC_GENERIC_DB_INVARIANT_FAILURE``.
    118   :http:statuscode:`502 Bad gateway`:
    119     The exchange could not reach its signing helper to create
    120     the confirmation signatures.  Returned with an error code of
    121     ``TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE``.
    122     Wallets should retry the request (with some delay) at a later time.
    123   :http:statuscode:`503 Service Unavailable`:
    124     The exchange currently has no signing keys available.
    125     This response comes with a standard `ErrorDetail` response with
    126     a code of ``TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING``.
    127 
    128   **Details:**
    129 
    130   .. ts:def:: RecoupRefreshRequest
    131 
    132     interface RecoupRefreshRequest {
    133       // Public key of the old coin that was melted.
    134       // The recouped value is credited to this coin.
    135       old_coin_pub: CoinPublicKey;
    136 
    137       // The refresh commitment of the original melt request,
    138       // see `TALER_RefreshCommitmentP`.  This identifies the
    139       // refresh operation.
    140       rc: HashCode;
    141 
    142       // Exactly one entry per coin the exchange signed in the
    143       // refresh operation, that is the ``n`` coins of the batch at
    144       // the ``noreveal_index`` returned in the `MeltResponse`, in the
    145       // order of the original request.
    146       // At least one entry MUST be a `RecoupedCoin` and its
    147       // ``coin_sig`` MUST be created with purpose
    148       // ``TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH``.
    149       coin_data: RecoupCoinData[];
    150     }
    151 
    152   Note that for denominations of cipher type Clause-Schnorr the client
    153   does not need to provide the session nonce or the R-value pair: the
    154   exchange derives the nonce from the ``blinding_seed`` of the original
    155   melt request and the coin's position in ``coin_data`` (exactly as the
    156   wallet does for a melt), and it stored the R-values it returned in
    157   :http:post:`/blinding-prepare </blinding-prepare>`.
    158 
    159   The exchange processes the request as
    160   :http:post:`/recoup-withdraw </recoup-withdraw>` does, with the refresh
    161   operation looked up under ``rc``, the hash over ``coin_data`` compared
    162   against the hash of the batch at the ``noreveal_index``, and the
    163   residual value of every disclosed coin credited to ``old_coin_pub``
    164   in one database transaction.
    165 
    166   .. ts:def:: RecoupRefreshResponse
    167 
    168     interface RecoupRefreshResponse {
    169       // Public key of the old coin that was credited.
    170       old_coin_pub: CoinPublicKey;
    171 
    172       // The refresh commitment of the refresh operation, as in the request.
    173       rc: HashCode;
    174 
    175       // Time when the exchange accepted the recoup.  All coins
    176       // of one request share this timestamp.
    177       timestamp: Timestamp;
    178 
    179       // Total amount credited to the old coin, that is the sum
    180       // of the ``amount`` values in ``recoups``.
    181       total_amount: Amount;
    182 
    183       // One entry per `RecoupedCoin` in the request, in the same order.
    184       recoups: RecoupedCoinResult[];
    185 
    186       // Signature over `TALER_RecoupRefreshBatchConfirmationPS` with
    187       // purpose ``TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH_BATCH``,
    188       // affirming the recoup of all coins in ``recoups``.
    189       exchange_sig: EddsaSignature;
    190 
    191       // Public key used to create ``exchange_sig``.
    192       // Should match one of the exchange's signing keys from ``/keys``.
    193       exchange_pub: EddsaPublicKey;
    194     }
    195 
    196   The coin histories report each recouped coin individually, see
    197   `CoinRecoupRefreshTransaction` for the recouped coin and
    198   `CoinRecoupRefreshReceiverTransaction` for the old coin.  Those entries
    199   carry a signature per coin over :ref:`TALER_RecoupRefreshConfirmationPS <TALER_RecoupRefreshConfirmationPS>`,
    200   which the exchange creates when a history is requested; the batch
    201   signature above is only part of the response to this request.