taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit ae44f3187c0428ff9c84c881e194df9f1642d06b
parent 540cd68e6ef2d56559d91657ecde3b789a441119
Author: Florian Dold <dold@taler.net>
Date:   Thu,  6 Aug 2026 19:02:48 +0200

wallet: only store denominations that can still be withdrawn from

An exchange advertises a denomination until its legal expiration, so most of a
/keys response is denominations no wallet can ever withdraw from -- 952 of 1022
on the demo exchange.  Ones already in the database are kept regardless: a coin
in the wallet may refer to them.

Issue: https://bugs.taler.net/n/11334

Diffstat:
Mpackages/taler-wallet-core/src/exchanges.ts | 37++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -973,6 +973,22 @@ function denomFamilyParamsKey(p: WalletDenomFamilyParams): string { } /** + * Is a denomination we have not seen before worth a row in the database? + * + * Only denominations that can still be withdrawn from are: the wallet gets a + * coin of a denomination by withdrawing or refreshing into it, and both pick + * from the withdrawable ones. A denomination it already has a row for is + * never dropped on this basis -- that row may be what a coin in the wallet + * refers to, and losing it would count the coin as vanished. + */ +function isDenomWorthStoring(d: DenominationInfo): boolean { + const expireWithdraw = AbsoluteTime.fromProtocolTimestamp( + d.stampExpireWithdraw, + ); + return !AbsoluteTime.isExpired(expireWithdraw); +} + +/** * Timestamp (in seconds) to ask the exchange to cherry-pick /keys by, or * undefined when the whole response should be downloaded. * @@ -2181,7 +2197,21 @@ export async function updateExchangeFromUrlHandler( ); } + let numDenomsSkipped = 0; + for (const currentDenom of denomInfos) { + const oldDenom = oldDenomByDph.get(currentDenom.denomPubHash); + + // A denomination that can no longer be withdrawn from is only of + // interest for coins we already hold, and we cannot hold a coin of one + // we never stored. Exchanges keep advertising these for years after + // they stop issuing them -- on the demo exchange 952 of 1022 -- so not + // writing them is most of the cost of adding an exchange. + if (!oldDenom && !isDenomWorthStoring(currentDenom)) { + numDenomsSkipped++; + continue; + } + const familyParams: WalletDenomFamilyParams = { exchangeBaseUrl: currentDenom.exchangeBaseUrl, exchangeMasterPub: currentDenom.exchangeMasterPub, @@ -2251,7 +2281,6 @@ export async function updateExchangeFromUrlHandler( isLost: currentDenom.isLost, }; - const oldDenom = oldDenomByDph.get(currentDenom.denomPubHash); if (oldDenom) { // FIXME: Do consistency check, report to auditor if necessary. // See https://bugs.taler.net/n/8594 @@ -2279,6 +2308,12 @@ export async function updateExchangeFromUrlHandler( } } + if (numDenomsSkipped > 0) { + logger.trace( + `did not store ${numDenomsSkipped} of ${denomInfos.length} denominations of ${exchangeBaseUrl}, no longer withdrawable`, + ); + } + // Update list issue date for all denominations, // and mark non-offered denominations as such. //