auto-refresh.rst (6942B)
1 Automatic coin renewal 2 ###################### 3 4 Wallet-core implements the September 2026 policy from 5 :doc:`../design-documents/071-auto-refresh`, with deterministic greedy output 6 selection. Wallet clients receive renewal information with each scoped balance. 7 8 Selection and eligibility 9 ========================= 10 11 For an input coin, let ``D`` be its deposit expiration, ``W`` its withdrawal 12 expiration, ``R = D - now``, and ``E = min(90 days, (D - W) / 4)``. Days are fixed 13 24-hour periods. Invalid or infinite lifetimes are reported; expired coins use 14 existing expiration and recovery handling. 15 16 The wallet considers compatible, verified, currently withdrawable denomination 17 keys, excluding revoked and lost keys. It selects outputs greedily in descending 18 face-value order, breaking ties by lower withdrawal fee, later deposit expiration, 19 and denomination hash. The refresh protocol permits at most 64 outputs. 20 This is deliberately best effort: it does not implement DD71's globally optimal 21 value/lifetime/coin-count selection. Spending existing coins retains DD91's 22 modified greedy algorithm and earliest-expiration preference. 23 24 The earliest selected output expiration determines the output lifetime. Total 25 cost includes melting fees, withdrawal fees, and unrepresentable remainder. 26 The wallet requires positive recovered value and an extension of validity, then 27 evaluates these strict conditions in order: 28 29 * Output remaining lifetime exceeds four times the input remaining lifetime. 30 * Input remaining lifetime is below 180 days, output remaining lifetime exceeds 31 360 days, total cost is zero, and external power is confirmed. 32 * Input remaining lifetime is below ``E``. 33 34 Decision, accounting, and execution use the same selected outputs. Inputs reserved 35 for payments or refreshes are unavailable for another automatic refresh. Before 36 sending a melt, the wallet revalidates eligibility and selected keys. A request 37 that might already have reached the exchange retains its original commitment 38 through retry and recovery. 39 40 Scheduling 41 ========== 42 43 A private random deadline per wallet and input denomination spreads renewal 44 traffic. Before ``D - E / 10``, the delay is at most the minimum of one day, 45 ``E / 10``, and half the time to that urgent boundary. Urgent inputs are due 46 immediately. Restarting, updating keys, or reopening the application does not 47 redraw or postpone a deadline. Temporarily ineligible inputs retain their deadline 48 while the wallet waits for a valid plan. Retry backoff is randomized and capped 49 by the time to urgency, or remaining lifetime once urgent. 50 51 Background balance reporting 52 ============================ 53 54 Renewal information is computed by the ``refresh-balance`` maintenance task and 55 persisted by balance scope. A balance request only reads the saved report and its 56 input generation; it does not load denominations, scan refresh history, or run 57 output selection. The report survives closing and reopening the wallet. 58 59 Changes to holdings, exchange keys and trust, refresh progress, and relevant 60 retry errors invalidate the report in the same transaction as their inputs. 61 The task reads a consistent snapshot, releases the database transaction, and 62 computes the report while periodically yielding to other wallet work. It publishes 63 only if the input generation is still current, then notifies balance clients. 64 A changed generation causes another calculation instead of publishing stale data. 65 66 Known warnings and recovery notices remain visible while a report is being 67 updated. A cost bound is withheld when its generation, balance amount, or time 68 validity no longer matches; clients see a checking indication until the new report 69 is ready. An empty cache also returns a checking indication without blocking the 70 balance request. The task schedules itself for the next relevant validity or key 71 freshness boundary, with a daily upper limit between checks. 72 73 Power observations 74 ================== 75 76 ``hintPowerState`` accepts ``{ powerSource: "external" | "battery" | "unknown" }`` 77 and returns an empty object. Observations are transient and expire after 60 78 seconds: a host should refresh its current observation at least every 30 seconds. 79 The browser integration uses supported battery observations and reports unknown 80 for unsupported or inconclusive readings. Unknown power never enables the free 81 opportunistic rule; necessary refreshes do not require external power. 82 83 Balance warnings and recovery notices 84 ==================================== 85 86 Each balance may contain ``refreshInfo`` with ``risks``, ``recoveries``, and 87 ``annualCostBound``. Risks identify the exchange, amount and earliest expiration. 88 They distinguish a pending renewal, a connection failure, an exchange error, 89 unavailable suitable replacements established from fresh keys, a check in 90 progress, and invalid validity dates. They do not assert device-wide offline 91 status. Pending and failing renewals retain expiration indications until success. 92 93 A completed group whose coins were close to expiration before melting supplies 94 one recovery notice, including the new expiration and next relevant date. 95 ``dismissWalletWarning`` accepts ``{ warningId: string }`` to persist dismissal. 96 Active expiration risks cannot be dismissed. A renewal notice does not imply the 97 wallet was previously offline. 98 99 Conditional cost bound 100 ====================== 101 102 The balance screen's expandable cost summary covers keeping the current balance 103 for 365 days without payments or additional withdrawals. It is a conditional 104 upper bound, not a predicted debit. It assumes continuously available compatible 105 families with stable values, fees and lifetime bounds, and reveal completing 106 before output withdrawal validity ends. Unpublished future offerings are a 107 projection, not a signed commitment. 108 109 Wallet-core checks all reachable compatible denominations, including small change, 110 and includes actual greedy-selection losses. It establishes conservative bounds 111 ``Gmin``, ``Hmax``, and loss fraction ``p``, then uses 112 ``Delta = Gmin - Hmax / 4``, ``N = 1 + floor(365 days / Delta)``, and 113 ``B * (1 - (1 - p)**N)``. Group bounds are rounded upward to Taler's supported 114 amount precision before summing. Missing or stale information, unrefreshable 115 change, nonpositive ``Delta`` and unsettled holdings make the estimate unavailable. 116 Changed balances or offerings cause recomputation. 117 118 The estimate excludes initial withdrawal fees, payment-related refreshes, and 119 losses from expiration or outages. Keeping a wallet offline beyond its coin 120 validity periods can still lose funds. 121 122 Development experiments 123 ======================= 124 125 With development mode enabled and an existing balance, use 126 ``taler://dev-experiment/dd71-risk``, ``dd71-recovered``, or 127 ``dd71-cost-unavailable`` to exercise the balance presentation. These transient 128 fixtures do not alter coins. ``dd71-clear`` removes them. The browser demo also 129 includes a pending risk, a dismissible recovery notice, and a cost bound.