taler-docs

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

071-auto-refresh.rst (15151B)


      1 DD 71: Auto-refresh
      2 ###################
      3 
      4 :Design status: Proposed
      5 :Implementation status: Prototype
      6 :DD shepherd: TBD
      7 :Historical contributors: Christian Grothoff
      8 :First published: 2025-10-23
      9 :Last substantive change: 2026-09-05
     10 :Implementation evidence: ``taler-typescript-core`` commit ``4889bee049023c59a125973532b847ec60ab6f1b`` (2026-08-19, feature-branch prototype of the earlier policy)
     11 
     12 Summary
     13 =======
     14 
     15 This document describes when the wallet should automatically refresh
     16 non-dirty coins, how exchanges should configure denomination keys for this
     17 policy, and how the wallet can bound the cost of keeping a balance.
     18 
     19 It addresses `issue 6563 <https://bugs.gnunet.org/view.php?id=6563>`_,
     20 including predictable refresh costs, and its duplicate
     21 `issue 7847 <https://bugs.gnunet.org/view.php?id=7847>`_, about synchronized
     22 refresh traffic.
     23 
     24 .. note::
     25 
     26    The prototype implements the earlier policy, not the revisions proposed here.
     27 
     28 
     29 Motivation
     30 ==========
     31 
     32 The wallet must refresh non-dirty coins before they expire, lest the user
     33 lose money. Refreshing too early causes avoidable fees and exchange load;
     34 waiting too long risks the wallet not going online before expiration.
     35 No policy can protect a wallet that remains offline beyond its coins'
     36 validity periods.
     37 
     38 
     39 Requirements
     40 ============
     41 
     42 * Preserve funds under ordinary operating conditions, without clearly
     43   avoidable refresh operations.
     44 * Spread automatic refresh traffic across wallets holding the same
     45   denomination, including when an exchange publishes replacement keys.
     46 * Explain expiration risk and the conditions under which refresh-cost
     47   estimates apply.
     48 * Within an equivalence class of otherwise interchangeable coins, the wallet
     49   MUST spend those with the earliest deposit expiration first.
     50 * Account for different denomination lifetimes and changes in the exchange's
     51   offerings. Operator recommendations are not assumptions that the wallet may
     52   make about an arbitrary exchange.
     53 
     54 
     55 Proposed Solution
     56 =================
     57 
     58 Lifetimes and output selection
     59 ------------------------------
     60 
     61 A day means 24 hours. The thresholds below use fixed durations of 90, 180,
     62 and 360 days, not calendar months. For an input denomination define::
     63 
     64    D = stamp_expire_deposit
     65    W = stamp_expire_withdraw
     66    G = D - W
     67    R = D - now
     68    E = min(90 days, G / 4)
     69 
     70 ``G`` is the deposit period after withdrawals close; ``E`` is the adaptive
     71 emergency threshold. This policy requires finite timestamps with ``G > 0``.
     72 An invalid lifetime must be reported rather than used to schedule refreshes.
     73 Already-expired coins follow existing expiry/recovery handling; they must not
     74 be treated as ordinary auto-refresh candidates.
     75 
     76 For each eligible input coin, consider feasible, nonempty output selections
     77 from currently withdrawable, verified, non-revoked, non-lost denomination
     78 keys at its exchange. Respect currency, cipher, age restrictions, and refresh
     79 protocol limits. The input must be fresh and available, rather than reserved
     80 for a payment or already participating in a refresh.
     81 
     82 Selections must fit the input value after melting and output withdrawal fees,
     83 as specified by ``/melt`` in the :doc:`exchange API <../core/api-exchange>`::
     84 
     85    recovered_value = sum of output coin face values
     86    total_cost = input_value - recovered_value
     87    output_expiration = earliest deposit expiration among selected outputs
     88    output_remaining = output_expiration - now
     89 
     90 ``total_cost`` includes melting fees, output withdrawal fees, and value that
     91 cannot be represented by the selected denominations. A refresh is free only
     92 if ``total_cost`` is zero, not merely when ``fee_refresh`` is zero.
     93 
     94 Select outputs in this order, before evaluating the refresh rules:
     95 
     96 1. Maximize recovered value.
     97 2. Among equally valuable selections, maximize ``output_expiration``.
     98 3. Among remaining ties, minimize the number of output coins.
     99 4. Break remaining ties by the lexicographic order of sorted denomination
    100    hash/count pairs.
    101 
    102 If the chosen selection cannot extend validity or recover positive value,
    103 do not melt; wait and report expiration risk when applicable.
    104 
    105 The decision and execution MUST use the same selected outputs. Revalidate
    106 input availability, keys, and rule eligibility before melting. If the plan
    107 has become invalid, recompute it rather than silently executing a different
    108 selection. Once a melt has succeeded, finish that refresh using its committed
    109 outputs through the existing refresh lifecycle.
    110 
    111 Refresh rules
    112 -------------
    113 
    114 Evaluate the following rules in priority order using the chosen output
    115 selection. Any matching rule makes the input eligible for scheduled refresh:
    116 
    117 1. ``output_remaining > 4 * R``: the refresh provides a substantial extension.
    118 2. ``R < 180 days``, ``output_remaining > 360 days``, ``total_cost == 0``, and
    119    confirmed external power: opportunistically refresh without losing value.
    120    Unknown power state does not qualify for this rule.
    121 3. ``R < E`` and ``output_expiration > D``: attempt an emergency extension.
    122 
    123 All inequalities are strict. Equality alone does not satisfy a rule; schedule
    124 its next evaluation for the first representable time after the boundary.
    125 Battery state gates only rule 2, not necessary refreshes under rules 1 or 3.
    126 Apply the decision to all available coins of the input denomination with the
    127 same value and compatibility constraints.
    128 
    129 A currently withdrawable output has at least its own ``G`` remaining, well
    130 above its emergency threshold of at most ``G / 4``. This prevents repeated
    131 emergency refreshes merely because slightly newer short-lived keys appear.
    132 
    133 Scheduling and retries
    134 ----------------------
    135 
    136 On first observing eligibility, choose an independent uniform random delay
    137 per wallet and input denomination, using private wallet randomness::
    138 
    139    urgent_boundary = D - E / 10
    140    delay_cap = min(1 day, E / 10, (urgent_boundary - now) / 2)
    141 
    142 Before the urgent boundary, draw a delay from zero to ``delay_cap`` and
    143 persist the execution deadline. At or beyond that boundary, attempt refresh
    144 immediately. This spreads traffic across wallets, including when new keys
    145 are published, while retaining time for retries.
    146 
    147 Restarts, checks, and key updates MUST NOT redraw or postpone the deadline.
    148 A missed deadline is due immediately if still eligible. Otherwise retain it
    149 until a valid plan is available, without repeatedly executing an ineligible
    150 task. Move it earlier if needed for urgency; clear it when no applicable fresh
    151 coins remain. Coins of the same denomination may share a wallet's deadline.
    152 
    153 Reevaluate on startup, relevant key or coin changes, external-power changes,
    154 and the next known rule boundary. Revalidate before execution and persist
    155 in-progress state to prevent duplicate refresh groups. Use randomized retry
    156 backoff capped by the time to the urgent boundary; once urgent, cap waits by
    157 remaining deposit lifetime without an additional DD71 delay. Avoid busy loops.
    158 Outages can still prevent successful refresh.
    159 
    160 Warnings
    161 --------
    162 
    163 Evaluate warnings independently of the selected rule. For ``0 < R < E``, show
    164 expiration risk in the currency balance with the exchange, affected amount,
    165 and earliest expiration. Pending or failing refreshes retain that indication
    166 until successful completion. Distinguish connectivity failures, exchange
    167 errors, unavailable suitable replacements according to fresh key information,
    168 and a pending refresh; do not infer device-wide offline status.
    169 
    170 After successfully refreshing coins whose pre-melt ``R`` was below ``E``,
    171 provide one recovery notice per refresh group, even if rule 1 matched. State
    172 that coins close to expiration were renewed; do not assert that the wallet
    173 was offline. Show the next relevant date, since safe reopening intervals
    174 depend on denomination lifetimes. Already-expired funds use the existing
    175 expiry indication.
    176 
    177 Exchange Configuration Recommendations
    178 ======================================
    179 
    180 For a general-purpose exchange, start with this guidance for every relevant
    181 denomination family::
    182 
    183    DURATION_SPEND = 720 days
    184    DURATION_WITHDRAW = 30 days
    185 
    186 These are recommendations, not protocol requirements or universal optima.
    187 In the exchange implementation, ``DURATION_SPEND`` runs from withdrawal
    188 expiration to deposit expiration: it is ``G``, not the interval from key
    189 validity start to deposit expiration. With this configuration, a coin acquired
    190 during its withdrawal window has between 720 and 750 days left to deposit.
    191 
    192 Rationale
    193 ---------
    194 
    195 * Replacement validity of 720--750 days makes rule 1 eligible with roughly
    196   180--187.5 days left, leaving substantial margin before the 90-day emergency
    197   threshold. Under stable offerings, paid refreshes are separated by at least
    198   ``720 - 750 / 4 = 532.5 days`` along each sequence of replacement coins.
    199 * The 30-day issuance window limits replacement-lifetime variation to about
    200   four percent and limits how long a key is used for issuing coins. It does
    201   not eliminate compromise risk during the longer spending period.
    202 * Longer spending periods require more coin-state storage; shorter issuance
    203   windows require more keys and key-management work. These values balance
    204   those costs with occasionally opened wallets, rather than representing a
    205   measured optimum. The 720 days are two fixed 360-day periods, not calendar
    206   years.
    207 
    208 Keep spending lifetimes comparable across denominations, including affordable
    209 change, and fees low enough to permit positive refresh outputs. Maintain
    210 continuous replacement-key coverage for all required values, ciphers, and age
    211 restrictions. Shorter spending periods require more frequent refreshes and
    212 shorter offline intervals; the adaptive rule remains a fallback.
    213 
    214 Follow the :ref:`exchange's denomination-key guidance <Coins-denomination-keys>`:
    215 withdrawal overlap must be below ``DURATION_WITHDRAW``; ``LOOKAHEAD_SIGN`` should
    216 be at least one year, with offline signing at least every six months. Keys
    217 must be signed and published, and are usable only once their validity starts.
    218 For lifetime or fee changes, introduce new configuration sections as the
    219 manual requires, preserving suitable replacements for existing coins.
    220 
    221 Conditional Annual Refresh-Cost Bound
    222 =====================================
    223 
    224 The fee summary should distinguish a conservative upper bound from an expected
    225 charge. The following bound covers keeping the current balance for 365 days
    226 without payments or additional withdrawals. It excludes initial withdrawal
    227 fees, payment-related refreshes, and losses caused by expiration or an outage.
    228 Those risks must not be presented as covered by the estimate.
    229 
    230 Assumptions
    231 -----------
    232 
    233 For this metric, a reasonable denomination/fee structure satisfies:
    234 
    235 * Continuous compatible offerings with stable values, fees, and lifetime
    236   bounds. Unpublished future offerings are projection assumptions, not signed
    237   commitments.
    238 * Every reachable denomination, including small change, admits positive
    239   value-first outputs. Refresh completes while output keys remain withdrawable;
    240   a delayed reveal outside that window invalidates the estimate.
    241 * ``Gmin > 0`` is a lower bound on remaining lifetime at output acquisition;
    242   ``Hmax`` bounds all obtainable output lifetimes from above. Full key lifetime
    243   from validity start to deposit expiration suffices for ``Hmax``.
    244 * ``Delta = Gmin - Hmax / 4 > 0``.
    245 * ``0 <= p < 1`` bounds total loss divided by input value for every paid refresh
    246   of every reachable denomination and projected selection, including output
    247   fees and rounding.
    248 
    249 If these assumptions cannot be established, report the bound as unavailable
    250 and explain why. Recompute or withdraw it when assumptions fail; do not ignore
    251 unrefreshable dust or assume unknown future fees are zero.
    252 
    253 Calculation and justification
    254 -----------------------------
    255 
    256 For current balance ``B`` and horizon ``T = 365 days``, compute::
    257 
    258    Delta = Gmin - Hmax / 4
    259    N = 1 + floor(T / Delta)
    260    annual_loss_bound = B * (1 - (1 - p) ** N)
    261 
    262 Round the monetary bound upward to the currency's supported amount precision.
    263 If computing separate bounds per exchange or compatibility group, sum their
    264 rounded bounds. The fee summary must show the horizon and assumptions, and
    265 label the result a conditional upper bound, not a predicted debit or a
    266 promise about future exchange offerings.
    267 
    268 A new coin starts with at least ``Gmin`` remaining. Neither paid rule can
    269 match above ``Hmax / 4``: rule 1 requires a fourfold extension, and rule 3 has
    270 ``E <= G / 4 <= Hmax / 4``. Paid refreshes are therefore separated by at least
    271 ``Delta`` along each sequence of replacement coins. Free refreshes cannot
    272 shorten that interval; scheduling delays only lengthen it. The initial ``1``
    273 allows an immediately due refresh of existing holdings.
    274 
    275 Each paid refresh preserves at least ``1 - p`` of its input, including when
    276 it splits into multiple outputs. Since every resulting sequence has at most
    277 ``N`` paid refreshes, at least ``B * (1 - p) ** N`` remains. If ``p == 0``, the
    278 bound is zero.
    279 
    280 With the recommended configuration, ``Gmin = 720 days``, ``Hmax = 750 days``,
    281 and ``Delta = 532.5 days``, giving ``N = 1``. If the total loss per paid refresh
    282 is bounded by one percent across all reachable denominations, a balance of
    283 100 currency units therefore has a conditional annual bound of 1 unit. The
    284 one-percent premise must be checked; the key durations alone do not imply it.
    285 
    286 
    287 Definition of Done
    288 ==================
    289 
    290 * [x] Earlier policy prototyped in a wallet-core feature branch
    291 * [ ] Revised policy reviewed, implemented, and merged
    292 * [ ] Tests cover adaptive and strict thresholds, mixed/empty outputs, fees and
    293   rounding, power state, persistent scheduling, retries, and warning overlap
    294 * [ ] Fee-bound tests cover zero cost, split outputs, initially due refreshes,
    295   and unavailable estimates
    296 * [ ] Exchange guidance checked against supported key rotation
    297 * [ ] GUI warnings and fee summaries designed and tested with dev experiments
    298 * [ ] Implemented behavior documented in the wallet reference
    299 
    300 Alternatives
    301 ============
    302 
    303 The older wallet policy checked an exchange after 75% of the period from
    304 withdrawal expiration to deposit expiration had passed, refreshing coins more
    305 than 50% into that period. Grouping these operations reduced separate checks,
    306 but did not account for replacement lifetimes or absolute offline margins.
    307 
    308 The earlier DD71 policy accepted any extension below a fixed 90-day threshold.
    309 That could repeatedly refresh short-lived coins whenever slightly newer keys
    310 appeared. The adaptive threshold retains an emergency path without treating
    311 all short-lived coins as perpetual emergencies.
    312 
    313 
    314 Drawbacks
    315 =========
    316 
    317 * This policy does not learn individual wallet usage patterns.
    318 * Value-first selection can defer a lifetime extension that would cost more.
    319 * The annual bound can be conservative or unavailable, especially with changing
    320   offerings or unrefreshable small denominations.
    321 * Independent scheduling reduces synchronized traffic; overdue startup checks,
    322   widespread outages, and urgent retries can still create bursts.
    323 * Longer spending lifetimes increase exchange storage obligations. Operator
    324   recommendations must balance those costs against wallet availability.