diff options
author | Florian Dold <florian@dold.me> | 2024-04-05 13:29:45 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2024-04-05 13:29:45 +0200 |
commit | 7b2f95e482367183ca77f619d9ecbe34d5fd85bd (patch) | |
tree | 6ad95fae73143d5af464c96dc4df1e844a6451c9 /packages/taler-wallet-core/src/exchanges.ts | |
parent | 7054acfd0470e13b8fc4c1f08834bc2fcc776ef4 (diff) | |
download | wallet-core-7b2f95e482367183ca77f619d9ecbe34d5fd85bd.tar.xz |
wallet-core: put exchange in update-unavailable if master pub / currency change unexpectedly
Diffstat (limited to 'packages/taler-wallet-core/src/exchanges.ts')
-rw-r--r-- | packages/taler-wallet-core/src/exchanges.ts | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts index fa2876e30..cae758a43 100644 --- a/packages/taler-wallet-core/src/exchanges.ts +++ b/packages/taler-wallet-core/src/exchanges.ts @@ -102,6 +102,7 @@ import { TaskRunResult, TaskRunResultType, TransactionContext, + computeDbBackoff, constructTaskIdentifier, getAutoRefreshExecuteThreshold, getExchangeEntryStatusFromRecord, @@ -1061,6 +1062,14 @@ async function internalWaitReadyExchange( ready = true; } break; + case ExchangeEntryDbUpdateStatus.UnavailableUpdate: + throw TalerError.fromDetail( + TalerErrorCode.WALLET_EXCHANGE_UNAVAILABLE, + { + exchangeBaseUrl: canonUrl, + innerError: retryInfo?.lastError, + }, + ); default: { if (retryInfo) { throw TalerError.fromDetail( @@ -1285,9 +1294,11 @@ export async function updateExchangeFromUrlHandler( return TaskRunResult.finished(); case ExchangeEntryDbUpdateStatus.InitialUpdate: case ExchangeEntryDbUpdateStatus.ReadyUpdate: - case ExchangeEntryDbUpdateStatus.UnavailableUpdate: updateRequestedExplicitly = true; break; + case ExchangeEntryDbUpdateStatus.UnavailableUpdate: + // Only retry when scheduled to respect backoff + break; case ExchangeEntryDbUpdateStatus.Ready: break; default: @@ -1407,8 +1418,6 @@ export async function updateExchangeFromUrlHandler( logger.trace("updating exchange info in database"); - let detailsPointerChanged = false; - let ageMask = 0; for (const x of keysInfo.currentDenominations) { if ( @@ -1442,18 +1451,42 @@ export async function updateExchangeFromUrlHandler( } const oldExchangeState = getExchangeState(r); const existingDetails = await getExchangeRecordsInternal(tx, r.baseUrl); + let detailsPointerChanged = false; if (!existingDetails) { detailsPointerChanged = true; } + let detailsIncompatible = false; if (existingDetails) { if (existingDetails.masterPublicKey !== keysInfo.masterPublicKey) { + detailsIncompatible = true; detailsPointerChanged = true; } if (existingDetails.currency !== keysInfo.currency) { + detailsIncompatible = true; detailsPointerChanged = true; } // FIXME: We need to do some consistency checks! } + if (detailsIncompatible) { + logger.warn( + `exchange ${r.baseUrl} has incompatible data in /keys, not updating`, + ); + // We don't support this gracefully right now. + // See https://bugs.taler.net/n/8576 + r.updateStatus = ExchangeEntryDbUpdateStatus.UnavailableUpdate; + r.updateRetryCounter = (r.updateRetryCounter ?? 0) + 1; + r.nextUpdateStamp = computeDbBackoff(r.updateRetryCounter); + r.nextRefreshCheckStamp = timestampPreciseToDb( + AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()), + ); + r.cachebreakNextUpdate = true; + await tx.exchanges.put(r); + return { + oldExchangeState, + newExchangeState: getExchangeState(r), + }; + } + r.updateRetryCounter = 0; const newDetails: ExchangeDetailsRecord = { auditors: keysInfo.auditors, currency: keysInfo.currency, @@ -1488,6 +1521,7 @@ export async function updateExchangeFromUrlHandler( updateClock: timestampPreciseToDb(TalerPreciseTimestamp.now()), }; } + r.updateStatus = ExchangeEntryDbUpdateStatus.Ready; r.cachebreakNextUpdate = false; await tx.exchanges.put(r); |