aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/exchanges.ts
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-04-05 13:29:45 +0200
committerFlorian Dold <florian@dold.me>2024-04-05 13:29:45 +0200
commit7b2f95e482367183ca77f619d9ecbe34d5fd85bd (patch)
tree6ad95fae73143d5af464c96dc4df1e844a6451c9 /packages/taler-wallet-core/src/exchanges.ts
parent7054acfd0470e13b8fc4c1f08834bc2fcc776ef4 (diff)
downloadwallet-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.ts40
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);