taler-docs

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

commit 30953a942d17a03abf4e5061b2bcbabc357bbd7d
parent 60cc468cad2b18d8c7ec23ae648747b5dfc47e08
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat, 17 Oct 2026 15:51:42 +0200

new /keys fields for v42 to bound purse expiration as needed for auditor

Diffstat:
Mcore/api-exchange.rst | 8+++++++-
Mcore/auditor/get-monitoring-historic-denomination-revenue.rst | 11+++++++++--
Mcore/exchange/get-keys.rst | 10++++++++++
Mcore/exchange/post-purses-PURSE_PUB-create.rst | 15++++++++++++++-
Mcore/exchange/post-purses-PURSE_PUB-deposit.rst | 10+++++++++-
Mcore/exchange/post-reserves-RESERVE_PUB-purse.rst | 9+++++++++
Mtaler-exchange-manual.rst | 19+++++++++++++++++++
7 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/core/api-exchange.rst b/core/api-exchange.rst @@ -70,7 +70,13 @@ The currently implemented protocol version is **v42**. adds the required ``reserve_pub`` field to the :http:post:`/reveal-withdraw </reveal-withdraw>` request body, so that a withdraw operation is identified by the pair - (reserve, commitment) everywhere + (reserve, commitment) everywhere; + bounds ``purse_expiration`` by the new ``max_p2p_expiration`` + of :http:get:`/keys </keys>` and by the legal expiration of the + denominations of the coins in the purse, with the new error + codes ``TALER_EC_EXCHANGE_PURSE_CREATE_EXPIRATION_TOO_LATE``, + ``TALER_EC_EXCHANGE_RESERVES_PURSE_EXPIRATION_TOO_LATE`` and + ``TALER_EC_EXCHANGE_PURSE_DENOMINATION_LEGAL_EXPIRES_TOO_SOON`` **Upcoming versions:** diff --git a/core/auditor/get-monitoring-historic-denomination-revenue.rst b/core/auditor/get-monitoring-historic-denomination-revenue.rst @@ -2,6 +2,12 @@ Get a list of historic denomination revenue stored by the auditor. + A denomination is booked here once its legal period is over, so that the + entry is final. There can nonetheless be more than one entry per + denomination: if the exchange moves value on a denomination that was + already booked, the auditor appends the additional revenue as another + entry instead of changing the one it already published. + The following query parameters are optional, and can be used to customise the response: **Request:** @@ -50,8 +56,9 @@ // Hash code of the denomination public key involved h_denom_pub : HashCode; - // Time when the denomination expired and thus the revenue - // was computed. + // Time when the denomination expired for deposits. Note that + // the revenue is only booked once the legal period of the + // denomination is over as well. revenue_timestamp : Timestamp; // Total fee revenue the exchange earned from coins of this diff --git a/core/exchange/get-keys.rst b/core/exchange/get-keys.rst @@ -165,6 +165,16 @@ // @since protocol **v35**. default_p2p_push_expiration: RelativeTime; + // How far in the future may the ``purse_expiration`` of a purse be? + // An expiring purse refunds the coins deposited into it, and the + // exchange must still be able to account for that refund, so a purse + // may not outlive the denominations of the coins in it. Applies to + // both purse-creating endpoints, and in addition no coin may be + // deposited into a purse that would outlive the + // ``stamp_expire_legal`` of the coin's own denomination. + // @since protocol **v42**. + max_p2p_expiration: RelativeTime; + // Threshold amounts beyond which wallet should // trigger the KYC process of the issuing exchange. // Optional option, if not given there is no limit. diff --git a/core/exchange/post-purses-PURSE_PUB-create.rst b/core/exchange/post-purses-PURSE_PUB-create.rst @@ -6,6 +6,13 @@ The request body must be a `PurseCreateRequest` object. + A purse that is never merged refunds its coins when it expires, and the + exchange must still be able to account for that refund. + ``purse_expiration`` is therefore limited to ``max_p2p_expiration`` (see + :http:get:`/keys </keys>`) from now, and in addition no coin may be + deposited into a purse that outlives the ``stamp_expire_legal`` of the + coin's own denomination. + **Response:** :http:statuscode:`200 OK`: @@ -17,8 +24,12 @@ This response comes with a standard `ErrorDetail` response. Possible error codes include ``TALER_EC_GENERIC_PARAMETER_MALFORMED``, ``TALER_EC_EXCHANGE_PURSE_CREATE_EXPIRATION_BEFORE_NOW``, - ``TALER_EC_EXCHANGE_PURSE_CREATE_EXPIRATION_IS_NEVER``, or + ``TALER_EC_EXCHANGE_PURSE_CREATE_EXPIRATION_IS_NEVER``, + ``TALER_EC_EXCHANGE_PURSE_CREATE_EXPIRATION_TOO_LATE``, + ``TALER_EC_EXCHANGE_PURSE_DENOMINATION_LEGAL_EXPIRES_TOO_SOON``, or ``TALER_EC_EXCHANGE_CREATE_PURSE_NEGATIVE_VALUE_AFTER_FEE``. + For the two expiration errors the ``detail`` of the `ErrorDetail` + gives the latest purse expiration that would have been accepted. :http:statuscode:`403 Forbidden`: A coin, denomination or contract signature is invalid. This response comes with a standard `ErrorDetail` response. @@ -111,6 +122,8 @@ // 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. + // Must not be further in the future than + // ``max_p2p_expiration`` of :http:get:`/keys </keys>`. purse_expiration: Timestamp; } diff --git a/core/exchange/post-purses-PURSE_PUB-deposit.rst b/core/exchange/post-purses-PURSE_PUB-deposit.rst @@ -6,6 +6,11 @@ The request body must be a `PurseDeposits` object. + A purse that is not decided refunds the coins deposited into it when it + expires, and the exchange must still be able to account for that refund. + A coin whose denomination would stop being legally valid before the + purse expires is therefore refused. + **Response:** :http:statuscode:`200 OK`: @@ -15,7 +20,10 @@ :http:statuscode:`400 Bad Request`: The request body is malformed or a parameter is invalid. This response comes with a standard `ErrorDetail` response with - a code of ``TALER_EC_GENERIC_PARAMETER_MALFORMED``. + a code of ``TALER_EC_GENERIC_PARAMETER_MALFORMED`` or of + ``TALER_EC_EXCHANGE_PURSE_DENOMINATION_LEGAL_EXPIRES_TOO_SOON``, + whose ``detail`` gives the ``stamp_expire_legal`` of the denomination + that is too short-lived for this purse. :http:statuscode:`403 Forbidden`: A coin or denomination signature is invalid. This response comes with a standard `ErrorDetail` response. diff --git a/core/exchange/post-reserves-RESERVE_PUB-purse.rst b/core/exchange/post-reserves-RESERVE_PUB-purse.rst @@ -6,6 +6,11 @@ The request body must be a `ReservePurseRequest` object. + A purse that is not paid in full refunds the coins that were deposited + into it when it expires, and the exchange must still be able to account + for that refund. ``purse_expiration`` is therefore limited to + ``max_p2p_expiration`` (see :http:get:`/keys </keys>`) from now. + **Response:** :http:statuscode:`200 OK`: @@ -24,6 +29,10 @@ A purse expiration time of "never" is not allowed. 4. ``TALER_EC_EXCHANGE_RESERVES_PURSE_FEE_TOO_LOW``: The specified purse fee is lower than allowed. + 5. ``TALER_EC_EXCHANGE_RESERVES_PURSE_EXPIRATION_TOO_LATE``: + The requested purse expiration time is further in the future than + ``max_p2p_expiration`` allows. The ``detail`` of the `ErrorDetail` + gives the latest purse expiration the exchange accepts. :http:statuscode:`403 Forbidden`: Account or contract signature is invalid. diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst @@ -684,6 +684,18 @@ Payment data is deleted whenever the legal expiration date for the ``DURATION_LEGAL`` configured in the respective section ``coin`` is reached (typically also after 10 years). +Because a purse refunds the coins deposited into it when it expires, and +the auditor has to be able to account for that refund, the expiration of +a purse is bounded by ``PURSE_EXPIRATION_LIMIT`` in the ``[exchange]`` +section. It must not exceed the shortest ``DURATION_LEGAL`` of any +denomination and is published to clients in ``/keys``; if the option is +not given, the exchange uses that shortest ``DURATION_LEGAL`` and logs a +warning. Lowering ``DURATION_LEGAL`` by some span X with effect from +time T therefore requires lowering ``PURSE_EXPIRATION_LIMIT`` by X at +T-X, so that the purses created before the change are short enough for +the denominations issued after it; otherwise deposits of the new coins +into those older purses are refused. + Basic Setup: Currency, Denominations and Keys ============================================= @@ -733,6 +745,13 @@ must then have the following options: values result in lower storage costs for the exchange. - ``DURATION_LEGAL``: How long is the coin of the given type legal? + ``DURATION_WITHDRAW`` plus ``DURATION_SPEND`` plus ``DURATION_LEGAL`` + must not exceed ``LEGAL_RESERVE_EXPIRATION_TIME`` of the + ``[exchangedb]`` section, as otherwise the garbage collection could + drop the denomination before the auditor is done accounting for it. + ``DURATION_LEGAL`` must also be at least ``PURSE_EXPIRATION_LIMIT`` + of the ``[exchange]`` section. The exchange refuses to start if + either is violated. - ``FEE_WITHDRAW``: What does it cost to withdraw this coin? Specified using the same format as value.