summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2023-01-07 16:24:30 +0100
committerÖzgür Kesim <oec-taler@kesim.org>2023-01-07 16:24:39 +0100
commitc7444f87f7c699f8da8fd5d1d687d6a28021e760 (patch)
treef0537e935e69de359523c304c46003a921893a6a
parentaac32217084215621a374f737dec5796838e1133 (diff)
downloaddocs-c7444f87f7c699f8da8fd5d1d687d6a28021e760.tar.gz
docs-c7444f87f7c699f8da8fd5d1d687d6a28021e760.tar.bz2
docs-c7444f87f7c699f8da8fd5d1d687d6a28021e760.zip
redo withdraw with age restriction
-rw-r--r--core/api-common.rst23
-rw-r--r--core/api-exchange.rst345
2 files changed, 196 insertions, 172 deletions
diff --git a/core/api-common.rst b/core/api-common.rst
index 4faaf88d..8468cc3b 100644
--- a/core/api-common.rst
+++ b/core/api-common.rst
@@ -830,30 +830,17 @@ within the
struct TALER_BlindedCoinHash h_coin_envelope;
};
-.. _TALER_WithdrawAgeRestrictedRequestPS:
+.. _TALER_AgeWithdrawRequestPS:
.. sourcecode:: c
- struct TALER_WithdrawAgeRestrictedRequestPS {
+ struct TALER_AgeWithdrawRequestPS {
/**
- * purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW_AGE_RESTRICTED
+ * purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_AGE_WITHDRAW
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
struct TALER_ReservePublicKeyP reserve_pub;
- struct GNUNET_HashCode h_age_restricted_coin_commitments;
- };
-
-
-.. _TALER_WithdrawAgeRestrictedRevealRequestPS:
-.. sourcecode:: c
-
- struct TALER_WithdrawAgeRestrictedRevealRequestPS {
- /**
- * purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW_AGE_RESTRICTED_REVEAL
- */
- struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
- struct GNUNET_HashCode denoms_h;
- struct GNUNET_HashCode coin_evs;
- struct GNUNET_HashCode disclosed_coins;
+ struct GNUNET_HashCode age_restricted_coins_commitment;
+ struct GNUNET_HashCode h_denoms_h;
};
diff --git a/core/api-exchange.rst b/core/api-exchange.rst
index 09ea52d3..0b90ea12 100644
--- a/core/api-exchange.rst
+++ b/core/api-exchange.rst
@@ -1255,7 +1255,7 @@ exchange.
// withdrawal.
// The value represents a valid age group from the list of permissible
// age groups as defined by the exchange's output to /keys.
- maximum_age_group: number;
+ maximum_age_group?: number;
}
@@ -1632,6 +1632,68 @@ exchange.
}
+.. _delete-reserve:
+
+.. http:DELETE:: /reserves/$RESERVE_PUB
+
+ Forcefully closes a reserve.
+ The request header must contain an *Account-Request-Signature*.
+ Note: this endpoint is not currently implemented!
+
+ **Request:**
+
+ *Account-Request-Signature*: The client must provide Base-32 encoded EdDSA signature made with ``$ACCOUNT_PRIV``, affirming its authorization to delete the account. The purpose used MUST be ``TALER_SIGNATURE_RESERVE_CLOSE``.
+
+ :query force=BOOLEAN: *Optional.* If set to 'true' specified, the exchange
+ will delete the account even if there is a balance remaining.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The operation succeeded, the exchange provides details
+ about the account deletion.
+ The response will include a `ReserveClosedResponse` object.
+ :http:statuscode:`403 Forbidden`:
+ 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.
+ :http:statuscode:`409 Conflict`:
+ The account is still has digital cash in it, the associated
+ wire method is ``void`` and the *force* option was not provided.
+ This response comes with a standard `ErrorDetail` response.
+
+ **Details:**
+
+ .. ts:def:: ReserveClosedResponse
+
+ interface ReserveClosedResponse {
+
+ // Final balance of the account.
+ closing_amount: Amount;
+
+ // Current time of the exchange, used as part of
+ // what the exchange signs over.
+ close_time: Timestamp;
+
+ // Hash of the wire account into which the remaining
+ // balance will be transferred. Note: may be the
+ // hash over ``payto://void/`, in which case the
+ // balance is forfeit to the profit of the exchange.
+ h_wire: HashCode;
+
+ // This is a signature over a
+ // struct ``TALER_AccountDeleteConfirmationPS`` with purpose
+ // ``TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED``.
+ exchange_sig: EddsaSignature;
+
+ }
+
+
+
+Withdraw
+~~~~~~~~
+
.. http:post:: /csr-withdraw
Obtain exchange-side input values in preparation for a
@@ -1701,6 +1763,7 @@ exchange.
r_pub_1: CsRPublic;
}
+
.. http:post:: /reserves/$RESERVE_PUB/withdraw
Withdraw a coin of the specified denomination. Note that the client should
@@ -1885,6 +1948,10 @@ exchange.
+Batch Withdraw
+~~~~~~~~~~~~~~
+
+
.. http:post:: /reserves/$RESERVE_PUB/batch-withdraw
Withdraw multiple coins from the same reserve. Note that the client should
@@ -1893,8 +1960,7 @@ exchange.
recover the information if necessary in case of transient failures, like
power outage, network outage, etc.
- **Request:** The request body must be a `BatchWithdrawRequest` object. TODO:
- describe differences.
+ **Request:** The request body must be a `BatchWithdrawRequest` object.
**Response:**
@@ -1903,14 +1969,6 @@ exchange.
Note that repeating exactly the same request will again yield the same
response, so if the network goes down during the transaction or before the
client can commit the coin signature to disk, the coin is not lost.
-
- If the reserve did not require age restriction to be set, the
- `BatchWithdrawResponse` will consist of the signatures of the blinded coins.
- However, if the reserve requires age restriction to be set for the coins,
- the request must have been a `WithdrawAgeRestrictedRequests`, containing
- all commitments to all coins with age restriction, and the response will
- contain the index that the client has not to reveal in a subsequent call to
- ``/reserves/$RESERVE_PUB/reveal/$RCH``.
:http:statuscode:`403 Forbidden`:
A signature is invalid.
This response comes with a standard `ErrorDetail` response.
@@ -1957,56 +2015,107 @@ exchange.
.. ts:def:: BatchWithdrawRequest
- type BatchWithdawRequest =
- | WithdrawRequests
- | WithdrawAgeRestrictedRequest
-
-
- .. ts:def:: WithdrawRequests
-
- interface WithdrawRequests {
+ interface BatchWithdrawRequest {
// Array of requests for the individual coins to withdraw.
planchets: WithdrawRequest[];
}
- .. ts:def:: WithdrawAgeRestrictedRequest
+ .. ts:def:: BatchWithdrawResponse
- interface WithdrawAgeRestrictedRequests {
- // Array of commitments for coins with age restriction.
- // The SHA512 hash value $RCH of this field has to be used in the
- // subsequent call to /reserve/$RESERVE_PUB/reveal/$RCH.
- age_restricted_coin_commitments: HashCode[];
+ interface BatchWithdrawResponse {
+ // Array of blinded signatures, in the same order as was
+ // given in the request.
+ ev_sigs: WithdrawResponse[];
- // Signature of `TALER_WithdrawAgeRestrictedRequestPS` created with
- // the `reserves's private key <reserve-priv>`
- // using purpose ``TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW_AGE_RESTRICTED``.
- // The field ``.h_age_restricted_coin_commitments`` in that struct MUST
- // be the SHA512 hash value of ``age_restricted_coin_commitments``
- // (which is also the value for $RSH in the subsequent request to
- // /reserve/$RESERVE_PUB/reveal/$RSH.)
- reserve_sig: EddsaSignature;
}
- .. ts:def:: BatchWithdrawResponse
+Withdraw with Age Restriction
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- type BatchWithdrawResponse =
- | BlindedSignaturesResponse
- | WithdrawRevealRequiredResponse;
+If the reserve was marked with a maximum age group, the client has to perform a
+cut&choose protocol with the exchange. It first calls
+``/reserves/$RESERVE_PUB/age-withdraw`` and commits to ``n*kappa`` coins. On
+success, the exchange answers this request with an noreveal-index. The client
+then has to call ``/age-withdraw/$ACH/reveal`` to reveal all ``n*(kappa - 1)``
+coins along with their age commitments to proof that they were appropriate.
+If so, the exchange will blindly sign ``n`` undisclosed coins from the request.
- .. ts:def:: BlindedSignaturesResponse
- interface BlindedSignaturesResponse {
- // Array of blinded signatures, in the same order as was
- // given in the request.
- ev_sigs: WithdrawResponse[];
+.. http:POST:: /reserves/$RESERVE_PUB/age-withdraw
+
+ Withdraw multiple coins *with age restriction* from the same reserve.
+ Note that the client should commit all of the request details, including the
+ private key of the coins and the blinding factors, to disk *before* issuing
+ this request, so that it can recover the information if necessary in case of
+ transient failures, like power outage, network outage, etc.
+
+ **Request:** The request body must be a `AgeWithdrawRequest` object.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The request was successful, and the response is a `AgeWithdrawResponse`.
+ Note that repeating exactly the same request will again yield the same
+ response, so if the network goes down during the transaction or before the
+ client can commit the coin signature to disk, the coin is not lost.
+ :http:statuscode:`403 Forbidden`:
+ A signature is invalid.
+ This response comes with a standard `ErrorDetail` response.
+ :http:statuscode:`404 Not found`:
+ A denomination key or the reserve are not known to the exchange. If the
+ denomination key is unknown, this suggests a bug in the wallet as the
+ wallet should have used current denomination keys from ``/keys``.
+ In this case, the response will be a `DenominationUnknownMessage`.
+ If the reserve is unknown, the wallet should not report a hard error yet, but
+ instead simply wait for up to a day, as the wire transaction might simply
+ not yet have completed and might be known to the exchange in the near future.
+ In this case, the wallet should repeat the exact same request later again
+ using exactly the same blinded coin.
+ :http:statuscode:`409 Conflict`:
+ The balance of the reserve is not sufficient to withdraw the coins of the
+ indicated denominations. The response is `WithdrawError` object.
+ :http:statuscode:`410 Gone`:
+ A requested denomination key is not yet or no longer valid.
+ It either before the validity start, past the expiration or was revoked.
+ The response is a `DenominationExpiredMessage`. Clients must evaluate the
+ error code provided to understand which of the cases this is and handle it
+ accordingly.
+ :http:statuscode:`451 Unavailable for Legal Reasons`:
+ This reserve has received funds from a purse or the amount withdrawn
+ exceeds another legal threshold and thus the reserve must
+ be upgraded to an account (with KYC) before the withdraw can
+ complete. Note that this response does NOT affirm that the
+ withdraw will ultimately complete with the requested amount.
+ The user should be redirected to the provided location to perform
+ the required KYC checks to open the account before withdrawing.
+ Afterwards, the request should be repeated.
+ The response will be an `KycNeededRedirect` object.
+
+ .. ts:def:: AgeWithdrawRequest
+
+ interface AgeWithdrawRequest {
+ // Commitment to the coins with age restriction. This is the SHA512
+ // hash value $ACH over all n*kappa `TALER_CoinPubHashP` values of all
+ // coins and their age commitments.
+ // It is also used in the subsequent call to /age-withdraw/$ACH/reveal.
+ age_restricted_coins_commitment: HashCode;
+ // Array of ``n`` hash codes of denomination public keys to order.
+ // These denominations MUST support age restriction as defined in the
+ // output to ``/keys``.
+ denoms_h: HashCode[];
+
+ // Signature of `TALER_AgeWithdrawRequestPS` created with
+ // the `reserves's private key <reserve-priv>`
+ // using purpose ``TALER_SIGNATURE_WALLET_RESERVE_AGE_WITHDRAW``.
+ reserve_sig: EddsaSignature;
}
- .. ts:def:: WithdrawRevealRequiredResponse
+ .. ts:def:: AgeWithdrawResponse
- interface WithdrawRevealRequiredResponse {
+ interface AgeWithdrawResponse {
// index of the commitments that the client doesn't
// have to disclose
noreveal_index: Integer;
@@ -2023,18 +2132,19 @@ exchange.
}
-.. http:POST:: /reserves/$RESERVE_PUB/reveal/$RCH
+
+.. http:POST:: /age-withdraw/$ACH/reveal
The client has previously committed to multiple coins with age restriction
- in a call to ``/reserve/$RESERVE_PUB/batch-withdraw`` and got a
- `WithdrawRevealRequiredResponse` from the exchange. By calling this
- endpoint, the client has to reveal each coin and their :math:`\kappa - 1`
+ in a call to ``/reserve/$RESERVE_PUB/age-withdraw`` and got a
+ `AgeWithdrawResponse` from the exchange. By calling this
+ endpoint, the client has to reveal each coin and their ``kappa - 1``
age commitments, except for the age commitments with index
``noreveal_index``. The hash of all commitments from the former withdraw
- request is given as the ``$RCH`` value in the URL to this endpoint.
+ request is given as the ``$ACH`` value in the URL to this endpoint.
- **Request:** The request body must be a `WithdrawRevealRequest` object.
+ **Request:** The request body must be a `AgeWithdrawRevealRequest` object.
**Response:**
@@ -2044,70 +2154,55 @@ exchange.
response, so if the network goes down during the transaction or before the
client can commit the coin signature to disk, the coin is not lost.
:http:statuscode:`404 Not found`:
- A denomination key is not known to the exchange. If the denomination key
- is unknown, this suggests a bug in the wallet as the wallet should have
- used current denomination keys from ``/keys``. The response will be a
- `DenominationUnknownMessage`.
+ The commitment $ACH was not found.
:http:statuscode:`409 Conflict`:
- There are multiple reasons for this:
-
- #. The balance of the reserve is not sufficient to withdraw the coins of
- the indicated denominations.
- #. A denomination referred to in the request doesn't support age
- restriction.
- #. An age commitment for one of the coins did not fulfill the required
- maximum age requirement of the corresponding reserve.
-
- The response is an `WithdrawError` object.
- :http:statuscode:`410 Gone`:
- A requested denomination key is not yet or no longer valid.
- It either before the validity start, past the expiration or was revoked.
- The response is a `DenominationExpiredMessage`. Clients must evaluate the
- error code provided to understand which of the cases this is and handle it
- accordingly.
-
+ An age commitment for one of the coins did not fulfill the required maximum
+ age requirement of the corresponding reserve. The response is an
+ `WithdrawError` object.
.. ts:def:: WithdrawRevealRequest
interface WithdrawRevealRequest {
- // Array of ``n`` hash codes of denomination public keys to order.
- // These denominations MUST support age restriction as defined in the
- // output to ``/keys``.
- denoms_h: HashCode[];
-
// Array of ``n`` entries with blinded coins, matching the respective
- // entries in ``denoms_h``. These are the non-desclosed coins from the
- // previous commitments.
+ // entries in ``denoms_h`` from the previous call to
+ // the /reserve/$RESERVE_PUB/age-withraw endpoint. These are the
+ // non-desclosed coins from the previous commitment.
coin_evs: CoinEnvelope[];
// Array of ``n`` arrays of ``kappa - 1`` disclosed coin public keys
// together with their age commitments.
disclosed_coins: DisclosedAgeRestrictedCoin[][];
- // Signature of `TALER_WithdrawAgeRestrictedRevealRequestPS` created with
- // the `reserves's private key <reserve-priv>`
- // using purpose ``TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW_AGE_RESTRICTED_REVEAL``.
- reserve_sig: EddsaSignature;
}
.. ts:def:: DisclosedAgeRestrictedCoin
interface DisclosedAgeRestrictedCoin {
- // Hash of the coin's public key.
- coin_pub_h: HashCode;
-
- // Age commitment for this coin, up to the maximum age group allowed
- // by the associated reserve. The length of the array therefore MUST be
- // equal to <maximum age group allowed according to reserve> (including 0).
- max_age_commitment: Edx25519PublicKey[];
+ // The coin's private key.
+ //
+ // The age commitment for this coin MUST be derived from this
+ // private key as follows:
+ //
+ // For age group $AG from 1 up to
+ // <maximum age group as defined in the reserve>
+ // (if they exist), set
+ // seed = HDKF(coin_priv, "age-commitment", $AG)
+ // p[$AG] = Edx25519_generate_private(seed)
+ // and calculate the corresponding Edx25519PublicKey as
+ // q[$AG] = Edx25519_public_from_private(p[$AG])
+ //
+ // For age groups _larger_ than the maximum age group allowed
+ // (if they exist), set
+ // f[$AG] = HDKF(coin_priv, "age-factor", $AG)
+ // and calculate the corresponding Edx25519PublicKey as
+ // q[$AG] = Edx25519_derive_public(PublishedBaseKey, f[$AG])
+ //
+ // Finally, with coin_priv and age commitment (q[]), the exchange
+ // will calculate the coin's public key coin_pub and use the
+ // TALER_CoinPubHashP(coin_pub, age_commitment_hash(q))
+ // during the verification of the original age-withdraw-commitment
+ coin_priv: EddsaPrivateKey;
- // For all age groups _larger_ than the maximum age, the client MUST provide
- // the scalar factors with which it had multiplied the published public
- // key `BasePublicKey`. Formaly, they are encoded as `Edx25519PrivateKey`.
- // The length of this array MUST be
- // ( <maximum age group defined in exchange>
- // - <maximum age group allowed according to reserve> ).
- larger_age_factors: Edx25519PrivateKey[];
}
.. ts:def:: BasePublicKey
@@ -2115,64 +2210,6 @@ exchange.
type BasePublicKey = Edx25519PublicKey(...); // TODO: definition!
-.. _delete-reserve:
-
-.. http:DELETE:: /reserves/$RESERVE_PUB
-
- Forcefully closes a reserve.
- The request header must contain an *Account-Request-Signature*.
- Note: this endpoint is not currently implemented!
-
- **Request:**
-
- *Account-Request-Signature*: The client must provide Base-32 encoded EdDSA signature made with ``$ACCOUNT_PRIV``, affirming its authorization to delete the account. The purpose used MUST be ``TALER_SIGNATURE_RESERVE_CLOSE``.
-
- :query force=BOOLEAN: *Optional.* If set to 'true' specified, the exchange
- will delete the account even if there is a balance remaining.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- The operation succeeded, the exchange provides details
- about the account deletion.
- The response will include a `ReserveClosedResponse` object.
- :http:statuscode:`403 Forbidden`:
- 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.
- :http:statuscode:`409 Conflict`:
- The account is still has digital cash in it, the associated
- wire method is ``void`` and the *force* option was not provided.
- This response comes with a standard `ErrorDetail` response.
-
- **Details:**
-
- .. ts:def:: ReserveClosedResponse
-
- interface ReserveClosedResponse {
-
- // Final balance of the account.
- closing_amount: Amount;
-
- // Current time of the exchange, used as part of
- // what the exchange signs over.
- close_time: Timestamp;
-
- // Hash of the wire account into which the remaining
- // balance will be transferred. Note: may be the
- // hash over ``payto://void/`, in which case the
- // balance is forfeit to the profit of the exchange.
- h_wire: HashCode;
-
- // This is a signature over a
- // struct ``TALER_AccountDeleteConfirmationPS`` with purpose
- // ``TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED``.
- exchange_sig: EddsaSignature;
-
- }
-
-
.. _deposit-par: